Skip to content

Commit 2fc0206

Browse files
committed
ref!: move to ESM for 2025
1 parent 3a727d1 commit 2fc0206

File tree

11 files changed

+209
-83
lines changed

11 files changed

+209
-83
lines changed

.jshintrc

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
2-
3-
4-
5-
6-
71
{
2+
"module": true,
83
"browser": true,
94
"node": true,
105
"esversion": 11,
116
"curly": true,
127
"sub": true,
138

14-
159
"bitwise": true,
1610
"eqeqeq": true,
1711
"forin": true,
@@ -23,7 +17,6 @@
2317
"plusplus": true,
2418
"undef": true,
2519
"unused": "vars",
26-
"strict": true,
2720
"maxdepth": 4,
2821
"maxstatements": 100,
2922
"maxcomplexity": 20

bin/_walk.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
"use strict";
1+
import Fs from "node:fs/promises";
2+
import Path from "node:path";
23

3-
const Fs = require("node:fs/promises");
4-
const Path = require("node:path");
4+
let Walk = {};
5+
Walk.skipDir = new Error("skip this directory");
56

6-
const skipDir = new Error("skip this directory");
7-
const _withFileTypes = { withFileTypes: true };
7+
let _withFileTypes = { withFileTypes: true };
88

99
/** @typedef {import('fs').Dirent} Dirent */
1010

@@ -24,7 +24,7 @@ const _withFileTypes = { withFileTypes: true };
2424
* @param {Dirent} [_dirent]
2525
* @returns {Promise<void>}
2626
*/
27-
const walk = async (pathname, walkFunc, _dirent) => {
27+
Walk.walk = async function (pathname, walkFunc, _dirent) {
2828
let err;
2929

3030
// special case of the very first run
@@ -41,7 +41,7 @@ const walk = async (pathname, walkFunc, _dirent) => {
4141

4242
// run the user-supplied function and either skip, bail, or continue
4343
let cont = await walkFunc(err, pathname, _dirent).catch(function (err) {
44-
if (skipDir === err) {
44+
if (Walk.skipDir === err) {
4545
return false;
4646
}
4747
throw err;
@@ -65,11 +65,9 @@ const walk = async (pathname, walkFunc, _dirent) => {
6565
);
6666

6767
for (let dirent of dirents) {
68-
await walk(Path.join(pathname, dirent.name), walkFunc, dirent);
68+
let path = Path.join(pathname, dirent.name);
69+
await Walk.walk(path, walkFunc, dirent);
6970
}
7071
};
7172

72-
module.exports = {
73-
walk,
74-
skipDir,
75-
};
73+
export default Walk;

bin/jswt-init.js

Lines changed: 148 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
#!/usr/bin/env node
2-
"use strict";
32

4-
//require("dotenv").config({ path: ".env" });
5-
//require("dotenv").config({ path: ".env.secret" });
3+
//import Dotenv from "dotenv";
4+
//Dotenv.config({ path: ".env" });
5+
//Dotenv.config({ path: ".env.secret" });
66

77
const PKG_NAME = "package.json";
88
const TSC_NAME = "tsconfig.json";
99
const JSC_NAME = "jsconfig.json";
1010

11-
var Fs = require("node:fs").promises;
12-
var Path = require("node:path");
13-
var spawn = require("node:child_process").spawn;
11+
import Fs from "node:fs/promises";
12+
import Path from "node:path";
13+
import ChildProcess from "node:child_process";
14+
15+
let modulePath = import.meta.url.slice("file://".length);
16+
let moduleDir = Path.dirname(modulePath);
1417

1518
async function main() {
1619
/* jshint maxcomplexity: 25 */
@@ -31,12 +34,6 @@ async function main() {
3134
pkgName = pkgName.slice(index);
3235
}
3336

34-
let jsconfig = await readJsConfig();
35-
if (!jsconfig) {
36-
let tsconfigTxt = await createTsConfig();
37-
jsconfig = await createJsConfig(pkg, tsconfigTxt);
38-
}
39-
4037
// await Fs.mkdir("./docs", { recursive: true });
4138
// let fh = await Fs.open("./docs/.gitkeep", "a");
4239
// await fh.close();
@@ -81,23 +78,35 @@ async function main() {
8178
await initFile(
8279
"./index.js",
8380
[
84-
`"use strict";`,
8581
"// auto-generated by `jswt reexport`",
8682
"// DO NOT EDIT",
8783
"",
88-
`module.exports = require("${prefix}/${pkgName}.js");`,
84+
`import ${pkgName} from "${prefix}/${pkgName}.js";`,
85+
"",
86+
`export default ${pkgName};`,
8987
"",
9088
].join("\n"),
9189
);
9290
}
9391

92+
let jsconfig = await readJsConfig();
93+
if (!jsconfig) {
94+
let tsconfigTxt = await createTsConfig();
95+
jsconfig = await createJsConfig(
96+
pkg,
97+
tsconfigTxt,
98+
`${prefix}/${pkgName}.js`,
99+
);
100+
}
101+
94102
let eslintFile = await whichEslint(".", pkg);
95103
let initJshint = !flags.noJshint && !eslintFile;
96104
if (initJshint) {
97105
await initFile(
98106
"./.jshintrc",
99107
[
100108
`{`,
109+
` "module": true,`,
101110
` "browser": true,`,
102111
` "node": true,`,
103112
` "esversion": 11,`,
@@ -115,7 +124,6 @@ async function main() {
115124
` "plusplus": true,`,
116125
` "undef": true,`,
117126
` "unused": "vars",`,
118-
` "strict": true,`,
119127
` "maxdepth": 4,`,
120128
` "maxstatements": 100,`,
121129
` "maxcomplexity": 20`,
@@ -145,7 +153,7 @@ async function main() {
145153
let hasTestRunnerScript = script.includes(testRunnerScript);
146154
if (hasTestRunnerScript) {
147155
await Fs.mkdir("./tests", { recursive: true });
148-
let testRunnerPath = Path.join(__dirname, "../tests/index.js");
156+
let testRunnerPath = Path.join(moduleDir, "../tests/index.js");
149157
let testRunnerText = await Fs.readFile(testRunnerPath, "utf8");
150158
await initFile("./tests/index.js", testRunnerText);
151159
}
@@ -169,7 +177,7 @@ async function main() {
169177
let ghaDir = `.github/workflows`;
170178
let ghaFile = `.github/workflows/node.js.yml`;
171179
await Fs.mkdir(`./${ghaDir}`, { recursive: true });
172-
let ghActionPath = Path.join(__dirname, `../${ghaFile}`);
180+
let ghActionPath = Path.join(moduleDir, `../${ghaFile}`);
173181
let ghActionText = await Fs.readFile(ghActionPath, "utf8");
174182
await initFile(`./${ghaFile}`, ghActionText);
175183
}
@@ -214,12 +222,12 @@ async function main() {
214222
await initFile(
215223
mainPath,
216224
[
217-
`"use strict";`,
218-
"",
219-
`let ${mainName} = module.exports;`,
225+
`let ${mainName} = {};`,
220226
"",
221227
`${mainName}.answer = 42;`,
222228
"",
229+
`export default ${mainName};`,
230+
"",
223231
].join("\n"),
224232
);
225233
}
@@ -229,6 +237,7 @@ async function main() {
229237
if (mainIsIndex) {
230238
let allArgs = ["pkg", "set", `main=${mainPath}`];
231239
await exec("npm", allArgs);
240+
await sortAndWritePackageJson();
232241
}
233242
}
234243

@@ -278,6 +287,7 @@ async function main() {
278287
`files[]=tests/*.js`,
279288
];
280289
await exec("npm", allArgs);
290+
await sortAndWritePackageJson();
281291
}
282292
}
283293

@@ -290,10 +300,57 @@ async function main() {
290300
void (await upsertNpmScript(
291301
"prepublish",
292302
"reexport-types",
293-
"npx -p jswt@1.x -- reexport",
303+
"npx -p jswt@2.x -- reexport",
294304
"reexport",
295305
));
296306

307+
{
308+
let result = await exec("npm", ["pkg", "get", "exports"]);
309+
let curScript = result.stdout.trim();
310+
if ("{}" === curScript) {
311+
let allArgs = [
312+
"pkg",
313+
"set",
314+
"type=module",
315+
`exports[.]=${mainPath}`,
316+
`exports[./*]=./*`,
317+
];
318+
await exec("npm", allArgs);
319+
await sortAndWritePackageJson();
320+
}
321+
}
322+
323+
{
324+
let result = await exec("npm", ["pkg", "get", "imports"]);
325+
let curScript = result.stdout.trim();
326+
if ("{}" === curScript) {
327+
let allArgs = [
328+
"pkg",
329+
"set",
330+
"type=module",
331+
`imports[${pkg.name}]=${mainPath}`,
332+
];
333+
await exec("npm", allArgs);
334+
await sortAndWritePackageJson();
335+
336+
await initFile(
337+
"./importmap.html",
338+
[
339+
`<script type="importmap">`,
340+
` {`,
341+
` "imports": {`,
342+
` "@root/passkey": "./passkey.js",`,
343+
` "@root/passkey/": "./lib/",`,
344+
` "localstore": "./vendor/localstore.js"`,
345+
` }`,
346+
` }`,
347+
`</script>`,
348+
"",
349+
].join("\n"),
350+
);
351+
}
352+
}
353+
297354
let jsconfigTxt = JSON.stringify(jsconfig, null, 2);
298355
// for stderr / debug output
299356
console.error(`./jsconfig.json:`);
@@ -505,13 +562,14 @@ async function createTsConfig() {
505562
"--allowJs",
506563
"--alwaysStrict",
507564
"--checkJs",
565+
"--module",
566+
"nodenext",
508567
"--moduleResolution",
509-
"node",
568+
"nodenext",
510569
"--noEmit",
511570
"--noImplicitAny",
512571
"--target",
513-
// can't be 'esnext' due to some resolution issues
514-
version || "es2022",
572+
version || "es2022", // can't be 'esnext' due to some resolution issues
515573
"--typeRoots",
516574
"./typings,./node_modules/@types",
517575
];
@@ -556,18 +614,20 @@ async function getLatest20xx() {
556614
return version;
557615
}
558616
version = m[0];
559-
//console.log("version", version);
617+
//console.log("DEBUG version", version);
560618
}
561619
return version;
562620
});
563621
}
564622

565623
/**
566624
* @param {Object} pkg
625+
* @param {String} pkg.name
567626
* @param {String} tsconfigTxt
627+
* @param {String} mainPath
568628
* @returns
569629
*/
570-
async function createJsConfig(pkg, tsconfigTxt) {
630+
async function createJsConfig(pkg, tsconfigTxt, mainPath) {
571631
if (!tsconfigTxt.includes(`"include":`)) {
572632
let includables = [
573633
"*.js",
@@ -584,6 +644,18 @@ async function createJsConfig(pkg, tsconfigTxt) {
584644
tsconfigTxt = tsconfigTxt.replace(/\n}[\s\n]*$/m, `${includeLine}\n}`);
585645
}
586646

647+
{
648+
let lines = [
649+
` "${pkg.name}": ["${mainPath}"]`,
650+
` "${pkg.name}/*": ["./*"]`,
651+
];
652+
let str = lines.join(`,\n`);
653+
tsconfigTxt = tsconfigTxt.replace(
654+
`// "paths": {},`,
655+
`"paths": {\n${str}\n }, `,
656+
);
657+
}
658+
587659
if (!tsconfigTxt.includes(`"exclude":`)) {
588660
let excludeLine = `,\n "exclude": ["node_modules"]`;
589661
tsconfigTxt = tsconfigTxt.replace(/\n}[\s\n]*$/m, `${excludeLine}\n}`);
@@ -665,6 +737,54 @@ async function initFile(fileName, initValue) {
665737
await Fs.writeFile(fileName, initValue, "utf8");
666738
}
667739

740+
async function sortAndWritePackageJson() {
741+
let pkg = await readPackageJson();
742+
743+
/** @type {Object.<String, any>} */
744+
let newPkg = {};
745+
let pkgKeys = Object.keys(pkg);
746+
747+
let orderedKeys = [
748+
"name",
749+
"version",
750+
"description",
751+
"main",
752+
"files",
753+
"type",
754+
"imports",
755+
"exports",
756+
"scripts",
757+
];
758+
for (let key of orderedKeys) {
759+
let hasKey = remove(pkgKeys, key);
760+
if (hasKey) {
761+
newPkg[key] = pkg[key];
762+
}
763+
}
764+
for (let key of pkgKeys) {
765+
newPkg[key] = pkg[key];
766+
}
767+
768+
let pkgJson = JSON.stringify(newPkg, null, 2);
769+
await Fs.writeFile(PKG_NAME, pkgJson, "utf8");
770+
}
771+
772+
/**
773+
* @param {Array<String>} arr
774+
* @param {String} str
775+
* @returns {String?}
776+
*/
777+
function remove(arr, str) {
778+
let index = arr.indexOf(str);
779+
if (index > -1) {
780+
let removed = arr.splice(index, 1);
781+
let el = removed[0] || null;
782+
return el;
783+
}
784+
785+
return null;
786+
}
787+
668788
/**
669789
* @param {String} metaKey - ex: lint, fmt, start
670790
* @param {String} scriptKey - ex: jshint, prettier
@@ -723,8 +843,8 @@ async function upsertNpmScript(
723843
* @param {Array<String>} args
724844
*/
725845
async function exec(exe, args) {
726-
return new Promise(function (resolve, reject) {
727-
let cmd = spawn(exe, args);
846+
return await new Promise(function (resolve, reject) {
847+
let cmd = ChildProcess.spawn(exe, args);
728848

729849
/** @type {Array<String>} */
730850
let stdout = [];

0 commit comments

Comments
 (0)