js-dev-tool 1.2.24 → 1.2.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-dev-tool",
3
- "version": "1.2.24",
3
+ "version": "1.2.25",
4
4
  "type": "commonjs",
5
5
  "bin": {
6
6
  "jstool": "tools.js",
@@ -39,6 +39,12 @@
39
39
  "import": "./progress/*.js",
40
40
  "require": "./progress/*.js"
41
41
  },
42
+ "./scripts/wp/*": {
43
+ "import": "./scripts/wp/*.mjs"
44
+ },
45
+ "./scripts/vitest/*": {
46
+ "import": "./scripts/vitest/*.mjs"
47
+ },
42
48
  "./basic-types": {
43
49
  "types": "./basic-types.d.ts"
44
50
  }
@@ -66,18 +72,18 @@
66
72
  "progress",
67
73
  "scripts",
68
74
  "tool-lib",
69
- "./index.js",
70
- "./tools.js",
71
- "./utils.js",
72
- "./tsconfig.json",
75
+ "index.js",
76
+ "tools.js",
77
+ "utils.js",
78
+ "tsconfig.json",
73
79
  "!tool-lib/cjbm-*",
74
- "!unzip.ts",
80
+ "!*zip.{j,t}s",
75
81
  "!scripts/bin",
76
82
  "!publish-version.json",
77
83
  "!scripts/*.mjs",
78
84
  "!scripts/smoke",
79
85
  "!regex-test.ts",
80
- "!extras/npm",
86
+ "!extras/{npm,navigator-uadata*}",
81
87
  "!/**/*.png",
82
88
  "!*@*.*",
83
89
  "!*fragments*",
@@ -85,16 +91,15 @@
85
91
  ],
86
92
  "peerDependencies": {
87
93
  "archiver": "^7.0.1",
88
- "webpack": "*"
94
+ "webpack": "*",
95
+ "typescript": "^6"
89
96
  },
90
97
  "dependencies": {
91
- "colors.ts": "^1.0.20",
92
- "fflate": "^0.8.3",
98
+ "colors.tsz": "^1.6.4",
93
99
  "literate-regex": "^0.6.11",
94
- "mini-semaphore": "^1.5.4",
95
100
  "replace": "^1.2.2",
96
101
  "rm-cstyle-cmts": "^3.4.4",
97
- "terser": "^5.48.0",
102
+ "terser": "^5.49.0",
98
103
  "tin-args": "^0.1.7",
99
104
  "ts-cc-map": "^1.1.0"
100
105
  }
