// Node-only source loading implementation; the public surface lives in index.ts. // @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off nodeBuiltinImport:off strictBooleanExpressions:off import crypto from 'node:crypto'; import fs from 'node:fs'; import { builtinModules, createRequire } from 'node:module'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { build, type Loader, type OnLoadArgs, type Plugin, transform, } from 'esbuild'; import { type ServerGlobalVarsOptions, serializeServerGlobalVars, } from '../server-global-vars'; const NODE_TARGET = 'node26.10'; const SOURCE_LOADERS = new Map([ ['.js', 'js'], ['.jsx', 'jsx'], ['.mjs', 'js'], ['.cjs', 'js'], ['.ts', 'ts'], ['.tsx', 'tsx'], ['.mts', 'ts'], ['.cts', 'ts'], ]); export type EffectSourceLoaderOptions = { resourcePath: string; appDir?: string; /** `source.globalVars`, replaced in the loaded source graph. */ globalVars?: ServerGlobalVarsOptions; onDependency?: (dependency: string) => void; }; function sourceLoader(args: OnLoadArgs): Loader | undefined { return SOURCE_LOADERS.get(path.extname(args.path).toLowerCase()); } function preserveSourceModuleSemantics(): Plugin { return { name: 'modern-js-effect-source-semantics', setup(buildApi) { buildApi.onLoad( { filter: /\.[cm]?[jt]sx?$/, namespace: 'file' }, async args => { const loader = sourceLoader(args); if (!loader) { return undefined; } const source = await fs.promises.readFile(args.path, 'utf8'); const canonicalSourcePath = await fs.promises.realpath(args.path); const compiled = await transform(source, { define: { __dirname: JSON.stringify(path.dirname(canonicalSourcePath)), __filename: JSON.stringify(canonicalSourcePath), 'import.meta.url': JSON.stringify( pathToFileURL(canonicalSourcePath).href, ), }, jsx: 'automatic', loader, sourcefile: args.path, target: NODE_TARGET, }); return { contents: compiled.code, loader: 'js', resolveDir: path.dirname(args.path), }; }, ); }, }; } const nodeBuiltins = new Set([ ...builtinModules, ...builtinModules.map(name => `node:${name}`), ]); const dependencyResolutionMarker = 'modern-js-effect-dependency-resolution'; // The BFF server runs lambdas inside these packages' Effect context storage. // A bundled copy would own a second storage that the server never enters. const BFF_RUNTIME_PACKAGE = /^@modern-js\/(?:bff-effect|plugin-bff)(?:\/|$)/; async function isEsmOnlyFile(filename: string) { const extension = path.extname(filename).toLowerCase(); if (extension === '.mjs' || extension === '.mts') { return true; } if (extension === '.cjs' || extension === '.cts') { return false; } let directory = path.dirname(filename); while (true) { const packagePath = path.join(directory, 'package.json'); try { const packageJson = JSON.parse( await fs.promises.readFile(packagePath, 'utf8'), ) as { type?: unknown }; return packageJson.type === 'module'; } catch (error) { if ( !error || typeof error !== 'object' || !('code' in error) || error.code !== 'ENOENT' ) { throw error; } } const parent = path.dirname(directory); if (parent === directory) { return false; } directory = parent; } } function isBareSpecifier(specifier: string) { return ( !specifier.startsWith('.') && !specifier.startsWith('/') && !path.isAbsolute(specifier) ); } /** * Keep installed executable dependencies external to preserve runtime identity. * Source requiring compilation is bundled even when pnpm injects a workspace * package into node_modules: Node does not strip types inside that directory. */ function externalizeInstalledDependencies(options: { runtimeResolveDir: string; }): Plugin { return { name: 'modern-js-effect-installed-dependencies', setup(buildApi) { buildApi.onResolve({ filter: /.*/ }, async args => { if (BFF_RUNTIME_PACKAGE.test(args.path)) { return { external: true, path: args.path }; } if ( !isBareSpecifier(args.path) || nodeBuiltins.has(args.path) || args.pluginData?.[dependencyResolutionMarker] === true ) { return nodeBuiltins.has(args.path) ? { external: true, path: args.path } : undefined; } const resolution = await buildApi.resolve(args.path, { importer: args.importer, kind: args.kind, namespace: args.namespace, pluginData: { ...args.pluginData, [dependencyResolutionMarker]: true, }, resolveDir: args.resolveDir, }); if (resolution.errors.length > 0) { return { external: true, path: args.path }; } if (resolution.external || !resolution.path) { return { external: true, path: args.path }; } const realPath = await fs.promises .realpath(resolution.path) .catch(() => resolution.path); const loader = SOURCE_LOADERS.get(path.extname(realPath).toLowerCase()); if ( realPath.includes(`${path.sep}node_modules${path.sep}`) && loader !== 'ts' && loader !== 'tsx' && loader !== 'jsx' ) { const runtimeResolution = await buildApi.resolve(args.path, { importer: '', kind: args.kind, namespace: 'file', pluginData: { [dependencyResolutionMarker]: true, }, resolveDir: options.runtimeResolveDir, }); if (runtimeResolution.errors.length === 0 && runtimeResolution.path) { // Node 26 loads installed ESM from CommonJS natively. Rebundling // it here would split dependency identity from the BFF runtime. return { external: true, path: args.path }; } } return { namespace: resolution.namespace, path: resolution.path, pluginData: resolution.pluginData, sideEffects: resolution.sideEffects, suffix: resolution.suffix, warnings: resolution.warnings, }; }); }, }; } export async function bundleEffectEntryForNode(options: { appDir: string; entryPath: string; format: 'cjs' | 'esm'; }) { await build({ absWorkingDir: options.appDir, allowOverwrite: true, bundle: true, entryPoints: [options.entryPath], format: options.format, logLevel: 'silent', outfile: options.entryPath, platform: 'node', plugins: [ externalizeInstalledDependencies({ runtimeResolveDir: options.appDir, }), preserveSourceModuleSemantics(), ], target: NODE_TARGET, }); } function isWatchableInput(filename: string) { return ( !filename.includes(`${path.sep}node_modules${path.sep}`) && (SOURCE_LOADERS.has(path.extname(filename).toLowerCase()) || path.extname(filename).toLowerCase() === '.json') ); } function normalizeImportedModule(module: unknown): unknown { if (!module || typeof module !== 'object') { return module; } const namespace = module as Record; const commonJsModule = namespace.default; if ( Object.keys(namespace).length === 1 && commonJsModule !== null && typeof commonJsModule === 'object' && (commonJsModule as Record).__esModule === true ) { return commonJsModule; } return module; } function hasErrorCode(error: unknown, code: string): boolean { return ( error !== null && typeof error === 'object' && 'code' in error && error.code === code ); } async function publishImmutableOutput(options: { cacheDirectory: string; contents: Uint8Array; outputName: string; }): Promise { const revision = crypto .createHash('sha256') .update(options.contents) .digest('hex'); const outputPath = path.join( options.cacheDirectory, `${options.outputName}-${revision}.mjs`, ); const temporaryPath = path.join( options.cacheDirectory, `.${options.outputName}-${crypto.randomUUID()}.tmp`, ); try { await fs.promises.writeFile(temporaryPath, options.contents, { flag: 'wx', }); try { await fs.promises.link(temporaryPath, outputPath); } catch (error) { if (!hasErrorCode(error, 'EEXIST')) { throw error; } const publishedContents = await fs.promises.readFile(outputPath); if (!publishedContents.equals(Buffer.from(options.contents))) { throw new Error( `Effect source cache entry does not match its content address: ${outputPath}`, ); } } } finally { await fs.promises.rm(temporaryPath, { force: true }); } return outputPath; } /** Loads a production artifact without changing its native Node boundary. */ export async function loadEffectBuiltModule( resourcePath: string, ): Promise { const canonicalPath = await fs.promises.realpath(path.resolve(resourcePath)); if (!(await isEsmOnlyFile(canonicalPath))) { return createRequire(canonicalPath)(canonicalPath); } return normalizeImportedModule( await import(pathToFileURL(canonicalPath).href), ); } /** * Loads an Effect source entry as native ESM while reporting its complete * local source graph to the framework watcher. */ export async function loadEffectSourceModule( options: EffectSourceLoaderOptions, ): Promise { const resourcePath = path.resolve(options.resourcePath); const appDir = path.resolve(options.appDir ?? path.dirname(resourcePath)); const tsconfigPath = path.join(appDir, 'tsconfig.json'); const cacheDirectory = path.join( appDir, 'node_modules', '.cache', 'modern-js', 'effect-source-loader', ); const outputName = crypto .createHash('sha256') .update(resourcePath) .digest('hex') .slice(0, 24); await fs.promises.mkdir(cacheDirectory, { recursive: true }); const result = await build({ absWorkingDir: appDir, banner: { js: `import { createRequire as __modernCreateEffectRequire } from 'node:module'; const require = __modernCreateEffectRequire(${JSON.stringify(pathToFileURL(resourcePath).href)});`, }, bundle: true, define: serializeServerGlobalVars(options.globalVars), entryPoints: [resourcePath], format: 'esm', jsx: 'automatic', logLevel: 'silent', metafile: true, outfile: path.join(cacheDirectory, `${outputName}.mjs`), platform: 'node', plugins: [ externalizeInstalledDependencies({ runtimeResolveDir: appDir, }), preserveSourceModuleSemantics(), ], sourcemap: 'inline', target: NODE_TARGET, tsconfig: fs.existsSync(tsconfigPath) ? tsconfigPath : undefined, write: false, }); for (const input of Object.keys(result.metafile.inputs)) { const dependency = path.isAbsolute(input) ? path.normalize(input) : path.resolve(appDir, input); if (isWatchableInput(dependency)) { options.onDependency?.(dependency); } } if (result.outputFiles.length !== 1) { throw new Error( `Expected one Effect source output, received ${result.outputFiles.length}`, ); } const outputPath = await publishImmutableOutput({ cacheDirectory, contents: result.outputFiles[0].contents, outputName, }); return normalizeImportedModule(await import(pathToFileURL(outputPath).href)); }