@knighted/duel 1.0.0-alpha.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 +43 -0
- package/dist/duel.cjs +111 -0
- package/dist/duel.js +105 -0
- package/dist/init.cjs +98 -0
- package/dist/init.js +92 -0
- package/dist/util.cjs +21 -0
- package/dist/util.js +13 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# [`@knighted/duel`](https://www.npmjs.com/package/@knighted/duel)
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://codecov.io/gh/knightedcodemonkey/duel)
|
|
5
|
+
[](https://www.npmjs.com/package/@knighted/duel)
|
|
6
|
+
|
|
7
|
+
Node.js tool for creating a TypeScript dual package.
|
|
8
|
+
|
|
9
|
+
Early stages of development. Inspired by https://github.com/microsoft/TypeScript/issues/49462.
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
Consider a project that is ESM-first, i.e. `"type": "module"` in package.json, that also wants to create a separate CJS build. It might have a tsconfig.json file that looks like the following.
|
|
14
|
+
|
|
15
|
+
**tsconfig.json**
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"compilerOptions": {
|
|
20
|
+
"target": "ESNext",
|
|
21
|
+
"module": "NodeNext",
|
|
22
|
+
"moduleResolution": "NodeNext",
|
|
23
|
+
"declaration": true,
|
|
24
|
+
"strict": true,
|
|
25
|
+
"outDir": "dist"
|
|
26
|
+
},
|
|
27
|
+
"include": ["src/*.ts"]
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Running the following will use the tsconfig.json defined above and create a separate CJS build in `dist/cjs`.
|
|
32
|
+
|
|
33
|
+
```console
|
|
34
|
+
user@comp ~ $ duel -p tsconfig.json -x .cjs
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Now you can update your `exports` in package.json to match the build output.
|
|
38
|
+
|
|
39
|
+
It should work similarly for a CJS first project. Except, your tsconfig.json would be slightly different and you'd want to pass `-x .mjs`.
|
|
40
|
+
|
|
41
|
+
## Gotchas
|
|
42
|
+
|
|
43
|
+
Unfortunately, TypeScript doesn't really understand dual packages very well. For instance, it will **always** create CJS exports when `--module commonjs` is used, even on files with an `.mts` extension. One reference issue is https://github.com/microsoft/TypeScript/issues/54573.
|
package/dist/duel.cjs
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.duel = void 0;
|
|
8
|
+
var _nodeProcess = require("node:process");
|
|
9
|
+
var _nodeUrl = require("node:url");
|
|
10
|
+
var _nodePath = require("node:path");
|
|
11
|
+
var _nodeChild_process = require("node:child_process");
|
|
12
|
+
var _promises = require("node:fs/promises");
|
|
13
|
+
var _nodeCrypto = require("node:crypto");
|
|
14
|
+
var _nodePerf_hooks = require("node:perf_hooks");
|
|
15
|
+
var _glob = require("glob");
|
|
16
|
+
var _specifier = require("@knighted/specifier");
|
|
17
|
+
var _init = require("./init.cjs");
|
|
18
|
+
var _util = require("./util.cjs");
|
|
19
|
+
const _filename = (0, _nodeUrl.fileURLToPath)(import.meta.url);
|
|
20
|
+
const _dirname = (0, _nodePath.dirname)(_filename);
|
|
21
|
+
const root = (0, _nodePath.join)(_dirname, '..');
|
|
22
|
+
const tsc = (0, _nodePath.join)(root, 'node_modules', '.bin', 'tsc');
|
|
23
|
+
const runBuild = project => {
|
|
24
|
+
const {
|
|
25
|
+
status,
|
|
26
|
+
error
|
|
27
|
+
} = (0, _nodeChild_process.spawnSync)(tsc, ['-p', project], {
|
|
28
|
+
stdio: 'inherit'
|
|
29
|
+
});
|
|
30
|
+
if (error) {
|
|
31
|
+
(0, _util.logError)(`Failed to compile: ${error.message}`);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (status === null) {
|
|
35
|
+
(0, _util.logError)(`Failed to compile. The process was terminated.`);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (status > 0) {
|
|
39
|
+
(0, _util.logError)('Compilation errors found.');
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
};
|
|
44
|
+
const duel = async args => {
|
|
45
|
+
const ctx = await (0, _init.init)(args);
|
|
46
|
+
if (ctx) {
|
|
47
|
+
const {
|
|
48
|
+
projectDir,
|
|
49
|
+
tsconfig,
|
|
50
|
+
targetExt,
|
|
51
|
+
configPath
|
|
52
|
+
} = ctx;
|
|
53
|
+
const startTime = _nodePerf_hooks.performance.now();
|
|
54
|
+
(0, _util.log)('Starting primary build...\n');
|
|
55
|
+
let success = runBuild(configPath);
|
|
56
|
+
if (success) {
|
|
57
|
+
const isCjsBuild = targetExt === '.cjs';
|
|
58
|
+
const hex = (0, _nodeCrypto.randomBytes)(4).toString('hex');
|
|
59
|
+
const {
|
|
60
|
+
outDir
|
|
61
|
+
} = tsconfig.compilerOptions;
|
|
62
|
+
const dualConfigPath = (0, _nodePath.join)(projectDir, `tsconfig.${hex}.json`);
|
|
63
|
+
const dualOutDir = isCjsBuild ? (0, _nodePath.join)(outDir, 'cjs') : (0, _nodePath.join)(outDir, 'mjs');
|
|
64
|
+
const tsconfigDual = {
|
|
65
|
+
...tsconfig,
|
|
66
|
+
compilerOptions: {
|
|
67
|
+
...tsconfig.compilerOptions,
|
|
68
|
+
outDir: dualOutDir,
|
|
69
|
+
module: isCjsBuild ? 'CommonJS' : 'NodeNext',
|
|
70
|
+
moduleResolution: isCjsBuild ? 'Node' : 'NodeNext'
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
await (0, _promises.writeFile)(dualConfigPath, JSON.stringify(tsconfigDual, null, 2));
|
|
74
|
+
(0, _util.log)('Starting dual build...\n');
|
|
75
|
+
success = runBuild(dualConfigPath);
|
|
76
|
+
await (0, _promises.rm)(dualConfigPath, {
|
|
77
|
+
force: true
|
|
78
|
+
});
|
|
79
|
+
if (success) {
|
|
80
|
+
const filenames = await (0, _glob.glob)(`${(0, _nodePath.join)(projectDir, dualOutDir)}/**/*{.js,.d.ts}`, {
|
|
81
|
+
ignore: 'node_modules/**'
|
|
82
|
+
});
|
|
83
|
+
for (const filename of filenames) {
|
|
84
|
+
const dts = /(\.d\.ts)$/;
|
|
85
|
+
const outFilename = dts.test(filename) ? filename.replace(dts, isCjsBuild ? '.d.cts' : '.d.mts') : filename.replace(/\.js$/, targetExt);
|
|
86
|
+
const code = await _specifier.specifier.update(filename, ({
|
|
87
|
+
value
|
|
88
|
+
}) => {
|
|
89
|
+
// Collapse any BinaryExpression or NewExpression to test for a relative specifier
|
|
90
|
+
const collapsed = value.replace(/['"`+)\s]|new String\(/g, '');
|
|
91
|
+
const relative = /^(?:\.|\.\.)\//i;
|
|
92
|
+
if (relative.test(collapsed)) {
|
|
93
|
+
// $2 is for any closing quotation/parens around BE or NE
|
|
94
|
+
return value.replace(/(.+)\.js([)'"`]*)?$/, `$1${targetExt}$2`);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
await (0, _promises.writeFile)(outFilename, code);
|
|
98
|
+
await (0, _promises.rm)(filename, {
|
|
99
|
+
force: true
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
(0, _util.log)(`Successfully created a dual ${targetExt.replace('.', '').toUpperCase()} build in ${Math.round(_nodePerf_hooks.performance.now() - startTime)}ms.`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
exports.duel = duel;
|
|
108
|
+
const realFileUrlArgv1 = await (0, _util.getRealPathAsFileUrl)(_nodeProcess.argv[1]);
|
|
109
|
+
if (import.meta.url === realFileUrlArgv1) {
|
|
110
|
+
await duel();
|
|
111
|
+
}
|
package/dist/duel.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { argv } from 'node:process';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { writeFile, rm } from 'node:fs/promises';
|
|
7
|
+
import { randomBytes } from 'node:crypto';
|
|
8
|
+
import { performance } from 'node:perf_hooks';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
import { specifier } from '@knighted/specifier';
|
|
11
|
+
import { init } from './init.js';
|
|
12
|
+
import { getRealPathAsFileUrl, logError, log } from './util.js';
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
const root = join(__dirname, '..');
|
|
16
|
+
const tsc = join(root, 'node_modules', '.bin', 'tsc');
|
|
17
|
+
const runBuild = project => {
|
|
18
|
+
const {
|
|
19
|
+
status,
|
|
20
|
+
error
|
|
21
|
+
} = spawnSync(tsc, ['-p', project], {
|
|
22
|
+
stdio: 'inherit'
|
|
23
|
+
});
|
|
24
|
+
if (error) {
|
|
25
|
+
logError(`Failed to compile: ${error.message}`);
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (status === null) {
|
|
29
|
+
logError(`Failed to compile. The process was terminated.`);
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
if (status > 0) {
|
|
33
|
+
logError('Compilation errors found.');
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
};
|
|
38
|
+
const duel = async args => {
|
|
39
|
+
const ctx = await init(args);
|
|
40
|
+
if (ctx) {
|
|
41
|
+
const {
|
|
42
|
+
projectDir,
|
|
43
|
+
tsconfig,
|
|
44
|
+
targetExt,
|
|
45
|
+
configPath
|
|
46
|
+
} = ctx;
|
|
47
|
+
const startTime = performance.now();
|
|
48
|
+
log('Starting primary build...\n');
|
|
49
|
+
let success = runBuild(configPath);
|
|
50
|
+
if (success) {
|
|
51
|
+
const isCjsBuild = targetExt === '.cjs';
|
|
52
|
+
const hex = randomBytes(4).toString('hex');
|
|
53
|
+
const {
|
|
54
|
+
outDir
|
|
55
|
+
} = tsconfig.compilerOptions;
|
|
56
|
+
const dualConfigPath = join(projectDir, `tsconfig.${hex}.json`);
|
|
57
|
+
const dualOutDir = isCjsBuild ? join(outDir, 'cjs') : join(outDir, 'mjs');
|
|
58
|
+
const tsconfigDual = {
|
|
59
|
+
...tsconfig,
|
|
60
|
+
compilerOptions: {
|
|
61
|
+
...tsconfig.compilerOptions,
|
|
62
|
+
outDir: dualOutDir,
|
|
63
|
+
module: isCjsBuild ? 'CommonJS' : 'NodeNext',
|
|
64
|
+
moduleResolution: isCjsBuild ? 'Node' : 'NodeNext'
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
await writeFile(dualConfigPath, JSON.stringify(tsconfigDual, null, 2));
|
|
68
|
+
log('Starting dual build...\n');
|
|
69
|
+
success = runBuild(dualConfigPath);
|
|
70
|
+
await rm(dualConfigPath, {
|
|
71
|
+
force: true
|
|
72
|
+
});
|
|
73
|
+
if (success) {
|
|
74
|
+
const filenames = await glob(`${join(projectDir, dualOutDir)}/**/*{.js,.d.ts}`, {
|
|
75
|
+
ignore: 'node_modules/**'
|
|
76
|
+
});
|
|
77
|
+
for (const filename of filenames) {
|
|
78
|
+
const dts = /(\.d\.ts)$/;
|
|
79
|
+
const outFilename = dts.test(filename) ? filename.replace(dts, isCjsBuild ? '.d.cts' : '.d.mts') : filename.replace(/\.js$/, targetExt);
|
|
80
|
+
const code = await specifier.update(filename, ({
|
|
81
|
+
value
|
|
82
|
+
}) => {
|
|
83
|
+
// Collapse any BinaryExpression or NewExpression to test for a relative specifier
|
|
84
|
+
const collapsed = value.replace(/['"`+)\s]|new String\(/g, '');
|
|
85
|
+
const relative = /^(?:\.|\.\.)\//i;
|
|
86
|
+
if (relative.test(collapsed)) {
|
|
87
|
+
// $2 is for any closing quotation/parens around BE or NE
|
|
88
|
+
return value.replace(/(.+)\.js([)'"`]*)?$/, `$1${targetExt}$2`);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
await writeFile(outFilename, code);
|
|
92
|
+
await rm(filename, {
|
|
93
|
+
force: true
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
log(`Successfully created a dual ${targetExt.replace('.', '').toUpperCase()} build in ${Math.round(performance.now() - startTime)}ms.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const realFileUrlArgv1 = await getRealPathAsFileUrl(argv[1]);
|
|
102
|
+
if (import.meta.url === realFileUrlArgv1) {
|
|
103
|
+
await duel();
|
|
104
|
+
}
|
|
105
|
+
export { duel };
|
package/dist/init.cjs
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.init = void 0;
|
|
7
|
+
var _nodeUtil = require("node:util");
|
|
8
|
+
var _nodePath = require("node:path");
|
|
9
|
+
var _promises = require("node:fs/promises");
|
|
10
|
+
var _util = require("./util.cjs");
|
|
11
|
+
const init = async args => {
|
|
12
|
+
const validTargetExts = ['.cjs', '.mjs'];
|
|
13
|
+
let parsed = null;
|
|
14
|
+
try {
|
|
15
|
+
const {
|
|
16
|
+
values
|
|
17
|
+
} = (0, _nodeUtil.parseArgs)({
|
|
18
|
+
args,
|
|
19
|
+
options: {
|
|
20
|
+
project: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
short: 'p',
|
|
23
|
+
default: 'tsconfig.json'
|
|
24
|
+
},
|
|
25
|
+
'target-extension': {
|
|
26
|
+
type: 'string',
|
|
27
|
+
short: 'x',
|
|
28
|
+
default: '.cjs'
|
|
29
|
+
},
|
|
30
|
+
help: {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
short: 'h',
|
|
33
|
+
default: false
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
parsed = values;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
(0, _util.logError)(err.message);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (parsed.help) {
|
|
43
|
+
(0, _util.log)('Usage: duel [options]\n');
|
|
44
|
+
(0, _util.log)('Options:');
|
|
45
|
+
(0, _util.log)("--project, -p \t\t\t Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.");
|
|
46
|
+
(0, _util.log)('--target-extension, -x \t\t Sets the file extension for the dual build. [.cjs,.mjs]');
|
|
47
|
+
(0, _util.log)('--help, -h \t\t\t Print this message.');
|
|
48
|
+
} else {
|
|
49
|
+
const {
|
|
50
|
+
project,
|
|
51
|
+
'target-extension': targetExt
|
|
52
|
+
} = parsed;
|
|
53
|
+
let configPath = (0, _nodePath.resolve)(project);
|
|
54
|
+
let stats = null;
|
|
55
|
+
if (!validTargetExts.includes(targetExt)) {
|
|
56
|
+
(0, _util.logError)(`Invalid arg '${targetExt}' for --target-extension. Must be one of ${validTargetExts.toString()}`);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
stats = await (0, _promises.stat)(configPath);
|
|
61
|
+
} catch {
|
|
62
|
+
(0, _util.logError)(`Provided --project '${project}' resolves to ${configPath} which is not a file or directory.`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (stats.isDirectory()) {
|
|
66
|
+
configPath = (0, _nodePath.join)(configPath, 'tsconfig.json');
|
|
67
|
+
try {
|
|
68
|
+
stats = await (0, _promises.stat)(configPath);
|
|
69
|
+
} catch {
|
|
70
|
+
(0, _util.logError)(`Provided --project '${project}' resolves to a directory ${(0, _nodePath.dirname)(configPath)} with no tsconfig.json.`);
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (stats.isFile()) {
|
|
75
|
+
let tsconfig = null;
|
|
76
|
+
try {
|
|
77
|
+
tsconfig = JSON.parse((await (0, _promises.readFile)(configPath)).toString());
|
|
78
|
+
} catch (err) {
|
|
79
|
+
(0, _util.logError)(`The config file found at ${configPath} is not parsable as JSON.`);
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (!tsconfig.compilerOptions?.outDir) {
|
|
83
|
+
(0, _util.logError)('You must define an `outDir` in your project config.');
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const projectDir = (0, _nodePath.dirname)(configPath);
|
|
87
|
+
return {
|
|
88
|
+
tsconfig,
|
|
89
|
+
targetExt,
|
|
90
|
+
projectDir,
|
|
91
|
+
configPath,
|
|
92
|
+
absoluteOutDir: (0, _nodePath.resolve)(projectDir, tsconfig.compilerOptions.outDir)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
};
|
|
98
|
+
exports.init = init;
|
package/dist/init.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { parseArgs } from 'node:util';
|
|
2
|
+
import { resolve, join, dirname } from 'node:path';
|
|
3
|
+
import { stat, readFile } from 'node:fs/promises';
|
|
4
|
+
import { logError, log } from './util.js';
|
|
5
|
+
const init = async args => {
|
|
6
|
+
const validTargetExts = ['.cjs', '.mjs'];
|
|
7
|
+
let parsed = null;
|
|
8
|
+
try {
|
|
9
|
+
const {
|
|
10
|
+
values
|
|
11
|
+
} = parseArgs({
|
|
12
|
+
args,
|
|
13
|
+
options: {
|
|
14
|
+
project: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
short: 'p',
|
|
17
|
+
default: 'tsconfig.json'
|
|
18
|
+
},
|
|
19
|
+
'target-extension': {
|
|
20
|
+
type: 'string',
|
|
21
|
+
short: 'x',
|
|
22
|
+
default: '.cjs'
|
|
23
|
+
},
|
|
24
|
+
help: {
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
short: 'h',
|
|
27
|
+
default: false
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
parsed = values;
|
|
32
|
+
} catch (err) {
|
|
33
|
+
logError(err.message);
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (parsed.help) {
|
|
37
|
+
log('Usage: duel [options]\n');
|
|
38
|
+
log('Options:');
|
|
39
|
+
log("--project, -p \t\t\t Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.");
|
|
40
|
+
log('--target-extension, -x \t\t Sets the file extension for the dual build. [.cjs,.mjs]');
|
|
41
|
+
log('--help, -h \t\t\t Print this message.');
|
|
42
|
+
} else {
|
|
43
|
+
const {
|
|
44
|
+
project,
|
|
45
|
+
'target-extension': targetExt
|
|
46
|
+
} = parsed;
|
|
47
|
+
let configPath = resolve(project);
|
|
48
|
+
let stats = null;
|
|
49
|
+
if (!validTargetExts.includes(targetExt)) {
|
|
50
|
+
logError(`Invalid arg '${targetExt}' for --target-extension. Must be one of ${validTargetExts.toString()}`);
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
stats = await stat(configPath);
|
|
55
|
+
} catch {
|
|
56
|
+
logError(`Provided --project '${project}' resolves to ${configPath} which is not a file or directory.`);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (stats.isDirectory()) {
|
|
60
|
+
configPath = join(configPath, 'tsconfig.json');
|
|
61
|
+
try {
|
|
62
|
+
stats = await stat(configPath);
|
|
63
|
+
} catch {
|
|
64
|
+
logError(`Provided --project '${project}' resolves to a directory ${dirname(configPath)} with no tsconfig.json.`);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (stats.isFile()) {
|
|
69
|
+
let tsconfig = null;
|
|
70
|
+
try {
|
|
71
|
+
tsconfig = JSON.parse((await readFile(configPath)).toString());
|
|
72
|
+
} catch (err) {
|
|
73
|
+
logError(`The config file found at ${configPath} is not parsable as JSON.`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (!tsconfig.compilerOptions?.outDir) {
|
|
77
|
+
logError('You must define an `outDir` in your project config.');
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const projectDir = dirname(configPath);
|
|
81
|
+
return {
|
|
82
|
+
tsconfig,
|
|
83
|
+
targetExt,
|
|
84
|
+
projectDir,
|
|
85
|
+
configPath,
|
|
86
|
+
absoluteOutDir: resolve(projectDir, tsconfig.compilerOptions.outDir)
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
};
|
|
92
|
+
export { init };
|
package/dist/util.cjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.logError = exports.log = exports.getRealPathAsFileUrl = void 0;
|
|
7
|
+
var _nodeUrl = require("node:url");
|
|
8
|
+
var _promises = require("node:fs/promises");
|
|
9
|
+
const log = (color = '\x1b[30m', msg = '') => {
|
|
10
|
+
// eslint-disable-next-line no-console
|
|
11
|
+
console.log(`${color}%s\x1b[0m`, msg);
|
|
12
|
+
};
|
|
13
|
+
exports.log = log;
|
|
14
|
+
const logError = log.bind(null, '\x1b[31m');
|
|
15
|
+
exports.logError = logError;
|
|
16
|
+
const getRealPathAsFileUrl = async path => {
|
|
17
|
+
const realPath = await (0, _promises.realpath)(path);
|
|
18
|
+
const asFileUrl = (0, _nodeUrl.pathToFileURL)(realPath).href;
|
|
19
|
+
return asFileUrl;
|
|
20
|
+
};
|
|
21
|
+
exports.getRealPathAsFileUrl = getRealPathAsFileUrl;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
import { realpath } from 'node:fs/promises';
|
|
3
|
+
const log = (color = '\x1b[30m', msg = '') => {
|
|
4
|
+
// eslint-disable-next-line no-console
|
|
5
|
+
console.log(`${color}%s\x1b[0m`, msg);
|
|
6
|
+
};
|
|
7
|
+
const logError = log.bind(null, '\x1b[31m');
|
|
8
|
+
const getRealPathAsFileUrl = async path => {
|
|
9
|
+
const realPath = await realpath(path);
|
|
10
|
+
const asFileUrl = pathToFileURL(realPath).href;
|
|
11
|
+
return asFileUrl;
|
|
12
|
+
};
|
|
13
|
+
export { log, logError, getRealPathAsFileUrl };
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@knighted/duel",
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
|
+
"description": "TypeScript dual packages.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist",
|
|
7
|
+
"bin": "dist/duel.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/duel.js",
|
|
11
|
+
"require": "./dist/duel.cjs",
|
|
12
|
+
"default": "./dist/duel.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=16.19.0"
|
|
18
|
+
},
|
|
19
|
+
"engineStrict": true,
|
|
20
|
+
"scripts": {
|
|
21
|
+
"prettier": "prettier -w src/*.js test/*.js",
|
|
22
|
+
"lint": "eslint src/*.js test/*.js",
|
|
23
|
+
"test": "c8 --reporter=text --reporter=text-summary --reporter=lcov node --test --test-reporter=spec test/*.js",
|
|
24
|
+
"build": "babel-dual-package --no-cjs-dir src",
|
|
25
|
+
"prepack": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"tsc",
|
|
29
|
+
"typescript",
|
|
30
|
+
"dual package",
|
|
31
|
+
"cjs",
|
|
32
|
+
"mjs"
|
|
33
|
+
],
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"author": "KCM <knightedcodemonkey@gmail.com>",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/knightedcodemonkey/duel.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/knightedcodemonkey/duel/issues"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"typescript": "^5.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"babel-dual-package": "^1.0.0-rc.5",
|
|
51
|
+
"c8": "^8.0.1",
|
|
52
|
+
"eslint": "^8.45.0",
|
|
53
|
+
"eslint-plugin-n": "^16.0.1",
|
|
54
|
+
"prettier": "^3.0.0",
|
|
55
|
+
"typescript": "^5.2.0-dev.20230727"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@knighted/specifier": "^1.0.0-alpha.5",
|
|
59
|
+
"glob": "^10.3.3",
|
|
60
|
+
"magic-string": "^0.30.1"
|
|
61
|
+
},
|
|
62
|
+
"prettier": {
|
|
63
|
+
"arrowParens": "avoid",
|
|
64
|
+
"printWidth": 90,
|
|
65
|
+
"semi": false,
|
|
66
|
+
"singleQuote": true
|
|
67
|
+
}
|
|
68
|
+
}
|