@@ -0,0 +1,78 @@
1
+ /*!
2
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
+ // Copyright (C) 2026 jeffy-g <hirotom1107@gmail.com>
4
+ // Released under the MIT license
5
+ // https://opensource.org/licenses/mit-license.php
6
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
+ */
8
+ /**
9
+ * @file lib/ts-const-enum-transform.mjs
10
+ */
11
+ import path from "node:path";
12
+ import ts from "typescript";
13
+ /** @type {ts.CompilerOptions} */
14
+ const compilerOptDefault = {
15
+ declaration: false,
16
+ declarationMap: false,
17
+ emitDeclarationOnly: false,
18
+ noEmit: false,
19
+ preserveConstEnums: false,
20
+ sourceMap: false,
21
+ };
22
+ /**
23
+ * + when could refers `vite` types
24
+ *
25
+ * &#64;import * as NsVite from "vite";
26
+ *
27
+ * ```
28
+ * import * as NsVite from "vite";
29
+ * // @ returns {NsVite.Plugin}
30
+ * ```
31
+ *
32
+ * @template {unknown} R
33
+ * @param {string=} cwd
34
+ * @param {ts.CompilerOptions=} compilerOpt
35
+ * @param {(tsEmitFileName: string) => boolean=} validateFileName
36
+ */
37
+ export function tsConstEnumPlugin(
38
+ cwd,
39
+ compilerOpt,
40
+ validateFileName = (fileName) => /\.(?:c|m)?jsx?$/.test(fileName)
41
+ ) {
42
+ /** @type {ts.Program | undefined} */
43
+ let program;
44
+ const dirname = path.dirname;
45
+ const normalize = path.normalize;
46
+ cwd ??= process.cwd();
47
+ const getProgram = () => {
48
+ if (program) return program;
49
+ const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, "tsconfig.json");
50
+ if (!configPath) throw new Error("tsconfig.json was not found.");
51
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
52
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, dirname(configPath), {
53
+ ...compilerOptDefault, ...compilerOpt
54
+ });
55
+ program = ts.createProgram(parsed.fileNames, parsed.options);
56
+ return program;
57
+ };
58
+ return /** @type {R} */({
59
+ name: "ts-const-enum-transform",
60
+ enforce: "pre",
61
+ handleHotUpdate() {
62
+ program = undefined;
63
+ },
64
+ /** @type {(code: string, id: string) => { code: string, map: null } | null} */
65
+ transform(_code, id) {
66
+ const tsc = getProgram();
67
+ const sourceFile = tsc.getSourceFile(
68
+ normalize(id.split("?")[0])
69
+ );
70
+ if (!sourceFile) return null;
71
+ let code = "";
72
+ tsc.emit(sourceFile, (outputName, outputText) => {
73
+ if (validateFileName(outputName)) code = outputText;
74
+ });
75
+ return code ? { code, map: null } : null;
76
+ },
77
+ });
78
+ }
@@ -0,0 +1,144 @@
1
+ /*!
2
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
+ // Copyright (C) 2020 jeffy-g <hirotom1107@gmail.com>
4
+ // Released under the MIT license
5
+ // https://opensource.org/licenses/mit-license.php
6
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
+ */
8
+ /// <reference path="../../basic-types.d.ts" preserve="true"/>
9
+ /**
10
+ * @file scripts/wp/webpack.config.util.mjs
11
+ */
12
+ import * as path from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import webpack from "webpack";
15
+ import * as progress from "./wp-progress.mjs";
16
+ const configFileName = fileURLToPath(import.meta.url);
17
+ export const CWD = process.cwd();
18
+ /**
19
+ * @typedef {(originId: string, module: webpack.Module) => string | number} TModuleIdMaker
20
+ */
21
+ /**
22
+ * __reduce webpack size by shorten modId__
23
+ *
24
+ * @param {TModuleIdMaker} maker
25
+ * @returns
26
+ */
27
+ export const mapModuleIds = maker => (/** @type {webpack.Compiler} */compiler) => {
28
+ const context = /** @type {string} */(compiler.options.context);
29
+ compiler.hooks.compilation.tap("ChangeModuleIdsPlugin", compilation => {
30
+ compilation.hooks.beforeModuleIds.tap("ChangeModuleIdsPlugin", modules => {
31
+ const chunkGraph = compilation.chunkGraph;
32
+ for (const module of modules) {
33
+ if (module.libIdent) {
34
+ const origId = module.libIdent({ context });
35
+ if (!origId) continue;
36
+ chunkGraph.setModuleId(module, maker(origId, module));
37
+ }
38
+ }
39
+ });
40
+ });
41
+ };
42
+ /** @type {TModuleIdMaker} */
43
+ export const numberMaker = ((cache) => {
44
+ let idx = 0;
45
+ return (oid, mod) => {
46
+ let nid = cache.get(oid);
47
+ if (typeof nid !== "number") {
48
+ cache.set(oid, (nid = idx++));
49
+ }
50
+ return nid;
51
+ };
52
+ })(/** @type {Map<string, number>} */(new Map()));
53
+ /**
54
+ * @param {NonNullable<WpConfig["entry"]>} entry
55
+ */
56
+ export function getIndexName(entry) {
57
+ const index = /** @type {webpack.EntryObject} */(entry).index || /** @type {webpack.EntryObject} */(entry).main;
58
+ if (typeof index === "string") {
59
+ return path.basename(index);
60
+ }
61
+ return Object.keys(entry)[0];
62
+ }
63
+ /**
64
+ * @typedef {"name" | "mode" | "target" | "entry" | "output" | "module" | "externalsPresets" | "resolve" | "devtool" | "plugins" | "profile" | "cache" | "recordsPath" | "externals" | "experiments"} TWpConfigRequiredKeys
65
+ * @typedef {RequireKeys<webpack.Configuration, TWpConfigRequiredKeys>} WpConfig
66
+ * @typedef {{ beautify?: true; forceSourceMap?: true, altEntry?: WpConfig["entry"]; tsconfig?: string; logsSubDir?: string }} TExtraOptions
67
+ */
68
+ /**
69
+ * @typedef {"standard" | "custom"=} TWPProgressType
70
+ */
71
+ /**
72
+ * @date 2026/06/19 09:55:39
73
+ */
74
+ const wpProgressType = /** @type {TWPProgressType} */(process.env.WP_PROGRESS_TYPE);
75
+ /**
76
+ * CAVEAT: `resolve`, `entry`, `externals`, `module`, `optimization` property is __empty object__
77
+ *
78
+ * @param {WpConfig["target"]} target
79
+ * @param {WpConfig["output"]} output
80
+ * @param {WpConfig["mode"]=} mode default is __`"production"`__
81
+ * @param {TExtraOptions=} extraOpt see {@link TExtraOptions}
82
+ * @return {WpConfig}
83
+ * @version 2.0
84
+ * @date 2022/3/20 - update jsdoc, added new parameter `extraOpt`
85
+ */
86
+ export const createWebpackConfig = (target, output, mode = "production", extraOpt = {}) => {
87
+ const {
88
+ altEntry,
89
+ forceSourceMap,
90
+ logsSubDir = "webpack"
91
+ } = extraOpt;
92
+ /**
93
+ * @type {WpConfig["entry"]}
94
+ */
95
+ const entry = altEntry ?? {};
96
+ const mtype = /** @type {webpack.LibraryOptions} */(output.library).type;
97
+ const mainName = `${target}@${mtype}_${getIndexName(entry)}`;
98
+ const outputModule = mtype === "module";
99
+ /** @type {WpConfig} */
100
+ const configObject = {
101
+ name: `${mainName}-${mode}`,
102
+ mode,
103
+ target,
104
+ entry,
105
+ output,
106
+ module: {
107
+ rules: []
108
+ },
109
+ externals: {},
110
+ experiments: {},
111
+ externalsPresets: { node: true },
112
+ resolve: {
113
+ },
114
+ devtool: (forceSourceMap || mode === "development") ? "source-map" : false,
115
+ plugins: [],
116
+ optimization: {
117
+ },
118
+ profile: false,
119
+ cache: {
120
+ type: "filesystem",
121
+ buildDependencies: {
122
+ config: [configFileName],
123
+ },
124
+ },
125
+ recordsPath: `${CWD}/logs/${logsSubDir? logsSubDir + "/" : "" }webpack-module-ids_${mainName}.json`
126
+ };
127
+ if (outputModule) {
128
+ configObject.experiments = {
129
+ outputModule
130
+ };
131
+ }
132
+ if (wpProgressType === "custom") {
133
+ configObject.plugins.push(
134
+ new webpack.ProgressPlugin(
135
+ progress.getWebpackProgressPluginHandler(mainName)
136
+ )
137
+ );
138
+ }
139
+ return configObject;
140
+ };
141
+ /**
142
+ * @typedef {Parameters<typeof createWebpackConfig>} TCreateWebpackConfigParameters
143
+ * @typedef {[TCreateWebpackConfigParameters[0], TCreateWebpackConfigParameters[1], altEntry?: webpack.EntryObject, tsconfig?: string]} TWebpackConfigParameters
144
+ */
@@ -0,0 +1,95 @@
1
+ /*!
2
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
+ // Copyright (C) 2025 jeffy-g <hirotom1107@gmail.com>
4
+ // Released under the MIT license
5
+ // https://opensource.org/licenses/mit-license.php
6
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7
+ */
8
+ /**
9
+ * @file scripts/wp/wp-progress.mjs
10
+ * @CAVEATS To enable `progress`, you need to install webpack and webpack-cli in package local.
11
+ */
12
+ import * as extras from "../../progress/progress-extras.js";
13
+ import * as lib from "../../common/index.js";
14
+ /**
15
+ * @typedef {(percentage: number, message: string, ...args: string[]) => void} TWebpackProgressHandler
16
+ * @typedef {(percentage: number, message: string, ...args: string[]) => Promise<void>} TWebpackProgressHandlerPromise
17
+ */
18
+ const PROGRESS_ROW_START = 4;
19
+ let rowStart = PROGRESS_ROW_START;
20
+ /**
21
+ * @param {number} pct
22
+ * @returns {string}
23
+ */
24
+ const formatPercentage = pct => `processing ${(pct * 100).toFixed(4)}%`;
25
+ /**
26
+ * @param {NodeJS.WriteStream} stream
27
+ */
28
+ const preparProgress = async (stream = process.stdout) => {
29
+ stream.write(`\x1b[${PROGRESS_ROW_START};1H`);
30
+ stream.write("\x1b[J");
31
+ };
32
+ /** @type {Map<string, number>} */
33
+ const rowsMap = new Map();
34
+ /** @type {(bunner: string) => TWebpackProgressHandler} */
35
+ const getWebpackProgressPluginHandler = ((bunner) => {
36
+ const cwd = process.cwd();
37
+ const render = lib.renderLine;
38
+ const cwdLen = cwd.length;
39
+ let dotted = 0;
40
+ const renderDot = () => {
41
+ process.stderr.write(".");
42
+ dotted++;
43
+ if (dotted % 100 === 0) {
44
+ process.stderr.write("\n");
45
+ }
46
+ };
47
+ const shortenProgress = (/** @type {number} */pct) => {
48
+ render(formatPercentage(pct));
49
+ pct >= 1 && (console.log(), dotted = 0);
50
+ };
51
+ let prepar = 0;
52
+ /**
53
+ * NOTE: 2025/11/17 15:58:11 - 複数の webpack process を確実に render する最適解だろう
54
+ *
55
+ * cursor position の取得、moveCursorTo などを試したが、期待する挙動に達するには壁があった...
56
+ *
57
+ * @type {TWebpackProgressHandler}
58
+ */
59
+ const v5Progress = /* async */ (percentage, message, ...args) => {
60
+ if (!prepar) {
61
+ /* await */ preparProgress();
62
+ prepar = 1;
63
+ }
64
+ if (!message) {
65
+ message = "- done -";
66
+ }
67
+ let pathOrPluginName = args.shift() || "";
68
+ if (pathOrPluginName) {
69
+ const x = pathOrPluginName.lastIndexOf(cwd) + 1;
70
+ if (x > 0) {
71
+ pathOrPluginName = pathOrPluginName.slice(x + cwdLen);
72
+ }
73
+ }
74
+ let row = rowsMap.get(bunner);
75
+ if (typeof row !== "number") {
76
+ rowsMap.set(bunner, (row = rowStart++));
77
+ }
78
+ render(
79
+ `[${bunner}]: ${(percentage * 100).toFixed(4)}%, process: [${message}]${pathOrPluginName ? `, info: [${pathOrPluginName}]` : ""}${args.length ? " - " : ""}${args.join(", ")}`, row
80
+ );
81
+ percentage >= 1 && console.log();
82
+ };
83
+ const processType = extras.checkENV();
84
+ if (processType === "ci" || process.env.CI_CODEX) {
85
+ return renderDot;
86
+ } else {
87
+ if (processType === "gitpod") {
88
+ return shortenProgress;
89
+ }
90
+ return v5Progress;
91
+ }
92
+ });
93
+ export {
94
+ getWebpackProgressPluginHandler
95
+ };
package/tools.js CHANGED
@@ -9,7 +9,7 @@
9
9
  */
