6ecb2c366f
Publish snapshot / snapshot (push) Successful in 1m2s
[fix] default parameter run records parameters in session for replay[fix] remove default parameters for several cubes
63 lines
2.3 KiB
JavaScript
63 lines
2.3 KiB
JavaScript
/**
|
|
* A module resolve hook that lets a hand-written cube import the packages nopy
|
|
* itself already has.
|
|
*
|
|
* A manifest is loaded with `import(manifestPath)`, so its imports resolve from
|
|
* its own directory. A cube sitting in an arbitrary `cubeDirs` entry — no
|
|
* package.json above it, no node_modules beside it — therefore cannot import
|
|
* `@bitsquare/nopy-cube` or `zod` at all, and the run dies on
|
|
* ERR_MODULE_NOT_FOUND before a single deploy is built.
|
|
*
|
|
* A published cube bundle never reaches this: it declares its own dependencies
|
|
* and Node resolves them normally. This is for the local tree.
|
|
*
|
|
* Plain `.mjs` rather than TypeScript because the hook runs on its own thread,
|
|
* loaded by Node directly from `dist` — there is no compile step in that path.
|
|
*
|
|
* @module cubes/resolve-hook
|
|
*/
|
|
|
|
import { createRequire } from 'node:module';
|
|
import { pathToFileURL } from 'node:url';
|
|
|
|
/**
|
|
* The specifiers worth rescuing: what a manifest legitimately needs and cannot
|
|
* be expected to install for itself. Anything else stays a hard failure — a
|
|
* cube that wants a library should depend on it.
|
|
*/
|
|
const FALLBACK_ROOTS = ['@bitsquare/nopy-cube', '@bitsquare/nopy', 'zod'];
|
|
|
|
/** @type {NodeRequire | undefined} */
|
|
let fallbackRequire;
|
|
|
|
/**
|
|
* @param {{ from: string }} data - a URL inside the running CLI's own package,
|
|
* which is where the fallback resolution starts from.
|
|
*/
|
|
export function initialize(data) {
|
|
fallbackRequire = createRequire(data.from);
|
|
}
|
|
|
|
/** True for `zod` and for subpaths like `zod/v4` or `@bitsquare/nopy/package.json`. */
|
|
function isCovered(specifier) {
|
|
return FALLBACK_ROOTS.some((root) => specifier === root || specifier.startsWith(`${root}/`));
|
|
}
|
|
|
|
export async function resolve(specifier, context, next) {
|
|
try {
|
|
// Normal resolution first, always. A consumer that has its own copy
|
|
// installed keeps using it, so the hook can never introduce version skew —
|
|
// it only fills in for a lookup that was going to fail.
|
|
return await next(specifier, context);
|
|
} catch (error) {
|
|
if (!fallbackRequire || !isCovered(specifier)) throw error;
|
|
try {
|
|
return { url: pathToFileURL(fallbackRequire.resolve(specifier)).href, shortCircuit: true };
|
|
} catch {
|
|
// The CLI cannot see it either. Report the original failure, which names
|
|
// the importer rather than the CLI.
|
|
throw error;
|
|
}
|
|
}
|
|
}
|