chore: import upstream snapshot with attribution
Build documentation / build (push) Failing after 0s
Unit tests / build (18) (push) Has been cancelled
Unit tests / build (20) (push) Has been cancelled
Unit tests / build (22) (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:44:39 +08:00
commit 311a3666c4
703 changed files with 71017 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
import { OUT_DIR } from "./build/constants.mjs";
import prepareOutDir from "../../../scripts/prepareOutDir.mjs";
import { colors, createLogger } from "../../../scripts/logger.mjs";
import { buildAll } from "./build/buildAll.mjs";
const log = createLogger("transformers");
log.section("BUILD");
log.info("Building transformers.js with esbuild...\n");
const startTime = performance.now();
try {
prepareOutDir(OUT_DIR);
await buildAll(log);
const endTime = performance.now();
const duration = (endTime - startTime).toFixed(2);
log.success(`All builds completed in ${colors.bright}${duration}ms${colors.reset}\n`);
} catch (error) {
log.error(`Build failed: ${error.message}`);
console.error(error);
process.exit(1);
}
@@ -0,0 +1,75 @@
import { build as esbuild } from "esbuild";
import path from "node:path";
import { stripNodePrefixPlugin } from "./plugins/stripNodePrefixPlugin.mjs";
import { ignoreModulesPlugin } from "./plugins/ignoreModulesPlugin.mjs";
import { postBuildPlugin } from "./plugins/postBuildPlugin.mjs";
import { externalNodeBuiltinsPlugin } from "./plugins/externalNodeBuiltinsPlugin.mjs";
import { OUT_DIR, ROOT_DIR, getEsbuildProdConfig } from "./constants.mjs";
import { reportSize } from "../../../../scripts/reportSize.mjs";
import { colors } from "../../../../scripts/logger.mjs";
import { BUILD_TARGETS } from "./targets.mjs";
/**
* Helper function to create build configurations.
*/
async function buildTarget(
{
name = "",
suffix = ".js",
format = "esm", // 'esm' | 'cjs'
ignoreModules = [],
externalModules = [],
usePostBuild = false,
},
log,
) {
const platform = format === "cjs" ? "node" : "neutral";
const regularFile = `transformers${name}${suffix}`;
const minFile = `transformers${name}.min${suffix}`;
const plugins = [];
// Add ignoreModulesPlugin FIRST so it can catch modules before stripNodePrefixPlugin marks them as external
if (ignoreModules.length > 0) {
plugins.push(ignoreModulesPlugin(ignoreModules));
}
plugins.push(stripNodePrefixPlugin());
plugins.push(externalNodeBuiltinsPlugin());
if (usePostBuild) {
plugins.push(postBuildPlugin(OUT_DIR, ROOT_DIR));
}
log.build(`Building ${colors.bright}${regularFile}${colors.reset}...`);
await esbuild({
...getEsbuildProdConfig(ROOT_DIR),
platform,
format,
outfile: path.join(OUT_DIR, regularFile),
external: externalModules,
plugins,
});
reportSize(path.join(OUT_DIR, regularFile), log);
log.build(`Building ${colors.bright}${minFile}${colors.reset}...`);
await esbuild({
...getEsbuildProdConfig(ROOT_DIR),
platform,
format,
outfile: path.join(OUT_DIR, minFile),
minify: true,
external: externalModules,
plugins,
legalComments: "none",
});
reportSize(path.join(OUT_DIR, minFile), log);
}
/**
* Build all targets for production
*/
export async function buildAll(log) {
for (const target of BUILD_TARGETS) {
log.section(target.name);
await buildTarget(target.config, log);
}
}
@@ -0,0 +1,60 @@
import { context } from "esbuild";
import path from "node:path";
import { stripNodePrefixPlugin } from "./plugins/stripNodePrefixPlugin.mjs";
import { ignoreModulesPlugin } from "./plugins/ignoreModulesPlugin.mjs";
import { postBuildPlugin } from "./plugins/postBuildPlugin.mjs";
import { externalNodeBuiltinsPlugin } from "./plugins/externalNodeBuiltinsPlugin.mjs";
import { rebuildPlugin } from "../../../../scripts/rebuildPlugin.mjs";
import { OUT_DIR, ROOT_DIR, getEsbuildDevConfig } from "./constants.mjs";
import { BUILD_TARGETS } from "./targets.mjs";
/**
* Create an esbuild context for a single build target
*/
async function createBuildContext(targetName, targetConfig, log) {
const { name, suffix, format, ignoreModules, externalModules, usePostBuild } = targetConfig;
const platform = format === "cjs" ? "node" : "neutral";
const outputFile = `transformers${name}${suffix}`;
const plugins = [];
// Add ignoreModulesPlugin FIRST so it can catch modules before stripNodePrefixPlugin marks them as external
if (ignoreModules.length > 0) {
plugins.push(ignoreModulesPlugin(ignoreModules));
}
plugins.push(stripNodePrefixPlugin());
plugins.push(externalNodeBuiltinsPlugin());
if (usePostBuild) {
plugins.push(postBuildPlugin(OUT_DIR, ROOT_DIR));
}
plugins.push(rebuildPlugin(targetName, log));
return context({
...getEsbuildDevConfig(ROOT_DIR),
platform,
format,
outfile: path.join(OUT_DIR, outputFile),
external: externalModules,
plugins,
});
}
/**
* Build all targets in watch mode for development
* @returns {Promise<Array>} Array of esbuild contexts that can be disposed later
*/
export async function buildAllWithWatch(log) {
log.dim("Creating build contexts...\n");
// Create contexts for all targets
const contexts = await Promise.all(BUILD_TARGETS.map((target) => createBuildContext(target.name, target.config, log)));
log.dim("Starting initial build...\n");
// Wait for the initial builds to complete
await Promise.all(contexts.map((ctx) => ctx.rebuild()));
// Start watching all targets
await Promise.all(contexts.map((ctx) => ctx.watch()));
return contexts;
}
@@ -0,0 +1,38 @@
import path from "node:path";
import { fileURLToPath } from "node:url";
export const DIST_FOLDER = "dist";
export const NODE_IGNORE_MODULES = ["onnxruntime-web"];
export const NODE_EXTERNAL_MODULES = [
"onnxruntime-common",
"onnxruntime-node",
"sharp",
// node:* modules are handled by externalNodeBuiltinsPlugin
];
export const WEB_IGNORE_MODULES = ["onnxruntime-node", "sharp", "fs", "path", "url", "stream", "stream/promises"];
export const WEB_EXTERNAL_MODULES = ["onnxruntime-common", "onnxruntime-web"];
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export const ROOT_DIR = path.join(__dirname, "../..");
export const OUT_DIR = path.join(ROOT_DIR, DIST_FOLDER);
export const getEsbuildDevConfig = (rootDir) => ({
bundle: true,
treeShaking: true,
logLevel: "info",
entryPoints: [path.join(rootDir, "src/transformers.js")],
platform: "neutral",
format: "esm",
sourcemap: true,
logOverride: {
// Suppress import.meta warning for CJS builds - it's handled gracefully in the code
"empty-import-meta": "silent",
},
});
export const getEsbuildProdConfig = (rootDir) => ({
...getEsbuildDevConfig(rootDir),
logLevel: "warning",
sourcemap: false,
});
@@ -0,0 +1,14 @@
/**
* Plugin to automatically mark all node:* imports as external.
* This prevents having to manually list all Node.js built-in modules.
*/
export const externalNodeBuiltinsPlugin = () => ({
name: "external-node-builtins",
setup(build) {
// Mark all node:* imports as external
build.onResolve({ filter: /^node:/ }, (args) => ({
path: args.path,
external: true,
}));
},
});
@@ -0,0 +1,49 @@
/**
* Plugin to ignore/exclude certain modules by returning an empty module.
* Equivalent to webpack's resolve.alias with false value.
*/
export const ignoreModulesPlugin = (modules = []) => ({
name: "ignore-modules",
setup(build) {
// Escape special regex characters in module names
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const escapedModules = modules.map(escapeRegex);
// Match both "module" and "node:module" patterns
const patterns = escapedModules.flatMap((mod) => [mod, `node:${mod}`]);
const filter = new RegExp(`^(${patterns.join("|")})$`);
build.onResolve({ filter }, (args) => {
return { path: args.path, namespace: "ignore-modules" };
});
build.onLoad({ filter: /.*/, namespace: "ignore-modules" }, (args) => {
switch (args.path) {
case "node:stream":
return {
contents: `
const noop = () => {};
export default {};
export const Readable = { fromWeb: noop };
`,
};
case "node:stream/promises":
return {
contents: `
const noop = () => {};
export default {};
export const pipeline = noop;
`,
};
case "node:fs":
case "node:path":
case "node:url":
case "sharp":
case "onnxruntime-node":
default:
return {
contents: `export default {};`,
};
}
});
},
});
@@ -0,0 +1,43 @@
import path from "node:path";
import { copyFileSync, unlinkSync, existsSync } from "node:fs";
import { colors, createLogger } from "../../../../../scripts/logger.mjs";
const log = createLogger("transformers");
/**
* Plugin to post-process build files.
* Equivalent to webpack's PostBuildPlugin.
*/
export const postBuildPlugin = (distDir, rootDir) => {
// it should copy the files only once. In watch mode for example it should not rerun every time
let completed = false;
return {
name: "post-build",
setup(build) {
build.onEnd(() => {
if (completed) return;
completed = true;
const ORT_JSEP_FILE = "ort-wasm-simd-threaded.jsep.mjs";
const ORT_BUNDLE_FILE = "ort.bundle.min.mjs";
// 1. Remove unnecessary files
const file = path.join(distDir, ORT_BUNDLE_FILE);
if (existsSync(file)) unlinkSync(file);
// 2. Copy unbundled JSEP file
const ORT_SOURCE_DIR = path.join(rootDir, "node_modules/onnxruntime-web/dist");
const src = path.join(ORT_SOURCE_DIR, ORT_JSEP_FILE);
if (existsSync(src)) {
const dest = path.join(distDir, ORT_JSEP_FILE);
copyFileSync(src, dest);
log.success(`${colors.gray}Copied ${ORT_JSEP_FILE}${colors.reset}`);
} else {
log.warning(`Could not find ${ORT_JSEP_FILE} in node_modules`);
}
});
},
};
};
@@ -0,0 +1,15 @@
/**
* Plugin to strip the "node:" prefix from module requests.
* Equivalent to webpack's StripNodePrefixPlugin.
*/
export const stripNodePrefixPlugin = () => ({
name: "strip-node-prefix",
setup(build) {
build.onResolve({ filter: /^node:/ }, (args) => {
return {
path: args.path.replace(/^node:/, ""),
external: true,
};
});
},
});
@@ -0,0 +1,51 @@
import { NODE_IGNORE_MODULES, NODE_EXTERNAL_MODULES, WEB_IGNORE_MODULES, WEB_EXTERNAL_MODULES } from "./constants.mjs";
/**
* Build target configuration
* Each target defines a specific build variant
*/
export const BUILD_TARGETS = [
{
name: "Bundle Build (ESM)",
config: {
name: "",
suffix: ".js",
format: "esm",
ignoreModules: WEB_IGNORE_MODULES,
usePostBuild: true,
},
},
{
name: "Web Build (ESM)",
config: {
name: ".web",
suffix: ".js",
format: "esm",
ignoreModules: WEB_IGNORE_MODULES,
externalModules: WEB_EXTERNAL_MODULES,
usePostBuild: false,
},
},
{
name: "Node Build (ESM)",
config: {
name: ".node",
suffix: ".mjs",
format: "esm",
ignoreModules: NODE_IGNORE_MODULES,
externalModules: NODE_EXTERNAL_MODULES,
usePostBuild: false,
},
},
{
name: "Node Build (CJS)",
config: {
name: ".node",
suffix: ".cjs",
format: "cjs",
ignoreModules: NODE_IGNORE_MODULES,
externalModules: NODE_EXTERNAL_MODULES,
usePostBuild: false,
},
},
];
+113
View File
@@ -0,0 +1,113 @@
import { spawn } from "node:child_process";
import { unlinkSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { OUT_DIR } from "./build/constants.mjs";
import prepareOutDir from "../../../scripts/prepareOutDir.mjs";
import { colors, createLogger } from "../../../scripts/logger.mjs";
import { buildAllWithWatch } from "./build/buildAllWithWatch.mjs";
const log = createLogger("transformers");
const startTime = performance.now();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT_DIR = path.join(__dirname, "..");
prepareOutDir(OUT_DIR);
// Remove tsbuildinfo to force TypeScript to rebuild type declarations
try {
unlinkSync(`${ROOT_DIR}/types/tsconfig.tsbuildinfo`);
} catch (err) {
// File doesn't exist, that's fine
}
log.section("BUILD");
log.info("Building transformers.js with esbuild in watch mode...");
// Build all targets with watch mode
const contexts = await buildAllWithWatch(log);
const endTime = performance.now();
const duration = (endTime - startTime).toFixed(2);
log.success(`All builds completed in ${colors.bright}${duration}ms${colors.reset}`);
// Generate initial TypeScript declarations, then start watch mode
log.section("TYPES");
log.info("Generating initial type declarations...");
await new Promise((resolve, reject) => {
const tscBuild = spawn("tsc", ["--build"], {
cwd: ROOT_DIR,
stdio: "pipe",
shell: true,
});
tscBuild.stdout.on("data", (data) => {
const output = data.toString().trim();
if (output && output.includes("error")) {
log.dim(output);
}
});
tscBuild.stderr.on("data", (data) => {
const output = data.toString().trim();
if (output) {
log.error(output);
}
});
tscBuild.on("exit", (code) => {
if (code === 0) {
log.done("Type declarations generated");
resolve();
} else {
reject(new Error(`TypeScript build failed with code ${code}`));
}
});
});
log.info("Starting TypeScript watch mode...\n");
const tscWatch = spawn("tsc", ["--build", "--watch", "--preserveWatchOutput"], {
cwd: ROOT_DIR,
stdio: "pipe",
shell: true,
});
tscWatch.stdout.on("data", (data) => {
const output = data.toString().trim();
if (output) {
output.split("\n").forEach((line) => {
// Filter out verbose output, only show important messages
if (
line.includes("error") ||
line.includes("File change detected") ||
line.includes("Found 0 errors") ||
(line.includes("Found") && line.includes("error"))
) {
log.dim(line);
}
});
}
});
tscWatch.stderr.on("data", (data) => {
const output = data.toString().trim();
if (output) {
output.split("\n").forEach((line) => {
log.error(line);
});
}
});
log.dim(`Watching for changes...\n`);
// Keep process alive and cleanup
process.on("SIGINT", async () => {
log.warning(`\nStopping watch mode...`);
tscWatch.kill();
await Promise.all(contexts.map((ctx) => ctx.dispose()));
log.dim("Goodbye!");
process.exit(0);
});