diff --git a/packages/core/src/module-resolver.ts b/packages/core/src/module-resolver.ts index a4ec4e22b9..42280bb36d 100644 --- a/packages/core/src/module-resolver.ts +++ b/packages/core/src/module-resolver.ts @@ -160,6 +160,10 @@ export class Resolver { constructor(readonly options: Options) {} beforeResolve(request: R): R { + if (request.specifier === '#the-file-list') { + return request.virtualize('/the-file-list'); + } + if (request.specifier === '@embroider/macros') { // the macros package is always handled directly within babel (not // necessarily as a real resolvable package), so we should not mess with it. diff --git a/packages/core/src/node-resolve.ts b/packages/core/src/node-resolve.ts index 17e2919a24..86cb928ad0 100644 --- a/packages/core/src/node-resolve.ts +++ b/packages/core/src/node-resolve.ts @@ -56,7 +56,7 @@ export function nodeResolve( type: 'found', result: { type: 'virtual' as 'virtual', - content: virtualContent(request.specifier, resolver), + content: virtualContent(request.specifier, resolver).src, filename: request.specifier, }, }; diff --git a/packages/core/src/virtual-content.ts b/packages/core/src/virtual-content.ts index fc9f6a4cbc..cfa8b7745a 100644 --- a/packages/core/src/virtual-content.ts +++ b/packages/core/src/virtual-content.ts @@ -2,6 +2,7 @@ import { dirname, basename, resolve, posix, sep, join } from 'path'; import type { Resolver, AddonPackage, Package } from '.'; import { explicitRelative, extensionsPattern } from '.'; import { compile } from './js-handlebars'; +import { readdirSync } from 'fs-extra'; const externalESPrefix = '/@embroider/ext-es/'; const externalCJSPrefix = '/@embroider/ext-cjs/'; @@ -10,29 +11,40 @@ const externalCJSPrefix = '/@embroider/ext-cjs/'; // this produces the corresponding contents. It's a static, stateless function // because we recognize that that process that did resolution might not be the // same one that loads the content. -export function virtualContent(filename: string, resolver: Resolver): string { +export function virtualContent(filename: string, resolver: Resolver): { src: string; watches: string[] } { + if (filename === '/the-file-list') { + let dir = join(resolver.options.appRoot, 'app'); + let files = readdirSync(dir); + return { + src: `export default [ + ${files.map(f => `"${f}"`).join(',')} + ]`, + watches: [join(resolver.options.appRoot, 'app', 'app.js')], + }; + } + let cjsExtern = decodeVirtualExternalCJSModule(filename); if (cjsExtern) { - return renderCJSExternalShim(cjsExtern); + return { src: renderCJSExternalShim(cjsExtern), watches: [] }; } let extern = decodeVirtualExternalESModule(filename); if (extern) { - return renderESExternalShim(extern); + return { src: renderESExternalShim(extern), watches: [] }; } let match = decodeVirtualPairComponent(filename); if (match) { - return pairedComponentShim(match); + return { src: pairedComponentShim(match), watches: [] }; } let fb = decodeFastbootSwitch(filename); if (fb) { - return fastbootSwitchTemplate(fb); + return { src: fastbootSwitchTemplate(fb), watches: [] }; } let im = decodeImplicitModules(filename); if (im) { - return renderImplicitModules(im, resolver); + return { src: renderImplicitModules(im, resolver), watches: [] }; } throw new Error(`not an @embroider/core virtual file: ${filename}`); diff --git a/packages/vite/src/esbuild-resolver.ts b/packages/vite/src/esbuild-resolver.ts index 41018b2311..beef04b4cb 100644 --- a/packages/vite/src/esbuild-resolver.ts +++ b/packages/vite/src/esbuild-resolver.ts @@ -39,7 +39,7 @@ export function esBuildResolver(root = process.cwd()): EsBuildPlugin { }); build.onLoad({ namespace: 'embroider', filter: /./ }, ({ path }) => { - let src = virtualContent(path, resolverLoader.resolver); + let { src } = virtualContent(path, resolverLoader.resolver); if (!macrosConfig) { macrosConfig = readJSONSync( resolve(locateEmbroiderWorkingDir(root), 'rewritten-app', 'macros-config.json') @@ -82,7 +82,7 @@ export function esBuildResolver(root = process.cwd()): EsBuildPlugin { build.onLoad({ filter: /\.[jt]s$/ }, ({ path, namespace }) => { let src: string; if (namespace === 'embroider') { - src = virtualContent(path, resolverLoader.resolver); + src = virtualContent(path, resolverLoader.resolver).src; } else { src = readFileSync(path, 'utf8'); } diff --git a/packages/vite/src/resolver.ts b/packages/vite/src/resolver.ts index 89ff3f56ec..ddcd47557a 100644 --- a/packages/vite/src/resolver.ts +++ b/packages/vite/src/resolver.ts @@ -29,7 +29,11 @@ export function resolver(): Plugin { }, load(id) { if (id.startsWith(virtualPrefix)) { - return virtualContent(id.slice(virtualPrefix.length), resolverLoader.resolver); + let { src, watches } = virtualContent(id.slice(virtualPrefix.length), resolverLoader.resolver); + for (let watch of watches) { + this.addWatchFile(watch); + } + return src; } }, };