diff --git a/src/build-actions.js b/src/build-actions.js index e90933d..cbfbf3d 100644 --- a/src/build-actions.js +++ b/src/build-actions.js @@ -242,6 +242,17 @@ const prepareToBuildAction = async (action, root, dist) => { return resolve(stats) }) }) + + // Fix for IOEXT-1726: webpack emits CommonJS (libraryTarget: 'commonjs2'), + // but Node walks up the directory tree to find the closest package.json + // when deciding the module type for the bundled index.js. If the user's + // project sets "type": "module" (ESM), Node parses the CJS bundle as ESM + // and aio-cli-plugin-app-dev's require()-based loader fails with + // "action not found, or does not export main". Drop a sibling package.json + // that pins the bundle output to CommonJS regardless of the project type. + fs.writeJsonSync(path.join(tempBuildDir, 'package.json'), { + type: 'commonjs' + }) } return { diff --git a/test/build.actions.test.js b/test/build.actions.test.js index 44898f5..7c25d18 100644 --- a/test/build.actions.test.js +++ b/test/build.actions.test.js @@ -278,6 +278,30 @@ describe('build by bundling js action file with webpack', () => { path.normalize('/dist/actions/sample-app-1.0.0/action.zip')) }) + test('should drop a sibling package.json with type: commonjs in the webpack temp dir (IOEXT-1726)', async () => { + await buildActions(config) + + const tempDir = path.normalize('/dist/actions/sample-app-1.0.0/action-temp') + + // confirm webpack was asked to emit the bundle to the expected temp dir + expect(webpack).toHaveBeenCalledWith(expect.arrayContaining([ + expect.objectContaining({ + output: expect.objectContaining({ + path: tempDir, + filename: 'index.js' + }) + }) + ])) + + // the sibling package.json must scope the bundle as CommonJS so that Node + // does not treat it as ESM when the user's project package.json declares + // "type": "module". + const siblingPath = path.join(tempDir, 'package.json').split(path.sep).join('/') + const siblingRaw = global.fakeFileSystem.files()[siblingPath] + expect(siblingRaw).toBeDefined() + expect(JSON.parse(siblingRaw)).toEqual({ type: 'commonjs' }) + }) + test('should bundle a single action file using webpack and zip it with includes', async () => { global.fakeFileSystem.reset() global.fakeFileSystem.addJson({