10
10
  // @ts-check
11
11
  "use strict";
12
- require("colors.ts");
12
+ require("colors.tsz");
13
13
  const fs = require("fs");
14
14
  const path = require("path");
15
15
  const rmc = require("rm-cstyle-cmts");
package/scripts/unzip.js DELETED
@@ -1,29 +0,0 @@
1
- "use strict";
2
- const fs = require("fs");
3
- const fflate = require("fflate");
4
- const { unzip } = fflate;
5
- /**
6
- * @param {string} fileName
7
- */
8
- const decompress = (fileName) => {
9
- fs.readFile(fileName, null, (err, data) => {
10
- if (err) {
11
- console.error(err);
12
- } else {
13
- console.time(fileName);
14
- unzip(data, (err, unzipped) => {
15
- console.timeEnd(fileName);
16
- if (err) {
17
- console.error(err);
18
- return;
19
- }
20
- Object.entries(unzipped).forEach(([filename, data]) => {
21
- fs.writeFile(filename, data, null, () => {
22
- console.log("write:", filename);
23
- });
24
- });
25
- });
26
- }
27
- });
28
- };
29
- module.exports = decompress;
package/scripts/zip.js DELETED
@@ -1,86 +0,0 @@
1
- const fs = require("fs");
2
- const path = require("path");
3
- const fflate = require("fflate");
4
- const { TextEncoder } = require("util");
5
- const ALREADY_COMPRESSED = [
6
- "7z", "aifc", "bz2", "doc", "docx",
7
- "gif", "gz", "heic", "heif", "jpeg",
8
- "jpg", "mov", "mp3", "mp4", "pdf",
9
- "png", "ppt", "pptx", "rar", "webm",
10
- "webp", "xls", "xlsx", "zip"
11
- ];
12
- /**
13
- * @param {string} fileName
14
- * @param {(out: Uint8Array | NodeJS.ErrnoException) => void} cb
15
- */
16
- const fileToU8 = (fileName, cb /* : (out: Uint8Array) => void */) => {
17
- fs.readFile(fileName, "utf8", (err, data) => {
18
- if (err) {
19
- cb(err);
20
- } else {
21
- cb(new TextEncoder().encode(data));
22
- }
23
- });
24
- };
25
- /**
26
- * @param {path.ParsedPath} parsedPath
27
- * @param {(out: Uint8Array | null) => void} callback
28
- * @param {string} [comment]
29
- */
30
- const processFile = function (parsedPath, callback, comment) {
31
- const filePath = `${parsedPath.dir}/${parsedPath.base}`;
32
- fileToU8(filePath, function (data) {
33
- if (data instanceof Uint8Array) {
34
- /** @type {fflate.AsyncZippable} */
35
- const zipObj = {
36
- [parsedPath.base]: [
37
- data, {
38
- level: ALREADY_COMPRESSED.indexOf(parsedPath.ext) === -1 ? 6 : 0,
39
- comment,
40
- },
41
- ],
42
- };
43
- console.time(filePath);
44
- fflate.zip(
45
- zipObj,
46
- {
47
- },
48
- function (err, out) {
49
- if (err) {
50
- console.log(err);
51
- callback(null);
52
- console.timeEnd(filePath);
53
- } else {
54
- console.timeEnd(filePath);
55
- callback(out);
56
- }
57
- },
58
- );
59
- } else {
60
- console.error(data);
61
- }
62
- });
63
- };
64
- /**
65
- * @param {string} inputPath
66
- * @param {string} [comment]
67
- * @param {string} [dest]
68
- */
69
- module.exports = function zip(inputPath, comment, dest) {
70
- let actualOutput = dest;
71
- const pp = path.parse(inputPath);
72
- processFile(
73
- pp,
74
- (out) => {
75
- if (out) {
76
- if (!actualOutput) {
77
- actualOutput = `${pp.dir ? pp.dir + "/" : ""}${pp.name}.zip`;
78
- }
79
- fs.writeFile(actualOutput, out, "binary", () => {
80
- console.log("done!!");
81
- });
82
- }
83
- },
84
- comment,
85
- );
86
- };