Fork @sinclair/typemap to @alkdev/typemap with @alkdev/typebox backend

- Rename package to @alkdev/typemap, update peerDeps to @alkdev/typebox
- Replace all @sinclair/typebox imports with @alkdev/typebox
- Replace @sinclair/hammer build system with standalone build.mjs
- Remove upstream-only files (.github, .vscode, design/, typemap.png)
- Update readme with fork notice and new package names
- Add fork copyright to license
This commit is contained in:
2026-04-23 15:36:51 +00:00
parent eb67d42876
commit 3b4dd4f1d1
70 changed files with 599 additions and 3302 deletions

219
build.mjs Normal file
View File

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