Skip to content

Commit c746d18

Browse files
committed
implement recommendations in nodejs/node#44859
1 parent f0024b2 commit c746d18

File tree

5 files changed

+67
-6
lines changed

5 files changed

+67
-6
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"devops"
1919
],
2020
"engines": {
21-
"node": ">=14"
21+
"node": ">=16"
2222
},
2323
"repository": {
2424
"type": "git",
@@ -27,7 +27,7 @@
2727
"bugs": {
2828
"url": "https://github.com/rockcarver/frodo-cli/issues"
2929
},
30-
"main": "esm/app.js",
30+
"main": "esm/launch.js",
3131
"scripts": {
3232
"test": "npx tsc && node --experimental-vm-modules node_modules/jest/bin/jest.js",
3333
"test:local": "npm run build && node --experimental-vm-modules node_modules/jest/bin/jest.js",
@@ -78,7 +78,7 @@
7878
],
7979
"license": "MIT",
8080
"bin": {
81-
"frodo": "./esm/app.js"
81+
"frodo": "./esm/launch.js"
8282
},
8383
"babel": {
8484
"plugins": [

src/app.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env -S node --no-warnings --enable-source-maps --experimental-specifier-resolution=node
2-
31
import { ConnectionProfile } from '@rockcarver/frodo-lib';
42
import { Command } from 'commander';
53

src/launch.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env node
2+
import { spawn } from 'node:child_process';
3+
import { createRequire } from 'module';
4+
5+
const require = createRequire(import.meta.url);
6+
7+
const launchArgs = [
8+
'--no-warnings',
9+
'--enable-source-maps',
10+
'--experimental-loader',
11+
require.resolve('./loader.js'),
12+
require.resolve('./app.js'),
13+
];
14+
const frodoArgs = process.argv.slice(2);
15+
16+
spawn(process.execPath, [...launchArgs, ...frodoArgs], {
17+
stdio: 'inherit',
18+
shell: false,
19+
});

src/loader.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { builtinModules } from 'node:module';
2+
import { dirname } from 'path';
3+
import { cwd } from 'process';
4+
import { fileURLToPath, pathToFileURL } from 'url';
5+
import { promisify } from 'util';
6+
7+
import resolveCallback from 'resolve/async.js';
8+
9+
const resolveAsync = promisify(resolveCallback);
10+
11+
const baseURL = pathToFileURL(cwd() + '/').href;
12+
13+
export async function resolve(specifier, context, next) {
14+
const { parentURL = baseURL } = context;
15+
16+
if (specifier.startsWith('node:') || builtinModules.includes(specifier)) {
17+
return next(specifier, context);
18+
}
19+
20+
// `resolveAsync` works with paths, not URLs
21+
if (specifier.startsWith('file://')) {
22+
specifier = fileURLToPath(specifier);
23+
}
24+
const parentPath = fileURLToPath(parentURL);
25+
26+
let url;
27+
try {
28+
const resolution = await resolveAsync(specifier, {
29+
basedir: dirname(parentPath),
30+
// For whatever reason, --experimental-specifier-resolution=node doesn't search for .mjs extensions
31+
// but it does search for index.mjs files within directories
32+
extensions: ['.js', '.json', '.node', '.mjs'],
33+
});
34+
url = pathToFileURL(resolution).href;
35+
} catch (error) {
36+
if (error.code === 'MODULE_NOT_FOUND') {
37+
// Match Node's error code
38+
error.code = 'ERR_MODULE_NOT_FOUND';
39+
}
40+
throw error;
41+
}
42+
43+
return next(url, context);
44+
}

0 commit comments

Comments
 (0)