@knighted/duel 2.0.0-rc.0 → 2.0.0-rc.2

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/README.md CHANGED
@@ -10,8 +10,10 @@ Tool for building a Node.js [dual package](https://nodejs.org/api/packages.html#
10
10
 
11
11
  - Bidirectional ESM ↔️ CJS dual builds inferred from the package.json `type`.
12
12
  - Correctly preserves module systems for `.mts` and `.cts` file extensions.
13
- - Resolves the [differences between ES modules and CommonJS](https://nodejs.org/api/esm.html#differences-between-es-modules-and-commonjs).
14
- - Use only one package.json and tsconfig.json.
13
+ - No extra configuration files needed, uses `package.json` and `tsconfig.json` files.
14
+ - Transforms the [differences between ES modules and CommonJS](https://nodejs.org/api/esm.html#differences-between-es-modules-and-commonjs).
15
+ - Works with monorepos.
16
+
15
17
 
16
18
  ## Requirements
17
19
 
@@ -68,12 +70,27 @@ If you prefer to have both builds in directories inside of your defined `outDir`
68
70
 
69
71
  Assuming an `outDir` of `dist`, running the above will create `dist/esm` and `dist/cjs` directories.
70
72
 
73
+ ### Module transforms
74
+
75
+ TypeScript will throw compiler errors when using `import.meta` globals while targeting a CommonJS dual build, but _will not_ throw compiler errors when the inverse is true, i.e. using CommonJS globals (`__filename`, `__dirname`, etc.) while targeting an ES module dual build. There is an [open issue](https://github.com/microsoft/TypeScript/issues/58658) regarding this unexpected behavior. You can use the `--modules` option to have the [differences between ES modules and CommonJS](https://nodejs.org/api/esm.html#differences-between-es-modules-and-commonjs) transformed by `duel` prior to running compilation with `tsc` so that there are no compilation or runtime errors.
76
+
77
+ Note, there is a slight performance penalty since your project needs to be copied first to run the transforms before compiling with `tsc`.
78
+
79
+ ```json
80
+ "scripts": {
81
+ "build": "duel --modules"
82
+ }
83
+ ```
84
+
85
+ This feature is still a work in progress regarding transforming `exports` when targeting an ES module build (relies on [`@knighted/module`](https://github.com/knightedcodemonkey/module)).
86
+
71
87
  ## Options
72
88
 
73
89
  The available options are limited, because you should define most of them inside your project's `tsconfig.json` file.
74
90
 
75
91
  - `--project, -p` The path to the project's configuration file. Defaults to `tsconfig.json`.
76
92
  - `--pkg-dir, -k` The directory to start looking for a package.json file. Defaults to the cwd.
93
+ - `--modules, -m` Transform module globals for dual build target. Defaults to false.
77
94
  - `--dirs, -d` Outputs both builds to directories inside of `outDir`. Defaults to `false`.
78
95
 
79
96
  You can run `duel --help` to get the same info. Below is the output of that:
@@ -84,6 +101,7 @@ Usage: duel [options]
84
101
  Options:
85
102
  --project, -p [path] Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.
86
103
  --pkg-dir, -k [path] The directory to start looking for a package.json file. Defaults to cwd.
104
+ --modules, -m Transform module globals for dual build target. Defaults to false.
87
105
  --dirs, -d Output both builds to directories inside of outDir. [esm, cjs].
88
106
  --help, -h Print this message.
89
107
  ```
@@ -94,7 +112,7 @@ These are definitely edge cases, and would only really come up if your project m
94
112
 
95
113
  - This is going to work best if your CJS-first project uses file extensions in _relative_ specifiers. This is completely acceptable in CJS projects, and [required in ESM projects](https://nodejs.org/api/esm.html#import-specifiers). This package makes no attempt to rewrite bare specifiers, or remap any relative specifiers to a directory index.
96
114
 
97
- - Unfortunately, TypeScript doesn't really build [dual packages](https://nodejs.org/api/packages.html#dual-commonjses-module-packages) very well in regards to preserving module system by file extension. For instance, there doesn't appear to be a way to convert an arbitrary `.ts` file into another module system, _while also preserving the module system of `.mts` and `.cts` files_, without requiring **multiple** package.json files. In my opinion, the `tsc` compiler is fundamentally broken in this regard, and at best is enforcing usage patterns it shouldn't. This is only mentioned for transparency, `duel` will correct for this and produce files with the module system you would expect based on the file's extension, so that it works with [how Node.js determines module systems](https://nodejs.org/api/packages.html#determining-module-system).
115
+ - Unfortunately, TypeScript doesn't really build [dual packages](https://nodejs.org/api/packages.html#dual-commonjses-module-packages) very well. One instance of unexpected behavior is when the compiler throws errors for ES module globals when running a dual CJS build, but not for the inverse case, despite both causing runtime errors in Node.js. See the [open issue](https://github.com/microsoft/TypeScript/issues/58658). You can circumvent this with `duel` by using the `--modules` option if your project uses module globals such as `import.meta` properties or `__dirname`, `__filename`, etc. in a CommonJS project.
98
116
 
99
117
  - If doing an `import type` across module systems, i.e. from `.mts` into `.cts`, or vice versa, you might encounter the compilation error ``error TS1452: 'resolution-mode' assertions are only supported when `moduleResolution` is `node16` or `nodenext`.``. This is a [known issue](https://github.com/microsoft/TypeScript/issues/49055) and TypeScript currently suggests installing the nightly build, i.e. `npm i typescript@next`.
100
118
 
@@ -102,4 +120,6 @@ These are definitely edge cases, and would only really come up if your project m
102
120
 
103
121
  ## Notes
104
122
 
105
- As far as I can tell, `duel` is one (if not the only) way to get a correct dual package build using `tsc` with only **one package.json and tsconfig.json file**, _while also preserving module system by file extension_. Basically, how you expect things to work. The Microsoft backed TypeScript team [keep](https://github.com/microsoft/TypeScript/pull/54546) [talking](https://github.com/microsoft/TypeScript/issues/54593) about dual build support, but they continue to [refuse to rewrite specifiers](https://github.com/microsoft/TypeScript/issues/16577).
123
+ As far as I can tell, `duel` is one (if not the only) way to get a correct dual package build using `tsc` without requiring multiple `tsconfig.json` files or extra configuration. The Microsoft backed TypeScript team [keep](https://github.com/microsoft/TypeScript/pull/54546) [talking](https://github.com/microsoft/TypeScript/issues/54593) about dual build support, but they continue to [refuse to rewrite specifiers](https://github.com/microsoft/TypeScript/issues/16577).
124
+
125
+ Fortunately, Node.js has added `--experimental-require-module` so that you can [`require()` ES modules](https://nodejs.org/api/esm.html#require) if they don't use top level await, which sets the stage for possibly no longer requiring dual builds.
package/dist/cjs/duel.cjs CHANGED
@@ -28,7 +28,7 @@ const handleErrorAndExit = message => {
28
28
  const duel = async (args) => {
29
29
  const ctx = await (0, init_js_1.init)(args);
30
30
  if (ctx) {
31
- const { projectDir, tsconfig, configPath, dirs, pkg } = ctx;
31
+ const { projectDir, tsconfig, configPath, modules, dirs, pkg } = ctx;
32
32
  const tsc = await (0, find_up_1.findUp)(async (dir) => {
33
33
  const tscBin = (0, node_path_1.join)(dir, 'node_modules', '.bin', 'tsc');
34
34
  if (await (0, find_up_1.pathExists)(tscBin)) {
@@ -38,7 +38,7 @@ const duel = async (args) => {
38
38
  const runBuild = (project, outDir) => {
39
39
  return new Promise((resolve, reject) => {
40
40
  const args = outDir ? ['-p', project, '--outDir', outDir] : ['-p', project];
41
- const build = (0, node_child_process_1.spawn)(tsc, args, { stdio: 'inherit' });
41
+ const build = (0, node_child_process_1.spawn)(tsc, args, { stdio: 'inherit', shell: node_process_1.platform === 'win32' });
42
42
  build.on('error', err => {
43
43
  reject(new Error(`Failed to compile: ${err.message}`));
44
44
  });
@@ -109,16 +109,36 @@ const duel = async (args) => {
109
109
  handleErrorAndExit(message);
110
110
  }
111
111
  if (success) {
112
- const compileFiles = (0, util_js_1.getCompileFiles)(tsc, projectDir);
113
112
  const subDir = (0, node_path_1.join)(projectDir, `_${hex}_`);
114
- const dualConfigPath = (0, node_path_1.join)(subDir, `tsconfig.${hex}.json`);
115
113
  const absoluteDualOutDir = (0, node_path_1.join)(projectDir, isCjsBuild ? (0, node_path_1.join)(outDir, 'cjs') : (0, node_path_1.join)(outDir, 'esm'));
116
114
  const tsconfigDual = getOverrideTsConfig();
117
115
  const pkgRename = 'package.json.bak';
116
+ let dualConfigPath = (0, node_path_1.join)(projectDir, `tsconfig.${hex}.json`);
118
117
  let errorMsg = '';
119
- // Copy project directory as a subdirectory
120
- await (0, promises_1.mkdir)(subDir);
121
- await Promise.all(compileFiles.map(file => (0, promises_1.cp)(file, (0, node_path_1.resolve)(subDir, (0, node_path_1.relative)(projectDir, file)))));
118
+ if (modules) {
119
+ const compileFiles = (0, util_js_1.getCompileFiles)(tsc, projectDir);
120
+ dualConfigPath = (0, node_path_1.join)(subDir, `tsconfig.${hex}.json`);
121
+ await (0, promises_1.mkdir)(subDir);
122
+ await Promise.all(compileFiles.map(file => (0, promises_1.cp)(file, (0, node_path_1.join)(subDir, (0, node_path_1.relative)(projectDir, file).replace(/^(\.\.\/)*/, '')))));
123
+ /**
124
+ * Transform ambiguous modules for the target dual build.
125
+ * @see https://github.com/microsoft/TypeScript/issues/58658
126
+ */
127
+ const toTransform = await (0, glob_1.glob)(`${subDir}/**/*{.js,.jsx,.ts,.tsx}`, {
128
+ ignore: 'node_modules/**',
129
+ });
130
+ for (const file of toTransform) {
131
+ /**
132
+ * Maybe include the option to transform modules implicitly
133
+ * (modules: true) so that `exports` are correctly converted
134
+ * when targeting a CJS dual build. Depends on @knighted/module
135
+ * supporting he `modules` option.
136
+ *
137
+ * @see https://github.com/microsoft/TypeScript/issues/58658
138
+ */
139
+ await (0, module_1.transform)(file, { out: file, type: isCjsBuild ? 'commonjs' : 'module' });
140
+ }
141
+ }
122
142
  /**
123
143
  * Create a new package.json with updated `type` field.
124
144
  * Create a new tsconfig.json.
@@ -128,16 +148,6 @@ const duel = async (args) => {
128
148
  type: isCjsBuild ? 'commonjs' : 'module',
129
149
  }));
130
150
  await (0, promises_1.writeFile)(dualConfigPath, JSON.stringify(tsconfigDual));
131
- /**
132
- * Transform ambiguous modules for the target dual build.
133
- * @see https://github.com/microsoft/TypeScript/issues/58658
134
- */
135
- const toTransform = await (0, glob_1.glob)(`${subDir}/**/*{.js,.jsx,.ts,.tsx}`, {
136
- ignore: 'node_modules/**',
137
- });
138
- for (const file of toTransform) {
139
- await (0, module_1.transform)(file, { out: file, type: isCjsBuild ? 'commonjs' : 'module' });
140
- }
141
151
  // Build dual
142
152
  (0, util_js_1.log)('Starting dual build...');
143
153
  try {
@@ -169,6 +179,6 @@ const duel = async (args) => {
169
179
  };
170
180
  exports.duel = duel;
171
181
  const realFileUrlArgv1 = await (0, util_js_1.getRealPathAsFileUrl)(node_process_1.argv[1]);
172
- if (require("node:url").pathToFileURL(__filename).toString() === realFileUrlArgv1) {
182
+ if (import.meta.url === realFileUrlArgv1) {
173
183
  await duel();
174
184
  }
package/dist/cjs/init.cjs CHANGED
@@ -32,6 +32,11 @@ const init = async (args) => {
32
32
  short: 'k',
33
33
  default: (0, node_process_1.cwd)(),
34
34
  },
35
+ modules: {
36
+ type: 'boolean',
37
+ short: 'm',
38
+ default: false,
39
+ },
35
40
  dirs: {
36
41
  type: 'boolean',
37
42
  short: 'd',
@@ -55,11 +60,12 @@ const init = async (args) => {
55
60
  (0, util_js_1.log)('Options:');
56
61
  (0, util_js_1.log)("--project, -p [path] \t Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.");
57
62
  (0, util_js_1.log)('--pkg-dir, -k [path] \t The directory to start looking for a package.json file. Defaults to cwd.');
63
+ (0, util_js_1.log)('--modules, -m \t\t Transform module globals for dual build target. Defaults to false.');
58
64
  (0, util_js_1.log)('--dirs, -d \t\t Output both builds to directories inside of outDir. [esm, cjs].');
59
65
  (0, util_js_1.log)('--help, -h \t\t Print this message.');
60
66
  }
61
67
  else {
62
- const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, dirs } = parsed;
68
+ const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, modules, dirs, } = parsed;
63
69
  let configPath = (0, node_path_1.resolve)(project);
64
70
  let stats = null;
65
71
  let pkg = null;
@@ -108,6 +114,7 @@ const init = async (args) => {
108
114
  return {
109
115
  pkg,
110
116
  dirs,
117
+ modules,
111
118
  tsconfig,
112
119
  projectDir,
113
120
  configPath,
@@ -1,6 +1,7 @@
1
1
  export function init(args: any): Promise<false | {
2
2
  pkg: import("read-package-up", { with: { "resolution-mode": "import" } }).NormalizedReadResult;
3
- dirs: boolean | undefined;
3
+ dirs: boolean;
4
+ modules: boolean;
4
5
  tsconfig: any;
5
6
  projectDir: string;
6
7
  configPath: string;
package/dist/cjs/util.cjs CHANGED
@@ -5,6 +5,7 @@ const node_url_1 = require("node:url");
5
5
  const promises_1 = require("node:fs/promises");
6
6
  const node_child_process_1 = require("node:child_process");
7
7
  const node_process_1 = require("node:process");
8
+ const node_os_1 = require("node:os");
8
9
  const log = (color = '\x1b[30m', msg = '') => {
9
10
  // eslint-disable-next-line no-console
10
11
  console.log(`${color}%s\x1b[0m`, msg);
@@ -19,11 +20,14 @@ const getRealPathAsFileUrl = async (path) => {
19
20
  };
20
21
  exports.getRealPathAsFileUrl = getRealPathAsFileUrl;
21
22
  const getCompileFiles = (tscBinPath, wd = (0, node_process_1.cwd)()) => {
22
- const { stdout } = (0, node_child_process_1.spawnSync)(tscBinPath, ['--listFilesOnly'], { cwd: wd });
23
+ const { stdout } = (0, node_child_process_1.spawnSync)(tscBinPath, ['--listFilesOnly'], {
24
+ cwd: wd,
25
+ shell: node_process_1.platform === 'win32',
26
+ });
23
27
  // Exclude node_modules and empty strings.
24
28
  return stdout
25
29
  .toString()
26
- .split('\n')
30
+ .split(node_os_1.EOL)
27
31
  .filter(path => !/node_modules|^$/.test(path));
28
32
  };
29
33
  exports.getCompileFiles = getCompileFiles;
package/dist/esm/duel.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { argv } from 'node:process';
2
+ import { argv, platform } from 'node:process';
3
3
  import { join, dirname, resolve, relative } from 'node:path';
4
4
  import { spawn } from 'node:child_process';
5
- import { writeFile, rm, rename, cp, mkdir } from 'node:fs/promises';
5
+ import { writeFile, rm, rename, mkdir, cp } from 'node:fs/promises';
6
6
  import { randomBytes } from 'node:crypto';
7
7
  import { performance } from 'node:perf_hooks';
8
8
  import { glob } from 'glob';
@@ -25,7 +25,7 @@ const handleErrorAndExit = message => {
25
25
  const duel = async (args) => {
26
26
  const ctx = await init(args);
27
27
  if (ctx) {
28
- const { projectDir, tsconfig, configPath, dirs, pkg } = ctx;
28
+ const { projectDir, tsconfig, configPath, modules, dirs, pkg } = ctx;
29
29
  const tsc = await findUp(async (dir) => {
30
30
  const tscBin = join(dir, 'node_modules', '.bin', 'tsc');
31
31
  if (await pathExists(tscBin)) {
@@ -35,7 +35,7 @@ const duel = async (args) => {
35
35
  const runBuild = (project, outDir) => {
36
36
  return new Promise((resolve, reject) => {
37
37
  const args = outDir ? ['-p', project, '--outDir', outDir] : ['-p', project];
38
- const build = spawn(tsc, args, { stdio: 'inherit' });
38
+ const build = spawn(tsc, args, { stdio: 'inherit', shell: platform === 'win32' });
39
39
  build.on('error', err => {
40
40
  reject(new Error(`Failed to compile: ${err.message}`));
41
41
  });
@@ -106,16 +106,36 @@ const duel = async (args) => {
106
106
  handleErrorAndExit(message);
107
107
  }
108
108
  if (success) {
109
- const compileFiles = getCompileFiles(tsc, projectDir);
110
109
  const subDir = join(projectDir, `_${hex}_`);
111
- const dualConfigPath = join(subDir, `tsconfig.${hex}.json`);
112
110
  const absoluteDualOutDir = join(projectDir, isCjsBuild ? join(outDir, 'cjs') : join(outDir, 'esm'));
113
111
  const tsconfigDual = getOverrideTsConfig();
114
112
  const pkgRename = 'package.json.bak';
113
+ let dualConfigPath = join(projectDir, `tsconfig.${hex}.json`);
115
114
  let errorMsg = '';
116
- // Copy project directory as a subdirectory
117
- await mkdir(subDir);
118
- await Promise.all(compileFiles.map(file => cp(file, resolve(subDir, relative(projectDir, file)))));
115
+ if (modules) {
116
+ const compileFiles = getCompileFiles(tsc, projectDir);
117
+ dualConfigPath = join(subDir, `tsconfig.${hex}.json`);
118
+ await mkdir(subDir);
119
+ await Promise.all(compileFiles.map(file => cp(file, join(subDir, relative(projectDir, file).replace(/^(\.\.\/)*/, '')))));
120
+ /**
121
+ * Transform ambiguous modules for the target dual build.
122
+ * @see https://github.com/microsoft/TypeScript/issues/58658
123
+ */
124
+ const toTransform = await glob(`${subDir}/**/*{.js,.jsx,.ts,.tsx}`, {
125
+ ignore: 'node_modules/**',
126
+ });
127
+ for (const file of toTransform) {
128
+ /**
129
+ * Maybe include the option to transform modules implicitly
130
+ * (modules: true) so that `exports` are correctly converted
131
+ * when targeting a CJS dual build. Depends on @knighted/module
132
+ * supporting he `modules` option.
133
+ *
134
+ * @see https://github.com/microsoft/TypeScript/issues/58658
135
+ */
136
+ await transform(file, { out: file, type: isCjsBuild ? 'commonjs' : 'module' });
137
+ }
138
+ }
119
139
  /**
120
140
  * Create a new package.json with updated `type` field.
121
141
  * Create a new tsconfig.json.
@@ -125,16 +145,6 @@ const duel = async (args) => {
125
145
  type: isCjsBuild ? 'commonjs' : 'module',
126
146
  }));
127
147
  await writeFile(dualConfigPath, JSON.stringify(tsconfigDual));
128
- /**
129
- * Transform ambiguous modules for the target dual build.
130
- * @see https://github.com/microsoft/TypeScript/issues/58658
131
- */
132
- const toTransform = await glob(`${subDir}/**/*{.js,.jsx,.ts,.tsx}`, {
133
- ignore: 'node_modules/**',
134
- });
135
- for (const file of toTransform) {
136
- await transform(file, { out: file, type: isCjsBuild ? 'commonjs' : 'module' });
137
- }
138
148
  // Build dual
139
149
  log('Starting dual build...');
140
150
  try {
@@ -1,6 +1,7 @@
1
1
  export function init(args: any): Promise<false | {
2
2
  pkg: import("read-package-up").NormalizedReadResult;
3
- dirs: boolean | undefined;
3
+ dirs: boolean;
4
+ modules: boolean;
4
5
  tsconfig: any;
5
6
  projectDir: string;
6
7
  configPath: string;
package/dist/esm/init.js CHANGED
@@ -26,6 +26,11 @@ const init = async (args) => {
26
26
  short: 'k',
27
27
  default: cwd(),
28
28
  },
29
+ modules: {
30
+ type: 'boolean',
31
+ short: 'm',
32
+ default: false,
33
+ },
29
34
  dirs: {
30
35
  type: 'boolean',
31
36
  short: 'd',
@@ -49,11 +54,12 @@ const init = async (args) => {
49
54
  log('Options:');
50
55
  log("--project, -p [path] \t Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.");
51
56
  log('--pkg-dir, -k [path] \t The directory to start looking for a package.json file. Defaults to cwd.');
57
+ log('--modules, -m \t\t Transform module globals for dual build target. Defaults to false.');
52
58
  log('--dirs, -d \t\t Output both builds to directories inside of outDir. [esm, cjs].');
53
59
  log('--help, -h \t\t Print this message.');
54
60
  }
55
61
  else {
56
- const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, dirs } = parsed;
62
+ const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, modules, dirs, } = parsed;
57
63
  let configPath = resolve(project);
58
64
  let stats = null;
59
65
  let pkg = null;
@@ -102,6 +108,7 @@ const init = async (args) => {
102
108
  return {
103
109
  pkg,
104
110
  dirs,
111
+ modules,
105
112
  tsconfig,
106
113
  projectDir,
107
114
  configPath,
package/dist/esm/util.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { pathToFileURL } from 'node:url';
2
2
  import { realpath } from 'node:fs/promises';
3
3
  import { spawnSync } from 'node:child_process';
4
- import { cwd } from 'node:process';
4
+ import { cwd, platform } from 'node:process';
5
+ import { EOL } from 'node:os';
5
6
  const log = (color = '\x1b[30m', msg = '') => {
6
7
  // eslint-disable-next-line no-console
7
8
  console.log(`${color}%s\x1b[0m`, msg);
@@ -13,11 +14,14 @@ const getRealPathAsFileUrl = async (path) => {
13
14
  return asFileUrl;
14
15
  };
15
16
  const getCompileFiles = (tscBinPath, wd = cwd()) => {
16
- const { stdout } = spawnSync(tscBinPath, ['--listFilesOnly'], { cwd: wd });
17
+ const { stdout } = spawnSync(tscBinPath, ['--listFilesOnly'], {
18
+ cwd: wd,
19
+ shell: platform === 'win32',
20
+ });
17
21
  // Exclude node_modules and empty strings.
18
22
  return stdout
19
23
  .toString()
20
- .split('\n')
24
+ .split(EOL)
21
25
  .filter(path => !/node_modules|^$/.test(path));
22
26
  };
23
27
  export { log, logError, getRealPathAsFileUrl, getCompileFiles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knighted/duel",
3
- "version": "2.0.0-rc.0",
3
+ "version": "2.0.0-rc.2",
4
4
  "description": "TypeScript dual packages.",
5
5
  "type": "module",
6
6
  "main": "dist/esm/duel.js",
@@ -18,9 +18,11 @@
18
18
  },
19
19
  "engineStrict": true,
20
20
  "scripts": {
21
- "prettier": "prettier -w src/*.js test/*.js",
21
+ "prettier": "prettier -w *.js src/*.js test/*.js",
22
22
  "lint": "eslint src/*.js test/*.js",
23
- "test": "c8 --reporter=text --reporter=text-summary --reporter=lcov node --test --test-reporter=spec test/*.js",
23
+ "test:integration": "node --test --test-reporter=spec test/integration.js",
24
+ "test:monorepos": "node --test --test-reporter=spec test/monorepos.js",
25
+ "test": "c8 --reporter=text --reporter=text-summary --reporter=lcov node --test --test-reporter=spec test/integration.js test/monorepos.js",
24
26
  "build": "node src/duel.js --dirs",
25
27
  "prepack": "npm run build"
26
28
  },
@@ -51,19 +53,22 @@
51
53
  "url": "https://github.com/knightedcodemonkey/duel/issues"
52
54
  },
53
55
  "peerDependencies": {
54
- "typescript": ">=4.0.0 || >=4.9.0-dev || >=5.3.0-dev || >=5.4.0-dev || >=5.5.0-dev || next"
56
+ "typescript": ">=5.5.0-dev || >=5.6.0-dev || >=5.7.0-dev || next"
55
57
  },
56
58
  "devDependencies": {
57
- "@types/node": "^20.11.0",
58
- "c8": "^8.0.1",
59
- "eslint": "^8.45.0",
60
- "eslint-plugin-n": "^16.0.1",
59
+ "@eslint/js": "^9.6.0",
60
+ "@types/node": "^22.7.4",
61
+ "c8": "^10.1.2",
62
+ "eslint": "^9.5.0",
63
+ "eslint-plugin-n": "^17.9.0",
64
+ "globals": "^15.6.0",
61
65
  "prettier": "^3.2.4",
62
- "typescript": "^5.5.0-dev.20240525",
63
- "vite": "^5.2.8"
66
+ "tsx": "^4.19.1",
67
+ "typescript": "^5.6.2",
68
+ "vite": "^5.4.8"
64
69
  },
65
70
  "dependencies": {
66
- "@knighted/module": "^1.0.0-alpha.3",
71
+ "@knighted/module": "^1.0.0-alpha.4",
67
72
  "@knighted/specifier": "^2.0.0-rc.1",
68
73
  "find-up": "^6.3.0",
69
74
  "glob": "^10.3.3",