@knighted/duel 4.0.0 → 4.0.2-rc.0

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/dist/cjs/duel.cjs CHANGED
@@ -9,7 +9,6 @@ const node_child_process_1 = require("node:child_process");
9
9
  const promises_1 = require("node:fs/promises");
10
10
  const node_crypto_1 = require("node:crypto");
11
11
  const node_perf_hooks_1 = require("node:perf_hooks");
12
- const glob_1 = require("glob");
13
12
  const find_up_1 = require("find-up");
14
13
  const module_1 = require("@knighted/module");
15
14
  const get_tsconfig_1 = require("get-tsconfig");
@@ -44,6 +43,13 @@ const logDiagnostics = (diags, projectDir, hazardAllowlist = null) => {
44
43
  }
45
44
  return hasError;
46
45
  };
46
+ const collectGlob = async (pattern, options) => {
47
+ const files = [];
48
+ for await (const file of (0, promises_1.glob)(pattern, options)) {
49
+ files.push(file);
50
+ }
51
+ return files;
52
+ };
47
53
  const duel = async (args) => {
48
54
  const ctx = await (0, init_js_1.init)(args);
49
55
  if (ctx) {
@@ -587,7 +593,7 @@ const duel = async (args) => {
587
593
  * Transform ambiguous modules for the target dual build.
588
594
  * @see https://github.com/microsoft/TypeScript/issues/58658
589
595
  */
590
- const toTransform = await (0, glob_1.glob)(`${subDir.replace(/\\/g, '/')}/**/*{.js,.jsx,.ts,.tsx}`, {
596
+ const toTransform = await collectGlob(`${subDir.replace(/\\/g, '/')}/**/*{.js,.jsx,.ts,.tsx}`, {
591
597
  ignore: `${subDir.replace(/\\/g, '/')}/**/node_modules/**`,
592
598
  });
593
599
  let transformDiagnosticsError = false;
@@ -659,12 +665,14 @@ const duel = async (args) => {
659
665
  }
660
666
  catch (err) {
661
667
  if (err?.code === 'ENOENT') {
662
- throw new Error(`Dual build output not found at ${shadowDualOutDir}`);
668
+ throw new Error(`Dual build output not found at ${shadowDualOutDir}`, {
669
+ cause: err,
670
+ });
663
671
  }
664
672
  throw err;
665
673
  }
666
674
  const dualGlob = dualTarget === 'commonjs' ? '**/*{.js,.cjs,.d.ts}' : '**/*{.js,.mjs,.d.ts}';
667
- const filenames = await (0, glob_1.glob)(`${absoluteDualOutDir.replace(/\\/g, '/')}/${dualGlob}`, {
675
+ const filenames = await collectGlob(`${absoluteDualOutDir.replace(/\\/g, '/')}/${dualGlob}`, {
668
676
  ignore: `${absoluteDualOutDir.replace(/\\/g, '/')}/**/node_modules/**`,
669
677
  });
670
678
  const rewriteSyntaxMode = dualTarget === 'commonjs' ? true : syntaxMode;
@@ -687,7 +695,7 @@ const duel = async (args) => {
687
695
  onRewrite: (from, to) => logVerbose(`Rewrote specifiers in ${from} -> ${to}`),
688
696
  });
689
697
  if (dirs && originalType === 'commonjs') {
690
- const primaryFiles = await (0, glob_1.glob)(`${primaryOutDir.replace(/\\/g, '/')}/**/*{.js,.cjs,.d.ts}`, {
698
+ const primaryFiles = await collectGlob(`${primaryOutDir.replace(/\\/g, '/')}/**/*{.js,.cjs,.d.ts}`, {
691
699
  ignore: `${primaryOutDir.replace(/\\/g, '/')}/**/node_modules/**`,
692
700
  });
693
701
  await (0, resolver_js_1.rewriteSpecifiersAndExtensions)(primaryFiles, {
package/dist/cjs/init.cjs CHANGED
@@ -99,7 +99,7 @@ const printHelp = () => {
99
99
  }
100
100
  };
101
101
  const init = async (args) => {
102
- let parsed = null;
102
+ let parsed;
103
103
  try {
104
104
  const { values } = (0, node_util_1.parseArgs)({
105
105
  args,
@@ -176,8 +176,8 @@ const init = async (args) => {
176
176
  else {
177
177
  const { project, 'pkg-dir': pkgDir, dirs, exports: exportsOpt, 'exports-config': exportsConfig, 'exports-validate': exportsValidate, 'rewrite-policy': rewritePolicy, 'detect-dual-package-hazard': detectDualPackageHazard, 'dual-package-hazard-allowlist': dualPackageHazardAllowlist, 'dual-package-hazard-scope': dualPackageHazardScope, verbose, mode, 'copy-mode': copyMode, } = parsed;
178
178
  let configPath = (0, node_path_1.resolve)(project);
179
- let stats = null;
180
- let pkg = null;
179
+ let stats;
180
+ let pkg;
181
181
  if (mode && !['none', 'globals', 'full'].includes(mode)) {
182
182
  (0, util_js_1.logError)('--mode expects one of: none | globals | full');
183
183
  return false;
package/dist/cjs/util.cjs CHANGED
@@ -7,7 +7,6 @@ const node_fs_1 = require("node:fs");
7
7
  const node_child_process_1 = require("node:child_process");
8
8
  const node_process_1 = require("node:process");
9
9
  const node_path_1 = require("node:path");
10
- const glob_1 = require("glob");
11
10
  const find_up_1 = require("find-up");
12
11
  const COLORS = {
13
12
  reset: '\x1b[0m',
@@ -181,12 +180,14 @@ const readExportsConfig = async (configPath, pkgDir) => {
181
180
  ? (0, node_path_1.resolve)(pkgDir, configPath)
182
181
  : (0, node_path_1.resolve)((0, node_process_1.cwd)(), configPath);
183
182
  const raw = await (0, promises_1.readFile)(abs, 'utf8');
184
- let parsed = null;
183
+ let parsed;
185
184
  try {
186
185
  parsed = JSON.parse(raw);
187
186
  }
188
187
  catch (err) {
189
- throw new Error(`Invalid JSON in --exports-config (${configPath}): ${err.message}`);
188
+ throw new Error(`Invalid JSON in --exports-config (${configPath}): ${err.message}`, {
189
+ cause: err,
190
+ });
190
191
  }
191
192
  const { entries, main } = parsed;
192
193
  if (!entries ||
@@ -279,7 +280,12 @@ const generateExports = async (options) => {
279
280
  return;
280
281
  }
281
282
  const baseEntry = baseMap.get(baseKey) ?? {};
282
- baseEntry[kind] = withDot;
283
+ if (kind === 'types') {
284
+ baseEntry.types = baseEntry.types ?? withDot;
285
+ }
286
+ else {
287
+ baseEntry[kind] = withDot;
288
+ }
283
289
  baseMap.set(baseKey, baseEntry);
284
290
  const subpath = useEntriesSubpaths
285
291
  ? ensureDotSlash(stripKnownExt(relFromRoot))
@@ -289,7 +295,8 @@ const generateExports = async (options) => {
289
295
  const mappedSubpath = baseToSubpath.get(baseKey);
290
296
  if (mappedSubpath) {
291
297
  const subEntry = subpathMap.get(mappedSubpath) ?? {};
292
- subEntry.types = useWildcard ? toWildcardValue(withDot) : withDot;
298
+ const nextType = useWildcard ? toWildcardValue(withDot) : withDot;
299
+ subEntry.types = subEntry.types ?? nextType;
293
300
  subpathMap.set(mappedSubpath, subEntry);
294
301
  }
295
302
  return;
@@ -301,10 +308,9 @@ const generateExports = async (options) => {
301
308
  baseToSubpath.set(baseKey, subpath);
302
309
  }
303
310
  };
304
- const esmFiles = await (0, glob_1.glob)(`${esmRootPosix}/**/*.{js,mjs,d.ts,d.mts}`, {
311
+ for await (const file of (0, promises_1.glob)(`${esmRootPosix}/**/*.{js,mjs,d.ts,d.mts}`, {
305
312
  ignore: esmIgnore,
306
- });
307
- for (const file of esmFiles) {
313
+ })) {
308
314
  if (/\.d\.(ts|mts)$/.test(file)) {
309
315
  recordPath('types', file, esmRoot);
310
316
  }
@@ -312,10 +318,9 @@ const generateExports = async (options) => {
312
318
  recordPath('import', file, esmRoot);
313
319
  }
314
320
  }
315
- const cjsFiles = await (0, glob_1.glob)(`${cjsRootPosix}/**/*.{js,cjs,d.ts,d.cts}`, {
321
+ for await (const file of (0, promises_1.glob)(`${cjsRootPosix}/**/*.{js,cjs,d.ts,d.cts}`, {
316
322
  ignore: cjsIgnore,
317
- });
318
- for (const file of cjsFiles) {
323
+ })) {
319
324
  if (/\.d\.(ts|cts)$/.test(file)) {
320
325
  recordPath('types', file, cjsRoot);
321
326
  }
package/dist/esm/duel.js CHANGED
@@ -3,10 +3,9 @@ import { argv } from 'node:process';
3
3
  import { pathToFileURL } from 'node:url';
4
4
  import { join, dirname, resolve, relative, sep } from 'node:path';
5
5
  import { spawn } from 'node:child_process';
6
- import { writeFile, rm, mkdir, cp, access, readdir } from 'node:fs/promises';
6
+ import { writeFile, rm, mkdir, cp, access, readdir, glob } from 'node:fs/promises';
7
7
  import { createHash } from 'node:crypto';
8
8
  import { performance } from 'node:perf_hooks';
9
- import { glob } from 'glob';
10
9
  import { findUp } from 'find-up';
11
10
  import { transform, collectProjectDualPackageHazards } from '@knighted/module';
12
11
  import { getTsconfig, parseTsconfig } from 'get-tsconfig';
@@ -41,6 +40,13 @@ const logDiagnostics = (diags, projectDir, hazardAllowlist = null) => {
41
40
  }
42
41
  return hasError;
43
42
  };
43
+ const collectGlob = async (pattern, options) => {
44
+ const files = [];
45
+ for await (const file of glob(pattern, options)) {
46
+ files.push(file);
47
+ }
48
+ return files;
49
+ };
44
50
  const duel = async (args) => {
45
51
  const ctx = await init(args);
46
52
  if (ctx) {
@@ -584,7 +590,7 @@ const duel = async (args) => {
584
590
  * Transform ambiguous modules for the target dual build.
585
591
  * @see https://github.com/microsoft/TypeScript/issues/58658
586
592
  */
587
- const toTransform = await glob(`${subDir.replace(/\\/g, '/')}/**/*{.js,.jsx,.ts,.tsx}`, {
593
+ const toTransform = await collectGlob(`${subDir.replace(/\\/g, '/')}/**/*{.js,.jsx,.ts,.tsx}`, {
588
594
  ignore: `${subDir.replace(/\\/g, '/')}/**/node_modules/**`,
589
595
  });
590
596
  let transformDiagnosticsError = false;
@@ -656,12 +662,14 @@ const duel = async (args) => {
656
662
  }
657
663
  catch (err) {
658
664
  if (err?.code === 'ENOENT') {
659
- throw new Error(`Dual build output not found at ${shadowDualOutDir}`);
665
+ throw new Error(`Dual build output not found at ${shadowDualOutDir}`, {
666
+ cause: err,
667
+ });
660
668
  }
661
669
  throw err;
662
670
  }
663
671
  const dualGlob = dualTarget === 'commonjs' ? '**/*{.js,.cjs,.d.ts}' : '**/*{.js,.mjs,.d.ts}';
664
- const filenames = await glob(`${absoluteDualOutDir.replace(/\\/g, '/')}/${dualGlob}`, {
672
+ const filenames = await collectGlob(`${absoluteDualOutDir.replace(/\\/g, '/')}/${dualGlob}`, {
665
673
  ignore: `${absoluteDualOutDir.replace(/\\/g, '/')}/**/node_modules/**`,
666
674
  });
667
675
  const rewriteSyntaxMode = dualTarget === 'commonjs' ? true : syntaxMode;
@@ -684,7 +692,7 @@ const duel = async (args) => {
684
692
  onRewrite: (from, to) => logVerbose(`Rewrote specifiers in ${from} -> ${to}`),
685
693
  });
686
694
  if (dirs && originalType === 'commonjs') {
687
- const primaryFiles = await glob(`${primaryOutDir.replace(/\\/g, '/')}/**/*{.js,.cjs,.d.ts}`, {
695
+ const primaryFiles = await collectGlob(`${primaryOutDir.replace(/\\/g, '/')}/**/*{.js,.cjs,.d.ts}`, {
688
696
  ignore: `${primaryOutDir.replace(/\\/g, '/')}/**/node_modules/**`,
689
697
  });
690
698
  await rewriteSpecifiersAndExtensions(primaryFiles, {
package/dist/esm/init.js CHANGED
@@ -96,7 +96,7 @@ const printHelp = () => {
96
96
  }
97
97
  };
98
98
  const init = async (args) => {
99
- let parsed = null;
99
+ let parsed;
100
100
  try {
101
101
  const { values } = parseArgs({
102
102
  args,
@@ -173,8 +173,8 @@ const init = async (args) => {
173
173
  else {
174
174
  const { project, 'pkg-dir': pkgDir, dirs, exports: exportsOpt, 'exports-config': exportsConfig, 'exports-validate': exportsValidate, 'rewrite-policy': rewritePolicy, 'detect-dual-package-hazard': detectDualPackageHazard, 'dual-package-hazard-allowlist': dualPackageHazardAllowlist, 'dual-package-hazard-scope': dualPackageHazardScope, verbose, mode, 'copy-mode': copyMode, } = parsed;
175
175
  let configPath = resolve(project);
176
- let stats = null;
177
- let pkg = null;
176
+ let stats;
177
+ let pkg;
178
178
  if (mode && !['none', 'globals', 'full'].includes(mode)) {
179
179
  logError('--mode expects one of: none | globals | full');
180
180
  return false;
package/dist/esm/util.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import { pathToFileURL } from 'node:url';
2
- import { realpath, readFile, writeFile, symlink, rm } from 'node:fs/promises';
2
+ import { realpath, readFile, writeFile, symlink, rm, glob } from 'node:fs/promises';
3
3
  import { existsSync, rmSync } from 'node:fs';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import { cwd, platform } from 'node:process';
6
6
  import { join, resolve, relative, parse as parsePath, posix, isAbsolute, sep, normalize as normalizePath, } from 'node:path';
7
- import { glob } from 'glob';
8
7
  import { findUp } from 'find-up';
9
8
  const COLORS = {
10
9
  reset: '\x1b[0m',
@@ -168,12 +167,14 @@ const readExportsConfig = async (configPath, pkgDir) => {
168
167
  ? resolve(pkgDir, configPath)
169
168
  : resolve(cwd(), configPath);
170
169
  const raw = await readFile(abs, 'utf8');
171
- let parsed = null;
170
+ let parsed;
172
171
  try {
173
172
  parsed = JSON.parse(raw);
174
173
  }
175
174
  catch (err) {
176
- throw new Error(`Invalid JSON in --exports-config (${configPath}): ${err.message}`);
175
+ throw new Error(`Invalid JSON in --exports-config (${configPath}): ${err.message}`, {
176
+ cause: err,
177
+ });
177
178
  }
178
179
  const { entries, main } = parsed;
179
180
  if (!entries ||
@@ -264,7 +265,12 @@ const generateExports = async (options) => {
264
265
  return;
265
266
  }
266
267
  const baseEntry = baseMap.get(baseKey) ?? {};
267
- baseEntry[kind] = withDot;
268
+ if (kind === 'types') {
269
+ baseEntry.types = baseEntry.types ?? withDot;
270
+ }
271
+ else {
272
+ baseEntry[kind] = withDot;
273
+ }
268
274
  baseMap.set(baseKey, baseEntry);
269
275
  const subpath = useEntriesSubpaths
270
276
  ? ensureDotSlash(stripKnownExt(relFromRoot))
@@ -274,7 +280,8 @@ const generateExports = async (options) => {
274
280
  const mappedSubpath = baseToSubpath.get(baseKey);
275
281
  if (mappedSubpath) {
276
282
  const subEntry = subpathMap.get(mappedSubpath) ?? {};
277
- subEntry.types = useWildcard ? toWildcardValue(withDot) : withDot;
283
+ const nextType = useWildcard ? toWildcardValue(withDot) : withDot;
284
+ subEntry.types = subEntry.types ?? nextType;
278
285
  subpathMap.set(mappedSubpath, subEntry);
279
286
  }
280
287
  return;
@@ -286,10 +293,9 @@ const generateExports = async (options) => {
286
293
  baseToSubpath.set(baseKey, subpath);
287
294
  }
288
295
  };
289
- const esmFiles = await glob(`${esmRootPosix}/**/*.{js,mjs,d.ts,d.mts}`, {
296
+ for await (const file of glob(`${esmRootPosix}/**/*.{js,mjs,d.ts,d.mts}`, {
290
297
  ignore: esmIgnore,
291
- });
292
- for (const file of esmFiles) {
298
+ })) {
293
299
  if (/\.d\.(ts|mts)$/.test(file)) {
294
300
  recordPath('types', file, esmRoot);
295
301
  }
@@ -297,10 +303,9 @@ const generateExports = async (options) => {
297
303
  recordPath('import', file, esmRoot);
298
304
  }
299
305
  }
300
- const cjsFiles = await glob(`${cjsRootPosix}/**/*.{js,cjs,d.ts,d.cts}`, {
306
+ for await (const file of glob(`${cjsRootPosix}/**/*.{js,cjs,d.ts,d.cts}`, {
301
307
  ignore: cjsIgnore,
302
- });
303
- for (const file of cjsFiles) {
308
+ })) {
304
309
  if (/\.d\.(ts|cts)$/.test(file)) {
305
310
  recordPath('types', file, cjsRoot);
306
311
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knighted/duel",
3
- "version": "4.0.0",
3
+ "version": "4.0.2-rc.0",
4
4
  "description": "TypeScript dual packages.",
5
5
  "type": "module",
6
6
  "main": "dist/esm/duel.js",
@@ -70,13 +70,13 @@
70
70
  }
71
71
  },
72
72
  "devDependencies": {
73
- "@eslint/js": "^9.39.1",
73
+ "@eslint/js": "^10.0.1",
74
74
  "@tsconfig/recommended": "^1.0.10",
75
75
  "@types/node": "^24.10.1",
76
- "c8": "^10.1.3",
76
+ "c8": "^11.0.0",
77
77
  "cross-spawn": "^7.0.6",
78
- "eslint": "^9.39.1",
79
- "eslint-plugin-n": "^17.23.1",
78
+ "eslint": "^10.0.3",
79
+ "eslint-plugin-n": "^17.24.0",
80
80
  "globals": "^16.3.0",
81
81
  "husky": "^9.1.7",
82
82
  "lint-staged": "^16.2.7",
@@ -84,7 +84,7 @@
84
84
  "prettier": "^3.6.2",
85
85
  "tsx": "^4.20.6",
86
86
  "typescript": "^5.9.3",
87
- "vite": "^7.2.4"
87
+ "vite": "^7.3.1"
88
88
  },
89
89
  "dependencies": {
90
90
  "@jridgewell/gen-mapping": "^0.3.13",
@@ -92,7 +92,6 @@
92
92
  "@knighted/module": "^1.5.0",
93
93
  "find-up": "^8.0.0",
94
94
  "get-tsconfig": "^4.13.0",
95
- "glob": "^13.0.0",
96
95
  "magic-string": "^0.30.21",
97
96
  "read-package-up": "^12.0.0"
98
97
  },