Compare commits
10 Commits
696a712c4d
...
3b4dd4f1d1
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b4dd4f1d1 | |||
|
|
eb67d42876 | ||
|
|
658d2c49c9 | ||
|
|
631fab497a | ||
|
|
d428962694 | ||
|
|
978cb5d962 | ||
|
|
59a723cca8 | ||
|
|
8b8d5eea09 | ||
|
|
a7b5e17cf5 | ||
|
|
657bbf295a |
0
.github/.keep
vendored
24
.github/workflows/build.yml
vendored
@@ -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
|
||||
23
.github/workflows/nightly.yml
vendored
@@ -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
|
||||
6
.vscode/settings.json
vendored
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"files.exclude": {
|
||||
"node_modules": true,
|
||||
"package-lock.json": true
|
||||
}
|
||||
}
|
||||
219
build.mjs
Normal 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);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 777 KiB |
BIN
design/font.ttf
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
BIN
design/zod.jpg
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,4 +1,4 @@
|
||||
import { TypeBox, Valibot, Zod, Syntax, Compile } from '@sinclair/typemap'
|
||||
import { TypeBox, Valibot, Zod, Syntax, Compile } from '@alkdev/typemap'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Syntax Types
|
||||
|
||||
@@ -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
|
||||
|
||||
72
hammer.mjs
@@ -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`)
|
||||
}
|
||||
3
license
@@ -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
24
package.json
@@ -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
@@ -4,431 +4,262 @@
|
||||
|
||||
<p>Syntax Compiler and Translation System for Runtime Types</p>
|
||||
|
||||
<img src="./typemap.png" />
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
[](https://badge.fury.io/js/%40sinclair%2Ftypemap)
|
||||

|
||||
[](https://github.com/sinclairzx81/typemap/actions/workflows/build.yml)
|
||||
[](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
|
||||
|
||||
@@ -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'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -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)))
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> :
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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'
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
@@ -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'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typemap
|
||||
@alkdev/typemap
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -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()])
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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}`)
|
||||
}
|
||||
@@ -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}`)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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'
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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 },
|
||||
}
|
||||
}
|
||||
@@ -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'])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)', () => {
|
||||
|
||||
@@ -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)', () => {
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"moduleResolution": "Node",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@sinclair/typemap": ["src/index.ts"]
|
||||
"@alkdev/typemap": ["src/index.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
typemap.png
|
Before Width: | Height: | Size: 700 KiB |