@knighted/duel 3.1.0 → 3.2.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/README.md +31 -18
- package/dist/cjs/duel.cjs +7 -11
- package/dist/cjs/init.cjs +45 -10
- package/dist/cjs/init.d.cts +1 -0
- package/dist/cjs/util.cjs +30 -4
- package/dist/cjs/util.d.cts +4 -2
- package/dist/esm/duel.js +8 -12
- package/dist/esm/init.d.ts +1 -0
- package/dist/esm/init.js +45 -10
- package/dist/esm/util.d.ts +4 -2
- package/dist/esm/util.js +28 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -71,16 +71,14 @@ Assuming an `outDir` of `dist`, running the above will create `dist/esm` and `di
|
|
|
71
71
|
|
|
72
72
|
### Module transforms
|
|
73
73
|
|
|
74
|
-
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
|
|
74
|
+
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 asymmetry. Prefer the single-switch `--mode` interface: `--mode globals` (equivalent to `--modules`) or `--mode full` (equivalent to `--modules --transform-syntax`) to have the [ESM vs CJS differences](https://nodejs.org/api/esm.html#differences-between-es-modules-and-commonjs) transformed by `duel` prior to running `tsc` so you avoid compilation or runtime errors. The legacy `--modules`/`--transform-syntax` flags remain supported.
|
|
75
75
|
|
|
76
76
|
`duel` infers the primary vs dual build orientation from your `package.json` `type`:
|
|
77
77
|
|
|
78
78
|
- `"type": "module"` → primary ESM, dual CJS
|
|
79
79
|
- `"type": "commonjs"` → primary CJS, dual ESM
|
|
80
80
|
|
|
81
|
-
The `--dirs` flag nests outputs under `outDir/esm` and `outDir/cjs` accordingly.
|
|
82
|
-
|
|
83
|
-
Note, there is a slight performance penalty since your project needs to be copied first to run the transforms before compiling with `tsc`.
|
|
81
|
+
The `--dirs` flag nests outputs under `outDir/esm` and `outDir/cjs` accordingly. There is a small performance cost because sources are copied to run the transform before `tsc`.
|
|
84
82
|
|
|
85
83
|
```json
|
|
86
84
|
"scripts": {
|
|
@@ -88,7 +86,31 @@ Note, there is a slight performance penalty since your project needs to be copie
|
|
|
88
86
|
}
|
|
89
87
|
```
|
|
90
88
|
|
|
91
|
-
|
|
89
|
+
For projects that need full syntax lowering, opt in explicitly:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
"scripts": {
|
|
93
|
+
"build": "duel --modules --transform-syntax"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Using the single switch:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
"scripts": {
|
|
101
|
+
"build": "duel --mode globals"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
"scripts": {
|
|
107
|
+
"build": "duel --mode full"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Pre-`tsc` transform (TypeScript 58658)
|
|
112
|
+
|
|
113
|
+
When you enable module transforms (`--mode globals`, `--mode full`, or `--modules`), `duel` copies your sources and runs [`@knighted/module`](https://github.com/knightedcodemonkey/module) **before** `tsc` so the transformed files no longer trigger TypeScript’s asymmetrical module-global errors (see [TypeScript#58658](https://github.com/microsoft/TypeScript/issues/58658)). No extra setup is needed: module transforms are the pre-`tsc` mitigation. If you also select full lowering (`--mode full` or `--transform-syntax`), that pre-`tsc` step performs full lowering instead of globals-only.
|
|
92
114
|
|
|
93
115
|
## Options
|
|
94
116
|
|
|
@@ -96,25 +118,16 @@ The available options are limited, because you should define most of them inside
|
|
|
96
118
|
|
|
97
119
|
- `--project, -p` The path to the project's configuration file. Defaults to `tsconfig.json`.
|
|
98
120
|
- `--pkg-dir, -k` The directory to start looking for a package.json file. Defaults to `--project` dir.
|
|
121
|
+
- `--mode` Optional shorthand for the module transform mode: `none` (default), `globals` (modules + globals-only), `full` (modules + full syntax lowering). Recommended.
|
|
99
122
|
- `--modules, -m` Transform module globals for dual build target. Defaults to false.
|
|
123
|
+
- `--transform-syntax, -s` Opt in to full syntax lowering via `@knighted/module` (default is globals-only). Implies `--modules`.
|
|
100
124
|
- `--dirs, -d` Outputs both builds to directories inside of `outDir`. Defaults to `false`.
|
|
101
125
|
- `--exports, -e` Generate `package.json` `exports` from build output. Values: `wildcard` | `dir` | `name`.
|
|
102
126
|
|
|
103
127
|
> [!NOTE]
|
|
104
128
|
> Exports keys are extensionless by design; the target `import`/`require`/`types` entries keep explicit file extensions so Node resolution remains deterministic.
|
|
105
129
|
|
|
106
|
-
You can run `duel --help` to get the same info.
|
|
107
|
-
|
|
108
|
-
```console
|
|
109
|
-
Usage: duel [options]
|
|
110
|
-
|
|
111
|
-
Options:
|
|
112
|
-
--project, -p [path] Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.
|
|
113
|
-
--pkg-dir, -k [path] The directory to start looking for a package.json file. Defaults to --project directory.
|
|
114
|
-
--modules, -m Transform module globals for dual build target. Defaults to false.
|
|
115
|
-
--dirs, -d Output both builds to directories inside of outDir. [esm, cjs].
|
|
116
|
-
--help, -h Print this message.
|
|
117
|
-
```
|
|
130
|
+
You can run `duel --help` to get the same info.
|
|
118
131
|
|
|
119
132
|
## Gotchas
|
|
120
133
|
|
|
@@ -122,7 +135,7 @@ These are definitely edge cases, and would only really come up if your project m
|
|
|
122
135
|
|
|
123
136
|
- 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.
|
|
124
137
|
|
|
125
|
-
- Unfortunately, `tsc` doesn't support [dual packages](https://nodejs.org/api/packages.html#dual-commonjses-module-packages) completely.
|
|
138
|
+
- Unfortunately, `tsc` doesn't support [dual packages](https://nodejs.org/api/packages.html#dual-commonjses-module-packages) completely. For mitigation details, see the pre-`tsc` transform note above (`--modules`).
|
|
126
139
|
|
|
127
140
|
- If running `duel` with your project's package.json file open in your editor, you may temporarily see the content replaced. This is because `duel` dynamically creates a new package.json using the `type` necessary for the dual build. Your original package.json will be restored after the build completes.
|
|
128
141
|
|
package/dist/cjs/duel.cjs
CHANGED
|
@@ -184,7 +184,7 @@ const generateExports = async (options) => {
|
|
|
184
184
|
const duel = async (args) => {
|
|
185
185
|
const ctx = await (0, init_js_1.init)(args);
|
|
186
186
|
if (ctx) {
|
|
187
|
-
const { projectDir, tsconfig, configPath, modules, dirs, pkg, exports: exportsOpt, } = ctx;
|
|
187
|
+
const { projectDir, tsconfig, configPath, modules, dirs, transformSyntax, pkg, exports: exportsOpt, } = ctx;
|
|
188
188
|
const tsc = await (0, find_up_1.findUp)(async (dir) => {
|
|
189
189
|
const tscBin = (0, node_path_1.join)(dir, 'node_modules', '.bin', 'tsc');
|
|
190
190
|
try {
|
|
@@ -233,6 +233,7 @@ const duel = async (args) => {
|
|
|
233
233
|
const runPrimaryBuild = () => {
|
|
234
234
|
return runBuild(configPath, primaryOutDir);
|
|
235
235
|
};
|
|
236
|
+
const syntaxMode = transformSyntax ? true : 'globals-only';
|
|
236
237
|
const updateSpecifiersAndFileExtensions = async (filenames, target, ext) => {
|
|
237
238
|
for (const filename of filenames) {
|
|
238
239
|
const dts = /(\.d\.ts)$/;
|
|
@@ -258,6 +259,7 @@ const duel = async (args) => {
|
|
|
258
259
|
const writeOptions = {
|
|
259
260
|
target,
|
|
260
261
|
rewriteSpecifier,
|
|
262
|
+
transformSyntax: syntaxMode,
|
|
261
263
|
...(outFilename === filename ? { inPlace: true } : { out: outFilename }),
|
|
262
264
|
};
|
|
263
265
|
await (0, module_1.transform)(filename, writeOptions);
|
|
@@ -267,7 +269,7 @@ const duel = async (args) => {
|
|
|
267
269
|
}
|
|
268
270
|
};
|
|
269
271
|
const logSuccess = start => {
|
|
270
|
-
(0, util_js_1.
|
|
272
|
+
(0, util_js_1.logSuccess)(`Successfully created a dual ${isCjsBuild ? 'CJS' : 'ESM'} build in ${Math.round(node_perf_hooks_1.performance.now() - start)}ms.`);
|
|
271
273
|
};
|
|
272
274
|
(0, util_js_1.log)('Starting primary build...');
|
|
273
275
|
let success = false;
|
|
@@ -303,18 +305,12 @@ const duel = async (args) => {
|
|
|
303
305
|
ignore: 'node_modules/**',
|
|
304
306
|
});
|
|
305
307
|
for (const file of toTransform) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
* (modules: true) so that `exports` are correctly converted
|
|
309
|
-
* when targeting a CJS dual build. Depends on @knighted/module
|
|
310
|
-
* supporting he `modules` option.
|
|
311
|
-
*
|
|
312
|
-
* @see https://github.com/microsoft/TypeScript/issues/58658
|
|
313
|
-
*/
|
|
308
|
+
const isTsLike = /\.[cm]?tsx?$/.test(file);
|
|
309
|
+
const transformSyntaxMode = syntaxMode === true && isTsLike ? 'globals-only' : syntaxMode;
|
|
314
310
|
await (0, module_1.transform)(file, {
|
|
315
311
|
out: file,
|
|
316
312
|
target: isCjsBuild ? 'commonjs' : 'module',
|
|
317
|
-
transformSyntax:
|
|
313
|
+
transformSyntax: transformSyntaxMode,
|
|
318
314
|
});
|
|
319
315
|
}
|
|
320
316
|
}
|
package/dist/cjs/init.cjs
CHANGED
|
@@ -41,6 +41,14 @@ const init = async (args) => {
|
|
|
41
41
|
type: 'string',
|
|
42
42
|
short: 'e',
|
|
43
43
|
},
|
|
44
|
+
'transform-syntax': {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
short: 's',
|
|
47
|
+
default: false,
|
|
48
|
+
},
|
|
49
|
+
mode: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
},
|
|
44
52
|
help: {
|
|
45
53
|
type: 'boolean',
|
|
46
54
|
short: 'h',
|
|
@@ -55,20 +63,27 @@ const init = async (args) => {
|
|
|
55
63
|
return false;
|
|
56
64
|
}
|
|
57
65
|
if (parsed.help) {
|
|
58
|
-
|
|
59
|
-
(0, util_js_1.log)('
|
|
60
|
-
(0, util_js_1.log)(
|
|
61
|
-
(0, util_js_1.log)(
|
|
62
|
-
(0, util_js_1.log)('--
|
|
63
|
-
(0, util_js_1.log)('--
|
|
64
|
-
(0, util_js_1.log)('--
|
|
65
|
-
(0, util_js_1.log)('--
|
|
66
|
+
const bare = { bare: true };
|
|
67
|
+
(0, util_js_1.log)('Usage: duel [options]\n', 'info', bare);
|
|
68
|
+
(0, util_js_1.log)('Options:', 'info', bare);
|
|
69
|
+
(0, util_js_1.log)("--project, -p [path] \t\t Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.", 'info', bare);
|
|
70
|
+
(0, util_js_1.log)('--pkg-dir, -k [path] \t\t The directory to start looking for a package.json file. Defaults to --project directory.', 'info', bare);
|
|
71
|
+
(0, util_js_1.log)('--modules, -m \t\t\t Transform module globals for dual build target. Defaults to false.', 'info', bare);
|
|
72
|
+
(0, util_js_1.log)('--dirs, -d \t\t\t Output both builds to directories inside of outDir. [esm, cjs].', 'info', bare);
|
|
73
|
+
(0, util_js_1.log)('--exports, -e \t\t\t Generate package.json exports. Values: wildcard | dir | name.', 'info', bare);
|
|
74
|
+
(0, util_js_1.log)('--transform-syntax, -s \t\t Opt in to full syntax lowering via @knighted/module (default is globals-only).', 'info', bare);
|
|
75
|
+
(0, util_js_1.log)('--mode [none|globals|full] \t Optional shorthand for module transforms and syntax lowering.', 'info', bare);
|
|
76
|
+
(0, util_js_1.log)('--help, -h \t\t\t Print this message.', 'info', bare);
|
|
66
77
|
}
|
|
67
78
|
else {
|
|
68
|
-
const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, modules, dirs, exports: exportsOpt, } = parsed;
|
|
79
|
+
const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, modules, dirs, exports: exportsOpt, 'transform-syntax': transformSyntax, mode, } = parsed;
|
|
69
80
|
let configPath = (0, node_path_1.resolve)(project);
|
|
70
81
|
let stats = null;
|
|
71
82
|
let pkg = null;
|
|
83
|
+
if (mode && !['none', 'globals', 'full'].includes(mode)) {
|
|
84
|
+
(0, util_js_1.logError)('--mode expects one of: none | globals | full');
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
72
87
|
if (targetExt) {
|
|
73
88
|
(0, util_js_1.logError)('--target-extension is deprecated. Define "type" in your package.json instead and the dual build will be inferred from that.');
|
|
74
89
|
return false;
|
|
@@ -105,10 +120,30 @@ const init = async (args) => {
|
|
|
105
120
|
(0, util_js_1.logError)('--exports expects one of: wildcard | dir | name');
|
|
106
121
|
return false;
|
|
107
122
|
}
|
|
123
|
+
let modulesFinal = modules;
|
|
124
|
+
let transformSyntaxFinal = transformSyntax;
|
|
125
|
+
if (mode) {
|
|
126
|
+
if (mode === 'none') {
|
|
127
|
+
modulesFinal = false;
|
|
128
|
+
transformSyntaxFinal = false;
|
|
129
|
+
}
|
|
130
|
+
else if (mode === 'globals') {
|
|
131
|
+
modulesFinal = true;
|
|
132
|
+
transformSyntaxFinal = false;
|
|
133
|
+
}
|
|
134
|
+
else if (mode === 'full') {
|
|
135
|
+
modulesFinal = true;
|
|
136
|
+
transformSyntaxFinal = true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (transformSyntax && !modules) {
|
|
140
|
+
modulesFinal = true;
|
|
141
|
+
}
|
|
108
142
|
return {
|
|
109
143
|
pkg,
|
|
110
144
|
dirs,
|
|
111
|
-
modules,
|
|
145
|
+
modules: modulesFinal,
|
|
146
|
+
transformSyntax: transformSyntaxFinal,
|
|
112
147
|
exports: exportsOpt,
|
|
113
148
|
tsconfig,
|
|
114
149
|
projectDir,
|
package/dist/cjs/init.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ export function init(args: any): Promise<false | {
|
|
|
2
2
|
pkg: import("read-package-up", { with: { "resolution-mode": "import" } }).NormalizedReadResult;
|
|
3
3
|
dirs: boolean;
|
|
4
4
|
modules: boolean;
|
|
5
|
+
transformSyntax: boolean;
|
|
5
6
|
exports: string | undefined;
|
|
6
7
|
tsconfig: {
|
|
7
8
|
compilerOptions?: import("get-tsconfig").TsConfigJson.CompilerOptions | undefined;
|
package/dist/cjs/util.cjs
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCompileFiles = exports.getRealPathAsFileUrl = exports.logError = exports.log = void 0;
|
|
3
|
+
exports.getCompileFiles = exports.getRealPathAsFileUrl = exports.logWarn = exports.logSuccess = exports.logError = exports.log = void 0;
|
|
4
4
|
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
8
|
const node_os_1 = require("node:os");
|
|
9
|
-
const
|
|
9
|
+
const COLORS = {
|
|
10
|
+
reset: '\x1b[0m',
|
|
11
|
+
info: '\x1b[36m',
|
|
12
|
+
success: '\x1b[32m',
|
|
13
|
+
warn: '\x1b[33m',
|
|
14
|
+
error: '\x1b[31m',
|
|
15
|
+
};
|
|
16
|
+
const log = (msg = '', level = 'info', opts = {}) => {
|
|
17
|
+
const { bare = false } = opts;
|
|
18
|
+
const palette = {
|
|
19
|
+
info: COLORS.info,
|
|
20
|
+
success: COLORS.success,
|
|
21
|
+
warn: COLORS.warn,
|
|
22
|
+
error: COLORS.error,
|
|
23
|
+
};
|
|
24
|
+
const badge = {
|
|
25
|
+
success: '[✓]',
|
|
26
|
+
warn: '[!]',
|
|
27
|
+
error: '[x]',
|
|
28
|
+
info: '[i]',
|
|
29
|
+
}[level];
|
|
30
|
+
const color = palette[level] ?? COLORS.info;
|
|
31
|
+
const prefix = !bare && badge ? `${badge} ` : '';
|
|
10
32
|
// eslint-disable-next-line no-console
|
|
11
|
-
console.log(`${color}%s
|
|
33
|
+
console.log(`${color}${prefix}%s${COLORS.reset}`, msg);
|
|
12
34
|
};
|
|
13
35
|
exports.log = log;
|
|
14
|
-
const
|
|
36
|
+
const logSuccess = msg => log(msg, 'success');
|
|
37
|
+
exports.logSuccess = logSuccess;
|
|
38
|
+
const logWarn = msg => log(msg, 'warn');
|
|
39
|
+
exports.logWarn = logWarn;
|
|
40
|
+
const logError = msg => log(msg, 'error');
|
|
15
41
|
exports.logError = logError;
|
|
16
42
|
const getRealPathAsFileUrl = async (path) => {
|
|
17
43
|
const realPath = await (0, promises_1.realpath)(path);
|
package/dist/cjs/util.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export function log(
|
|
2
|
-
export
|
|
1
|
+
export function log(msg?: string, level?: string, opts?: {}): void;
|
|
2
|
+
export function logError(msg: any): void;
|
|
3
|
+
export function logSuccess(msg: any): void;
|
|
4
|
+
export function logWarn(msg: any): void;
|
|
3
5
|
export function getRealPathAsFileUrl(path: any): Promise<string>;
|
|
4
6
|
export function getCompileFiles(tscBinPath: any, wd?: string): string[];
|
package/dist/esm/duel.js
CHANGED
|
@@ -9,7 +9,7 @@ import { glob } from 'glob';
|
|
|
9
9
|
import { findUp } from 'find-up';
|
|
10
10
|
import { transform } from '@knighted/module';
|
|
11
11
|
import { init } from './init.js';
|
|
12
|
-
import { getRealPathAsFileUrl, getCompileFiles, logError,
|
|
12
|
+
import { getRealPathAsFileUrl, getCompileFiles, log, logError, logSuccess as logSuccessBadge, } from './util.js';
|
|
13
13
|
const stripKnownExt = path => {
|
|
14
14
|
return path.replace(/(\.d\.(?:ts|mts|cts)|\.(?:mjs|cjs|js))$/, '');
|
|
15
15
|
};
|
|
@@ -181,7 +181,7 @@ const generateExports = async (options) => {
|
|
|
181
181
|
const duel = async (args) => {
|
|
182
182
|
const ctx = await init(args);
|
|
183
183
|
if (ctx) {
|
|
184
|
-
const { projectDir, tsconfig, configPath, modules, dirs, pkg, exports: exportsOpt, } = ctx;
|
|
184
|
+
const { projectDir, tsconfig, configPath, modules, dirs, transformSyntax, pkg, exports: exportsOpt, } = ctx;
|
|
185
185
|
const tsc = await findUp(async (dir) => {
|
|
186
186
|
const tscBin = join(dir, 'node_modules', '.bin', 'tsc');
|
|
187
187
|
try {
|
|
@@ -230,6 +230,7 @@ const duel = async (args) => {
|
|
|
230
230
|
const runPrimaryBuild = () => {
|
|
231
231
|
return runBuild(configPath, primaryOutDir);
|
|
232
232
|
};
|
|
233
|
+
const syntaxMode = transformSyntax ? true : 'globals-only';
|
|
233
234
|
const updateSpecifiersAndFileExtensions = async (filenames, target, ext) => {
|
|
234
235
|
for (const filename of filenames) {
|
|
235
236
|
const dts = /(\.d\.ts)$/;
|
|
@@ -255,6 +256,7 @@ const duel = async (args) => {
|
|
|
255
256
|
const writeOptions = {
|
|
256
257
|
target,
|
|
257
258
|
rewriteSpecifier,
|
|
259
|
+
transformSyntax: syntaxMode,
|
|
258
260
|
...(outFilename === filename ? { inPlace: true } : { out: outFilename }),
|
|
259
261
|
};
|
|
260
262
|
await transform(filename, writeOptions);
|
|
@@ -264,7 +266,7 @@ const duel = async (args) => {
|
|
|
264
266
|
}
|
|
265
267
|
};
|
|
266
268
|
const logSuccess = start => {
|
|
267
|
-
|
|
269
|
+
logSuccessBadge(`Successfully created a dual ${isCjsBuild ? 'CJS' : 'ESM'} build in ${Math.round(performance.now() - start)}ms.`);
|
|
268
270
|
};
|
|
269
271
|
log('Starting primary build...');
|
|
270
272
|
let success = false;
|
|
@@ -300,18 +302,12 @@ const duel = async (args) => {
|
|
|
300
302
|
ignore: 'node_modules/**',
|
|
301
303
|
});
|
|
302
304
|
for (const file of toTransform) {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
* (modules: true) so that `exports` are correctly converted
|
|
306
|
-
* when targeting a CJS dual build. Depends on @knighted/module
|
|
307
|
-
* supporting he `modules` option.
|
|
308
|
-
*
|
|
309
|
-
* @see https://github.com/microsoft/TypeScript/issues/58658
|
|
310
|
-
*/
|
|
305
|
+
const isTsLike = /\.[cm]?tsx?$/.test(file);
|
|
306
|
+
const transformSyntaxMode = syntaxMode === true && isTsLike ? 'globals-only' : syntaxMode;
|
|
311
307
|
await transform(file, {
|
|
312
308
|
out: file,
|
|
313
309
|
target: isCjsBuild ? 'commonjs' : 'module',
|
|
314
|
-
transformSyntax:
|
|
310
|
+
transformSyntax: transformSyntaxMode,
|
|
315
311
|
});
|
|
316
312
|
}
|
|
317
313
|
}
|
package/dist/esm/init.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export function init(args: any): Promise<false | {
|
|
|
2
2
|
pkg: import("read-package-up").NormalizedReadResult;
|
|
3
3
|
dirs: boolean;
|
|
4
4
|
modules: boolean;
|
|
5
|
+
transformSyntax: boolean;
|
|
5
6
|
exports: string | undefined;
|
|
6
7
|
tsconfig: {
|
|
7
8
|
compilerOptions?: import("get-tsconfig").TsConfigJson.CompilerOptions | undefined;
|
package/dist/esm/init.js
CHANGED
|
@@ -38,6 +38,14 @@ const init = async (args) => {
|
|
|
38
38
|
type: 'string',
|
|
39
39
|
short: 'e',
|
|
40
40
|
},
|
|
41
|
+
'transform-syntax': {
|
|
42
|
+
type: 'boolean',
|
|
43
|
+
short: 's',
|
|
44
|
+
default: false,
|
|
45
|
+
},
|
|
46
|
+
mode: {
|
|
47
|
+
type: 'string',
|
|
48
|
+
},
|
|
41
49
|
help: {
|
|
42
50
|
type: 'boolean',
|
|
43
51
|
short: 'h',
|
|
@@ -52,20 +60,27 @@ const init = async (args) => {
|
|
|
52
60
|
return false;
|
|
53
61
|
}
|
|
54
62
|
if (parsed.help) {
|
|
55
|
-
|
|
56
|
-
log('
|
|
57
|
-
log(
|
|
58
|
-
log(
|
|
59
|
-
log('--
|
|
60
|
-
log('--
|
|
61
|
-
log('--
|
|
62
|
-
log('--
|
|
63
|
+
const bare = { bare: true };
|
|
64
|
+
log('Usage: duel [options]\n', 'info', bare);
|
|
65
|
+
log('Options:', 'info', bare);
|
|
66
|
+
log("--project, -p [path] \t\t Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.", 'info', bare);
|
|
67
|
+
log('--pkg-dir, -k [path] \t\t The directory to start looking for a package.json file. Defaults to --project directory.', 'info', bare);
|
|
68
|
+
log('--modules, -m \t\t\t Transform module globals for dual build target. Defaults to false.', 'info', bare);
|
|
69
|
+
log('--dirs, -d \t\t\t Output both builds to directories inside of outDir. [esm, cjs].', 'info', bare);
|
|
70
|
+
log('--exports, -e \t\t\t Generate package.json exports. Values: wildcard | dir | name.', 'info', bare);
|
|
71
|
+
log('--transform-syntax, -s \t\t Opt in to full syntax lowering via @knighted/module (default is globals-only).', 'info', bare);
|
|
72
|
+
log('--mode [none|globals|full] \t Optional shorthand for module transforms and syntax lowering.', 'info', bare);
|
|
73
|
+
log('--help, -h \t\t\t Print this message.', 'info', bare);
|
|
63
74
|
}
|
|
64
75
|
else {
|
|
65
|
-
const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, modules, dirs, exports: exportsOpt, } = parsed;
|
|
76
|
+
const { project, 'target-extension': targetExt, 'pkg-dir': pkgDir, modules, dirs, exports: exportsOpt, 'transform-syntax': transformSyntax, mode, } = parsed;
|
|
66
77
|
let configPath = resolve(project);
|
|
67
78
|
let stats = null;
|
|
68
79
|
let pkg = null;
|
|
80
|
+
if (mode && !['none', 'globals', 'full'].includes(mode)) {
|
|
81
|
+
logError('--mode expects one of: none | globals | full');
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
69
84
|
if (targetExt) {
|
|
70
85
|
logError('--target-extension is deprecated. Define "type" in your package.json instead and the dual build will be inferred from that.');
|
|
71
86
|
return false;
|
|
@@ -102,10 +117,30 @@ const init = async (args) => {
|
|
|
102
117
|
logError('--exports expects one of: wildcard | dir | name');
|
|
103
118
|
return false;
|
|
104
119
|
}
|
|
120
|
+
let modulesFinal = modules;
|
|
121
|
+
let transformSyntaxFinal = transformSyntax;
|
|
122
|
+
if (mode) {
|
|
123
|
+
if (mode === 'none') {
|
|
124
|
+
modulesFinal = false;
|
|
125
|
+
transformSyntaxFinal = false;
|
|
126
|
+
}
|
|
127
|
+
else if (mode === 'globals') {
|
|
128
|
+
modulesFinal = true;
|
|
129
|
+
transformSyntaxFinal = false;
|
|
130
|
+
}
|
|
131
|
+
else if (mode === 'full') {
|
|
132
|
+
modulesFinal = true;
|
|
133
|
+
transformSyntaxFinal = true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (transformSyntax && !modules) {
|
|
137
|
+
modulesFinal = true;
|
|
138
|
+
}
|
|
105
139
|
return {
|
|
106
140
|
pkg,
|
|
107
141
|
dirs,
|
|
108
|
-
modules,
|
|
142
|
+
modules: modulesFinal,
|
|
143
|
+
transformSyntax: transformSyntaxFinal,
|
|
109
144
|
exports: exportsOpt,
|
|
110
145
|
tsconfig,
|
|
111
146
|
projectDir,
|
package/dist/esm/util.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export function log(
|
|
2
|
-
export
|
|
1
|
+
export function log(msg?: string, level?: string, opts?: {}): void;
|
|
2
|
+
export function logError(msg: any): void;
|
|
3
|
+
export function logSuccess(msg: any): void;
|
|
4
|
+
export function logWarn(msg: any): void;
|
|
3
5
|
export function getRealPathAsFileUrl(path: any): Promise<string>;
|
|
4
6
|
export function getCompileFiles(tscBinPath: any, wd?: string): string[];
|
package/dist/esm/util.js
CHANGED
|
@@ -3,11 +3,35 @@ import { realpath } from 'node:fs/promises';
|
|
|
3
3
|
import { spawnSync } from 'node:child_process';
|
|
4
4
|
import { cwd, platform } from 'node:process';
|
|
5
5
|
import { EOL } from 'node:os';
|
|
6
|
-
const
|
|
6
|
+
const COLORS = {
|
|
7
|
+
reset: '\x1b[0m',
|
|
8
|
+
info: '\x1b[36m',
|
|
9
|
+
success: '\x1b[32m',
|
|
10
|
+
warn: '\x1b[33m',
|
|
11
|
+
error: '\x1b[31m',
|
|
12
|
+
};
|
|
13
|
+
const log = (msg = '', level = 'info', opts = {}) => {
|
|
14
|
+
const { bare = false } = opts;
|
|
15
|
+
const palette = {
|
|
16
|
+
info: COLORS.info,
|
|
17
|
+
success: COLORS.success,
|
|
18
|
+
warn: COLORS.warn,
|
|
19
|
+
error: COLORS.error,
|
|
20
|
+
};
|
|
21
|
+
const badge = {
|
|
22
|
+
success: '[✓]',
|
|
23
|
+
warn: '[!]',
|
|
24
|
+
error: '[x]',
|
|
25
|
+
info: '[i]',
|
|
26
|
+
}[level];
|
|
27
|
+
const color = palette[level] ?? COLORS.info;
|
|
28
|
+
const prefix = !bare && badge ? `${badge} ` : '';
|
|
7
29
|
// eslint-disable-next-line no-console
|
|
8
|
-
console.log(`${color}%s
|
|
30
|
+
console.log(`${color}${prefix}%s${COLORS.reset}`, msg);
|
|
9
31
|
};
|
|
10
|
-
const
|
|
32
|
+
const logSuccess = msg => log(msg, 'success');
|
|
33
|
+
const logWarn = msg => log(msg, 'warn');
|
|
34
|
+
const logError = msg => log(msg, 'error');
|
|
11
35
|
const getRealPathAsFileUrl = async (path) => {
|
|
12
36
|
const realPath = await realpath(path);
|
|
13
37
|
const asFileUrl = pathToFileURL(realPath).href;
|
|
@@ -24,4 +48,4 @@ const getCompileFiles = (tscBinPath, wd = cwd()) => {
|
|
|
24
48
|
.split(EOL)
|
|
25
49
|
.filter(path => !/node_modules|^$/.test(path));
|
|
26
50
|
};
|
|
27
|
-
export { log, logError, getRealPathAsFileUrl, getCompileFiles };
|
|
51
|
+
export { log, logError, logSuccess, logWarn, getRealPathAsFileUrl, getCompileFiles };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/duel",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "TypeScript dual packages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/esm/duel.js",
|
|
@@ -67,7 +67,6 @@
|
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@eslint/js": "^9.39.1",
|
|
70
|
-
"@knighted/module": "^1.0.0-rc.2",
|
|
71
70
|
"@tsconfig/recommended": "^1.0.10",
|
|
72
71
|
"@types/node": "^24.10.1",
|
|
73
72
|
"c8": "^10.1.3",
|
|
@@ -83,6 +82,7 @@
|
|
|
83
82
|
"vite": "^7.2.4"
|
|
84
83
|
},
|
|
85
84
|
"dependencies": {
|
|
85
|
+
"@knighted/module": "^1.0.0-rc.6",
|
|
86
86
|
"find-up": "^8.0.0",
|
|
87
87
|
"get-tsconfig": "^4.13.0",
|
|
88
88
|
"glob": "^13.0.0",
|