Compare commits

...

10 Commits

Author SHA1 Message Date
3b4dd4f1d1 Fork @sinclair/typemap to @alkdev/typemap with @alkdev/typebox backend
- Rename package to @alkdev/typemap, update peerDeps to @alkdev/typebox
- Replace all @sinclair/typebox imports with @alkdev/typebox
- Replace @sinclair/hammer build system with standalone build.mjs
- Remove upstream-only files (.github, .vscode, design/, typemap.png)
- Update readme with fork notice and new package names
- Add fork copyright to license
2026-04-23 15:36:51 +00:00
sinclairzx81
eb67d42876 Revision 0.10.1 (#39)
* Zod: Use Offset on String DateTime Format

* Version
2025-06-26 19:21:28 +09:00
Mudit Somani
658d2c49c9 Update Issue Path to use Standard Schema Array Convention (#36)
* Fix issue path to follow standard schema spec

* Refactor into different file
2025-06-26 19:08:04 +09:00
sinclair
631fab497a Revision 0.10.0 2025-06-03 17:12:40 +09:00
Kavishka Ganganatha
d428962694 Valibot Pipe Inference (#31)
- Fixes Pipe inference on Valibot 1.x, noting additional `readonly` constraint added post 1.0.
2025-06-03 17:09:31 +09:00
sinclair
978cb5d962 Revision 0.9.1 2025-04-02 23:05:26 +09:00
sinclair
59a723cca8 Revision 0.9.0 2025-03-19 14:05:52 +09:00
sinclair
8b8d5eea09 Valibot 1.0.0 2025-03-19 14:05:15 +09:00
sinclair
a7b5e17cf5 Revision 0.8.19 2025-03-12 19:45:30 +09:00
sinclairzx81
657bbf295a Revision 0.8.18 (#27)
* Fix Valibot Enum Mapping Path

* Version
2025-02-18 21:32:40 +09:00
69 changed files with 674 additions and 3287 deletions

0
.github/.keep vendored
View File

View File

@@ -1,24 +0,0 @@
name: Build
on: [push, pull_request]
jobs:
TypeBox-Adapter:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: [16.x, 18.x, 20.x]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v3
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- name: Install Packages
run: npm install
- name: Build Library
run: npm run build
- name: Test Library
run: npm run test

View File

@@ -1,23 +0,0 @@
name: Build Nightly
on:
schedule:
- cron: '0 18 * * *' # 6pm Daily
jobs:
TypeBox-Adapter-Nightly:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: [20.x]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- name: Install Node
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
- name: Install Packages
run: npm install
- name: Build Library
run: npm run build

View File

@@ -1,6 +0,0 @@
{
"files.exclude": {
"node_modules": true,
"package-lock.json": true
}
}

219
build.mjs Normal file
View File

@@ -0,0 +1,219 @@
import * as Fs from "node:fs";
import * as Path from "node:path";
import { execSync } from "node:child_process";
const TARGET = "target/build";
function shell(cmd) {
console.log(`> ${cmd}`);
execSync(cmd, { stdio: "inherit" });
}
function rmrf(dir) {
Fs.rmSync(dir, { recursive: true, force: true });
}
function mkdirp(dir) {
Fs.mkdirSync(dir, { recursive: true });
}
function cp(src, dest) {
mkdirp(Path.dirname(dest));
Fs.copyFileSync(src, dest);
}
// --- Clean ---
function clean() {
rmrf("target");
}
// --- Remove MIT Notices from dist ---
function removeNotices(dir) {
function escape(content) {
return content
.split("")
.map((c) => `\\${c}`)
.join("");
}
function removeNotice(content) {
const open = escape(
"/*--------------------------------------------------------------------------",
);
const close = escape(
"---------------------------------------------------------------------------*/",
);
const criteria = "Permission is hereby granted, free of charge";
const pattern = new RegExp(`${open}[\\s\\S]*?${close}`, "gm");
while (true) {
const match = pattern.exec(content);
if (match === null) return content.trimStart();
if (!match[0].includes(criteria)) continue;
content = content.replace(match[0], "");
}
}
function processFile(sourcePath) {
const sourceContent = Fs.readFileSync(sourcePath, "utf-8");
const targetContent = removeNotice(sourceContent);
Fs.writeFileSync(sourcePath, targetContent);
}
function walk(sourcePath) {
const stat = Fs.statSync(sourcePath);
if (stat.isDirectory()) {
for (const entry of Fs.readdirSync(sourcePath)) {
walk(Path.join(sourcePath, entry));
}
} else if (stat.isFile()) {
processFile(sourcePath);
}
}
walk(dir);
}
// --- ESM Specifier Rewrite ---
function convertToEsm(dir) {
function shouldSkipSpecifier(captured) {
const specifier = captured.slice(1, captured.length - 1);
return (
specifier.includes(".mjs") ||
specifier.startsWith("@alkdev/typebox") ||
specifier.startsWith("valibot") ||
specifier.startsWith("zod")
);
}
function replaceInlineImportSpecifiers(content) {
const pattern = /import\((.*?)\)/g;
while (true) {
const match = pattern.exec(content);
if (match === null) return content;
const captured = match[1];
if (shouldSkipSpecifier(captured)) continue;
const specifier = captured.slice(1, captured.length - 1);
content = content.replace(captured, `"${specifier}.mjs"`);
}
}
function replaceExportSpecifiers(content) {
const pattern = /(export|import)(.*) from ('(.*)');/g;
while (true) {
const match = pattern.exec(content);
if (match === null) return content;
const captured = match[3];
if (shouldSkipSpecifier(captured)) continue;
const specifier = captured.slice(1, captured.length - 1);
content = content.replace(captured, `'${specifier}.mjs'`);
}
}
function replaceSpecifiers(content) {
return replaceInlineImportSpecifiers(replaceExportSpecifiers(content));
}
function newExtension(ext) {
return ext === ".js" ? ".mjs" : ext === ".ts" ? ".mts" : ext;
}
function processFile(sourcePath) {
const ext = Path.extname(sourcePath);
if (![".js", ".ts"].includes(ext)) return;
const dirname = Path.dirname(sourcePath);
const basename = Path.basename(sourcePath, ext);
const newExt = newExtension(ext);
const sourceContent = Fs.readFileSync(sourcePath, "utf-8");
const targetContent = replaceSpecifiers(sourceContent);
const targetPath = Path.join(dirname, `${basename}${newExt}`);
Fs.writeFileSync(sourcePath, targetContent);
Fs.renameSync(sourcePath, targetPath);
}
function walk(sourcePath) {
const stat = Fs.statSync(sourcePath);
if (stat.isDirectory()) {
for (const entry of Fs.readdirSync(sourcePath)) {
walk(Path.join(sourcePath, entry));
}
} else if (stat.isFile()) {
processFile(sourcePath);
}
}
walk(dir);
}
// --- Build CJS ---
function buildCjs() {
console.log("building...cjs");
const target = `${TARGET}/build/cjs`;
shell(
`tsc -p ./src/tsconfig.json --outDir ${target} --target ES2020 --module Node16 --moduleResolution Node16 --declaration`,
);
removeNotices(target);
}
// --- Build ESM ---
function buildEsm() {
console.log("building...esm");
const target = `${TARGET}/build/esm`;
shell(
`tsc -p ./src/tsconfig.json --outDir ${target} --target ES2020 --module ESNext --moduleResolution Bundler --declaration`,
);
convertToEsm(target);
removeNotices(target);
}
// --- Build package.json ---
function buildPackageJson() {
console.log("building...package.json");
const rootPkg = JSON.parse(Fs.readFileSync("package.json", "utf-8"));
const pkg = {
name: rootPkg.name,
version: rootPkg.version,
description: rootPkg.description,
keywords: rootPkg.keywords,
author: rootPkg.author,
license: rootPkg.license,
repository: rootPkg.repository,
scripts: { test: "echo test" },
types: "./build/cjs/index.d.ts",
main: "./build/cjs/index.js",
module: "./build/esm/index.mjs",
"esm.sh": { bundle: false },
exports: {
".": {
require: {
types: "./build/cjs/index.d.ts",
default: "./build/cjs/index.js",
},
import: {
types: "./build/esm/index.d.mts",
default: "./build/esm/index.mjs",
},
},
},
peerDependencies: rootPkg.peerDependencies,
};
Fs.writeFileSync(`${TARGET}/package.json`, JSON.stringify(pkg, null, 2));
}
// --- Test ---
function test(filter = "") {
shell(
`tsc -p ./test/tsconfig.json --outDir target/test --target ES2020 --module Node16 --moduleResolution Node16`,
);
shell(`mocha target/test/index.js -g "${filter}"`);
}
// --- Main ---
const command = process.argv[2] || "build";
if (command === "clean") {
clean();
} else if (command === "test") {
test(process.argv[3] || "");
} else if (command === "build") {
test();
clean();
buildCjs();
buildEsm();
buildPackageJson();
cp("readme.md", `${TARGET}/readme.md`);
cp("license", `${TARGET}/license`);
shell(`cd ${TARGET} && npm pack`);
console.log("done!");
} else {
console.error(`unknown command: ${command}`);
process.exit(1);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 777 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,4 +1,4 @@
import { TypeBox, Valibot, Zod, Syntax, Compile } from '@sinclair/typemap'
import { TypeBox, Valibot, Zod, Syntax, Compile } from '@alkdev/typemap'
// ------------------------------------------------------------------
// Syntax Types

View File

@@ -29,7 +29,7 @@
// import { Schema as et } from '@effect/schema/Schema'
// import { Schema as es } from '@effect/schema'
// import * as ast from '@effect/schema/AST'
// import * as tb from '@sinclair/typebox'
// import * as tb from '@alkdev/typebox'
// // ------------------------------------------------------------------
// // Effect Guard

View File

@@ -1,72 +0,0 @@
import * as Build from './task/build'
import * as Fs from 'node:fs'
// ------------------------------------------------------------------
// Benchmark
// ------------------------------------------------------------------
export async function benchmark(target = 'target/benchmark') {
await shell(`hammer run task/benchmark/index.ts --dist ${target}`)
}
// ------------------------------------------------------------------
// Clean
// ------------------------------------------------------------------
export async function clean() {
await folder('target').delete()
}
// ------------------------------------------------------------------
// Start
// ------------------------------------------------------------------
export async function start() {
await shell('hammer run example/index.ts --dist target/example')
}
// -------------------------------------------------------------------------------
// Format
// -------------------------------------------------------------------------------
export async function format() {
await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write test src')
}
// ------------------------------------------------------------------
// Test
// ------------------------------------------------------------------
export async function test(filter = '') {
await shell(`hammer build ./test/index.ts --dist target/test --platform node`)
await shell(`mocha target/test/index.js -g "${filter}"`)
}
// ------------------------------------------------------------------
// Build
// ------------------------------------------------------------------
export async function build_check(target = 'target/build') {
const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8'))
await shell(`cd ${target} && attw sinclair-typemap-${version}.tgz`)
}
export async function build(target = 'target/build') {
await test()
await clean()
await Promise.all([
Build.Package.build(target),
Build.Esm.build(target),
Build.Cjs.build(target),
])
await folder(target).add('readme.md')
await folder(target).add('license')
await shell(`cd ${target} && npm pack`)
await build_check(target)
}
// -------------------------------------------------------------
// Publish
// -------------------------------------------------------------
export async function publish(otp, target = 'target/build') {
const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8'))
if(version.includes('-dev')) throw Error(`package version should not include -dev specifier`)
await shell(`cd ${target} && npm publish sinclair-typemap-${version}.tgz --access=public --otp ${otp}`)
await shell(`git tag ${version}`)
await shell(`git push origin ${version}`)
}
// -------------------------------------------------------------
// Publish-Dev
// -------------------------------------------------------------
export async function publish_dev(otp, target = 'target/build') {
const { version } = JSON.parse(Fs.readFileSync(`${target}/package.json`, 'utf8'))
if(!version.includes('-dev')) throw Error(`development package version should include -dev specifier`)
await shell(`cd ${target} && npm publish sinclair-typemap-${version}.tgz --access=public --otp ${otp} --tag dev`)
}

View File

@@ -1,8 +1,9 @@
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
Copyright (c) 2024-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Copyright (c) 2026 alkdev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

2325
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,26 @@
{
"name": "@sinclair/typemap",
"version": "0.8.17",
"name": "@alkdev/typemap",
"version": "0.10.1",
"description": "Syntax Compiler and Translation System for Runtime Types",
"author": "sinclairzx81",
"author": "alkdev",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/sinclairzx81/typemap"
"url": "https://git.alk.dev/alkdev/typemap"
},
"scripts": {
"benchmark": "hammer task benchmark",
"clean": "hammer task clean",
"start": "hammer task start",
"format": "hammer task format",
"test": "hammer task test",
"build": "hammer task build",
"publish": "hammer task publish"
"clean": "node build.mjs clean",
"format": "prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write test src",
"test": "node build.mjs test",
"build": "node build.mjs build"
},
"peerDependencies": {
"@sinclair/typebox": "^0.34.24",
"valibot": "^1.0.0-rc.0",
"@alkdev/typebox": "^0.34.49",
"valibot": "^1.0.0",
"zod": "^3.24.1"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.2",
"@sinclair/hammer": "^0.18.0",
"@types/mocha": "^10.0.10",
"@types/node": "^22.10.2",
"mocha": "^11.0.1",

399
readme.md
View File

@@ -4,431 +4,262 @@
<p>Syntax Compiler and Translation System for Runtime Types</p>
<img src="./typemap.png" />
<br />
<br />
[![npm version](https://badge.fury.io/js/%40sinclair%2Ftypemap.svg)](https://badge.fury.io/js/%40sinclair%2Ftypemap)
![Downloads](https://img.shields.io/npm/dm/%40sinclair%2Ftypemap)
[![Build](https://github.com/sinclairzx81/typemap/actions/workflows/build.yml/badge.svg)](https://github.com/sinclairzx81/typemap/actions/workflows/build.yml)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
</div>
## About This Fork
This is the **@alkdev/typemap** fork — a community-maintained continuation of TypeMap 0.x. The original TypeMap project has been archived after a complete rewrite; this fork continues the 0.x API with the `@alkdev/typebox` backend.
- **Supply chain security**: Published from our own infrastructure; no dependency on upstream publish access.
- **Stability**: No breaking rewrites planned. Bug fixes and compatibility patches only.
- **Drop-in replacement**: `@alkdev/typemap` is API-compatible with `@sinclair/typemap` 0.x, using `@alkdev/typebox` in place of `@sinclair/typebox`.
## Install
```bash
$ npm install @sinclair/typemap --save
$ npm install @alkdev/typemap --save
```
## Usage
Parse and Compile Types from TypeScript Syntax ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgYQuYAbApnAvnAMyjTgHIABAZ2ADsBjDAQ2CgHoYBPMLERsUgFADWrFGjCYcAFS5ZKcAOrAYACzgBlDjRiMAHkLoQaleADdGGYABNGMaHAC8Y9NgAUAAySMAXHBNRaAHMAGjgAI19-ILx3AEo4EThDYzMLa1toXwA1NJs7KAAeKQB5MIArLDoYAoQBOHqGxqbmlta2tsT6nzgpdRgAmhC69pHRsZbO8N9e-qDh8YXFidFcAD5VoUScyzycAHdlNT7GGhsoKw06FR5GAyMTOCg5AFcMeCdzHYyoAG1SAD8TCczlZSABdAB0n3SMCwriQTUSyQeT0orxgvmOp0Y53UVxuWQAjBCAEovN41YbdUjXDAYCCkUJLZmI0RdSKzQbBYYRMh7aAYUEs4UNSa8qKDAS4eIi2WtRJrIA))
Parse and Compile Types from TypeScript Syntax
```typescript
import { Compile } from '@sinclair/typemap'
import { Compile } from "@alkdev/typemap";
// Compile Types With Syntax
const validator = Compile(`{ a: string, b: string }`);
const validator = Compile(`{ a: string, b: string }`) // const validator: Validator<TObject<{
// a: TString,
// b: TString
// }>>
// Validate with Standard Schema
const result = validator['~standard'].validate({ // const result: StandardSchemaV1.Result<{
a: 'hello', // a: string,
b: 'world' // b: string
}) // }>
const result = validator["~standard"].validate({
a: "hello",
b: "world",
});
```
## Overview
TypeMap is a syntax frontend and compiler backend for the [TypeBox](https://github.com/sinclairzx81/typebox), [Valibot](https://github.com/fabian-hiller/valibot) and [Zod](https://github.com/colinhacks/zod) runtime type libraries. It offers a common TypeScript syntax for type construction, a runtime compiler for high-performance validation and type translation from one library to another.
TypeMap is written as an advanced type mapping system for the TypeBox project. It is designed to accelerate remote type libraries on TypeBox infrastructure as well enabling TypeBox to integrate with remote type library infrastructure via reverse type remapping. This project also offers high-performance validation for frameworks that orientate around the [Standard Schema](https://github.com/standard-schema/standard-schema) TypeScript interface.
License: MIT
## Contents
- [Install](#Install)
- [Usage](#Usage)
- [Overview](#Overview)
- [Example](#Example)
- [Mapping](#Section-Mapping)
- [Syntax](#Mapping-Syntax)
- [TypeBox](#Mapping-TypeBox)
- [Valibot](#Mapping-Valibot)
- [Zod](#Mapping-Zod)
- [Syntax](#Section-Syntax)
- [Types](#Syntax-Types)
- [Options](#Syntax-Options)
- [Parameters](#Syntax-Parameters)
- [Generics](#Syntax-Generics)
- [Static](#Section-Static)
- [Json Schema](#Json-Schema)
- [Tree Shake](#Tree-Shake)
- [Compile](#Compile)
- [Benchmark](#Benchmark)
- [Contribute](#Contribute)
TypeMap is a syntax frontend and compiler backend for the [TypeBox](https://git.alk.dev/alkdev/typebox), [Valibot](https://github.com/fabian-hiller/valibot) and [Zod](https://github.com/colinhacks/zod) runtime type libraries. It offers a common TypeScript syntax for type construction, a runtime compiler for high-performance validation and type translation from one library to another.
## Example
Use TypeScript syntax to create types for TypeBox, Valibot and Zod ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAagIYA2wARhDIQFoQAmcAvnAGZQQhwDkAAgGdgAOwDGZEsCgB6GOgwgSYXgChVMmXADKqETBK4UCwerEQRg+NrgBeOAAMEquHFwAuOCICuIShih8FzhUTx8-AKDXAC8w338oVRYHdU04ACVvfVAMY0xTVXNLeGQ7POw8AAptAEpXeobGpubGtKKrFE9kAHlKACsMMRgAHiQAOgnWAD4zCw6iMtIKahhqupaNzYa2ufgiT16Boe0xAAtFElG4CbHWQhuZwt24OjKGRjWtr++d4pfPd6HQYjcaTFj3CZTIA))
Use TypeScript syntax to create types for TypeBox, Valibot and Zod
```typescript
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
// Syntax Types
import { TypeBox, Valibot, Zod } from "@alkdev/typemap";
const S = `{
x: number,
y: number,
z: number
}`
}`;
// Runtime Types
const T = TypeBox(S) // const T: TObject<{ ... }>
const V = Valibot(S) // const V: ObjectSchema<{ ... }, ...>
const Z = Zod(S) // const Z: ZodObject<{ ... }, ...>
const T = TypeBox(S);
const V = Valibot(S);
const Z = Zod(S);
```
Translate TypeBox, Valibot and Zod types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAagIYA2wARhDIQFoQAmcAvnAGZQQhwDkAAgGdgAOwDGZEsCgB6GOgwgSYXgChVMmXADKqETBK44AWgB8cBszPFyVGifNpMOXOrEQRg+MjgBeFAouABSkFNQwQZZBAAYIqnBwuABccCIAriCUGFD48XCoKemZ2bkJAF6FGVlQqizRAJSNQA))
Translate TypeBox, Valibot and Zod types
```typescript
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
import { TypeBox, Valibot, Zod } from "@alkdev/typemap";
// Syntax -> Zod -> Valibot -> TypeBox
const T = TypeBox(Valibot(Zod(`{
const T = TypeBox(
Valibot(
Zod(`{
x: number,
y: number,
z: number
}`)))
}`),
),
);
```
Compile Valibot and Zod types on TypeBox infrastructure ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgYQuYAbApnAvnAMyjTgHIABAZ2ADsBjDAQ2CgHoYBPMLERsUgFADQkWHABehYiDLiIAE0EDWrOAC0FcACpcsQuhBqV4auAF4JAOggAjAFZY6MABRI47j56-efHlXAMjEwAudQUAeXtHGAAeNwF3AA9Q8UsaAFcQGywoZwBKABpfYpLi-yTQjXkAOUzsqCLPBLgOFLS6nPzG0p7S8pbKhVqsnILm8TaMkdzC3rmy1XcJsJqOqAFcPPntnfd-XAA+IX8AJR4+OEYaeRQ0MEw9AUDjFHNb9GxnNS3d3v9n+DIUIANUYGGA8kYMGgMS0kQcTji7mav1RfUWcGS2mG9W6yLRBIWHla2LWY0JFK8-WWWhxORRlIp+wOR2UqgAEsAAOYAC20POI6V5EHS8FB4MhMGAhn0hheJzeyEsyB5jgA1q5GT5-ABJGA5KHSoyhACMAAYAPpm61W63NLEmvFauYqZokgBMTudPX8VV8oQALNazSBKHBnHwwMREnlxqEAMzenb+HTcACyFw8gZDYfcEbAUYgMY2eSAA))
```typescript
import { Compile } from '@sinclair/typemap'
import z from 'zod'
// Zod Type
const Z = z.object({ // const Z: ZodObject<{
x: z.number(), // x: ZodNumber,
y: z.number(), // y: ZodNumber,
z: z.number(), // z: ZodNumber
}) // }>
// Remap and Compile
const C = Compile(Z) // const C: Validator<TObject<{
// x: TNumber,
// y: TNumber,
// z: TNumber
// }>>
// High Throughout Validation
const R = C.Check({ // Iterations: 10_000_000
x: 1, //
y: 2, // Zod : 4000ms (approx)
z: 3 // TypeMap : 40ms (approx)
})
```
<a name="Section-Mapping"></a>
## Mapping
TypeMap is designed for runtime type translation. It provides one mapping function per library which can be used to translate remote types into types specific to that library. All mapping functions make a best effort attempt to translate the structures and semantics from each library. If no translation is possible, these functions return a `never` representation.
<a name="Mapping-Syntax"></a>
TypeMap is designed for runtime type translation. It provides one mapping function per library which can be used to translate remote types into types specific to that library.
### Syntax
Use the `Syntax` function to translate types into a Syntax string ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYhZgKAKCGhIsOACo4WGnHgkylWvWasOXXgCMIOYWOjxpsuADdipchVNYmwHTH3hDUmXIBeFpRXcQAJsJCDBDoNPDIcAC8KBjYOAAUFGFQ9ADmANoAuhQAlHD5BYVFxQXs7HDBoeEAXJTJaVkUxfFomLg5QSFhcAAqUTFtCTAAdAByAK4gWjxQ8Tl5JYuLZRVd8D21FOiT01BNJfE93DwAQrodld0Aav2tcfGmw-XoqXMLSx+l5ZfwV5vPqX2zSutnsEBgFzWcAAWrdYrh4u5hjoIEweFh0G9PtiVj8YZsUWiMUDCvFof4ckA))
```typescript
import { Syntax } from '@sinclair/typemap'
import { Syntax } from "@alkdev/typemap";
const S = Syntax('string[]') // const S: 'string[]' (Syntax)
const T = Syntax(t.Number()) // const T: 'number' (TypeBox)
const V = Syntax(v.string()) // const V: 'string' (Valibot)
const Z = Syntax(z.boolean()) // const Z: 'boolean' (Zod)
const S = Syntax("string[]");
const T = Syntax(t.Number());
const V = Syntax(v.string());
const Z = Syntax(z.boolean());
```
<a name="Mapping-TypeBox"></a>
### TypeBox
Use the `TypeBox` function to translate types and syntax into TypeBox types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA84C+cAZlBCHAOQACAzsAHYDGANgIbBQD0M6GIbMJQBQw0JFhwAVHDa048UuSp1GrDt16YARnhHjo8GXLgA3EmQqVTbFsF0x94Q9NnyAXheWV3EACYiwkwQDLTwAMpwALwofDi4ABSUYVCMAOYA2gC6lACUcAWFRcUlBVxccMGhEQBcKACCUFBsqAA8yOEwqQxpAHxwCeGoDDBsuLlBIWEo0bGY8QkwAHQAcgCuINoYUAm5+aUHpeWVU-DIdcjrm9uHCWjzeBNV0wBqs-fYeAmmSynpu-tDkCyhVnvAXhdOt00rcXrZ7BAYE9TnAAFrvOJfdxLXQQFgYNgMAHA4HHMFoi44PEEhgHBKo-y5IA))
```typescript
import { TypeBox } from '@sinclair/typemap'
import { TypeBox } from "@alkdev/typemap";
const S = TypeBox('string[]') // const S: TArray<TString> (Syntax)
const T = TypeBox(t.Number()) // const T: TNumber (TypeBox)
const V = TypeBox(v.string()) // const V: TString (Valibot)
const Z = TypeBox(z.boolean()) // const Z: TBoolean (Zod)
const S = TypeBox("string[]");
const T = TypeBox(t.Number());
const V = TypeBox(v.string());
const Z = TypeBox(z.boolean());
```
<a name="Mapping-Valibot"></a>
### Valibot
Use the `Valibot` function to translate types and syntax into Valibot types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgNQIYBtgCMLwL5wBmUEIcA5AAIDOwAdgMbqrBQD0MAnmAKYiphyAKCGhIsOACo4qanHjFSFGvSYt2XXjgAewsdHjTZcAG5ESZciYzZce8Aaky5AL3NLyLiABNhQhhB01PAAynAAvCg2ODAAFOTBUPQA5gDaALrkAJRwuXn5BYW5bGxwAUGhAFymAHQAglBQqJwhDAAWfKgAPDW9AHxwsSGcdDCo2ln+gcFwACoRUZgxsTA1AHIAriBYPFCxWTlFR0UlZdPws9Um61s7UK0d-AWxs9w8AEIQE1MVKAtoS1wsWuiRS+0Ox0hxVK5RmyCuNRCMCSdGSD06zwBthgk1h8AAWv9okCXDUcBB0DxUHRwVCoac8XB8QjPhSqXR0U88rF8T4skA))
```typescript
import { Valibot } from '@sinclair/typemap'
import { Valibot } from "@alkdev/typemap";
const S = Valibot('string[]') // const S: v.ArraySchema<...> (Syntax)
const T = Valibot(t.Number()) // const T: v.NumberSchema (TypeBox)
const V = Valibot(v.string()) // const V: v.StringSchema (Valibot)
const Z = Valibot(z.boolean()) // const Z: v.BooleanSchema (Zod)
const S = Valibot("string[]");
const T = Valibot(t.Number());
const V = Valibot(v.string());
const Z = Valibot(z.boolean());
```
<a name="Mapping-Zod"></a>
### Zod
Use the `Zod` function to translate types and syntax into Zod types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgLQgEzgXzgMyhEOAcgAEBnYAOwGMAbAQ2CgHoYBPMAUxHrCICh+oSLDgAqOPTJx4eAsXJU6jFuy4AjCAA8Bw6PAlS4AN1z5CRY-VrBNMXeH3jJ0gF5n5RV+gH9qESjJ4AGU4AF4UdAAKIiCoKgBzAG0AXSIASjgs7JzcvLzmZjh-QJCALjhXADpUNABBKCh6NgAeKvaAPjgo4LZKGHotdL8AoLgAFXDItCiYKoA5AFcQdU4oKPTM-O2drMLi0fhxiurapZW13Kjxjk4AIW1hkrGANSnaqOMquMSNrd2ATl9s94C8TjV0MEYPFKAkri9rLYIDAnocUO9otVNBBaJx6JQ-oCiXBgWjkODag8cXjKDkorV0kA))
```typescript
import { Zod } from '@sinclair/typemap'
import { Zod } from "@alkdev/typemap";
const S = Zod('string[]') // const S: z.ZodArray<...> (Syntax)
const T = Zod(t.Number()) // const T: z.ZodNumber (TypeBox)
const V = Zod(v.string()) // const V: z.ZodString (Valibot)
const Z = Zod(z.boolean()) // const Z: z.ZodBoolean (Zod)
const S = Zod("string[]");
const T = Zod(t.Number());
const V = Zod(v.string());
const Z = Zod(z.boolean());
```
<a name="Section-Syntax"></a>
## Syntax
TypeMap provides an optional TypeScript syntax parser that can be used to construct library types. Syntax parsing is implemented at runtime as well as in the type system. This feature can be used to uniformly construct types across libraries, as well as create types with embedded remote types.
<a name="Syntax-Types"></a>
TypeMap provides an optional TypeScript syntax parser that can be used to construct library types. Syntax parsing is implemented at runtime as well as in the type system.
### Types
Syntax types can be created by passing a string parameter to any library mapping function. TypeMap supports most TypeScript syntax. If the string contains a syntax error, the function will return a `never` type. ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA84C+cAZlBCHAOQACAzsAHYDGANgIbBQD0M6GIbMJQBQwphAa14yOAF4UfHLgAUlJLgBccAIwAaOKi0AmQpQCUcS1es3LXLnHGTpW5AHkARgCsMTGAB4kYVsQ0LDwiLh7K00UABlgGAwoNhZ-bQA+XWDI3LzI6MtDeMTk1P8jDJz8mtq7BwIqsQkpOABlOQVMJVUAQn7zOvDop1a21wA5DAA3ZLgAWnbUBhg2fABRKDIoIA))
```typescript
import { TypeBox } from '@sinclair/typemap'
import { TypeBox } from "@alkdev/typemap";
const T = TypeBox('{ x: 1, y: 2 }') // const T: TObject<{
// x: TLiteral<1>,
// y: TLiteral<2>
// }>
const T = TypeBox("{ x: 1, y: 2 }");
const S = TypeBox('!!!') // const S: TNever - Syntax Error
const S = TypeBox("!!!");
```
<a name="Syntax-Options"></a>
### Options
You can pass Json Schema options on the last parameter of a syntax type. TypeMap translates known [keywords](https://json-schema.org/understanding-json-schema/reference/type) into appropriate runtime representations if possible ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAWhACZwC+cAZlBCHAOQACAzsAHYDGANgIbAoAehjoMIPmEYAoaVwgdW8ZHAC8KMTlwAKRkqicA5o0JI45i5avW4QoXHmLlALhQBlGAY6G1iaeepoCRhXRnEBHkYbaJjY23tzUUxQ-SMTaQoASjic3Ly7C0CoYNDw4Ej-PKrq6wKKWTkFJTg3XxJSXSRcAH5XDgBXEAAjDChKE0Qa8wLHZtb1AC8AOgghgCsMLhhtJEq+UlJgGGAFPh4ABTpMWGAMVldqM9YMKasC81xXZYHh0e1MlZgY6nHj-DLZV6Q2J1AGpLb-IA))
```typescript
import { TypeBox, Zod } from '@sinclair/typemap'
import { TypeBox, Zod } from "@alkdev/typemap";
const T = TypeBox('string', { // const T: TString = {
format: 'email' // type: 'string',
}) // format: 'email'
// }
const T = TypeBox("string", {
format: "email",
});
const S = Zod('{ x?: number }', { // const S = z.object({
additionalProperties: false // x: z.number().optional()
}) // }).strict()
const S = Zod("{ x?: number }", {
additionalProperties: false,
});
```
<a name="Syntax-Parameters"></a>
### Parameters
Syntax types can be parameterized to receive exterior types. Parameters are automatically translated to the receiving type ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgNQIYBtgCMIwDRwBaEAJnAL5wBmUEIcA5AAIDOwAdgMbqrBQD0MAJ5gApiFRgGAKGmcI7FvGRwAvCgzZcACgbsAriCyioDAJRxLV6zdvX+-OPMXKAXHAByh41ADKnAAtxVFkHOAAFVChUEFEYExQ4CTAxMipoOBgogHM4ollnJSI1IlJtJBVyAgADJAA3DH1RFndkAG0AXQpqizsbMML4QndiEgB5LAArUU4YAB4kaT7lldW1yzDLBvQmltKSAEEoaKE50a8jEwA+JfW7++WwqsQ4ADp3iiugA))
```typescript
import { Valibot, Zod } from '@sinclair/typemap'
import { Valibot, Zod } from "@alkdev/typemap";
const V = Valibot('number') // const V: NumberSchema
const V = Valibot("number");
// Parameter V mapped for target Z
const Z = Zod({ V }, `{ values: V[] }`) // const Z: ZodObject<{
// values: ZodArray<ZodNumber>
// }, { ... }>
const Z = Zod({ V }, `{ values: V[] }`);
```
<a name="Syntax-Generics"></a>
### Generics
Use parameterized types with functions to create generic syntax types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAagIYA2wARhDIQFoQAmcAvnAGZQQhwDkAAgGdgAOwDGZEsCgB6GOgwgSYXgChVMmXADiGERijAxKBerEQRg+EQxiY0OAF44AHmRwMuGHsaC4ESgArWxgAPgAKZAAuFABKJ1CTTBxccKR3FkIAAyRVODhcGORCPLhUIpL8gC8iuFUWLNj1TTgASUsYEnEMZjRMQTMLKxQnYhDocNIKahhw3hEAVxBKA15Y+PzNre38lvMOlCKAeSCQlwRSnavrm9vblvzClAA5JZWoSruv75+4B7Kiq9lgZ8JdfuCIX8tNVAW8QWDIYi7i0WKFBgcAMqjGx2CYMRhzKyGEQAczWG0ReyG8Axx1OdnOCKRzJ2-yeyAxMGJJM+LL523+5RQnO5oP54s2-xqwq5oh5TIlSJRoSAA))
```typescript
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
import { TypeBox, Valibot, Zod } from "@alkdev/typemap";
// Generic Type
const Vector = <T extends object>(T: T) => TypeBox({ T }, `{
const Vector = <T extends object>(T: T) =>
TypeBox(
{ T },
`{
x: T,
y: T,
z: T
}`)
}`,
);
// Instanced Types
const T = Vector(Valibot("number"));
const T = Vector(Valibot('number')) // const T: TObject<{
// x: TNumber,
// y: TNumber,
// z: TNumber,
// }>
const S = Vector(Zod('string')) // const S: TObject<{
// x: TString,
// y: TString,
// z: TString,
// }>
const S = Vector(Zod("string"));
```
## Static
Use Static to infer for library and syntax types
Use Static to infer for library and syntax types
```typescript
import { type Static } from '@sinclair/typemap'
import { type Static } from "@alkdev/typemap";
const T = t.Number() // TypeBox
const V = v.string() // Valibot
const Z = z.boolean() // Zod
const S = 'string[]' // Syntax
const T = t.Number();
const V = v.string();
const Z = z.boolean();
const S = "string[]";
type S = Static<typeof S> // string[]
type T = Static<typeof T> // number
type V = Static<typeof V> // string
type Z = Static<typeof Z> // boolean
type S = Static<typeof S>;
type T = Static<typeof T>;
type V = Static<typeof V>;
type Z = Static<typeof Z>;
```
<a name="Json-Schema"></a>
## Json Schema
Use `TypeBox` to transform remote library types into Json Schema ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA84CGAznAFJEQB2AygMYAWGIBcAvnAGZQQhwDkAASLBKtADYFgUAPQx0TAmD4AoZaEiw4AKkIkAXp268+eiABMVy2lSLwAWnAC8cPQDoIAIwBWGWjAAUSHDBIaFh4REh0tJw1pS2cHYAXC6uduYA8t6+MAA8CMrBuClulACuIB4YUP4AlAA0kU3NTdEhxanpZgByFVVQANyFcKglruWV1XWNLbOzbcGjnea9k4PDemMT-XVze80LLmNdq-1DrLWutlDAfrv7D60xrI0ARNe3MK+Nrr8AfKo2mhMDh8BhROYMCQ5JgSMQyBRKHA6IxmKo4glkE4EVQUQp-HZao95jEMfAsc4CsTqftDjCMCk+J4fH4+PVhjTOU8QlAMABHMpSDBmFIAbT4uDZ-FQUpMfAAuuyucqIocCGYzMAYMAqAQxAAFbiYWDAKEpDh6ogYJUq23BQ5gI3VbVmxAcu3Kw5FFJIemM7bVPhsG0ez0xUJLX3yf19QPB92hmleo6IOB+-gBqBB1gJxPEw45vNctqsIA))
Use `TypeBox` to transform remote library types into Json Schema
```typescript
import { TypeBox as JsonSchema } from '@sinclair/typemap'
import { TypeBox as JsonSchema } from "@alkdev/typemap";
const Z = z.object({ // const Z: z.ZodObject<{
x: z.number(), // x: z.ZodNumber;
y: z.number(), // y: z.ZodNumber;
z: z.number() // z: z.ZodNumber;
}).strict() // }, "strict", ...>
const Z = z
.object({
x: z.number(),
y: z.number(),
z: z.number(),
})
.strict();
// TypeBox encodes types as Json Schema
const T = JsonSchema(Z) // const T = {
// type: 'object',
// required: ['x', 'y', 'z'],
// additionalProperties: false,
// properties: {
// x: { type: 'number' },
// y: { type: 'number' },
// z: { type: 'number' }
// }
// }
const T = JsonSchema(Z);
```
<a name="Tree-Shake"></a>
## Tree Shake
TypeMap takes on TypeBox, Valibot and Zod as peer dependencies. If bundling, it is recommended that you import specific translation functions. By doing this it will by-pass library imports and enable unused libraries to be omitted from the bundle.
TypeMap takes on TypeBox, Valibot and Zod as peer dependencies. If bundling, it is recommended that you import specific translation functions to enable unused libraries to be omitted from the bundle.
```typescript
import { TypeBoxFromZod } from '@sinclair/typemap' // Use TypeBox & Zod, Tree Shake Valibot
import { TypeBoxFromZod } from "@alkdev/typemap";
import * as z from 'zod'
import * as z from "zod";
const T = TypeBoxFromZod(z.object({ // const T: TObject<{
x: z.number(), // x: TNumber;
y: z.number(), // y: TNumber;
z: z.number() // z: TNumber;
})) // }>
const T = TypeBoxFromZod(
z.object({
x: z.number(),
y: z.number(),
z: z.number(),
}),
);
```
## Compile
Use the `Compile` function to compile TypeBox, Valibot and Zod on TypeBox infrastructure ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199#code/JYWwDg9gTgLgBAbzgYQuYAbApgGjgLQgBM4BfOAMyjTgHIABAZ2ADsBjDAQ2CgHoYAnmCwhOYWgCgJvXijRhMWAsTgAVIVilsILRvABunDMCKcY0OAF456bAApCROwAMEEuB4AeALjgsAriAARlhQOO4eAr4BwaHhHnAAXtGBIVASpM4AlFlaOnpwAEoAjFZwhsam5lAAdMgAFlhsANZ2SD5wxXhRcABMeMlwAMxkWQlwMnAAgmxsWNhQZlhEUpMAyjCcLKZQJGtsjaLSvMdwNedwAO71wAdwjPUQ-hgk9Zz6SiFYLH6cIMt0DZbHYkABqRhMZmgkgk2l08EKvTKFUh1QA2rQAH56YGcXa0AC6NRRVSwbTgHS6cB6-SSvhGpCyQA))
Use the `Compile` function to compile TypeBox, Valibot and Zod on TypeBox infrastructure
```typescript
import { Compile, Zod } from '@sinclair/typemap'
import { Compile, Zod } from "@alkdev/typemap";
// Compile Zod Type
const validator = Compile(Zod(`{
const validator = Compile(
Zod(`{
x: number,
y: number,
z: number
}`))
}`),
);
const R1 = validator.Check({ x: 1, y: 2, z: 3 }) // Accelerated
const R1 = validator.Check({ x: 1, y: 2, z: 3 });
// Standard Schema
//
// ... which should have been named 'Standard Validator'
const R2 = validator['~standard'].validate({ x: 1, y: 2, z: 3 })
const R2 = validator["~standard"].validate({ x: 1, y: 2, z: 3 });
```
## Benchmark
This project manages a small benchmark that compares validation performance using Zod, Valibot, and TypeBox validators. For more comprehensive community benchmarks, refer to the [runtime-type-benchmarks](https://github.com/moltar/typescript-runtime-type-benchmarks) project.
### Test
Benchmarks are run for the following type.
```typescript
type T = { x: number, y: string, z: boolean }
```
### Results
Results show the approximate elapsed time to complete the given iterations
```typescript
(index) library using iterations elapsed
0 'valibot ' 'valibot ' 10000000 '1534 ms '
1 'valibot ' 'typebox:value ' 10000000 '1377 ms '
2 'valibot ' 'typebox:compile ' 10000000 '46 ms '
(index) library using iterations elapsed
0 'zod ' 'zod ' 10000000 '4669 ms '
1 'zod ' 'typebox:value ' 10000000 '1359 ms '
2 'zod ' 'typebox:compile ' 10000000 '47 ms '
```
## Contribute
This project is open to community contributions. Please ensure you submit an open issue before creating a pull request. TypeBox and associated projects preference open community discussion before accepting new features.
This project is open to community contributions. Please ensure you submit an open issue before creating a pull request.
License: MIT

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,15 +26,15 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TypeCompiler, TypeCheck } from '@sinclair/typebox/compiler'
import { Value } from '@sinclair/typebox/value'
import { TypeCompiler, TypeCheck } from '@alkdev/typebox/compiler'
import { Value } from '@alkdev/typebox/value'
import { IsEvalSupported } from './environment'
import { Validator } from './validator'
import { type TTypeBox, TypeBox } from '../typebox/typebox'
import { type TSyntaxOptions } from '../options'
import { type TParameter } from '../typebox/typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as g from '../guard'
// ------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,10 +1,10 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Copyright (c) 2024-2025 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -26,15 +26,16 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { removeNotices } from '../notices/remove-notices'
import { convertToEsm } from './convert-to-esm'
import { compile } from './compile'
/** Builds the ESM version of this package */
export async function build(target: string) {
console.log('building...esm')
const buildTarget = `${target}/build/esm`
await compile(buildTarget)
await convertToEsm(buildTarget)
await removeNotices(buildTarget)
/**
* Converts a json pointer path (https://datatracker.ietf.org/doc/html/rfc6901)
* to a format which is followed by standard-schema and zod
*/
export function ZodPathFromJsonPointer(jsonPointer: string): PropertyKey[] {
if (jsonPointer === '') return []
if (jsonPointer === '/') return ['']
return jsonPointer
.substring(1)
.split('/')
.map((segment) => segment.replace(/~1/g, '/').replace(/~0/g, '~'))
.map((segment) => (isNaN(segment as any) ? segment : parseInt(segment)))
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,9 +26,10 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TypeCheck, ValueErrorIterator } from '@sinclair/typebox/compiler'
import { Value } from '@sinclair/typebox/value'
import * as t from '@sinclair/typebox'
import { TypeCheck, ValueErrorIterator } from '@alkdev/typebox/compiler'
import { Value } from '@alkdev/typebox/value'
import * as t from '@alkdev/typebox'
import { ZodPathFromJsonPointer } from './path'
import * as s from './standard'
// ------------------------------------------------------------------
@@ -46,8 +47,8 @@ export class StandardSchemaProps<Type extends t.TSchema, Static = t.Static<Type>
// ----------------------------------------------------------------
// StandardSchemaV1.Props<Input, Output>
// ----------------------------------------------------------------
public get vendor(): '@sinclair/typemap' {
return '@sinclair/typemap'
public get vendor(): '@alkdev/typemap' {
return '@alkdev/typemap'
}
public get version(): 1 {
return 1
@@ -65,7 +66,7 @@ export class StandardSchemaProps<Type extends t.TSchema, Static = t.Static<Type>
// ----------------------------------------------------------------
private __createIssues(value: unknown) {
const errors = [...Value.Errors(this.__check.Schema(), value)]
const issues: s.StandardSchemaV1.Issue[] = errors.map((error) => ({ ...error, path: [error.path] }))
const issues: s.StandardSchemaV1.Issue[] = errors.map((error) => ({ ...error, path: ZodPathFromJsonPointer(error.path) }))
return { issues }
}
private __createValue(value: unknown) {

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as z from 'zod'

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
/** Syntax Options and Constraints */
// prettier-ignore

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -27,8 +27,8 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { Validator } from './compile/validator'
import * as s from '@sinclair/typebox/syntax'
import * as t from '@sinclair/typebox'
import * as s from '@alkdev/typebox/syntax'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as z from 'zod'

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
// ------------------------------------------------------------------
// Characters

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -29,7 +29,7 @@ THE SOFTWARE.
import { type TTypeBoxFromValibot, TypeBoxFromValibot } from '../typebox/typebox-from-valibot'
import { type TSyntaxFromTypeBox, SyntaxFromTypeBox } from './syntax-from-typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
/** Creates Syntax from Valibot */

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -29,7 +29,7 @@ THE SOFTWARE.
import { type TTypeBoxFromZod, TypeBoxFromZod } from '../typebox/typebox-from-zod'
import { type TSyntaxFromTypeBox, SyntaxFromTypeBox } from './syntax-from-typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as z from 'zod'
/** Creates Syntax from Zod */

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,8 +26,8 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TSyntax, Syntax } from '@sinclair/typebox/syntax'
import * as t from '@sinclair/typebox'
import { TSyntax, Syntax } from '@alkdev/typebox/syntax'
import * as t from '@alkdev/typebox'
// ------------------------------------------------------------------
// TypeBoxFromSyntax

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
// ------------------------------------------------------------------
// TypeBoxFromTypeBox

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as Guard from '../guard'
@@ -262,7 +262,7 @@ function FromDate(type: BaseSchema): t.TSchema {
// Enum
// ------------------------------------------------------------------
t.TypeRegistry.Set<TValibotEnum>('ValibotEnum', (schema, value) => {
return v.safeParse(schema.schema, value).success
return v.safeParse(schema.type, value).success
})
export interface TValibotEnum<Type extends v.EnumSchema<v.Enum, any> = v.EnumSchema<v.Enum, any>> extends t.TSchema {
[t.Kind]: 'ValibotEnum'
@@ -272,7 +272,10 @@ export interface TValibotEnum<Type extends v.EnumSchema<v.Enum, any> = v.EnumSch
function ValibotEnum<Type extends v.EnumSchema<v.Enum, any>>(type: Type, options?: t.SchemaOptions): TValibotEnum<Type> {
return t.CreateType({ [t.Kind]: 'ValibotEnum', type }, options) as never
}
type TFromEnum<Enum extends v.EnumSchema<v.Enum, any>> = TValibotEnum<Enum>
// prettier-ignore
type TFromEnum<Enum extends v.EnumSchema<v.Enum, any>,
Result = TValibotEnum<Enum>
> = Result
function FromEnum<Type extends BaseSchema>(type: Type): t.TSchema {
return ValibotEnum(type as never as v.EnumSchema<v.Enum, any>, Options(type))
}
@@ -740,7 +743,7 @@ function FromVoid(type: BaseSchema): t.TSchema {
// prettier-ignore
type TFromType<Type extends BaseSchema> = (
// Pipes - Extract First Type And Remap
Type extends { pipe: [infer Type extends BaseSchema, ...any[]] } ? TFromType<Type> :
Type extends { pipe: readonly [infer Type extends BaseSchema, ...any[]] } ? TFromType<Type> :
// Types
Type extends v.AnySchema ? TFromAny<Type> :
Type extends v.ArraySchema<infer Type extends BaseSchema, any> ? TFromArray<Type> :
@@ -749,7 +752,7 @@ type TFromType<Type extends BaseSchema> = (
Type extends v.BooleanSchema<any> ? TFromBoolean<Type> :
Type extends v.CustomSchema<unknown, any> ? TFromCustom<Type> :
Type extends v.DateSchema<any> ? TFromDate<Type> :
Type extends v.EnumSchema<v.Enum, any> ? TFromEnum<Type> :
Type extends v.EnumSchema<any, any> ? TFromEnum<Type> : // note: unable to match on v.Enum parameter. use any and push type through for mapping
Type extends v.FileSchema<any> ? TFromFile<Type> :
Type extends v.FunctionSchema<any> ? TFromFunction<Type> :
Type extends v.InstanceSchema<v.Class, any> ? TFromInstance<Type> :

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as z from 'zod'
// ------------------------------------------------------------------
@@ -48,7 +48,7 @@ t.FormatRegistry.Set('cidr', (value) => check(z.string().cidr(), value))
t.FormatRegistry.Set('cuid', (value) => check(z.string().cuid(), value))
t.FormatRegistry.Set('cuid2', (value) => check(z.string().cuid2(), value))
t.FormatRegistry.Set('date', (value) => check(z.string().date(), value))
t.FormatRegistry.Set('datetime', (value) => check(z.string().datetime(), value))
t.FormatRegistry.Set('datetime', (value) => check(z.string().datetime({ offset: true }), value))
t.FormatRegistry.Set('duration', (value) => check(z.string().duration(), value))
t.FormatRegistry.Set('email', (value) => check(z.string().email(), value))
t.FormatRegistry.Set('emoji', (value) => check(z.string().emoji(), value))

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -33,7 +33,7 @@ import { type TTypeBoxFromZod, TypeBoxFromZod } from './typebox-from-zod'
import { type TSyntaxOptions } from '../options'
import * as g from '../guard'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
// ------------------------------------------------------------------------------
//

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -32,4 +32,4 @@ import * as v from 'valibot'
export type BaseConstraint = v.BaseValidation<any, unknown, v.BaseIssue<unknown>> | v.BaseMetadata<any> | v.RegexAction<any, any>
export type BaseRecordKey = v.BaseSchema<string, string | number | symbol, v.BaseIssue<unknown>>
export type BaseSchema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>
export type BaseError = v.ErrorMessage<any>
export type BaseError = undefined // v.ErrorMessage<any>

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -29,7 +29,7 @@ THE SOFTWARE.
import { TTypeBoxFromSyntax, TypeBoxFromSyntax } from '../typebox/typebox-from-syntax'
import { ValibotFromTypeBox, TValibotFromTypeBox } from './valibot-from-typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
// ------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as c from './common'

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -29,7 +29,7 @@ THE SOFTWARE.
import { type TTypeBoxFromZod, TypeBoxFromZod } from '../typebox/typebox-from-zod'
import { type TValibotFromTypeBox, ValibotFromTypeBox } from './valibot-from-typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as z from 'zod'

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -35,7 +35,7 @@ import { type TSyntaxOptions } from '../options'
import { type TParameter, type TContextFromParameter, ContextFromParameter } from '../typebox/typebox'
import * as g from '../guard'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as c from './common'

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -28,7 +28,7 @@ THE SOFTWARE.
import { TTypeBoxFromSyntax, TypeBoxFromSyntax } from '../typebox/typebox-from-syntax'
import { ZodFromTypeBox, TZodFromTypeBox } from './zod-from-typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as z from 'zod'
// ------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -26,7 +26,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as z from 'zod'
// ------------------------------------------------------------------

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)
@@ -29,7 +29,7 @@ THE SOFTWARE.
import { type TTypeBoxFromValibot, TypeBoxFromValibot } from '../typebox/typebox-from-valibot'
import { type TZodFromTypeBox, ZodFromTypeBox } from './zod-from-typebox'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
import * as z from 'zod'

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
@alkdev/typemap
The MIT License (MIT)

View File

@@ -1,82 +0,0 @@
import { Value } from '@sinclair/typebox/value'
import { Compile, TypeBox } from '@sinclair/typemap'
import * as v from 'valibot'
import * as z from 'zod'
// ------------------------------------------------------------------
// Benchmark
// ------------------------------------------------------------------
function benchmark(library: string, using: string, callback: Function) {
const [now, iterations] = [Date.now(), 10_000_000]
for (let i = 0; i < iterations; i++) if (!callback()) throw Error('Invalid' + library + using)
const elapsed = `${Date.now() - now} ms`.padEnd(8)
return { library: library.padEnd(12), using: using.padEnd(16), iterations, elapsed }
}
// ------------------------------------------------------------------
// Zod
// ------------------------------------------------------------------
function zod() {
const T = z.object({
x: z.string(),
y: z.number(),
z: z.boolean(),
})
return benchmark('zod', 'zod', () => T.safeParse({ x: 'hello', y: 42, z: true }).success)
}
function zod_using_value() {
const T = TypeBox(
z.object({
x: z.string(),
y: z.number(),
z: z.boolean(),
}),
)
return benchmark('zod', 'typebox:value', () => Value.Check(T, { x: 'hello', y: 42, z: true }))
}
function zod_using_compiler() {
const T = Compile(
z.object({
x: z.string(),
y: z.number(),
z: z.boolean(),
}),
)
return benchmark('zod', 'typebox:compile', () => T.Check({ x: 'hello', y: 42, z: true }))
}
// ------------------------------------------------------------------
// Valibot
// ------------------------------------------------------------------
function valibot() {
const T = v.object({
x: v.string(),
y: v.number(),
z: v.boolean(),
})
return benchmark('valibot', 'valibot', () => v.safeParse(T, { x: 'hello', y: 42, z: true }).success)
}
function valibot_using_value() {
const T = TypeBox(
v.object({
x: v.string(),
y: v.number(),
z: v.boolean(),
}),
)
return benchmark('valibot', 'typebox:value', () => Value.Check(T, { x: 'hello', y: 42, z: true }))
}
function valibot_using_compiler() {
const T = Compile(
v.object({
x: v.string(),
y: v.number(),
z: v.boolean(),
}),
)
return benchmark('valibot', 'typebox:compile', () => T.Check({ x: 'hello', y: 42, z: true }))
}
console.log('running benchmark')
console.table([valibot(), valibot_using_value(), valibot_using_compiler()])
console.table([zod(), zod_using_value(), zod_using_compiler()])

View File

@@ -1,38 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { removeNotices } from '../notices/remove-notices'
import { compile } from './compile'
/** Builds the CommonJS version of this package */
export async function build(target: string) {
console.log('building...cjs')
const buildTarget = `${target}/build/cjs`
await compile(buildTarget)
await removeNotices(buildTarget)
}

View File

@@ -1,40 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
declare function shell(command: string): Promise<void>
// prettier-ignore
export async function compile(target: string) {
const options = [
`--outDir ${target}`,
'--target ES2020',
'--module CommonJS',
'--declaration',
].join(' ')
await shell(`tsc -p ./src/tsconfig.json ${options}`)
}

View File

@@ -1,40 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
declare function shell(command: string): Promise<void>
// prettier-ignore
export async function compile(target: string) {
const options = [
`--outDir ${target}`,
'--target ES2020',
'--module ESNext',
'--declaration',
].join(' ')
await shell(`tsc -p ./src/tsconfig.json ${options}`)
}

View File

@@ -1,120 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as Path from 'node:path'
import * as Fs from 'node:fs'
// ------------------------------------------------------------------
// Specifier Rewrite
// ------------------------------------------------------------------
function shouldSkipSpecifier(captured: string) {
const specifier = captured.slice(1, captured.length - 1)
return (
specifier.includes('.mjs') || // mitigate duplicate rewrite
specifier.startsWith("@sinclair/parsebox") ||
specifier.startsWith("@sinclair/typebox") ||
specifier.startsWith("valibot") ||
specifier.startsWith("zod")
)
}
// prettier-ignore
function replaceInlineImportSpecifiers(content: string): string {
const pattern = /import\((.*?)\)/g
while (true) {
const match = pattern.exec(content)
if (match === null) return content
const captured = match[1]
if(shouldSkipSpecifier(captured)) continue
const specifier = captured.slice(1, captured.length - 1)
content = content.replace(captured, `"${specifier}.mjs"`)
}
}
// prettier-ignore
function replaceExportSpecifiers(content: string): string {
const pattern = /(export|import)(.*) from ('(.*)');/g
while(true) {
const match = pattern.exec(content)
if(match === null) return content
const captured = match[3]
if(shouldSkipSpecifier(captured)) continue
const specifier = captured.slice(1, captured.length - 1)
content = content.replace(captured, `'${specifier}.mjs'`)
}
}
function replaceSpecifiers(content: string): string {
const pass1 = replaceExportSpecifiers(content)
const pass2 = replaceInlineImportSpecifiers(pass1)
return pass2
}
// ------------------------------------------------------------------
// ConvertToEsm
// ------------------------------------------------------------------
// prettier-ignore
function shouldProcess(sourcePath: string) {
const extname = Path.extname(sourcePath)
return ['.js', '.ts'].includes(extname)
}
// prettier-ignore
function newExtension(extname: string) {
return (
extname === '.js' ? '.mjs' :
extname === '.ts' ? '.mts' :
extname
)
}
// prettier-ignore
function processFile(sourcePath: string) {
if(!shouldProcess(sourcePath)) return
const extname = Path.extname(sourcePath)
const dirname = Path.dirname(sourcePath)
const basename = Path.basename(sourcePath, extname)
const new_extname = newExtension(extname)
const sourceContent = Fs.readFileSync(sourcePath, 'utf-8')
const targetContent = replaceSpecifiers(sourceContent)
const targetPath = `${Path.join(dirname, basename)}${new_extname}`
Fs.writeFileSync(sourcePath, targetContent)
Fs.renameSync(sourcePath, targetPath)
}
// prettier-ignore
function processSourcePath(sourcePath: string) {
const stat = Fs.statSync(sourcePath)
if(stat.isDirectory()) return readDirectory(sourcePath)
if(stat.isFile()) return processFile(sourcePath)
}
// prettier-ignore
function readDirectory(sourceDirectory: string) {
for(const entry of Fs.readdirSync(sourceDirectory)) {
const sourcePath = Path.join(sourceDirectory, entry)
processSourcePath(sourcePath)
}
}
/** Converts the JavaScript and TypeScript declaration modules in the given source directory to use .mjs extensions */
export function convertToEsm(sourceDirectory: string) {
readDirectory(sourceDirectory)
}

View File

@@ -1,31 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
export * as Package from './package/build'
export * as Esm from './esm/build'
export * as Cjs from './cjs/build'

View File

@@ -1,82 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as Path from 'node:path'
import * as Fs from 'node:fs'
// ----------------------------------------------------------------------
// Remove Module Level MIT Notice on Package Distribution
//
// The MIT copyright notice the unnecessarily increases the distribution
// size of the package, this code removes it. The MIT license is available
// in the package root.
//
// ----------------------------------------------------------------------
// prettier-ignore
function escape(content: string) {
return content.split('').map((c) => `\\${c}`).join('')
}
// prettier-ignore
function removeNotice(content: string): string {
const open = escape('/*--------------------------------------------------------------------------')
const close = escape('---------------------------------------------------------------------------*/')
const critera = 'Permission is hereby granted, free of charge'
const pattern = new RegExp(`${open}[\\s\\S]*?${close}`, 'gm')
while (true) {
const match = pattern.exec(content)
if (match === null) return content.trimStart()
if (!match[0].includes(critera)) continue
content = content.replace(match[0], '')
}
}
// ------------------------------------------------------------------
// Directory Enumeration
// ------------------------------------------------------------------
// prettier-ignore
function processFile(sourcePath: string) {
const sourceContent = Fs.readFileSync(sourcePath, 'utf-8')
const targetContent = removeNotice(sourceContent)
Fs.writeFileSync(sourcePath, targetContent)
}
// prettier-ignore
function processSourcePath(sourcePath: string) {
const stat = Fs.statSync(sourcePath)
if(stat.isDirectory()) return readDirectory(sourcePath)
if(stat.isFile()) return processFile(sourcePath)
}
// prettier-ignore
function readDirectory(sourceDirectory: string) {
for(const entry of Fs.readdirSync(sourceDirectory)) {
const sourcePath = Path.join(sourceDirectory, entry)
processSourcePath(sourcePath)
}
}
/** Removes the MIT copyright notices from each source file in the given directory */
export function removeNotices(sourceDirectory: string) {
readDirectory(sourceDirectory)
}

View File

@@ -1,38 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typebox
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { createPackageJsonRedirect } from './create-package-json-redirect'
import { createPackageJson } from './create-package-json'
/** Builds package.json and redirect directories */
export async function build(target: string) {
console.log('building...package.json')
const submodules = [] as string[]
await createPackageJsonRedirect(target, submodules)
await createPackageJson(target, submodules)
}

View File

@@ -1,50 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typebox
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as Fs from 'node:fs'
// prettier-ignore
function writeRedirect(target: string, submodule: string) {
Fs.mkdirSync(`${target}/${submodule}`, { recursive: true })
Fs.writeFileSync(`${target}/${submodule}/package.json`,JSON.stringify({
main: `../build/cjs/${submodule}/index.js`,
types: `../build/cjs/${submodule}/index.d.ts`,
}, null, 2))
}
// --------------------------------------------------------------------------------------------------------------------------
// Builds redirect directories for earlier versions of Node. Note that TypeScript will use these directories to
// resolve types when tsconfig.json is configured for `moduleResolution: 'node'`. This approach is referred to as
// `package-json-redirect` and enables correct type resolution in lieu of a correct end user configuration.
//
// https://github.com/andrewbranch/example-subpath-exports-ts-compat/tree/main/examples/node_modules/package-json-redirects
// --------------------------------------------------------------------------------------------------------------------------
// prettier-ignore
export function createPackageJsonRedirect(target: string, submodules: string[]) {
submodules.forEach((submodule) => writeRedirect(target, submodule))
}

View File

@@ -1,103 +0,0 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as Fs from 'node:fs'
import * as Path from 'node:path'
// prettier-ignore
export function createPackageJson(target: string, submodules: string[]) {
const content = JSON.stringify(resolvePackageJson(submodules), null, 2)
const targetPath = Path.join(target, 'package.json')
const targetDir = Path.dirname(targetPath)
Fs.mkdirSync(targetDir, { recursive: true })
Fs.writeFileSync(targetPath, content, 'utf-8')
}
// prettier-ignore
function resolvePackageJson(submodules: string[]) {
return {
...resolveMetadata(),
...resolveExports(submodules)
}
}
// prettier-ignore
function resolveSubmoduleExports(submodule: string) {
return {
require: {
types: `./build/cjs/${submodule}/index.d.ts`,
default: `./build/cjs/${submodule}/index.js`,
},
import: {
types: `./build/esm/${submodule}/index.d.mts`,
default: `./build/esm/${submodule}/index.mjs`,
}
}
}
// prettier-ignore
function resolveExports(submodules: string[]) {
const exports = submodules.reduce((acc, submodule) => {
return { ...acc, [`./${submodule}`]: resolveSubmoduleExports(submodule) }
}, {
// ... and root module
".": {
"require": {
"types": "./build/cjs/index.d.ts",
"default": "./build/cjs/index.js",
},
"import": {
"types": "./build/esm/index.d.mts",
"default": "./build/esm/index.mjs",
}
}
})
return { exports }
}
// prettier-ignore
function resolveMetadata() {
const packagePath = Path.join(process.cwd(), 'package.json')
const packageJson = JSON.parse(Fs.readFileSync(packagePath, 'utf-8'))
return {
name: packageJson.name,
version: packageJson.version,
description: packageJson.description,
keywords: packageJson.keywords,
author: packageJson.author,
license: packageJson.license,
repository: packageJson.repository,
// dependencies: packageJson.dependencies,
peerDependencies: packageJson.peerDependencies,
optionalDependencies: packageJson.optionalDependencies,
// flagged by socket.dev if not present
scripts: { test: 'echo test' },
types: "./build/cjs/index.d.ts",
main: "./build/cjs/index.js",
module: "./build/esm/index.mjs",
// disable auto bundle strategy: see https://github.com/esm-dev/esm.sh#bundling-strategy
'esm.sh': { 'bundle': false },
}
}

View File

@@ -1,5 +1,6 @@
import { Assert } from './assert'
import { TypeBox, Valibot, Zod, Compile } from '@sinclair/typemap'
import { TypeBox, Valibot, Zod, Compile } from '@alkdev/typemap'
import { ZodPathFromJsonPointer } from 'src/compile/path'
describe('Compile', () => {
// ----------------------------------------------------------------
@@ -53,3 +54,38 @@ describe('Compile', () => {
Assert.IsTrue(R.issues!.length > 0)
})
})
describe('ZodPathFromJsonPointer', () => {
it('Should convert empty string', () => {
const jsonPointer = ''
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), [])
})
it('Should convert whole object path', () => {
const jsonPointer = '/'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), [''])
})
it('Should convert nested object path', () => {
const jsonPointer = '/a/b'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), ['a', 'b'])
})
it('Should convert array path', () => {
const jsonPointer = '/a/0'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), ['a', 0])
})
it('Should convert keys which looks like array index', () => {
const jsonPointer = '/a/"0"'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), ['a', '"0"'])
})
it('Should convert keys with / escape', () => {
const jsonPointer = '/a~1b'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), ['a/b'])
})
it('Should convert keys with ~ escape', () => {
const jsonPointer = '/m~0n'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), ['m~n'])
})
it('Should convert keys with ~ and / escape', () => {
const jsonPointer = '/m~01n'
Assert.IsEqual(ZodPathFromJsonPointer(jsonPointer), ['m~1n'])
})
})

View File

@@ -1,5 +1,5 @@
import { Assert } from './assert'
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
import { TypeBox, Valibot, Zod } from '@alkdev/typemap'
describe('SyntaxOptions', () => {
it('Should map Options (Zod)', () => {

View File

@@ -1,6 +1,6 @@
import { Assert } from './assert'
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
import { KindGuard } from '@sinclair/typebox'
import { TypeBox, Valibot, Zod } from '@alkdev/typemap'
import { KindGuard } from '@alkdev/typebox'
describe('Parameters', () => {
it('Should map Parameters (Zod)', () => {

View File

@@ -1,7 +1,7 @@
import { TypeBox } from '@sinclair/typemap'
import { TypeGuard } from '@sinclair/typebox'
import { TypeBox } from '@alkdev/typemap'
import { TypeGuard } from '@alkdev/typebox'
import { Assert } from './assert'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
describe('TypeBox from Valibot', () => {
@@ -423,4 +423,13 @@ describe('TypeBox from Valibot', () => {
const T = TypeBox(v.void())
Assert.IsTrue(TypeGuard.IsVoid(T))
})
// ----------------------------------------------------------------
// Pipe
// ----------------------------------------------------------------
it('Should map Pipe', () => {
const S = v.pipe(v.literal('hello'), v.length(5))
const T = TypeBox(S)
Assert.IsTrue(TypeGuard.IsLiteral(T))
Assert.IsEqual(T.const, 'hello')
})
})

View File

@@ -1,7 +1,7 @@
import { TypeBox } from '@sinclair/typemap'
import { TypeGuard } from '@sinclair/typebox'
import { TypeBox } from '@alkdev/typemap'
import { TypeGuard } from '@alkdev/typebox'
import { Assert } from './assert'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as z from 'zod'
describe('TypeBox From Zod', () => {

View File

@@ -1,7 +1,7 @@
import { TypeBox, Valibot } from '@sinclair/typemap'
import { TypeGuard } from '@sinclair/typebox'
import { TypeBox, Valibot } from '@alkdev/typemap'
import { TypeGuard } from '@alkdev/typebox'
import { Assert } from './assert'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as v from 'valibot'
describe('Valibot from TypeBox', () => {

View File

@@ -1,7 +1,7 @@
import { TypeBox, Zod } from '@sinclair/typemap'
import { TypeGuard } from '@sinclair/typebox'
import { TypeBox, Zod } from '@alkdev/typemap'
import { TypeGuard } from '@alkdev/typebox'
import { Assert } from './assert'
import * as t from '@sinclair/typebox'
import * as t from '@alkdev/typebox'
import * as z from 'zod'
describe('Zod From TypeBox', () => {

View File

@@ -5,7 +5,7 @@
"moduleResolution": "Node",
"baseUrl": ".",
"paths": {
"@sinclair/typemap": ["src/index.ts"]
"@alkdev/typemap": ["src/index.ts"]
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 KiB