mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
- scripts/build/prepublish.ts: APP_DIR -> DIST_DIR; remove Step 1 and Step 2.5 hack blocks; fix MCP esbuild outfile (app/ -> dist/); update all log messages - scripts/build/build-next-isolated.mjs: remove legacy-app-snapshot entry from getTransientBuildPaths() (App-Router collision hack deleted) - scripts/build/assembleStandalone.mjs: fix standalone package.json after copy — removes "type":"module" so Next.js standalone server.js (CJS) loads correctly; also adds .build/next/ to allowed staging prefixes so server bundles are kept - scripts/build/pack-artifact-policy.ts: app/ -> dist/ in all PACK_ARTIFACT_* paths; add ".build/next/" to APP_STAGING_ALLOWED_PATH_PREFIXES (Layer 1 distDir change) - scripts/build/validate-pack-artifact.ts: dist/ check instead of app/ - scripts/build/postinstall.mjs: all app/ paths -> dist/ - scripts/build/postinstallSupport.mjs: hasStandaloneAppBundle checks dist/server.js - bin/cli/commands/serve.mjs: APP_DIR -> dist/ - package.json: files[] "app/" -> "dist/" - .gitignore: remove both /app and /app/ entries (no longer needed) Smoke: NO_APP_DIR_OK; DIST_OK; check:pack-artifact PASS; health 200 from dist/
585 lines
24 KiB
JavaScript
585 lines
24 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* assembleStandalone.mjs - Shared standalone bundle assembler for OmniRoute.
|
|
*
|
|
* Task 0.1 Inventory: Copy/sync operations across the three build scripts
|
|
* -----------------------------------------------------------------------
|
|
* Operation build-next-isolated prepublish electron Status
|
|
* --------------------------------------------------- ------------------- ----------- -------- ------
|
|
* .next/standalone -> outDir (cp) Y Y Y SHARED
|
|
* .next/static -> outDir/.next/static (cp) Y Y Y SHARED
|
|
* public/ -> outDir/public/ (cp) Y Y Y SHARED
|
|
* wreq-js/rust -> outDir/node_modules/wreq-js/rust Y - - SHARED (native asset)
|
|
* better-sqlite3/build -> outDir/node_modules/better-sqlite3/ Y - - SHARED (native asset)
|
|
* @swc/helpers -> outDir/node_modules/@swc/helpers Y Y Y SHARED (extra module)
|
|
* pino-abstract-transport -> outDir/node_modules/... Y - - SHARED (extra module)
|
|
* pino-pretty -> outDir/node_modules/pino-pretty Y - - SHARED (extra module)
|
|
* split2 -> outDir/node_modules/split2 Y - - SHARED (extra module)
|
|
* src/lib/db/migrations -> outDir/migrations Y Y - SHARED (extra module)
|
|
* src/mitm/server.cjs -> outDir/src/mitm/server.cjs Y - - SHARED (extra module)
|
|
* scripts/dev/run-standalone.mjs -> outDir/dev/run-standalone Y - - SHARED (extra module)
|
|
* scripts/dev/standalone-server-ws.mjs -> outDir/server-ws Y Y - SHARED (extra module)
|
|
* scripts/dev/peer-stamp.mjs -> outDir/peer-stamp.mjs Y Y - SHARED (extra module)
|
|
* scripts/dev/responses-ws-proxy.mjs -> outDir/responses-ws- Y Y - SHARED (extra module)
|
|
* scripts/build/runtime-env.mjs -> outDir/build/runtime-env Y - - SHARED (extra module)
|
|
* scripts/build/bootstrap-env.mjs -> outDir/build/bootstrap- Y - - SHARED (extra module)
|
|
* scripts/dev/healthcheck.mjs -> outDir/healthcheck.mjs Y - - SHARED (extra module)
|
|
* playwright-core -> outDir/node_modules/playwright-core Y - - SHARED (extra module)
|
|
* sqlite-vec -> outDir/node_modules/sqlite-vec Y - - SHARED (extra module)
|
|
* sqlite-vec-linux-x64/arm64/darwin-x64/arm64/win-x64 (same) Y - - SHARED (extra module)
|
|
* abs-path sanitization in server.js + required-server-files - Y Y SHARED (opt-in: sanitizePaths)
|
|
* Turbopack hashed-chunk patch (.next/server/ *.js) - Y - SHARED (opt-in: patchTurbopackChunks)
|
|
* --- npm-UNIQUE ---
|
|
* MITM tsc compile -> app/src/mitm/ - Y - UNIQUE (prepublish)
|
|
* MCP server esbuild -> app/open-sse/mcp-server/server.js - Y - UNIQUE (prepublish)
|
|
* CLI esbuild -> bin/omniroute.mjs - Y - UNIQUE (prepublish)
|
|
* sidecar/doc copies (.env.example, docs/, sync-env, etc.) - Y - UNIQUE (prepublish)
|
|
* prune + validate (pack-artifact-policy) - Y - UNIQUE (prepublish)
|
|
* data/ dir creation - Y - UNIQUE (prepublish)
|
|
* --- electron-UNIQUE ---
|
|
* better-sqlite3 + keytar native strip (ABI rebuild) - - Y UNIQUE (electron)
|
|
* symlink guard (assertBundleIsPackagable) - - Y UNIQUE (electron)
|
|
* removeGeneratedElectronArtifacts - - Y UNIQUE (electron)
|
|
*/
|
|
|
|
import fs from "node:fs/promises";
|
|
import fsSync from "node:fs";
|
|
import path from "node:path";
|
|
|
|
/**
|
|
* Check whether a path exists (async).
|
|
* @param {string} targetPath
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async function exists(targetPath) {
|
|
try {
|
|
await fs.access(targetPath);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Copy native standalone assets (wreq-js rust/, better-sqlite3 build/).
|
|
*
|
|
* The destination is derived as <rootDir>/<distDir>/standalone/node_modules/...
|
|
* for backward compatibility with existing callers and tests.
|
|
*
|
|
* @param {string} rootDir - project root (node_modules are read from here)
|
|
* @param {typeof fs} [fsImpl] - fs/promises implementation (injectable for tests)
|
|
* @param {Console|{log:Function}} [log] - logger
|
|
* @returns {Promise<boolean>} true if any asset was copied
|
|
*/
|
|
export async function syncStandaloneNativeAssets(rootDir, fsImpl = fs, log = console) {
|
|
const nextDistDir = process.env.NEXT_DIST_DIR || ".build/next";
|
|
const standaloneRoot = path.join(rootDir, nextDistDir, "standalone");
|
|
return syncNativeAssetsToDir(rootDir, standaloneRoot, fsImpl, log);
|
|
}
|
|
|
|
/**
|
|
* Copy extra modules and sidecars into the Next.js standalone output.
|
|
*
|
|
* The destination is derived as <rootDir>/<distDir>/standalone/...
|
|
* where distDir defaults to ".build/next" (overridable via NEXT_DIST_DIR).
|
|
*
|
|
* @param {string} rootDir - project root
|
|
* @param {typeof fs} [fsImpl] - fs/promises implementation (injectable for tests)
|
|
* @param {Console|{log:Function}} [log] - logger
|
|
* @returns {Promise<boolean>} true if any module was copied
|
|
*/
|
|
export async function syncStandaloneExtraModules(rootDir, fsImpl = fs, log = console) {
|
|
const nextDistDir = process.env.NEXT_DIST_DIR || ".build/next";
|
|
const standaloneRoot = path.join(rootDir, nextDistDir, "standalone");
|
|
return syncExtraModulesToDir(rootDir, standaloneRoot, fsImpl, log);
|
|
}
|
|
|
|
/**
|
|
* Internal: copy native assets to an arbitrary outDir.
|
|
*
|
|
* @param {string} projectRoot
|
|
* @param {string} outDir
|
|
* @param {typeof fs} fsImpl
|
|
* @param {Console|{log:Function}} log
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async function syncNativeAssetsToDir(projectRoot, outDir, fsImpl, log) {
|
|
const nativeAssetDirs = [
|
|
{
|
|
label: "wreq-js native runtime",
|
|
sourcePath: path.join(projectRoot, "node_modules", "wreq-js", "rust"),
|
|
destinationPath: path.join(outDir, "node_modules", "wreq-js", "rust"),
|
|
},
|
|
{
|
|
label: "better-sqlite3 native binary",
|
|
sourcePath: path.join(projectRoot, "node_modules", "better-sqlite3", "build"),
|
|
destinationPath: path.join(outDir, "node_modules", "better-sqlite3", "build"),
|
|
},
|
|
];
|
|
|
|
let changed = false;
|
|
|
|
for (const entry of nativeAssetDirs) {
|
|
if (!(await exists(entry.sourcePath))) continue;
|
|
|
|
const mkdir =
|
|
typeof fsImpl.mkdir === "function" ? fsImpl.mkdir.bind(fsImpl) : fs.mkdir.bind(fs);
|
|
await mkdir(path.dirname(entry.destinationPath), { recursive: true });
|
|
await fsImpl.cp(entry.sourcePath, entry.destinationPath, {
|
|
recursive: true,
|
|
force: true,
|
|
});
|
|
log.log(
|
|
`[assembleStandalone] Copied native standalone asset: ${path.relative(
|
|
projectRoot,
|
|
entry.destinationPath
|
|
)}`
|
|
);
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
/**
|
|
* Internal: copy extra modules/sidecars to an arbitrary outDir.
|
|
*
|
|
* @param {string} projectRoot
|
|
* @param {string} outDir
|
|
* @param {typeof fs} fsImpl
|
|
* @param {Console|{log:Function}} log
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async function syncExtraModulesToDir(projectRoot, outDir, fsImpl, log) {
|
|
const entries = [
|
|
{
|
|
label: "@swc/helpers",
|
|
sourcePath: path.join(projectRoot, "node_modules", "@swc", "helpers"),
|
|
destRelative: path.join("node_modules", "@swc", "helpers"),
|
|
},
|
|
{
|
|
label: "pino-abstract-transport",
|
|
sourcePath: path.join(projectRoot, "node_modules", "pino-abstract-transport"),
|
|
destRelative: path.join("node_modules", "pino-abstract-transport"),
|
|
},
|
|
{
|
|
label: "pino-pretty",
|
|
sourcePath: path.join(projectRoot, "node_modules", "pino-pretty"),
|
|
destRelative: path.join("node_modules", "pino-pretty"),
|
|
},
|
|
{
|
|
label: "split2",
|
|
sourcePath: path.join(projectRoot, "node_modules", "split2"),
|
|
destRelative: path.join("node_modules", "split2"),
|
|
},
|
|
{
|
|
label: "migrations",
|
|
sourcePath: path.join(projectRoot, "src", "lib", "db", "migrations"),
|
|
destRelative: "migrations",
|
|
},
|
|
{
|
|
label: "MITM server",
|
|
sourcePath: path.join(projectRoot, "src", "mitm", "server.cjs"),
|
|
destRelative: path.join("src", "mitm", "server.cjs"),
|
|
},
|
|
{
|
|
label: "run-standalone script",
|
|
sourcePath: path.join(projectRoot, "scripts", "dev", "run-standalone.mjs"),
|
|
destRelative: path.join("dev", "run-standalone.mjs"),
|
|
},
|
|
{
|
|
// WS-aware wrapper that run-standalone.mjs prefers over bare server.js.
|
|
// It installs the trusted peer-IP stamp the authz middleware needs to
|
|
// allow loopback/LAN access to LOCAL_ONLY routes; without it the Docker
|
|
// container fails closed (every LOCAL_ONLY request 403s). Imports
|
|
// peer-stamp.mjs + responses-ws-proxy.mjs, so all three are co-located.
|
|
label: "WS/peer-stamp standalone server wrapper",
|
|
sourcePath: path.join(projectRoot, "scripts", "dev", "standalone-server-ws.mjs"),
|
|
destRelative: "server-ws.mjs",
|
|
},
|
|
{
|
|
label: "peer-stamp helper (server-ws.mjs dependency)",
|
|
sourcePath: path.join(projectRoot, "scripts", "dev", "peer-stamp.mjs"),
|
|
destRelative: "peer-stamp.mjs",
|
|
},
|
|
{
|
|
label: "responses-ws-proxy (server-ws.mjs dependency)",
|
|
sourcePath: path.join(projectRoot, "scripts", "dev", "responses-ws-proxy.mjs"),
|
|
destRelative: "responses-ws-proxy.mjs",
|
|
},
|
|
{
|
|
label: "runtime-env script",
|
|
sourcePath: path.join(projectRoot, "scripts", "build", "runtime-env.mjs"),
|
|
destRelative: path.join("build", "runtime-env.mjs"),
|
|
},
|
|
{
|
|
label: "bootstrap-env script",
|
|
sourcePath: path.join(projectRoot, "scripts", "build", "bootstrap-env.mjs"),
|
|
destRelative: path.join("build", "bootstrap-env.mjs"),
|
|
},
|
|
{
|
|
label: "healthcheck script",
|
|
sourcePath: path.join(projectRoot, "scripts", "dev", "healthcheck.mjs"),
|
|
destRelative: "healthcheck.mjs",
|
|
},
|
|
{
|
|
label: "public directory",
|
|
sourcePath: path.join(projectRoot, "public"),
|
|
destRelative: "public",
|
|
},
|
|
{
|
|
label: "playwright-core (dynamic import by gemini-web executor)",
|
|
sourcePath: path.join(projectRoot, "node_modules", "playwright-core"),
|
|
destRelative: path.join("node_modules", "playwright-core"),
|
|
},
|
|
{
|
|
label: "sqlite-vec wrapper (vector memory - loaded at runtime via createRequire)",
|
|
sourcePath: path.join(projectRoot, "node_modules", "sqlite-vec"),
|
|
destRelative: path.join("node_modules", "sqlite-vec"),
|
|
},
|
|
// sqlite-vec's native vec0.so lives in a platform-specific package resolved at
|
|
// runtime via require.resolve(). Next.js does NOT trace it into the standalone
|
|
// (the externalized wrapper is copied, but its optional platform dep is missed -
|
|
// Next.js #88844), so without this the bundled/Docker build silently degrades
|
|
// vector search to FTS5: the wrapper loads but getLoadablePath() throws
|
|
// MODULE_NOT_FOUND. Copy whichever platform package npm actually installed. See #3066.
|
|
...[
|
|
"sqlite-vec-linux-x64",
|
|
"sqlite-vec-linux-arm64",
|
|
"sqlite-vec-darwin-x64",
|
|
"sqlite-vec-darwin-arm64",
|
|
"sqlite-vec-windows-x64",
|
|
].map((pkg) => ({
|
|
label: pkg,
|
|
sourcePath: path.join(projectRoot, "node_modules", pkg),
|
|
destRelative: path.join("node_modules", pkg),
|
|
})),
|
|
];
|
|
|
|
let changed = false;
|
|
|
|
for (const entry of entries) {
|
|
if (!(await exists(entry.sourcePath))) continue;
|
|
|
|
const destPath = path.join(outDir, entry.destRelative);
|
|
const mkdir =
|
|
typeof fsImpl.mkdir === "function" ? fsImpl.mkdir.bind(fsImpl) : fs.mkdir.bind(fs);
|
|
await mkdir(path.dirname(destPath), { recursive: true });
|
|
await fsImpl.cp(entry.sourcePath, destPath, { recursive: true, force: true });
|
|
log.log(`[assembleStandalone] Synced standalone module: ${entry.label}`);
|
|
changed = true;
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
/**
|
|
* Sanitize absolute build-machine paths in server.js and required-server-files.json.
|
|
* Replaces the build root with "." so paths resolve relative to wherever the standalone
|
|
* bundle is installed.
|
|
*
|
|
* @param {string} projectRoot - repo root (the path to replace)
|
|
* @param {string} outDir - assembled standalone output directory
|
|
* @returns {number} number of path replacements made
|
|
*/
|
|
export function assemblePathSanitize(projectRoot, outDir) {
|
|
const buildRoot = projectRoot.replace(/\\/g, "/"); // normalise for regex safety
|
|
const sanitizeTargets = [
|
|
path.join(outDir, "server.js"),
|
|
path.join(outDir, ".next", "required-server-files.json"),
|
|
];
|
|
|
|
let sanitisedCount = 0;
|
|
for (const filePath of sanitizeTargets) {
|
|
if (!fsSync.existsSync(filePath)) continue;
|
|
let content = fsSync.readFileSync(filePath, "utf8");
|
|
// Escape special regex characters in the path
|
|
const escaped = buildRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
const re = new RegExp(escaped, "g");
|
|
const matches = content.match(re);
|
|
if (matches) {
|
|
content = content.replace(re, ".");
|
|
fsSync.writeFileSync(filePath, content);
|
|
sanitisedCount += matches.length;
|
|
}
|
|
}
|
|
return sanitisedCount;
|
|
}
|
|
|
|
/**
|
|
* Strip Turbopack hashed externals from compiled chunks.
|
|
* Even when Turbopack is disabled at build time, some instrumentation chunks
|
|
* may still emit require('package-<16hexchars>') instead of require('package').
|
|
* We strip the hex suffix from all .js files in outDir/.next/server/.
|
|
*
|
|
* @param {string} outDir - assembled standalone output directory
|
|
* @returns {{ patchedFiles: number, patchedMatches: number }}
|
|
*/
|
|
export function patchTurbopackChunks(outDir) {
|
|
const serverOutput = path.join(outDir, ".next", "server");
|
|
const HASH_RE = /(['"\\])([a-z@][a-z0-9@./_-]+?-[0-9a-f]{16}(?:\/[^'"\\]+)?)\1/g;
|
|
let patchedFiles = 0;
|
|
let patchedMatches = 0;
|
|
|
|
const walkDir = (dir) => {
|
|
let entries = [];
|
|
try {
|
|
entries = fsSync.readdirSync(dir);
|
|
} catch {
|
|
return;
|
|
}
|
|
for (const entry of entries) {
|
|
const full = path.join(dir, entry);
|
|
try {
|
|
const st = fsSync.statSync(full);
|
|
if (st.isDirectory()) {
|
|
walkDir(full);
|
|
continue;
|
|
}
|
|
if (!entry.endsWith(".js")) continue;
|
|
const src = fsSync.readFileSync(full, "utf8");
|
|
let count = 0;
|
|
const patched = src.replace(HASH_RE, (_, q, name) => {
|
|
const base = name.replace(/-[0-9a-f]{16}(?=\/|$)/, "");
|
|
count++;
|
|
return `${q}${base}${q}`;
|
|
});
|
|
if (count > 0) {
|
|
fsSync.writeFileSync(full, patched);
|
|
patchedFiles++;
|
|
patchedMatches += count;
|
|
}
|
|
} catch {
|
|
/* skip unreadable files */
|
|
}
|
|
}
|
|
};
|
|
|
|
if (fsSync.existsSync(serverOutput)) {
|
|
walkDir(serverOutput);
|
|
}
|
|
|
|
return { patchedFiles, patchedMatches };
|
|
}
|
|
|
|
/**
|
|
* Assemble the Next.js standalone bundle into outDir.
|
|
*
|
|
* Copies <distDir>/standalone -> outDir, then <distDir>/static -> outDir/.next/static,
|
|
* projectRoot/public -> outDir/public, native assets, and extra modules/sidecars.
|
|
* Optionally sanitizes abs paths and patches Turbopack chunks.
|
|
*
|
|
* This is a synchronous function for use in build scripts.
|
|
*
|
|
* @param {object} opts
|
|
* @param {string} opts.distDir - Next.js distDir (e.g. ".next" or ".build/next")
|
|
* @param {string} opts.outDir - destination directory for the assembled bundle
|
|
* @param {string} [opts.projectRoot] - repo root; defaults to process.cwd()
|
|
* @param {boolean} [opts.sanitizePaths] - replace build-machine abs paths with "." (default false)
|
|
* @param {boolean} [opts.patchTurbopackChunks] - strip hashed externals from .next/server js files (default false)
|
|
* @param {boolean} [opts.copyNatives] - copy native assets + extra modules (default true)
|
|
* @returns {void}
|
|
*/
|
|
export function assembleStandalone({
|
|
distDir,
|
|
outDir,
|
|
projectRoot = process.cwd(),
|
|
sanitizePaths = false,
|
|
patchTurbopackChunks: doPatchChunks = false,
|
|
copyNatives = true,
|
|
}) {
|
|
if (!distDir) throw new Error("[assembleStandalone] distDir is required");
|
|
if (!outDir) throw new Error("[assembleStandalone] outDir is required");
|
|
|
|
const standaloneDir = path.resolve(path.join(distDir, "standalone"));
|
|
const resolvedOutDir = path.resolve(outDir);
|
|
if (!fsSync.existsSync(standaloneDir)) {
|
|
throw new Error(
|
|
`[assembleStandalone] standalone dir not found: ${standaloneDir}. Run \`next build\` first.`
|
|
);
|
|
}
|
|
|
|
// 1. Copy <distDir>/standalone -> outDir (skip when outDir IS the standalone dir — in-place mode)
|
|
fsSync.mkdirSync(resolvedOutDir, { recursive: true });
|
|
if (resolvedOutDir !== standaloneDir) {
|
|
fsSync.cpSync(standaloneDir, resolvedOutDir, { recursive: true });
|
|
}
|
|
|
|
// 1.5. Fix package.json in outDir: Next.js standalone's server.js is CommonJS (uses require()),
|
|
// but the root package.json (which Next copies into the standalone) has "type":"module".
|
|
// Remove "type" from the outDir's package.json so Node.js treats .js files as CJS in this dir.
|
|
// Without this, `node server.js` (or `import("./server.js")`) fails with
|
|
// ReferenceError: require is not defined in ES module scope
|
|
const outDirPkgJson = path.join(resolvedOutDir, "package.json");
|
|
if (fsSync.existsSync(outDirPkgJson)) {
|
|
try {
|
|
const pkg = JSON.parse(fsSync.readFileSync(outDirPkgJson, "utf8"));
|
|
if (pkg.type === "module") {
|
|
delete pkg.type;
|
|
fsSync.writeFileSync(outDirPkgJson, JSON.stringify(pkg, null, 2) + "\n");
|
|
console.log("[assembleStandalone] Removed 'type':'module' from standalone package.json (server.js is CJS)");
|
|
}
|
|
} catch (err) {
|
|
console.warn(`[assembleStandalone] Could not patch standalone package.json: ${err.message}`);
|
|
}
|
|
}
|
|
|
|
// 2. Copy <distDir>/static -> resolvedOutDir/.next/static
|
|
const staticSrc = path.join(distDir, "static");
|
|
const staticDest = path.join(resolvedOutDir, ".next", "static");
|
|
if (fsSync.existsSync(staticSrc)) {
|
|
fsSync.mkdirSync(path.dirname(staticDest), { recursive: true });
|
|
fsSync.cpSync(staticSrc, staticDest, { recursive: true, force: true });
|
|
}
|
|
|
|
// 3. Copy projectRoot/public -> resolvedOutDir/public
|
|
const publicSrc = path.join(projectRoot, "public");
|
|
const publicDest = path.join(resolvedOutDir, "public");
|
|
if (fsSync.existsSync(publicSrc)) {
|
|
fsSync.cpSync(publicSrc, publicDest, { recursive: true, force: true });
|
|
}
|
|
|
|
// 4. Optionally sanitize abs paths
|
|
if (sanitizePaths) {
|
|
const count = assemblePathSanitize(projectRoot, resolvedOutDir);
|
|
if (count > 0) {
|
|
console.log(`[assembleStandalone] Sanitised ${count} hardcoded path references`);
|
|
}
|
|
}
|
|
|
|
// 5. Optionally patch Turbopack hashed chunks
|
|
if (doPatchChunks) {
|
|
const { patchedFiles, patchedMatches } = patchTurbopackChunks(resolvedOutDir);
|
|
if (patchedMatches > 0) {
|
|
console.log(
|
|
`[assembleStandalone] Hash-strip: patched ${patchedMatches} hashed require() in ${patchedFiles} server chunk file(s)`
|
|
);
|
|
}
|
|
}
|
|
|
|
// 6. Optionally copy native assets + extra modules (synchronous)
|
|
if (copyNatives) {
|
|
const nativeAssets = [
|
|
{
|
|
label: "wreq-js native runtime",
|
|
src: path.join(projectRoot, "node_modules", "wreq-js", "rust"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "wreq-js", "rust"),
|
|
},
|
|
{
|
|
label: "better-sqlite3 native binary",
|
|
src: path.join(projectRoot, "node_modules", "better-sqlite3", "build"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "better-sqlite3", "build"),
|
|
},
|
|
];
|
|
|
|
for (const asset of nativeAssets) {
|
|
if (!fsSync.existsSync(asset.src)) continue;
|
|
fsSync.mkdirSync(path.dirname(asset.dest), { recursive: true });
|
|
fsSync.cpSync(asset.src, asset.dest, { recursive: true, force: true });
|
|
console.log(`[assembleStandalone] Copied native asset: ${asset.label}`);
|
|
}
|
|
|
|
const extraModules = [
|
|
{
|
|
label: "@swc/helpers",
|
|
src: path.join(projectRoot, "node_modules", "@swc", "helpers"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "@swc", "helpers"),
|
|
},
|
|
{
|
|
label: "pino-abstract-transport",
|
|
src: path.join(projectRoot, "node_modules", "pino-abstract-transport"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "pino-abstract-transport"),
|
|
},
|
|
{
|
|
label: "pino-pretty",
|
|
src: path.join(projectRoot, "node_modules", "pino-pretty"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "pino-pretty"),
|
|
},
|
|
{
|
|
label: "split2",
|
|
src: path.join(projectRoot, "node_modules", "split2"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "split2"),
|
|
},
|
|
{
|
|
label: "migrations",
|
|
src: path.join(projectRoot, "src", "lib", "db", "migrations"),
|
|
dest: path.join(resolvedOutDir, "migrations"),
|
|
},
|
|
{
|
|
label: "MITM server",
|
|
src: path.join(projectRoot, "src", "mitm", "server.cjs"),
|
|
dest: path.join(resolvedOutDir, "src", "mitm", "server.cjs"),
|
|
},
|
|
{
|
|
label: "run-standalone script",
|
|
src: path.join(projectRoot, "scripts", "dev", "run-standalone.mjs"),
|
|
dest: path.join(resolvedOutDir, "dev", "run-standalone.mjs"),
|
|
},
|
|
{
|
|
label: "WS/peer-stamp standalone server wrapper",
|
|
src: path.join(projectRoot, "scripts", "dev", "standalone-server-ws.mjs"),
|
|
dest: path.join(resolvedOutDir, "server-ws.mjs"),
|
|
},
|
|
{
|
|
label: "peer-stamp helper",
|
|
src: path.join(projectRoot, "scripts", "dev", "peer-stamp.mjs"),
|
|
dest: path.join(resolvedOutDir, "peer-stamp.mjs"),
|
|
},
|
|
{
|
|
label: "responses-ws-proxy",
|
|
src: path.join(projectRoot, "scripts", "dev", "responses-ws-proxy.mjs"),
|
|
dest: path.join(resolvedOutDir, "responses-ws-proxy.mjs"),
|
|
},
|
|
{
|
|
label: "runtime-env script",
|
|
src: path.join(projectRoot, "scripts", "build", "runtime-env.mjs"),
|
|
dest: path.join(resolvedOutDir, "build", "runtime-env.mjs"),
|
|
},
|
|
{
|
|
label: "bootstrap-env script",
|
|
src: path.join(projectRoot, "scripts", "build", "bootstrap-env.mjs"),
|
|
dest: path.join(resolvedOutDir, "build", "bootstrap-env.mjs"),
|
|
},
|
|
{
|
|
label: "healthcheck script",
|
|
src: path.join(projectRoot, "scripts", "dev", "healthcheck.mjs"),
|
|
dest: path.join(resolvedOutDir, "healthcheck.mjs"),
|
|
},
|
|
{
|
|
label: "public directory",
|
|
src: path.join(projectRoot, "public"),
|
|
dest: path.join(resolvedOutDir, "public"),
|
|
},
|
|
{
|
|
label: "playwright-core",
|
|
src: path.join(projectRoot, "node_modules", "playwright-core"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "playwright-core"),
|
|
},
|
|
{
|
|
label: "sqlite-vec wrapper",
|
|
src: path.join(projectRoot, "node_modules", "sqlite-vec"),
|
|
dest: path.join(resolvedOutDir, "node_modules", "sqlite-vec"),
|
|
},
|
|
...[
|
|
"sqlite-vec-linux-x64",
|
|
"sqlite-vec-linux-arm64",
|
|
"sqlite-vec-darwin-x64",
|
|
"sqlite-vec-darwin-arm64",
|
|
"sqlite-vec-windows-x64",
|
|
].map((pkg) => ({
|
|
label: pkg,
|
|
src: path.join(projectRoot, "node_modules", pkg),
|
|
dest: path.join(resolvedOutDir, "node_modules", pkg),
|
|
})),
|
|
];
|
|
|
|
for (const mod of extraModules) {
|
|
if (!fsSync.existsSync(mod.src)) continue;
|
|
fsSync.mkdirSync(path.dirname(mod.dest), { recursive: true });
|
|
fsSync.cpSync(mod.src, mod.dest, { recursive: true, force: true });
|
|
console.log(`[assembleStandalone] Synced module: ${mod.label}`);
|
|
}
|
|
}
|
|
}
|