96 lines
4.2 KiB
JavaScript
96 lines
4.2 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
// Makes the two ESM-only server dependencies loadable by the embedded Node 18
|
||
|
|
// (nodejs-mobile) runtime, which cannot require() ESM. Run AFTER
|
||
|
|
// `npm install` inside nodejs-assets/nodejs-project (re-run after any install).
|
||
|
|
//
|
||
|
|
// • kysely (used: routes/categories.cts -> db/kysely.cts) — bundled to a
|
||
|
|
// self-contained CommonJS file; its package entry is repointed at it.
|
||
|
|
// • openid-client (UNUSED in single-user local mode, but eagerly require()'d
|
||
|
|
// at boot via auth.cts/authOidc.cts -> oidcService.cts) — replaced with a
|
||
|
|
// CommonJS stub so boot doesn't crash. Any actual use throws.
|
||
|
|
//
|
||
|
|
// Both are loaded on the web app (Node 22, native ESM); this only affects the
|
||
|
|
// on-device copy.
|
||
|
|
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
const esbuild = require('esbuild'); // from the mobile project's own node_modules
|
||
|
|
|
||
|
|
const PROJECT = path.join(__dirname, '..', 'nodejs-assets', 'nodejs-project');
|
||
|
|
const NM = path.join(PROJECT, 'node_modules');
|
||
|
|
|
||
|
|
function fail(msg) {
|
||
|
|
console.error('prepare-local-mode-deps: ' + msg);
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── kysely → CommonJS ────────────────────────────────────────────────────────
|
||
|
|
(function bundleKysely() {
|
||
|
|
const dir = path.join(NM, 'kysely');
|
||
|
|
if (!fs.existsSync(dir)) fail('kysely not installed — run `npm install` in nodejs-project first.');
|
||
|
|
|
||
|
|
const entry = path.join(dir, 'dist', 'index.js'); // ESM entry
|
||
|
|
const outfile = path.join(dir, 'dist', 'index.cjs');
|
||
|
|
esbuild.buildSync({
|
||
|
|
entryPoints: [entry],
|
||
|
|
bundle: true,
|
||
|
|
format: 'cjs',
|
||
|
|
platform: 'node',
|
||
|
|
target: 'node18',
|
||
|
|
outfile,
|
||
|
|
logLevel: 'silent',
|
||
|
|
});
|
||
|
|
|
||
|
|
const pkgPath = path.join(dir, 'package.json');
|
||
|
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
||
|
|
pkg.main = './dist/index.cjs';
|
||
|
|
pkg.exports = {
|
||
|
|
'.': { require: './dist/index.cjs', import: './dist/index.js', default: './dist/index.cjs' },
|
||
|
|
'./package.json': './package.json',
|
||
|
|
};
|
||
|
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
||
|
|
console.log(' kysely -> bundled to CommonJS (dist/index.cjs)');
|
||
|
|
})();
|
||
|
|
|
||
|
|
// ── openid-client → CommonJS stub ────────────────────────────────────────────
|
||
|
|
(function stubOpenidClient() {
|
||
|
|
const dir = path.join(NM, 'openid-client');
|
||
|
|
fs.mkdirSync(dir, { recursive: true });
|
||
|
|
fs.writeFileSync(
|
||
|
|
path.join(dir, 'package.json'),
|
||
|
|
JSON.stringify({ name: 'openid-client', version: '0.0.0-local-stub', main: 'index.js' }, null, 2) + '\n',
|
||
|
|
);
|
||
|
|
fs.writeFileSync(
|
||
|
|
path.join(dir, 'index.js'),
|
||
|
|
"'use strict';\n" +
|
||
|
|
'// Local-mode stub. OIDC/SSO is not available when running on-device.\n' +
|
||
|
|
'function notSupported() { throw new Error("OIDC is not available in local mode"); }\n' +
|
||
|
|
'module.exports = new Proxy({}, { get: function () { return notSupported; } });\n',
|
||
|
|
);
|
||
|
|
console.log(' openid-client -> CommonJS stub (OIDC disabled in local mode)');
|
||
|
|
})();
|
||
|
|
|
||
|
|
// ── ICU-less \p{} regex compatibility ────────────────────────────────────────
|
||
|
|
// nodejs-mobile's Node 18 ships WITHOUT ICU, so V8 cannot resolve Unicode
|
||
|
|
// property escapes (\p{...}) — any regex using them throws "Invalid property
|
||
|
|
// name" at compile time. path-to-regexp (express 5's router) uses
|
||
|
|
// \p{ID_Start}/\p{ID_Continue} at module load to validate route-param names,
|
||
|
|
// which crashes server boot. Rewrite to ASCII-safe classes; every route param
|
||
|
|
// in this app is ASCII (:id, :userId, …). (minimatch also contains \p{} but only
|
||
|
|
// as lazy POSIX-class strings that this app's globs never trigger — left as-is.)
|
||
|
|
(function patchPathToRegexp() {
|
||
|
|
const f = path.join(NM, 'path-to-regexp', 'dist', 'index.js');
|
||
|
|
if (!fs.existsSync(f)) return;
|
||
|
|
let s = fs.readFileSync(f, 'utf8');
|
||
|
|
const before = s;
|
||
|
|
s = s.replace(/\\p\{ID_Start\}/g, 'a-zA-Z').replace(/\\p\{ID_Continue\}/g, 'a-zA-Z0-9');
|
||
|
|
if (s !== before) {
|
||
|
|
fs.writeFileSync(f, s);
|
||
|
|
console.log(' path-to-regexp -> ASCII identifier regex (ICU-less \\p{} fix)');
|
||
|
|
}
|
||
|
|
})();
|
||
|
|
|
||
|
|
console.log('prepare-local-mode-deps: done.');
|