diff --git a/packages/boot/src/__tests__/fixtures/cjs.artifact.cjs b/packages/boot/src/__tests__/fixtures/cjs.artifact.cjs new file mode 100644 index 000000000000..3dccd4045522 --- /dev/null +++ b/packages/boot/src/__tests__/fixtures/cjs.artifact.cjs @@ -0,0 +1 @@ +export class DummyCJSClass {} diff --git a/packages/boot/src/__tests__/fixtures/esm.artifact.mjs b/packages/boot/src/__tests__/fixtures/esm.artifact.mjs new file mode 100644 index 000000000000..8660cab0d69e --- /dev/null +++ b/packages/boot/src/__tests__/fixtures/esm.artifact.mjs @@ -0,0 +1 @@ +export class DummyESMClass {} diff --git a/packages/boot/src/__tests__/unit/booters/booter-utils.unit.ts b/packages/boot/src/__tests__/unit/booters/booter-utils.unit.ts index 769ebe638e81..554c499c85bc 100644 --- a/packages/boot/src/__tests__/unit/booters/booter-utils.unit.ts +++ b/packages/boot/src/__tests__/unit/booters/booter-utils.unit.ts @@ -66,7 +66,37 @@ describe('booter-utils unit tests', () => { const files = [resolve(sandbox.path, 'multiple.artifact.js')]; const NUM_CLASSES = 2; // Number of classes in above file - const classes = loadClassesFromFiles(files, sandbox.path); + const classes = await loadClassesFromFiles(files, sandbox.path); + expect(classes).to.have.lengthOf(NUM_CLASSES); + expect(classes[0]).to.be.a.Function(); + expect(classes[1]).to.be.a.Function(); + }); + + it('loads classes from CJS files', async () => { + const artifactFilename = 'multiple.artifact.cjs'; + await sandbox.copyFile( + resolve(__dirname, '../../fixtures/multiple.artifact.cjs'), + ); + const NUM_CLASSES = 2; + const classes = await loadClassesFromFiles( + [resolve(sandbox.path, artifactFilename)], + sandbox.path, + ); + expect(classes).to.have.lengthOf(NUM_CLASSES); + expect(classes[0]).to.be.a.Function(); + expect(classes[1]).to.be.a.Function(); + }); + + it('loads classes from ESM files', async () => { + const artifactFilename = 'multiple.artifact.mjs'; + await sandbox.copyFile( + resolve(__dirname, '../../fixtures/multiple.artifact.mjs'), + ); + const NUM_CLASSES = 2; + const classes = await loadClassesFromFiles( + [resolve(sandbox.path, artifactFilename)], + sandbox.path, + ); expect(classes).to.have.lengthOf(NUM_CLASSES); expect(classes[0]).to.be.a.Function(); expect(classes[1]).to.be.a.Function(); @@ -78,16 +108,16 @@ describe('booter-utils unit tests', () => { ); const files = [resolve(sandbox.path, 'empty.artifact.js')]; - const classes = loadClassesFromFiles(files, sandbox.path); + const classes = await loadClassesFromFiles(files, sandbox.path); expect(classes).to.be.an.Array(); expect(classes).to.be.empty(); }); it('throws an error given a non-existent file', async () => { const files = [resolve(sandbox.path, 'fake.artifact.js')]; - expect(() => loadClassesFromFiles(files, sandbox.path)).to.throw( - /Cannot find module/, - ); + await expect( + loadClassesFromFiles(files, sandbox.path), + ).to.be.rejectedWith(/Cannot find module/); }); }); }); diff --git a/packages/boot/src/booters/base-artifact.booter.ts b/packages/boot/src/booters/base-artifact.booter.ts index 50150a50bbd0..5653dcdf31fd 100644 --- a/packages/boot/src/booters/base-artifact.booter.ts +++ b/packages/boot/src/booters/base-artifact.booter.ts @@ -137,6 +137,9 @@ export class BaseArtifactBooter implements Booter { * and then process the artifact classes as appropriate. */ async load() { - this.classes = loadClassesFromFiles(this.discovered, this.projectRoot); + this.classes = await loadClassesFromFiles( + this.discovered, + this.projectRoot, + ); } } diff --git a/packages/boot/src/booters/booter-utils.ts b/packages/boot/src/booters/booter-utils.ts index 52fa5f58bff2..a4bd6d3d2fc8 100644 --- a/packages/boot/src/booters/booter-utils.ts +++ b/packages/boot/src/booters/booter-utils.ts @@ -46,14 +46,14 @@ export function isClass(target: any): target is Constructor { * @param projectRootDir - The project root directory * @returns An array of Class constructors from a file */ -export function loadClassesFromFiles( +export async function loadClassesFromFiles( files: string[], projectRootDir: string, -): Constructor<{}>[] { +): Promise[]> { const classes: Constructor<{}>[] = []; for (const file of files) { debug('Loading artifact file %j', path.relative(projectRootDir, file)); - const moduleObj = require(file); + const moduleObj = await import(file); for (const k in moduleObj) { const exported = moduleObj[k]; if (isClass(exported)) {