@checkdigit/typescript-config 3.3.0-PR.30-1eae → 3.3.0-PR.30-dfde

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/builder.mjs CHANGED
@@ -39,7 +39,14 @@ function setup(type2) {
39
39
  });
40
40
  };
41
41
  }
42
- async function builder_default({ type: type2, entryPoint, inDir: inDir2, outDir: outDir2, outFile }) {
42
+ async function builder_default({
43
+ type: type2,
44
+ entryPoint,
45
+ inDir: inDir2,
46
+ outDir: outDir2,
47
+ outFile,
48
+ external = []
49
+ }) {
43
50
  const messages2 = [];
44
51
  assert.ok(
45
52
  entryPoint === void 0 && outFile === void 0 || entryPoint !== void 0 && outFile !== void 0,
@@ -47,14 +54,37 @@ async function builder_default({ type: type2, entryPoint, inDir: inDir2, outDir:
47
54
  );
48
55
  const allSourceFiles = await getFiles(inDir2);
49
56
  const productionSourceFiles = entryPoint === void 0 ? allSourceFiles.filter((file) => file.endsWith(".ts")) : [path.join(inDir2, entryPoint)];
50
- const configFile = typescript.readConfigFile("./tsconfig.json", (name) => typescript.sys.readFile(name));
51
- const compilerOptions = typescript.parseJsonConfigFileContent(configFile.config, typescript.sys, "./");
52
57
  const program = typescript.createProgram(productionSourceFiles, {
53
- ...compilerOptions.options,
58
+ module: typescript.ModuleKind.ESNext,
59
+ moduleResolution: typescript.ModuleResolutionKind.Bundler,
60
+ target: typescript.ScriptTarget.ESNext,
61
+ declaration: true,
54
62
  noEmitOnError: true,
55
63
  emitDeclarationOnly: true,
56
64
  rootDir: inDir2,
57
- outDir: outDir2
65
+ outDir: outDir2,
66
+ noLib: false,
67
+ skipLibCheck: true,
68
+ strict: true,
69
+ preserveConstEnums: true,
70
+ noImplicitReturns: true,
71
+ noUnusedLocals: true,
72
+ noUnusedParameters: true,
73
+ alwaysStrict: true,
74
+ verbatimModuleSyntax: false,
75
+ noFallthroughCasesInSwitch: true,
76
+ forceConsistentCasingInFileNames: true,
77
+ emitDecoratorMetadata: true,
78
+ experimentalDecorators: true,
79
+ resolveJsonModule: true,
80
+ esModuleInterop: true,
81
+ noUncheckedIndexedAccess: true,
82
+ noPropertyAccessFromIndexSignature: true,
83
+ allowUnusedLabels: false,
84
+ allowUnreachableCode: false,
85
+ noImplicitOverride: true,
86
+ useUnknownInCatchVariables: true,
87
+ exactOptionalPropertyTypes: true
58
88
  });
59
89
  const emitResult = program.emit();
60
90
  const allDiagnostics = typescript.sortAndDeduplicateDiagnostics([
@@ -90,7 +120,7 @@ async function builder_default({ type: type2, entryPoint, inDir: inDir2, outDir:
90
120
  setup: setup(type2)
91
121
  }
92
122
  ]
93
- } : { outfile: path.join(outDir2, outFile) }
123
+ } : { outfile: path.join(outDir2, outFile), external }
94
124
  });
95
125
  messages2.push(...buildResult.errors.map((error) => `esbuild error: ${error.text}`));
96
126
  messages2.push(...buildResult.warnings.map((warning) => `esbuild warning: ${warning.text}`));
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@checkdigit/typescript-config","version":"3.3.0-PR.30-1eae","description":"Check Digit standard Typescript configuration","prettier":"@checkdigit/prettier-config","engines":{"node":">=16"},"bin":{"builder":"./bin/builder.mjs"},"peerDependencies":{"@types/node":">=16","esbuild":"0.17.18","typescript":">=5.0.4 <5.1"},"repository":{"type":"git","url":"git+https://github.com/checkdigit/typescript-config.git"},"author":"Check Digit, LLC","license":"MIT","bugs":{"url":"https://github.com/checkdigit/typescript-config/issues"},"homepage":"https://github.com/checkdigit/typescript-config#readme","scripts":{"preversion":"npm test","postversion":"git push && git push --tags","prepare":"npm run build-builder","lint:fix":"eslint -f unix --ext .ts,.mts src --fix","lint":"eslint -f unix --ext .ts,.mts src","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style","build-builder":"esbuild src/builder/index.mts --bundle --platform=node --format=esm --external:typescript --external:esbuild --outfile=build-builder/builder.mjs && mkdir -p bin && { echo '#!/usr/bin/env node'; cat build-builder/builder.mjs; } > bin/builder.mjs && chmod +x bin/builder.mjs","build-tsc-cjs":"rimraf build-tsc-cjs && tsc --outDir build-tsc-cjs","build-esbuild-cjs":"rimraf build-esbuild-cjs && esbuild ./src/*.ts ./src/*/*.ts --platform=node --bundle --format=cjs --sourcemap=inline --sources-content=false --outdir=build-esbuild-cjs","build-esbuild-cjs-bundle":"rimraf build-esbuild-cjs-bundle && esbuild src/test/index.test.ts --bundle --platform=node --format=cjs --sourcemap=inline --sources-content=false --outfile=build-esbuild-cjs-bundle/test/index.test.cjs","build-esbuild-esm":"rimraf build-esbuild-esm && node bin/builder.mjs --outDir=build-esbuild-esm","build-esbuild-esm-bundle":"rimraf build-esbuild-esm-bundle && esbuild src/test/index.test.ts --bundle --platform=node --format=esm --sourcemap=inline --sources-content=false --outfile=build-esbuild-esm-bundle/test/index.test.mjs","test-jest-esm":"NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage=false src/*.mts src/*/*.mts src/*/*/*.mts","test-jest-cjs":"jest --coverage=false src/*.ts src/*/*.ts src/*/*/*.ts","test-tsc-cjs":"node --test build-tsc-cjs/test/index.test.js","test-esbuild-cjs":"node --test build-esbuild-cjs/test/index.test.js","test-esbuild-cjs-bundle":"node --test build-esbuild-cjs-bundle/test/index.test.cjs","test-esbuild-esm":"node --test build-esbuild-esm/test/index.test.mjs","test-esbuild-esm-bundle":"echo 'node -test build-esbuild-esm-bundle/test/index.test.mjs'","ci:test":"npm run test-jest-cjs && npm run test-jest-esm &&npm run test-tsc-cjs && npm run test-esbuild-cjs && npm run test-esbuild-cjs-bundle && npm run test-esbuild-esm && npm run test-esbuild-esm-bundle","ci:compile":"npm run build-builder && npm run build-tsc-cjs && npm run build-esbuild-cjs && npm run build-esbuild-cjs-bundle && npm run build-esbuild-esm && npm run build-esbuild-esm-bundle","ci:lint":"npm run lint","ci:style":"npm run prettier"},"devDependencies":{"@checkdigit/prettier-config":"^3.4.0","@types/debug":"^4.1.7","@types/jest":"^29.5.1","@types/uuid":"^9.0.1","@typescript-eslint/eslint-plugin":"^5.59.6","@typescript-eslint/parser":"^5.59.6","debug":"^4.3.4","eslint":"^8.40.0","eslint-config-prettier":"^8.8.0","get-port":"^6.1.2","got":"^11.8.6","jest":"^29.5.0","rimraf":"^5.0.0","ts-jest":"^29.1.0","uuid":"^9.0.0"},"eslintConfig":{"parser":"@typescript-eslint/parser","plugins":["@typescript-eslint"],"parserOptions":{"project":"./tsconfig.json"},"extends":["eslint:all","plugin:@typescript-eslint/recommended","plugin:@typescript-eslint/recommended-requiring-type-checking","plugin:@typescript-eslint/strict","prettier"],"rules":{"@typescript-eslint/non-nullable-type-assertion-style":"error","capitalized-comments":"off","one-var":"off","sort-keys":"off","sort-imports":"off","func-style":["error","declaration",{"allowArrowFunctions":true}],"no-magic-numbers":["error",{"ignore":[0,1,2]}],"no-undefined":"off","no-ternary":"off"},"overrides":[{"files":["*.spec.mts","*.test.mts","*.spec.ts","*.test.ts"],"rules":{"@typescript-eslint/non-nullable-type-assertion-style":"off","@typescript-eslint/ban-types":"off","@typescript-eslint/require-await":"off","@typescript-eslint/consistent-type-definitions":"off","@typescript-eslint/ban-ts-comment":"off","@typescript-eslint/no-unnecessary-condition":"off","@typescript-eslint/consistent-indexed-object-style":"off","@typescript-eslint/no-unused-vars":"off","@typescript-eslint/no-unsafe-member-access":"off","line-comment-position":"off","no-inline-comments":"off","no-param-reassign":"off","id-length":"off","no-magic-numbers":"off","func-names":"off","no-duplicate-imports":"off","symbol-description":"off","no-invalid-this":"off","max-lines-per-function":"off","max-lines":"off"}}]},"jest":{"moduleFileExtensions":["js","mjs","cjs","ts","mts","json","node"],"extensionsToTreatAsEsm":[".mts"],"transform":{"^.+\\.mts$":["ts-jest",{"isolatedModules":true,"diagnostics":false,"useESM":true}],"^.+\\.ts$":["ts-jest",{"isolatedModules":true,"diagnostics":false,"useESM":false}]},"collectCoverageFrom":["<rootDir>/src/**","!<rootDir>/src/**/*.spec.mts","!<rootDir>/src/**/*.test.mts","!<rootDir>/src/**/*.spec.ts","!<rootDir>/src/**/*.test.ts"],"testMatch":["<rootDir>/src/**/*.spec.ts","<rootDir>/src/**/*.spec.mts"]},"files":["tsconfig.json","SECURITY.md","/src/"]}
1
+ {"name":"@checkdigit/typescript-config","version":"3.3.0-PR.30-dfde","description":"Check Digit standard Typescript configuration","prettier":"@checkdigit/prettier-config","engines":{"node":">=16"},"bin":{"builder":"./bin/builder.mjs"},"peerDependencies":{"@types/node":">=16","esbuild":"0.17.18","typescript":">=5.0.4 <5.1"},"repository":{"type":"git","url":"git+https://github.com/checkdigit/typescript-config.git"},"author":"Check Digit, LLC","license":"MIT","bugs":{"url":"https://github.com/checkdigit/typescript-config/issues"},"homepage":"https://github.com/checkdigit/typescript-config#readme","scripts":{"preversion":"npm test","postversion":"git push && git push --tags","prepare":"npm run build-builder","lint:fix":"eslint -f unix --ext .ts,.mts src --fix","lint":"eslint -f unix --ext .ts,.mts src","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style","build-builder":"esbuild src/builder/index.mts --bundle --platform=node --format=esm --external:typescript --external:esbuild --outfile=build-builder/builder.mjs && mkdir -p bin && { echo '#!/usr/bin/env node'; cat build-builder/builder.mjs; } > bin/builder.mjs && chmod +x bin/builder.mjs","build-tsc-cjs":"rimraf build-tsc-cjs && tsc --outDir build-tsc-cjs","build-esbuild-cjs":"rimraf build-esbuild-cjs && esbuild ./src/*.ts ./src/*/*.ts --platform=node --bundle --format=cjs --sourcemap=inline --sources-content=false --outdir=build-esbuild-cjs","build-esbuild-cjs-bundle":"rimraf build-esbuild-cjs-bundle && esbuild src/test/index.test.ts --bundle --platform=node --format=cjs --sourcemap=inline --sources-content=false --outfile=build-esbuild-cjs-bundle/test/index.test.cjs","build-esbuild-esm":"rimraf build-esbuild-esm && node bin/builder.mjs --outDir=build-esbuild-esm","build-esbuild-esm-bundle":"rimraf build-esbuild-esm-bundle && esbuild src/test/index.test.ts --bundle --platform=node --format=esm --sourcemap=inline --sources-content=false --outfile=build-esbuild-esm-bundle/test/index.test.mjs","test-jest-esm":"NODE_OPTIONS=\"--experimental-vm-modules\" jest --coverage=false src/*.mts src/*/*.mts src/*/*/*.mts","test-jest-cjs":"jest --coverage=false src/*.ts src/*/*.ts src/*/*/*.ts","test-tsc-cjs":"node --test build-tsc-cjs/test/index.test.js","test-esbuild-cjs":"node --test build-esbuild-cjs/test/index.test.js","test-esbuild-cjs-bundle":"node --test build-esbuild-cjs-bundle/test/index.test.cjs","test-esbuild-esm":"node --test build-esbuild-esm/test/index.test.mjs","test-esbuild-esm-bundle":"echo 'node -test build-esbuild-esm-bundle/test/index.test.mjs'","ci:test":"npm run test-jest-cjs && npm run test-jest-esm &&npm run test-tsc-cjs && npm run test-esbuild-cjs && npm run test-esbuild-cjs-bundle && npm run test-esbuild-esm && npm run test-esbuild-esm-bundle","ci:compile":"npm run build-builder && npm run build-tsc-cjs && npm run build-esbuild-cjs && npm run build-esbuild-cjs-bundle && npm run build-esbuild-esm && npm run build-esbuild-esm-bundle","ci:lint":"npm run lint","ci:style":"npm run prettier"},"devDependencies":{"@checkdigit/prettier-config":"^3.4.0","@types/debug":"^4.1.7","@types/jest":"^29.5.1","@types/uuid":"^9.0.1","@typescript-eslint/eslint-plugin":"^5.59.6","@typescript-eslint/parser":"^5.59.6","debug":"^4.3.4","eslint":"^8.40.0","eslint-config-prettier":"^8.8.0","get-port":"^6.1.2","got":"^11.8.6","jest":"^29.5.0","rimraf":"^5.0.0","ts-jest":"^29.1.0","uuid":"^9.0.0"},"eslintConfig":{"parser":"@typescript-eslint/parser","plugins":["@typescript-eslint"],"parserOptions":{"project":"./tsconfig.json"},"extends":["eslint:all","plugin:@typescript-eslint/recommended","plugin:@typescript-eslint/recommended-requiring-type-checking","plugin:@typescript-eslint/strict","prettier"],"rules":{"@typescript-eslint/non-nullable-type-assertion-style":"error","capitalized-comments":"off","one-var":"off","sort-keys":"off","sort-imports":"off","func-style":["error","declaration",{"allowArrowFunctions":true}],"no-magic-numbers":["error",{"ignore":[0,1,2]}],"no-undefined":"off","no-ternary":"off"},"overrides":[{"files":["*.spec.mts","*.test.mts","*.spec.ts","*.test.ts"],"rules":{"@typescript-eslint/non-nullable-type-assertion-style":"off","@typescript-eslint/ban-types":"off","@typescript-eslint/require-await":"off","@typescript-eslint/consistent-type-definitions":"off","@typescript-eslint/ban-ts-comment":"off","@typescript-eslint/no-unnecessary-condition":"off","@typescript-eslint/consistent-indexed-object-style":"off","@typescript-eslint/no-unused-vars":"off","@typescript-eslint/no-unsafe-member-access":"off","line-comment-position":"off","no-inline-comments":"off","no-param-reassign":"off","id-length":"off","no-magic-numbers":"off","func-names":"off","no-duplicate-imports":"off","symbol-description":"off","no-invalid-this":"off","max-lines-per-function":"off","max-lines":"off","max-statements":"off","no-await-in-loop":"off"}}]},"jest":{"moduleFileExtensions":["js","mjs","cjs","ts","mts","json","node"],"extensionsToTreatAsEsm":[".mts"],"transform":{"^.+\\.mts$":["ts-jest",{"isolatedModules":true,"diagnostics":false,"useESM":true}],"^.+\\.ts$":["ts-jest",{"isolatedModules":true,"diagnostics":false,"useESM":false}]},"collectCoverageFrom":["<rootDir>/src/**","!<rootDir>/src/**/*.spec.mts","!<rootDir>/src/**/*.test.mts","!<rootDir>/src/**/*.spec.ts","!<rootDir>/src/**/*.test.ts"],"testMatch":["<rootDir>/src/**/*.spec.ts","<rootDir>/src/**/*.spec.mts"]},"files":["tsconfig.json","SECURITY.md","/src/"]}
@@ -33,6 +33,11 @@ export interface BuilderOptions {
33
33
  * build file, relative to the outDir
34
34
  */
35
35
  outFile?: string;
36
+
37
+ /**
38
+ * external modules to exclude from the bundle
39
+ */
40
+ external?: string[];
36
41
  }
37
42
 
38
43
  /**
@@ -73,7 +78,14 @@ function setup(type: 'module' | 'commonjs') {
73
78
  }
74
79
 
75
80
  // eslint-disable-next-line func-names,max-lines-per-function,max-statements
76
- export default async function ({ type, entryPoint, inDir, outDir, outFile }: BuilderOptions): Promise<string[]> {
81
+ export default async function ({
82
+ type,
83
+ entryPoint,
84
+ inDir,
85
+ outDir,
86
+ outFile,
87
+ external = [],
88
+ }: BuilderOptions): Promise<string[]> {
77
89
  const messages: string[] = [];
78
90
 
79
91
  assert.ok(
@@ -88,15 +100,37 @@ export default async function ({ type, entryPoint, inDir, outDir, outFile }: Bui
88
100
  const productionSourceFiles =
89
101
  entryPoint === undefined ? allSourceFiles.filter((file) => file.endsWith('.ts')) : [path.join(inDir, entryPoint)];
90
102
 
91
- const configFile = typescript.readConfigFile('./tsconfig.json', (name) => typescript.sys.readFile(name));
92
- const compilerOptions = typescript.parseJsonConfigFileContent(configFile.config, typescript.sys, './');
93
-
94
103
  const program = typescript.createProgram(productionSourceFiles, {
95
- ...compilerOptions.options,
104
+ module: typescript.ModuleKind.ESNext,
105
+ moduleResolution: typescript.ModuleResolutionKind.Bundler,
106
+ target: typescript.ScriptTarget.ESNext,
107
+ declaration: true,
96
108
  noEmitOnError: true,
97
109
  emitDeclarationOnly: true,
98
110
  rootDir: inDir,
99
111
  outDir,
112
+ noLib: false,
113
+ skipLibCheck: true,
114
+ strict: true,
115
+ preserveConstEnums: true,
116
+ noImplicitReturns: true,
117
+ noUnusedLocals: true,
118
+ noUnusedParameters: true,
119
+ alwaysStrict: true,
120
+ verbatimModuleSyntax: false,
121
+ noFallthroughCasesInSwitch: true,
122
+ forceConsistentCasingInFileNames: true,
123
+ emitDecoratorMetadata: true,
124
+ experimentalDecorators: true,
125
+ resolveJsonModule: true,
126
+ esModuleInterop: true,
127
+ noUncheckedIndexedAccess: true,
128
+ noPropertyAccessFromIndexSignature: true,
129
+ allowUnusedLabels: false,
130
+ allowUnreachableCode: false,
131
+ noImplicitOverride: true,
132
+ useUnknownInCatchVariables: true,
133
+ exactOptionalPropertyTypes: true,
100
134
  });
101
135
  const emitResult = program.emit();
102
136
  const allDiagnostics = typescript.sortAndDeduplicateDiagnostics([
@@ -139,7 +173,7 @@ export default async function ({ type, entryPoint, inDir, outDir, outFile }: Bui
139
173
  },
140
174
  ],
141
175
  }
142
- : { outfile: path.join(outDir, outFile) }),
176
+ : { outfile: path.join(outDir, outFile), external }),
143
177
  });
144
178
 
145
179
  messages.push(...buildResult.errors.map((error) => `esbuild error: ${error.text}`));
@@ -26,9 +26,59 @@ const exportDefaultFunctionModule = {
26
26
  [`index.ts`]: `export default function () { return 'hello world' }\n`,
27
27
  };
28
28
 
29
- async function write(dir: string, files: Record<string, string>): Promise<void> {
30
- await fs.mkdir(dir, { recursive: true });
31
- await Promise.all(Object.entries(files).map(([name, content]) => fs.writeFile(path.join(dir, name), content)));
29
+ const importExternalModule = {
30
+ [`index.ts`]: `
31
+ import { hello as test } from 'test-esm-module';
32
+ import util from 'node:util';
33
+ export const hello = { test, message: util.format('hello %s', 'world') };
34
+ `,
35
+ };
36
+
37
+ const testNodeModules = {
38
+ [`test-cjs-module`]: {
39
+ source: {
40
+ [`index.js`]: `module.exports.goodbye = 'world';`,
41
+ [`index.d.ts`]: `export declare const goodbye = "world";\n`,
42
+ },
43
+ },
44
+ [`test-esm-module`]: {
45
+ type: 'module',
46
+ source: {
47
+ [`index.js`]: `export const hello = 'world';`,
48
+ [`index.d.ts`]: `export declare const hello = "world";\n`,
49
+ },
50
+ },
51
+ } as const;
52
+
53
+ interface NodeModule {
54
+ [name: string]: {
55
+ type?: 'module' | 'commonjs';
56
+ source: {
57
+ [file: string]: string;
58
+ };
59
+ };
60
+ }
61
+
62
+ async function writeNodeModules(directory: string, nodeModules: NodeModule) {
63
+ const nodeModulesDirectory = path.join(directory, 'node_modules');
64
+ for (const [name, nodeModule] of Object.entries(nodeModules)) {
65
+ const nodeModuleDirectory = path.join(nodeModulesDirectory, name);
66
+ await fs.mkdir(nodeModuleDirectory, { recursive: true });
67
+ await fs.writeFile(
68
+ path.join(nodeModuleDirectory, 'package.json'),
69
+ JSON.stringify({
70
+ type: nodeModule.type ?? 'commonjs',
71
+ })
72
+ );
73
+ for (const [file, content] of Object.entries(nodeModule.source)) {
74
+ await fs.writeFile(path.join(nodeModuleDirectory, file), content);
75
+ }
76
+ }
77
+ }
78
+
79
+ async function write(directory: string, files: Record<string, string>): Promise<void> {
80
+ await fs.mkdir(directory, { recursive: true });
81
+ await Promise.all(Object.entries(files).map(([name, content]) => fs.writeFile(path.join(directory, name), content)));
32
82
  }
33
83
 
34
84
  async function read(dir: string): Promise<Record<string, string>> {
@@ -330,4 +380,89 @@ describe('test builder', () => {
330
380
  const output = await import(path.join(outDir, 'index.mjs'));
331
381
  assert.equal(output.default, 'worldworld');
332
382
  });
383
+
384
+ it('should bundle an ESM module that imports external modules', async () => {
385
+ const id = uuid();
386
+ const moduleDir = path.join(os.tmpdir(), `in-dir-${id}`);
387
+ const inDir = path.join(moduleDir, 'src');
388
+ const outDir = path.join(os.tmpdir(), `out-dir-${id}`, 'build');
389
+ await write(inDir, importExternalModule);
390
+ await writeNodeModules(moduleDir, testNodeModules);
391
+ assert.deepEqual(
392
+ await builder({ type: 'module', entryPoint: 'index.ts', outFile: 'index.mjs', inDir, outDir }),
393
+ []
394
+ );
395
+ assert.deepEqual(await read(outDir), {
396
+ 'index.d.ts': 'export declare const hello: {\n test: string;\n message: string;\n};\n',
397
+ 'index.mjs':
398
+ 'var hello = "world";\n' +
399
+ '\n' +
400
+ 'import util from "node:util";\n' +
401
+ 'var hello2 = { test: hello, message: util.format("hello %s", "world") };\n' +
402
+ 'export {\n' +
403
+ ' hello2 as hello\n' +
404
+ '};\n',
405
+ });
406
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
407
+ const output = await import(path.join(outDir, 'index.mjs'));
408
+ assert.deepEqual(output.hello, {
409
+ message: 'hello world',
410
+ test: 'world',
411
+ });
412
+ });
413
+
414
+ it('should bundle an ESM module that imports external modules, but excludes them', async () => {
415
+ const id = uuid();
416
+ const moduleDir = path.join(os.tmpdir(), `in-dir-${id}`);
417
+ const inDir = path.join(moduleDir, 'src');
418
+ const outDir = path.join(os.tmpdir(), `out-dir-${id}`, 'build');
419
+ await write(inDir, importExternalModule);
420
+ await writeNodeModules(moduleDir, testNodeModules);
421
+ assert.deepEqual(
422
+ await builder({
423
+ type: 'module',
424
+ entryPoint: 'index.ts',
425
+ outFile: 'index.mjs',
426
+ inDir,
427
+ outDir,
428
+ external: ['*'],
429
+ }),
430
+ []
431
+ );
432
+ assert.deepEqual(await read(outDir), {
433
+ 'index.d.ts': 'export declare const hello: {\n test: string;\n message: string;\n};\n',
434
+ 'index.mjs':
435
+ 'import { hello as test } from "test-esm-module";\n' +
436
+ 'import util from "node:util";\n' +
437
+ 'var hello = { test, message: util.format("hello %s", "world") };\n' +
438
+ 'export {\n' +
439
+ ' hello\n' +
440
+ '};\n',
441
+ });
442
+ });
443
+
444
+ it('should bundle a commonjs module that imports external ESM modules', async () => {
445
+ const id = uuid();
446
+ const moduleDir = path.join(os.tmpdir(), `in-dir-${id}`);
447
+ const inDir = path.join(moduleDir, 'src');
448
+ const outDir = path.join(os.tmpdir(), `out-dir-${id}`, 'build');
449
+ await write(inDir, importExternalModule);
450
+ await writeNodeModules(moduleDir, testNodeModules);
451
+ assert.deepEqual(
452
+ await builder({
453
+ type: 'commonjs',
454
+ entryPoint: 'index.ts',
455
+ outFile: 'index.cjs',
456
+ inDir,
457
+ outDir,
458
+ }),
459
+ []
460
+ );
461
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
462
+ const output = require(path.join(outDir, 'index.cjs'));
463
+ assert.deepEqual(output.hello, {
464
+ message: 'hello world',
465
+ test: 'world',
466
+ });
467
+ });
333
468
  });