Remove @sinclair/hammer dependency and task runner
- Remove @sinclair/hammer from devDependencies - Remove hammer.mjs entry point - Remove task/ directory (build scripts, benchmarks) - Add build.mjs: standalone build script replicating the CJS/ESM compilation, package.json generation, notice stripping, and ESM specifier rewrite logic - Update npm scripts to use build.mjs and direct tsc/mocha instead of hammer task commands
This commit is contained in:
205
build.mjs
Normal file
205
build.mjs
Normal file
@@ -0,0 +1,205 @@
|
||||
import * as Fs from 'node:fs'
|
||||
import * as Path from 'node:path'
|
||||
import { execSync } from 'node:child_process'
|
||||
|
||||
const TARGET = 'target/build'
|
||||
const SUBMODULES = ['compiler', 'errors', 'parser', 'syntax', 'system', 'type', 'value']
|
||||
|
||||
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 replaceInlineImportSpecifiers(content) {
|
||||
const pattern = /import\((.*?)\)/g
|
||||
while (true) {
|
||||
const match = pattern.exec(content)
|
||||
if (match === null) return content
|
||||
const captured = match[1]
|
||||
if (captured.includes('.mjs')) 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]
|
||||
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 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' },
|
||||
},
|
||||
...SUBMODULES.reduce((acc, sub) => {
|
||||
acc[`./${sub}`] = {
|
||||
require: { types: `./build/cjs/${sub}/index.d.ts`, default: `./build/cjs/${sub}/index.js` },
|
||||
import: { types: `./build/esm/${sub}/index.d.mts`, default: `./build/esm/${sub}/index.mjs` },
|
||||
}
|
||||
return acc
|
||||
}, {}),
|
||||
}
|
||||
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 },
|
||||
sideEffects: [
|
||||
'./build/esm/type/registry/format.mjs',
|
||||
'./build/esm/type/registry/type.mjs',
|
||||
'./build/esm/type/system/policy.mjs',
|
||||
'./build/cjs/type/registry/format.js',
|
||||
'./build/cjs/type/registry/type.js',
|
||||
'./build/cjs/type/system/policy.js',
|
||||
],
|
||||
exports,
|
||||
}
|
||||
Fs.writeFileSync(`${TARGET}/package.json`, JSON.stringify(pkg, null, 2))
|
||||
// redirect package.json for older Node resolution
|
||||
for (const sub of SUBMODULES) {
|
||||
mkdirp(`${TARGET}/${sub}`)
|
||||
Fs.writeFileSync(
|
||||
`${TARGET}/${sub}/package.json`,
|
||||
JSON.stringify({ main: `../build/cjs/${sub}/index.js`, types: `../build/cjs/${sub}/index.d.ts` }, null, 2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Main ---
|
||||
const command = process.argv[2] || 'build'
|
||||
|
||||
if (command === 'clean') {
|
||||
clean()
|
||||
} else if (command === 'build') {
|
||||
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)
|
||||
}
|
||||
118
hammer.mjs
118
hammer.mjs
@@ -1,118 +0,0 @@
|
||||
import * as Benchmark from './task/benchmark'
|
||||
import * as Build from './task/build'
|
||||
import * as Fs from 'fs'
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Clean
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function clean() {
|
||||
await folder('node_modules/typebox').delete()
|
||||
await folder('target').delete()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Format
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function format() {
|
||||
await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test task example/index.ts')
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Start
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function start() {
|
||||
await shell(`hammer run example/index.ts --dist target/example`)
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// Benchmark
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function benchmark() {
|
||||
await Benchmark.compression()
|
||||
await Benchmark.measurement()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Test
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function test_typescript() {
|
||||
for (const version of [
|
||||
'4.9.5', '5.0.4', '5.1.3', '5.1.6',
|
||||
'5.2.2', '5.3.2', '5.3.3', '5.4.3',
|
||||
'5.4.5', '5.5.2', '5.5.3', '5.5.4',
|
||||
'5.6.2', '5.6.3', '5.7.2', '5.7.3',
|
||||
'5.8.2', '5.8.3', 'next', 'latest'
|
||||
]) {
|
||||
await shell(`npm install typescript@${version} --no-save`)
|
||||
await test_static()
|
||||
}
|
||||
}
|
||||
export async function test_static() {
|
||||
await shell(`tsc -v`)
|
||||
await shell(`tsc -p test/static/tsconfig.json --noEmit --strict`)
|
||||
}
|
||||
export async function test_runtime(filter = '') {
|
||||
await shell(`hammer build ./test/runtime/index.ts --dist target/test/runtime --platform node`)
|
||||
await shell(`mocha target/test/runtime/index.js -g "${filter}"`)
|
||||
}
|
||||
export async function test(filter = '') {
|
||||
await test_static()
|
||||
await test_runtime(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-typebox-${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)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Build To
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function build_to(remote = 'target/remote', target = 'target/build') {
|
||||
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`)
|
||||
const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8'))
|
||||
const filename = `${target}/sinclair-typebox-${version}.tgz`
|
||||
await folder(remote).add(filename)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Install
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function install_local() {
|
||||
await clean()
|
||||
await build('target/typebox')
|
||||
await folder('node_modules').add('target/typebox')
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Publish
|
||||
// -------------------------------------------------------------
|
||||
export async function publish(target = 'target/build') {
|
||||
const { name, version } = JSON.parse(Fs.readFileSync(`${target}/package.json`, 'utf8'))
|
||||
console.log('publishing ... ', { name, version })
|
||||
await shell(`git tag ${version}`)
|
||||
await shell(`git push origin ${version}`)
|
||||
}
|
||||
2188
package-lock.json
generated
2188
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -16,23 +16,15 @@
|
||||
"url": "https://git.alk.dev/alkdev/typebox"
|
||||
},
|
||||
"scripts": {
|
||||
"test:typescript": "hammer task test_typescript",
|
||||
"test:static": "hammer task test_static",
|
||||
"test:runtime": "hammer task test_runtime",
|
||||
"install:local": "hammer task install_local",
|
||||
"benchmark": "hammer task benchmark",
|
||||
"build:to": "hammer task build_to",
|
||||
"build": "hammer task build",
|
||||
"test": "hammer task test",
|
||||
"clean": "hammer task clean",
|
||||
"format": "hammer task format",
|
||||
"start": "hammer task start",
|
||||
"publish": "hammer task publish",
|
||||
"publish:dev": "hammer task publish_dev"
|
||||
"test:static": "tsc -p test/static/tsconfig.json --noEmit --strict",
|
||||
"test:runtime": "tsc -p src/tsconfig.json --outDir target/test/runtime --target ES2020 --module Node16 --moduleResolution Node16 && mocha target/test/runtime/index.js",
|
||||
"build": "node build.mjs build",
|
||||
"clean": "node build.mjs clean",
|
||||
"test": "npm run test:static && npm run test:runtime",
|
||||
"format": "prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arethetypeswrong/cli": "^0.13.2",
|
||||
"@sinclair/hammer": "^0.18.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "^22.13.5",
|
||||
"ajv": "^8.12.0",
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { shell } from '@sinclair/hammer'
|
||||
import { statSync, readdirSync } from 'fs'
|
||||
import { basename, extname } from 'path'
|
||||
|
||||
export async function measure(test: string) {
|
||||
await shell(`hammer build task/benchmark/compression/module/${test}.ts --dist target/benchmark/compression`)
|
||||
const compiled = statSync(`target/benchmark/compression/${test}.js`)
|
||||
await shell(`hammer build task/benchmark/compression/module/${test}.ts --dist target/benchmark/compression --minify`)
|
||||
const minified = statSync(`target/benchmark/compression/${test}.js`)
|
||||
return {
|
||||
test: test.padEnd(20),
|
||||
compiled: `${(compiled.size / 1000).toFixed(1)} kb`.padStart(8),
|
||||
minified: `${(minified.size / 1000).toFixed(1)} kb`.padStart(8),
|
||||
ratio: compiled.size / minified.size,
|
||||
}
|
||||
}
|
||||
|
||||
export async function compression() {
|
||||
const tests = readdirSync('task/benchmark/compression/module').map((name) => basename(name, extname(name)))
|
||||
const results = await Promise.all(tests.map((test) => measure(test)))
|
||||
const present = results.reduce((acc, c) => {
|
||||
return { ...acc, [c.test.replace(/-/g, '/')]: { Compiled: c.compiled, Minified: c.minified, Compression: `${c.ratio.toFixed(2)} x` } }
|
||||
}, {})
|
||||
console.table(present)
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import { TypeCompiler } from '@alkdev/typebox/compiler'
|
||||
|
||||
console.log(TypeCompiler)
|
||||
@@ -1,3 +0,0 @@
|
||||
import * as Errors from '@alkdev/typebox/errors'
|
||||
|
||||
console.log(Errors)
|
||||
@@ -1,3 +0,0 @@
|
||||
import * as Syntax from '@alkdev/typebox/syntax'
|
||||
|
||||
console.log(Syntax)
|
||||
@@ -1,3 +0,0 @@
|
||||
import { TypeSystem } from '@alkdev/typebox/system'
|
||||
|
||||
console.log(TypeSystem)
|
||||
@@ -1,3 +0,0 @@
|
||||
import { Value } from '@alkdev/typebox/value'
|
||||
|
||||
console.log(Value)
|
||||
@@ -1,3 +0,0 @@
|
||||
import { Type } from '@alkdev/typebox'
|
||||
|
||||
const T = Type.String()
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './compression/index'
|
||||
export * from './measurement/index'
|
||||
@@ -1,5 +0,0 @@
|
||||
import { shell } from '@sinclair/hammer'
|
||||
|
||||
export async function measurement() {
|
||||
await shell(`hammer run task/benchmark/measurement/module/index.ts --dist target/benchmark/measurement`)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export namespace Benchmark {
|
||||
export function Measure(execute: Function, iterations: number = 16_000_000) {
|
||||
const start = Date.now()
|
||||
for (let i = 0; i < iterations; i++) execute()
|
||||
return { iterations, completed: Date.now() - start }
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import { Type } from '@alkdev/typebox'
|
||||
|
||||
export namespace Cases {
|
||||
export const Literal_String = Type.Literal('hello')
|
||||
|
||||
export const Literal_Number = Type.Literal(1)
|
||||
|
||||
export const Literal_Boolean = Type.Literal(true)
|
||||
|
||||
export const Primitive_Number = Type.Number()
|
||||
|
||||
export const Primitive_String = Type.String()
|
||||
|
||||
export const Primitive_String_Pattern = Type.String({ pattern: 'foo', default: 'foo' })
|
||||
|
||||
export const Primitive_Boolean = Type.Boolean()
|
||||
|
||||
export const Primitive_Null = Type.Null()
|
||||
|
||||
export const Object_Unconstrained = Type.Object({
|
||||
number: Type.Number(),
|
||||
negNumber: Type.Number(),
|
||||
maxNumber: Type.Number(),
|
||||
string: Type.String(),
|
||||
longString: Type.String(),
|
||||
boolean: Type.Boolean(),
|
||||
deeplyNested: Type.Object({
|
||||
foo: Type.String(),
|
||||
num: Type.Number(),
|
||||
bool: Type.Boolean(),
|
||||
}),
|
||||
})
|
||||
|
||||
export const Object_Constrained = Type.Object(Object_Unconstrained.properties, {
|
||||
additionalProperties: false,
|
||||
})
|
||||
|
||||
export const Object_Vector3 = Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number(),
|
||||
z: Type.Number(),
|
||||
})
|
||||
|
||||
export const Object_Box3D = Type.Object({
|
||||
scale: Object_Vector3,
|
||||
position: Object_Vector3,
|
||||
rotate: Object_Vector3,
|
||||
pivot: Object_Vector3,
|
||||
})
|
||||
export const Object_Recursive = Type.Recursive(
|
||||
(Recursive) =>
|
||||
Type.Object({
|
||||
id: Type.String(),
|
||||
nodes: Type.Array(Recursive),
|
||||
}),
|
||||
{
|
||||
default: {
|
||||
id: '',
|
||||
nodes: [
|
||||
{
|
||||
id: '',
|
||||
nodes: [
|
||||
{ id: '', nodes: [] },
|
||||
{ id: '', nodes: [] },
|
||||
{ id: '', nodes: [] },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '',
|
||||
nodes: [
|
||||
{ id: '', nodes: [] },
|
||||
{ id: '', nodes: [] },
|
||||
{ id: '', nodes: [] },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '',
|
||||
nodes: [
|
||||
{ id: '', nodes: [] },
|
||||
{ id: '', nodes: [] },
|
||||
{ id: '', nodes: [] },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
// prettier-ignore
|
||||
export const Tuple_Primitive = Type.Tuple([
|
||||
Type.String(),
|
||||
Type.Number(),
|
||||
Type.Boolean()
|
||||
])
|
||||
// prettier-ignore
|
||||
export const Tuple_Object = Type.Tuple([
|
||||
Type.Object({ x: Type.Number(), y: Type.Number() }),
|
||||
Type.Object({ a: Type.String(), b: Type.String() })
|
||||
])
|
||||
// prettier-ignore
|
||||
export const Composite_Intersect = Type.Intersect([
|
||||
Type.Object({ x: Type.Number(), y: Type.Number() }),
|
||||
Type.Object({ a: Type.String(), b: Type.String() })
|
||||
], { default: { x: 1, y: 2, a: 'a', b: 'b' } })
|
||||
|
||||
// prettier-ignore
|
||||
export const Composite_Union = Type.Union([
|
||||
Type.Object({ x: Type.Number(), y: Type.Number() }),
|
||||
Type.Object({ a: Type.String(), b: Type.String() })
|
||||
], { default: { a: 'a', b: 'b' } })
|
||||
|
||||
export const Math_Vector4 = Type.Tuple([Type.Number(), Type.Number(), Type.Number(), Type.Number()])
|
||||
|
||||
export const Math_Matrix4 = Type.Array(Type.Array(Type.Number()), {
|
||||
default: [
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1],
|
||||
],
|
||||
})
|
||||
|
||||
export const Array_Primitive_Number = Type.Array(Type.Number(), { minItems: 4 })
|
||||
|
||||
export const Array_Primitive_String = Type.Array(Type.String(), { minItems: 4 })
|
||||
|
||||
export const Array_Primitive_Boolean = Type.Array(Type.Boolean(), { minItems: 4 })
|
||||
|
||||
export const Array_Object_Unconstrained = Type.Array(Object_Unconstrained, { minItems: 4 })
|
||||
|
||||
export const Array_Object_Constrained = Type.Array(Object_Constrained, { minItems: 4 })
|
||||
|
||||
export const Array_Object_Recursive = Type.Array(Object_Recursive, { minItems: 4 })
|
||||
|
||||
export const Array_Tuple_Primitive = Type.Array(Tuple_Primitive, { minItems: 4 })
|
||||
|
||||
export const Array_Tuple_Object = Type.Array(Tuple_Object, { minItems: 4 })
|
||||
|
||||
export const Array_Composite_Intersect = Type.Array(Composite_Intersect, { minItems: 4 })
|
||||
|
||||
export const Array_Composite_Union = Type.Array(Composite_Union, { minItems: 4 })
|
||||
|
||||
export const Array_Math_Vector4 = Type.Array(Math_Vector4, { minItems: 4 })
|
||||
|
||||
export const Array_Math_Matrix4 = Type.Array(Math_Matrix4, { minItems: 4 })
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { Cases } from './cases'
|
||||
import { Benchmark } from './benchmark'
|
||||
import { TypeCompiler } from '@alkdev/typebox/compiler'
|
||||
import { TSchema, TypeGuard } from '@alkdev/typebox'
|
||||
import { Value } from '@alkdev/typebox/value'
|
||||
|
||||
import Ajv from 'ajv'
|
||||
|
||||
const ajv = new Ajv() // ensure single instance
|
||||
|
||||
export namespace CheckBenchmark {
|
||||
function Measure<T extends TSchema>(type: string, schema: T) {
|
||||
console.log('CheckBenchmark.Measure(', type, ')')
|
||||
|
||||
const iterations = 1_000_000
|
||||
const V = Value.Create(schema)
|
||||
|
||||
const AC = ajv.compile(schema)
|
||||
const A = Benchmark.Measure(() => {
|
||||
if (!AC(V)) throw Error()
|
||||
}, iterations)
|
||||
|
||||
const CC = TypeCompiler.Compile(schema)
|
||||
const T = Benchmark.Measure(() => {
|
||||
if (!CC.Check(V)) throw Error()
|
||||
}, iterations)
|
||||
|
||||
const VC = Benchmark.Measure(() => {
|
||||
if (!Value.Check(schema, V)) throw Error()
|
||||
}, iterations)
|
||||
|
||||
return { type, ajv: A, compiler: T, value: VC }
|
||||
}
|
||||
|
||||
export function* Execute() {
|
||||
for (const [type, schema] of Object.entries(Cases)) {
|
||||
if (!TypeGuard.IsSchema(schema)) throw Error('Invalid TypeBox schema')
|
||||
yield Measure(type, schema)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { Cases } from './cases'
|
||||
import { Benchmark } from './benchmark'
|
||||
import { TypeCompiler } from '@alkdev/typebox/compiler'
|
||||
import { TSchema, TypeGuard } from '@alkdev/typebox'
|
||||
import Ajv from 'ajv'
|
||||
|
||||
const ajv = new Ajv() // ensure single instance
|
||||
|
||||
export namespace CompileBenchmark {
|
||||
function Measure<T extends TSchema>(type: string, schema: T) {
|
||||
const iterations = 1000
|
||||
console.log('CompileBenchmark.Measure(', type, ')')
|
||||
// -------------------------------------------------------------------------------
|
||||
// Note: Ajv caches schemas by reference. To ensure we measure actual
|
||||
// compilation times, we must pass a new reference via { ...schema }
|
||||
// -------------------------------------------------------------------------------
|
||||
const AC = Benchmark.Measure(() => ajv.compile({ ...schema }), iterations)
|
||||
const CC = Benchmark.Measure(() => TypeCompiler.Compile({ ...schema }), iterations)
|
||||
return { type, ajv: AC, compiler: CC }
|
||||
}
|
||||
|
||||
export function* Execute() {
|
||||
for (const [type, schema] of Object.entries(Cases)) {
|
||||
if (!TypeGuard.IsSchema(schema)) throw Error('Invalid TypeBox schema')
|
||||
// -------------------------------------------------------------------------------
|
||||
// Note: it is not possible to benchmark recursive schemas as ajv will cache and
|
||||
// track duplicate $id (resulting in compile error). It is not possible to ammend
|
||||
// recursive $id's without potentially biasing results, so we omit on this case.
|
||||
// -------------------------------------------------------------------------------
|
||||
if (type === 'Object_Recursive' || type === 'Array_Object_Recursive') continue
|
||||
|
||||
yield Measure(type, schema)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import { CompileBenchmark } from './compile'
|
||||
import { CheckBenchmark } from './check'
|
||||
import { Result } from './result'
|
||||
|
||||
export function present(results: Result[]) {
|
||||
console.table(
|
||||
results.reduce((acc, result) => {
|
||||
const ratio = result.ajv.completed / result.compiler.completed
|
||||
if (result.value) {
|
||||
return {
|
||||
...acc,
|
||||
[result.type.padEnd(26, ' ')]: {
|
||||
Iterations: result.compiler.iterations,
|
||||
ValueCheck: `${result.value.completed} ms`.padStart(10),
|
||||
Ajv: `${result.ajv.completed} ms`.padStart(10),
|
||||
TypeCompiler: `${result.compiler.completed} ms`.padStart(10),
|
||||
Performance: `${ratio.toFixed(2)} x`.padStart(10, ' '),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...acc,
|
||||
[result.type.padEnd(26, ' ')]: {
|
||||
Iterations: result.compiler.iterations,
|
||||
Ajv: `${result.ajv.completed} ms`.padStart(10),
|
||||
TypeCompiler: `${result.compiler.completed} ms`.padStart(10),
|
||||
Performance: `${ratio.toFixed(2)} x`.padStart(10, ' '),
|
||||
},
|
||||
}
|
||||
}
|
||||
}, {}),
|
||||
)
|
||||
}
|
||||
|
||||
present([...CompileBenchmark.Execute()])
|
||||
present([...CheckBenchmark.Execute()])
|
||||
@@ -1,15 +0,0 @@
|
||||
export type Result = {
|
||||
type: string
|
||||
ajv: {
|
||||
iterations: number
|
||||
completed: number
|
||||
}
|
||||
compiler: {
|
||||
iterations: number
|
||||
completed: number
|
||||
}
|
||||
value?: {
|
||||
iterations: number
|
||||
completed: number
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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,41 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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 Node16',
|
||||
'--moduleResolution Node16',
|
||||
'--declaration',
|
||||
].join(' ')
|
||||
await shell(`tsc -p ./src/tsconfig.json ${options}`)
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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 { 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)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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',
|
||||
'--moduleResolution Bundler',
|
||||
'--declaration',
|
||||
].join(' ')
|
||||
await shell(`tsc -p ./src/tsconfig.json ${options}`)
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// 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(captured.includes('.mjs')) 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]
|
||||
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 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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 = ['compiler', 'errors', 'parser', 'syntax', 'system', 'type', 'value']
|
||||
await createPackageJsonRedirect(target, submodules)
|
||||
await createPackageJson(target, submodules)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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: 'Node16'`. 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,109 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@alkdev/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2026 Haydn Paterson
|
||||
|
||||
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,
|
||||
// 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 },
|
||||
// specify modules with potential for side effects
|
||||
'sideEffects': [
|
||||
'./build/esm/type/registry/format.mjs',
|
||||
'./build/esm/type/registry/type.mjs',
|
||||
'./build/esm/type/system/policy.mjs',
|
||||
'./build/cjs/type/registry/format.js',
|
||||
'./build/cjs/type/registry/type.js',
|
||||
'./build/cjs/type/system/policy.js'
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user