@knighted/duel 1.0.0-alpha.3 → 1.0.0-alpha.4
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 +3 -3
- package/dist/duel.cjs +51 -5
- package/dist/duel.js +53 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
Node.js tool for creating a TypeScript dual package.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Inspired by https://github.com/microsoft/TypeScript/issues/49462.
|
|
10
10
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
@@ -79,8 +79,8 @@ Options:
|
|
|
79
79
|
|
|
80
80
|
## Gotchas
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
These are definitely edge cases, and would only really come up if your project mixes file extensions. For example, if you have `.ts` files combined with `.mts`, and/or `.cts`. For most project, things should just work as expected.
|
|
83
83
|
|
|
84
|
-
*
|
|
84
|
+
* 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_. In my opinion, the `tsc` compiler is fundamentally broken in this regard, and at best is enforcing usage patterns it shouldn't. If you want to see one of my extended rants on this, check out this [comment](https://github.com/microsoft/TypeScript/pull/50985#issuecomment-1656991606). This is only mentioned for transparency, `duel` will correct for this and produce files with the module system you would expect based on the files extension, so that it works with [how Node.js determines module systems](https://nodejs.org/api/packages.html#determining-module-system).
|
|
85
85
|
|
|
86
86
|
* 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`.
|
package/dist/duel.cjs
CHANGED
|
@@ -15,7 +15,6 @@ var _glob = require("glob");
|
|
|
15
15
|
var _specifier = require("@knighted/specifier");
|
|
16
16
|
var _init = require("./init.cjs");
|
|
17
17
|
var _util = require("./util.cjs");
|
|
18
|
-
// TypeScript is defined as a peer dependency.
|
|
19
18
|
const tsc = (0, _nodePath.join)((0, _nodeProcess.cwd)(), 'node_modules', '.bin', 'tsc');
|
|
20
19
|
const runBuild = project => {
|
|
21
20
|
const {
|
|
@@ -45,7 +44,8 @@ const duel = async args => {
|
|
|
45
44
|
projectDir,
|
|
46
45
|
tsconfig,
|
|
47
46
|
targetExt,
|
|
48
|
-
configPath
|
|
47
|
+
configPath,
|
|
48
|
+
absoluteOutDir
|
|
49
49
|
} = ctx;
|
|
50
50
|
const startTime = _nodePerf_hooks.performance.now();
|
|
51
51
|
(0, _util.log)('Starting primary build...\n');
|
|
@@ -58,13 +58,15 @@ const duel = async args => {
|
|
|
58
58
|
} = tsconfig.compilerOptions;
|
|
59
59
|
const dualConfigPath = (0, _nodePath.join)(projectDir, `tsconfig.${hex}.json`);
|
|
60
60
|
const dualOutDir = isCjsBuild ? (0, _nodePath.join)(outDir, 'cjs') : (0, _nodePath.join)(outDir, 'mjs');
|
|
61
|
+
// Using structuredClone() would require node >= 17.0.0
|
|
61
62
|
const tsconfigDual = {
|
|
62
63
|
...tsconfig,
|
|
63
64
|
compilerOptions: {
|
|
64
65
|
...tsconfig.compilerOptions,
|
|
65
66
|
outDir: dualOutDir,
|
|
66
|
-
module: isCjsBuild ? 'CommonJS' : '
|
|
67
|
-
|
|
67
|
+
module: isCjsBuild ? 'CommonJS' : 'ESNext',
|
|
68
|
+
// Best way to make this work given how tsc works
|
|
69
|
+
moduleResolution: 'Node'
|
|
68
70
|
}
|
|
69
71
|
};
|
|
70
72
|
await (0, _promises.writeFile)(dualConfigPath, JSON.stringify(tsconfigDual, null, 2));
|
|
@@ -74,7 +76,8 @@ const duel = async args => {
|
|
|
74
76
|
force: true
|
|
75
77
|
});
|
|
76
78
|
if (success) {
|
|
77
|
-
const
|
|
79
|
+
const absoluteDualOutDir = (0, _nodePath.join)(projectDir, dualOutDir);
|
|
80
|
+
const filenames = await (0, _glob.glob)(`${absoluteDualOutDir}/**/*{.js,.d.ts}`, {
|
|
78
81
|
ignore: 'node_modules/**'
|
|
79
82
|
});
|
|
80
83
|
for (const filename of filenames) {
|
|
@@ -96,6 +99,49 @@ const duel = async args => {
|
|
|
96
99
|
force: true
|
|
97
100
|
});
|
|
98
101
|
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* This is a fix for tsc compiler which doesn't seem to support
|
|
105
|
+
* converting an arbitrary `.ts` file, into another module system,
|
|
106
|
+
* while also preserving the module systems of `.mts` and `.cts` files.
|
|
107
|
+
*
|
|
108
|
+
* Hopefully it can be removed when TS updates their supported options,
|
|
109
|
+
* or at least how the combination of `--module` and `--moduleResolution`
|
|
110
|
+
* currently work.
|
|
111
|
+
*
|
|
112
|
+
* @see https://github.com/microsoft/TypeScript/pull/50985#issuecomment-1656991606
|
|
113
|
+
*/
|
|
114
|
+
if (isCjsBuild) {
|
|
115
|
+
const mjsFiles = await (0, _glob.glob)(`${absoluteOutDir}/**/*.mjs`, {
|
|
116
|
+
ignore: ['node_modules/**', `${absoluteDualOutDir}/**`]
|
|
117
|
+
});
|
|
118
|
+
for (const filename of mjsFiles) {
|
|
119
|
+
const relativeFn = (0, _nodePath.relative)(absoluteOutDir, filename);
|
|
120
|
+
await (0, _promises.copyFile)(filename, (0, _nodePath.join)(absoluteDualOutDir, relativeFn));
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
const cjsFiles = await (0, _glob.glob)(`${absoluteOutDir}/**/*.cjs`, {
|
|
124
|
+
ignore: ['node_modules/**', `${absoluteDualOutDir}/**`]
|
|
125
|
+
});
|
|
126
|
+
for (const filename of cjsFiles) {
|
|
127
|
+
const relativeFn = (0, _nodePath.relative)(absoluteOutDir, filename);
|
|
128
|
+
await (0, _promises.copyFile)(filename, (0, _nodePath.join)(absoluteDualOutDir, relativeFn));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Now copy the good .mjs files from the dual out dir
|
|
133
|
+
* to the original out dir, but build the file path
|
|
134
|
+
* from the original out dir to distinguish from the
|
|
135
|
+
* dual build .mjs files.
|
|
136
|
+
*/
|
|
137
|
+
const mjsFiles = await (0, _glob.glob)(`${absoluteOutDir}/**/*.mjs`, {
|
|
138
|
+
ignore: ['node_modules/**', `${absoluteDualOutDir}/**`]
|
|
139
|
+
});
|
|
140
|
+
for (const filename of mjsFiles) {
|
|
141
|
+
const relativeFn = (0, _nodePath.relative)(absoluteOutDir, filename);
|
|
142
|
+
await (0, _promises.copyFile)((0, _nodePath.join)(absoluteDualOutDir, relativeFn), filename);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
99
145
|
(0, _util.log)(`Successfully created a dual ${targetExt.replace('.', '').toUpperCase()} build in ${Math.round(_nodePerf_hooks.performance.now() - startTime)}ms.`);
|
|
100
146
|
}
|
|
101
147
|
}
|
package/dist/duel.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { argv, cwd } from 'node:process';
|
|
3
|
-
import { join } from 'node:path';
|
|
3
|
+
import { join, relative } from 'node:path';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
|
-
import { writeFile, rm } from 'node:fs/promises';
|
|
5
|
+
import { writeFile, copyFile, rm } 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';
|
|
9
9
|
import { specifier } from '@knighted/specifier';
|
|
10
10
|
import { init } from './init.js';
|
|
11
11
|
import { getRealPathAsFileUrl, logError, log } from './util.js';
|
|
12
|
-
|
|
13
|
-
// TypeScript is defined as a peer dependency.
|
|
14
12
|
const tsc = join(cwd(), 'node_modules', '.bin', 'tsc');
|
|
15
13
|
const runBuild = project => {
|
|
16
14
|
const {
|
|
@@ -40,7 +38,8 @@ const duel = async args => {
|
|
|
40
38
|
projectDir,
|
|
41
39
|
tsconfig,
|
|
42
40
|
targetExt,
|
|
43
|
-
configPath
|
|
41
|
+
configPath,
|
|
42
|
+
absoluteOutDir
|
|
44
43
|
} = ctx;
|
|
45
44
|
const startTime = performance.now();
|
|
46
45
|
log('Starting primary build...\n');
|
|
@@ -53,13 +52,15 @@ const duel = async args => {
|
|
|
53
52
|
} = tsconfig.compilerOptions;
|
|
54
53
|
const dualConfigPath = join(projectDir, `tsconfig.${hex}.json`);
|
|
55
54
|
const dualOutDir = isCjsBuild ? join(outDir, 'cjs') : join(outDir, 'mjs');
|
|
55
|
+
// Using structuredClone() would require node >= 17.0.0
|
|
56
56
|
const tsconfigDual = {
|
|
57
57
|
...tsconfig,
|
|
58
58
|
compilerOptions: {
|
|
59
59
|
...tsconfig.compilerOptions,
|
|
60
60
|
outDir: dualOutDir,
|
|
61
|
-
module: isCjsBuild ? 'CommonJS' : '
|
|
62
|
-
|
|
61
|
+
module: isCjsBuild ? 'CommonJS' : 'ESNext',
|
|
62
|
+
// Best way to make this work given how tsc works
|
|
63
|
+
moduleResolution: 'Node'
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
await writeFile(dualConfigPath, JSON.stringify(tsconfigDual, null, 2));
|
|
@@ -69,7 +70,8 @@ const duel = async args => {
|
|
|
69
70
|
force: true
|
|
70
71
|
});
|
|
71
72
|
if (success) {
|
|
72
|
-
const
|
|
73
|
+
const absoluteDualOutDir = join(projectDir, dualOutDir);
|
|
74
|
+
const filenames = await glob(`${absoluteDualOutDir}/**/*{.js,.d.ts}`, {
|
|
73
75
|
ignore: 'node_modules/**'
|
|
74
76
|
});
|
|
75
77
|
for (const filename of filenames) {
|
|
@@ -91,6 +93,49 @@ const duel = async args => {
|
|
|
91
93
|
force: true
|
|
92
94
|
});
|
|
93
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* This is a fix for tsc compiler which doesn't seem to support
|
|
99
|
+
* converting an arbitrary `.ts` file, into another module system,
|
|
100
|
+
* while also preserving the module systems of `.mts` and `.cts` files.
|
|
101
|
+
*
|
|
102
|
+
* Hopefully it can be removed when TS updates their supported options,
|
|
103
|
+
* or at least how the combination of `--module` and `--moduleResolution`
|
|
104
|
+
* currently work.
|
|
105
|
+
*
|
|
106
|
+
* @see https://github.com/microsoft/TypeScript/pull/50985#issuecomment-1656991606
|
|
107
|
+
*/
|
|
108
|
+
if (isCjsBuild) {
|
|
109
|
+
const mjsFiles = await glob(`${absoluteOutDir}/**/*.mjs`, {
|
|
110
|
+
ignore: ['node_modules/**', `${absoluteDualOutDir}/**`]
|
|
111
|
+
});
|
|
112
|
+
for (const filename of mjsFiles) {
|
|
113
|
+
const relativeFn = relative(absoluteOutDir, filename);
|
|
114
|
+
await copyFile(filename, join(absoluteDualOutDir, relativeFn));
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
const cjsFiles = await glob(`${absoluteOutDir}/**/*.cjs`, {
|
|
118
|
+
ignore: ['node_modules/**', `${absoluteDualOutDir}/**`]
|
|
119
|
+
});
|
|
120
|
+
for (const filename of cjsFiles) {
|
|
121
|
+
const relativeFn = relative(absoluteOutDir, filename);
|
|
122
|
+
await copyFile(filename, join(absoluteDualOutDir, relativeFn));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Now copy the good .mjs files from the dual out dir
|
|
127
|
+
* to the original out dir, but build the file path
|
|
128
|
+
* from the original out dir to distinguish from the
|
|
129
|
+
* dual build .mjs files.
|
|
130
|
+
*/
|
|
131
|
+
const mjsFiles = await glob(`${absoluteOutDir}/**/*.mjs`, {
|
|
132
|
+
ignore: ['node_modules/**', `${absoluteDualOutDir}/**`]
|
|
133
|
+
});
|
|
134
|
+
for (const filename of mjsFiles) {
|
|
135
|
+
const relativeFn = relative(absoluteOutDir, filename);
|
|
136
|
+
await copyFile(join(absoluteDualOutDir, relativeFn), filename);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
94
139
|
log(`Successfully created a dual ${targetExt.replace('.', '').toUpperCase()} build in ${Math.round(performance.now() - startTime)}ms.`);
|
|
95
140
|
}
|
|
96
141
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/duel",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.4",
|
|
4
4
|
"description": "TypeScript dual packages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"url": "https://github.com/knightedcodemonkey/duel/issues"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"typescript": "
|
|
47
|
+
"typescript": ">=4.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"babel-dual-package": "^1.0.0-rc.5",
|