@@ -23,7 +23,7 @@ export function buildEsbuildOptions(
2323 options : NormalizedEsBuildExecutorOptions ,
2424 context : ExecutorContext
2525) : esbuild . BuildOptions {
26- const outExtension = getOutExtension ( format , options ) ;
26+ const outExtension = getOutExtension ( format , options , context ) ;
2727
2828 const esbuildOptions : esbuild . BuildOptions = {
2929 ...options . userDefinedBuildOptions ,
@@ -74,7 +74,7 @@ export function buildEsbuildOptions(
7474 esbuildOptions . entryPoints = entryPoints ;
7575 } else if ( options . platform === 'node' && format === 'cjs' ) {
7676 // When target platform Node and target format is CJS, then also transpile workspace libs used by the app.
77- // Provide a `require` override in the main entry file so workspace libs can be loaded when running the app.
77+ // Provide a loader override in the main entry file so workspace libs can be loaded when running the app.
7878 const paths = options . isTsSolutionSetup
7979 ? createPathsFromTsConfigReferences ( context )
8080 : getTsConfigCompilerPaths ( context ) ;
@@ -91,7 +91,13 @@ export function buildEsbuildOptions(
9191
9292 esbuildOptions . entryPoints = [
9393 // Write a main entry file that registers workspace libs and then calls the user-defined main.
94- writeTmpEntryWithRequireOverrides ( paths , outExtension , options , context ) ,
94+ writeTmpEntryWithRequireOverrides (
95+ paths ,
96+ outExtension ,
97+ options ,
98+ context ,
99+ format
100+ ) ,
95101 ...entryPointsFromProjects . map ( ( f ) => {
96102 /**
97103 * Maintain same directory structure as the workspace, so that other workspace libs may be used by the project.
@@ -255,12 +261,14 @@ function getProjectEntryPoint(projectPkgJson: any, projectPath: string) {
255261
256262export function getOutExtension (
257263 format : 'cjs' | 'esm' ,
258- options : Pick < NormalizedEsBuildExecutorOptions , 'userDefinedBuildOptions' >
264+ options : Pick < NormalizedEsBuildExecutorOptions , 'userDefinedBuildOptions' > ,
265+ context ?: ExecutorContext
259266) : '.cjs' | '.mjs' | '.js' {
260267 const userDefinedExt = options . userDefinedBuildOptions ?. outExtension ?. [ '.js' ] ;
261268 // Allow users to change the output extensions from default CJS and ESM extensions.
262269 // CJS -> .js
263270 // ESM -> .mjs
271+
264272 return userDefinedExt === '.js' && format === 'cjs'
265273 ? '.js'
266274 : userDefinedExt === '.mjs' && format === 'esm'
@@ -275,7 +283,7 @@ export function getOutfile(
275283 options : NormalizedEsBuildExecutorOptions ,
276284 context : ExecutorContext
277285) {
278- const ext = getOutExtension ( format , options ) ;
286+ const ext = getOutExtension ( format , options , context ) ;
279287 const candidate = joinPathFragments (
280288 context . target . options . outputPath ,
281289 options . outputFileName
@@ -288,7 +296,8 @@ function writeTmpEntryWithRequireOverrides(
288296 paths : Record < string , string [ ] > ,
289297 outExtension : '.cjs' | '.js' | '.mjs' ,
290298 options : NormalizedEsBuildExecutorOptions ,
291- context : ExecutorContext
299+ context : ExecutorContext ,
300+ format : 'cjs' | 'esm' = 'cjs'
292301) : { in : string ; out : string } {
293302 const project = context . projectGraph ?. nodes [ context . projectName ] ;
294303 // Write a temp main entry source that registers workspace libs.
@@ -309,7 +318,7 @@ function writeTmpEntryWithRequireOverrides(
309318
310319 writeFileSync (
311320 mainWithRequireOverridesInPath ,
312- getRegisterFileContent ( project , paths , mainFile , outExtension )
321+ getRegisterFileContent ( project , paths , mainFile , outExtension , format )
313322 ) ;
314323
315324 let mainWithRequireOverridesOutPath : string ;
@@ -335,7 +344,8 @@ export function getRegisterFileContent(
335344 project : ProjectGraphProjectNode ,
336345 paths : Record < string , string [ ] > ,
337346 mainFile : string ,
338- outExtension = '.js'
347+ outExtension = '.js' ,
348+ format : 'cjs' | 'esm' = 'cjs'
339349) {
340350 mainFile = normalizePath ( mainFile ) ;
341351
@@ -364,7 +374,58 @@ export function getRegisterFileContent(
364374 return acc ;
365375 } , [ ] ) ;
366376
367- return `
377+ if ( format === 'esm' ) {
378+ return `
379+ /**
380+ * IMPORTANT: Do not modify this file.
381+ * This file allows the app to run without bundling in workspace libraries.
382+ * Must be contained in the ".nx" folder inside the output path.
383+ */
384+ import { pathToFileURL } from 'node:url';
385+ import { dirname, join } from 'node:path';
386+ import { fileURLToPath } from 'node:url';
387+ import { existsSync } from 'node:fs';
388+
389+ const __filename = fileURLToPath(import.meta.url);
390+ const __dirname = dirname(__filename);
391+ const distPath = __dirname;
392+ const manifest = ${ JSON . stringify ( manifest ) } ;
393+
394+ // Resolver for workspace libs
395+ const originalResolve = import.meta.resolve;
396+ if (originalResolve) {
397+ import.meta.resolve = function(specifier, parent) {
398+ const matchingEntry = manifest.find(
399+ (entry) => specifier === entry.module || specifier.startsWith(entry.module + '/')
400+ );
401+
402+ if (matchingEntry) {
403+ if (matchingEntry.exactMatch) {
404+ const candidate = join(distPath, matchingEntry.exactMatch);
405+ if (existsSync(candidate)) {
406+ return pathToFileURL(candidate).href;
407+ }
408+ } else {
409+ const re = new RegExp(matchingEntry.module.replace(/\\*$/, "(?<rest>.*)"));
410+ const match = specifier.match(re);
411+ if (match?.groups) {
412+ const candidate = join(distPath, matchingEntry.pattern.replace("*", ""), match.groups.rest);
413+ if (existsSync(candidate)) {
414+ return pathToFileURL(candidate).href;
415+ }
416+ }
417+ }
418+ }
419+
420+ return originalResolve.call(this, specifier, parent);
421+ };
422+ }
423+
424+ // Call the user-defined main.
425+ await import(pathToFileURL(join(distPath, '${ mainFile } ')).href);
426+ ` ;
427+ } else {
428+ return `
368429/**
369430 * IMPORTANT: Do not modify this file.
370431 * This file allows the app to run without bundling in workspace libraries.
@@ -420,6 +481,7 @@ function isFile(s) {
420481// Call the user-defined main.
421482module.exports = require('${ mainFile } ');
422483` ;
484+ }
423485}
424486
425487function getPrefixLength ( pattern : string ) : number {
@@ -438,8 +500,13 @@ function getPrefixLength(pattern: string): number {
438500function getTsConfigCompilerPaths ( context : ExecutorContext ) : {
439501 [ key : string ] : string [ ] ;
440502} {
503+ const rootTsConfigPath = getRootTsConfigPath ( context ) ;
504+ if ( ! rootTsConfigPath ) {
505+ return { } ;
506+ }
507+
441508 const tsconfigPaths = require ( 'tsconfig-paths' ) ;
442- const tsConfigResult = tsconfigPaths . loadConfig ( getRootTsConfigPath ( context ) ) ;
509+ const tsConfigResult = tsconfigPaths . loadConfig ( rootTsConfigPath ) ;
443510 if ( tsConfigResult . resultType !== 'success' ) {
444511 throw new Error ( 'Cannot load tsconfig file' ) ;
445512 }
@@ -454,7 +521,5 @@ function getRootTsConfigPath(context: ExecutorContext): string | null {
454521 }
455522 }
456523
457- throw new Error (
458- 'Could not find a root tsconfig.json or tsconfig.base.json file.'
459- ) ;
524+ return null ;
460525}
0 commit comments