js-dev-tool 1.0.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/LICENSE +21 -0
- package/README.md +150 -0
- package/basic-types.d.ts +279 -0
- package/common/index.d.ts +43 -0
- package/common/index.js +101 -0
- package/extras/tiny-progress.d.ts +14 -0
- package/extras/tiny-progress.js +74 -0
- package/index.d.ts +27 -0
- package/index.js +15 -0
- package/lib/unzip.min.js +812 -0
- package/lib/zip.min.js +1036 -0
- package/lib/zlibjs.d.ts +34 -0
- package/package.json +51 -0
- package/progress/index.d.ts +92 -0
- package/progress/index.js +305 -0
- package/progress/progress-extras.js +90 -0
- package/progress/rnd-spinner.js +55 -0
- package/progress/spinners.d.ts +74 -0
- package/progress/spinners.json +805 -0
- package/progress/test.js +94 -0
- package/regex.d.ts +154 -0
- package/scripts/publish-version.json +3 -0
- package/scripts/unzip.js +30 -0
- package/scripts/zip.js +138 -0
- package/tool-lib/cjbm.js +239 -0
- package/tool-lib/cjmb-regex-latest.svg +366 -0
- package/tool-lib/cjmb-regex.svg +90 -0
- package/tool-lib/cmt-trick.js +125 -0
- package/tool-lib/ps.js +158 -0
- package/tool-lib/rws.js +181 -0
- package/tool-lib/tools.d.ts +245 -0
- package/tool-lib/zip-task.js +34 -0
- package/tools.d.ts +7 -0
- package/tools.js +450 -0
- package/tsconfig.json +25 -0
- package/utils.d.ts +194 -0
- package/utils.js +643 -0
package/utils.js
ADDED
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
3
|
+
<one line to give the program's name and a brief idea of what it does.>
|
|
4
|
+
Copyright (C) 2017 jeffy-g hirotom1107@gmail.com
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU Affero General Public License as
|
|
8
|
+
published by the Free Software Foundation, either version 3 of the
|
|
9
|
+
License, or (at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU Affero General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU Affero General Public License
|
|
17
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
18
|
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
19
|
+
*/
|
|
20
|
+
/// <reference types="./basic-types"/>
|
|
21
|
+
// @ts-check
|
|
22
|
+
|
|
23
|
+
// NOTE: fs-extra are bit slower.
|
|
24
|
+
const fs = require("fs");
|
|
25
|
+
// const util = require('util');
|
|
26
|
+
const path = require("path");
|
|
27
|
+
|
|
28
|
+
const lib = require("./common");
|
|
29
|
+
const getExtraArgs = require("tin-args");
|
|
30
|
+
|
|
31
|
+
const CI = !!process.env.CI;
|
|
32
|
+
const log = (() => {
|
|
33
|
+
return CI ? () => ({}) : console.log;
|
|
34
|
+
})();
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* get node version at runtime.
|
|
38
|
+
*
|
|
39
|
+
* format must be `v\d+.\d+.\d+`
|
|
40
|
+
*
|
|
41
|
+
* ex:
|
|
42
|
+
* ```
|
|
43
|
+
* const utils = require("./utils");
|
|
44
|
+
* const nv = utils.extractVersion();
|
|
45
|
+
* console.log(nv); // => {major: 10, minor: 9, patch: 0}
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @param {string} versionString default is process.version
|
|
49
|
+
*/
|
|
50
|
+
function extractVersion(versionString = process.version) {
|
|
51
|
+
const RE_VERSION = /v(\d+).(\d+).(\d+)/;
|
|
52
|
+
// NOTE: pv is Array.isArray(pv), extend Array
|
|
53
|
+
let pv = RE_VERSION.exec(versionString);
|
|
54
|
+
const [major = 0, minor = 0, patch = 0] = pv
|
|
55
|
+
? pv
|
|
56
|
+
.map((value, i) => {
|
|
57
|
+
return (i > 0 && +value) || void 0;
|
|
58
|
+
})
|
|
59
|
+
.slice(1)
|
|
60
|
+
: [];
|
|
61
|
+
console.log("result:", major, minor, patch);
|
|
62
|
+
return { major, minor, patch };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* use toLocaleString
|
|
67
|
+
* @param {any} ymd use simple year month day formant? default `false`
|
|
68
|
+
* + should be truthy/falsy value
|
|
69
|
+
*/
|
|
70
|
+
function dateStringForFile(ymd = false) {
|
|
71
|
+
// return new Date().toLocaleString().replace(/\//g, "-").replace(/:/g, "_").replace(/ /g, "@");
|
|
72
|
+
return new Date()
|
|
73
|
+
.toLocaleString(void 0, {
|
|
74
|
+
year: "2-digit",
|
|
75
|
+
month: "2-digit",
|
|
76
|
+
day: "2-digit",
|
|
77
|
+
hour: ymd ? void 0 : "2-digit",
|
|
78
|
+
minute: ymd ? void 0 : "2-digit",
|
|
79
|
+
second: ymd ? void 0 : "2-digit",
|
|
80
|
+
// DEVNOTE: 191215 - "-" character appeared in node v13.3.0 (maybe
|
|
81
|
+
})
|
|
82
|
+
.replace(/(-|\/|:| )/g, (match, $1) => {
|
|
83
|
+
switch ($1) {
|
|
84
|
+
case "-":
|
|
85
|
+
case "/":
|
|
86
|
+
case ":":
|
|
87
|
+
return "";
|
|
88
|
+
case " ":
|
|
89
|
+
return "@";
|
|
90
|
+
}
|
|
91
|
+
return match;
|
|
92
|
+
});
|
|
93
|
+
// return new Date().toLocaleString().replace(/(\/|:| )/g, (match, $1) => {
|
|
94
|
+
// switch($1) {
|
|
95
|
+
// case "/": return "-";
|
|
96
|
+
// case ":": return "_";
|
|
97
|
+
// case " ": return "@";
|
|
98
|
+
// }
|
|
99
|
+
// return match;
|
|
100
|
+
// });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @param {string} path
|
|
106
|
+
* @param {(dirent: import("fs").Dirent) => void} handler
|
|
107
|
+
*/
|
|
108
|
+
function walkDirSync(path, handler) {
|
|
109
|
+
fs.readdirSync(path, { withFileTypes: true }).forEach(handler);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* write text content to dest path.
|
|
114
|
+
* when not exists parent directory, creat it.
|
|
115
|
+
*
|
|
116
|
+
* @param {string|NodeJS.ReadableStream|Buffer} content text? content.
|
|
117
|
+
* @param {string} dest content output path
|
|
118
|
+
* @param {() => void} [callback] the callback function
|
|
119
|
+
*/
|
|
120
|
+
function writeTextUTF8(content, dest, callback) {
|
|
121
|
+
// need dest parent dir check.
|
|
122
|
+
lib.checkParentDirectory(dest);
|
|
123
|
+
|
|
124
|
+
// actually, can write as binary
|
|
125
|
+
const ws = fs.createWriteStream(dest);
|
|
126
|
+
ws.on("error", function (err) {
|
|
127
|
+
log("WriteStream.error evnet!", arguments);
|
|
128
|
+
}).on("close", function (/*no args*/) {
|
|
129
|
+
// DEVNOTE: this event never occurs when WriteStream.write returned `true`
|
|
130
|
+
// log("[close] %s, stream closed", dest);
|
|
131
|
+
callback && callback();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (content instanceof Buffer) {
|
|
135
|
+
content = content.toString();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (typeof content === "string") {
|
|
139
|
+
// chunk <string> | <Buffer> | <Uint8Array> | <any>
|
|
140
|
+
const success = ws.write(content);
|
|
141
|
+
// const success = ws.write(content, function (/*no args*/) {
|
|
142
|
+
// // log(arguments);
|
|
143
|
+
// log("callback of WriteStream.write");
|
|
144
|
+
// });
|
|
145
|
+
// log("writeTextUTF8: write: %s,", dest, success);
|
|
146
|
+
// DEVNOTE: "drain" event callback -> WriteStream.write callback
|
|
147
|
+
// -> WriteStream.end() => "close" event callback.
|
|
148
|
+
if (!success) {
|
|
149
|
+
ws.once("drain", function () {
|
|
150
|
+
// log("[drain] file written: %s,", dest, ws.bytesWritten);
|
|
151
|
+
ws.end(); // -> call close()
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
// process.nextTick(callback);
|
|
155
|
+
callback && callback();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// NOTE: see https://nodejs.org/dist/latest-v6.x/docs/api/stream.html#stream_readable_pipe_destination_options
|
|
159
|
+
else if ("readable" in content) {
|
|
160
|
+
// Readable stream?
|
|
161
|
+
content.pipe(ws);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @typedef {(err: any, data: string) => void} TFsCallback
|
|
167
|
+
*/
|
|
168
|
+
/**
|
|
169
|
+
* @template {TFsCallback | undefined} C description
|
|
170
|
+
* @template {Conditional<C, string, void>} R description
|
|
171
|
+
* @param {string} from file path.
|
|
172
|
+
* @param {C} [callback]
|
|
173
|
+
* @returns {R} description
|
|
174
|
+
*/
|
|
175
|
+
function readTextUTF8(from, callback) {
|
|
176
|
+
if (typeof callback === "function") {
|
|
177
|
+
fs.readFile(from, "utf8", callback);
|
|
178
|
+
} else {
|
|
179
|
+
return /** @type {R} */ (fs.readFileSync(from, "utf8"));
|
|
180
|
+
}
|
|
181
|
+
return /** @type {R} */ (undefined);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @template T
|
|
186
|
+
* @typedef {Record<string, T>} TypedRecord<T>
|
|
187
|
+
*/
|
|
188
|
+
/**
|
|
189
|
+
* @template T
|
|
190
|
+
* @typedef {TBD<(err: any, data: TypedRecord<T>) => void>} TReadJsonCallback
|
|
191
|
+
*/
|
|
192
|
+
/**
|
|
193
|
+
* NOTE: when callback specified, returns undefined
|
|
194
|
+
*
|
|
195
|
+
* @template T
|
|
196
|
+
* @template {TReadJsonCallback<T>} C description
|
|
197
|
+
* @template {Conditional<C, TypedRecord<T>, void>} R description
|
|
198
|
+
* @param {string} path file path.
|
|
199
|
+
* @param {C} [callback]
|
|
200
|
+
* @returns {R} description
|
|
201
|
+
*/
|
|
202
|
+
function readJson(path, callback) {
|
|
203
|
+
if (typeof callback === "function") {
|
|
204
|
+
readTextUTF8(path, (err, data) => {
|
|
205
|
+
callback(err, JSON.parse(data));
|
|
206
|
+
});
|
|
207
|
+
} else {
|
|
208
|
+
const data = readTextUTF8(path);
|
|
209
|
+
return JSON.parse(data);
|
|
210
|
+
}
|
|
211
|
+
return /** @type {R} */ (undefined);
|
|
212
|
+
}
|
|
213
|
+
// // OK
|
|
214
|
+
// /** @type {Record<string, {}>} */
|
|
215
|
+
// const config = readJson("path");
|
|
216
|
+
// // OK
|
|
217
|
+
// readJson("path", (err, data) => err);
|
|
218
|
+
// // OK
|
|
219
|
+
// const config2 = readTextUTF8("path");
|
|
220
|
+
// // OK
|
|
221
|
+
// readTextUTF8("path", (err, data) => err);
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* use "rm-cstyle-cmts"
|
|
225
|
+
*
|
|
226
|
+
* @param {string} source
|
|
227
|
+
*/
|
|
228
|
+
function removeJsonComments(source) {
|
|
229
|
+
if (typeof source !== "string") {
|
|
230
|
+
throw new TypeError("invalid text content!");
|
|
231
|
+
}
|
|
232
|
+
return require("rm-cstyle-cmts")(source);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** @type {(options: any) => void} */
|
|
236
|
+
let nodeReplace;
|
|
237
|
+
/**
|
|
238
|
+
* @param {RegExp} regex
|
|
239
|
+
* @param {string | Function} replacement
|
|
240
|
+
* @param {string[]} paths Paths that do not exist are ignored
|
|
241
|
+
* @param {boolean} [async]
|
|
242
|
+
*
|
|
243
|
+
* @date 2019-4-26
|
|
244
|
+
*/
|
|
245
|
+
// DEVNOTE: 2020/9/20 - Added exception handling code
|
|
246
|
+
function fireReplace(regex, replacement, paths, async = false) {
|
|
247
|
+
// @ts-ignore "replace" is peerDependencies
|
|
248
|
+
nodeReplace === void 0 && (nodeReplace = require("replace"));
|
|
249
|
+
// replace init.tsx init.js ./lib/index.html && replace \\.\\/pkg\\.json ../package.json ./lib/app-properties.js
|
|
250
|
+
if (Array.isArray(paths)) {
|
|
251
|
+
// DEVNOTE: 2020/5/11 22:41:06 - exclude non exists files
|
|
252
|
+
paths = paths.filter((path) => fs.existsSync(path));
|
|
253
|
+
nodeReplace({
|
|
254
|
+
regex, //: /init\.tsx/g,
|
|
255
|
+
replacement, //: "init.js",
|
|
256
|
+
paths, //: ["./lib/index.html"],
|
|
257
|
+
recursive: false,
|
|
258
|
+
silent: false,
|
|
259
|
+
// for test?
|
|
260
|
+
preview: false,
|
|
261
|
+
// replace function.
|
|
262
|
+
// funcFile: "js source path",
|
|
263
|
+
//
|
|
264
|
+
async,
|
|
265
|
+
// regexp flags, if "regex" are plain string then needed.
|
|
266
|
+
ignoreCase: false,
|
|
267
|
+
multiline: false,
|
|
268
|
+
});
|
|
269
|
+
} else {
|
|
270
|
+
throw new Error(`invalid paths parameter: paths=[${paths}]`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* create sourceName zip. (using zip.min.js
|
|
276
|
+
*
|
|
277
|
+
* @param {string} scriptPath simple script file name. e.g - webpack (original path are "./lib/webpack.js")
|
|
278
|
+
* @param {string} comment the zip file comment.
|
|
279
|
+
*/
|
|
280
|
+
function compressScript(scriptPath, comment = "") {
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
const zlibZip = require("./lib/zip.min").Zlib.Zip;
|
|
283
|
+
// const zlibZip = require("zlibjs/bin/zip.min").Zlib.Zip;
|
|
284
|
+
const zip = new zlibZip();
|
|
285
|
+
|
|
286
|
+
const scriptBin = fs.readFileSync(scriptPath);
|
|
287
|
+
// plainData1
|
|
288
|
+
zip.addFile(scriptBin, {
|
|
289
|
+
// filename: stringToByteArray("webpack.js"),
|
|
290
|
+
filename: stringToByteArray(path.basename(scriptPath)),
|
|
291
|
+
comment: stringToByteArray(comment),
|
|
292
|
+
// STORE or DEFLATE, default: DEFLATE...?
|
|
293
|
+
compressionMethod: zlibZip.CompressionMethod.DEFLATE,
|
|
294
|
+
os: zlibZip.OperatingSystem.MSDOS,
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
console.log(`added ${scriptPath} to zip`);
|
|
298
|
+
console.log("start compress...");
|
|
299
|
+
console.time("zip:compress");
|
|
300
|
+
const compressed = zip.compress();
|
|
301
|
+
console.timeEnd("zip:compress");
|
|
302
|
+
console.log("compress done.\n");
|
|
303
|
+
|
|
304
|
+
const pp = path.parse(scriptPath);
|
|
305
|
+
const output = `${pp.dir ? pp.dir + "/" : ""}${pp.name}.zip`;
|
|
306
|
+
fs.writeFile(output, compressed, (err) => {
|
|
307
|
+
console.log(`\nzip file created, error: ${err}\n => ${output}`);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* @param {string} str
|
|
312
|
+
*/
|
|
313
|
+
function stringToByteArray(str) {
|
|
314
|
+
const array = new Uint8Array(str.length);
|
|
315
|
+
for (let i = 0, il = str.length; i < il; ++i) {
|
|
316
|
+
array[i] = str.charCodeAt(i) & 0xff;
|
|
317
|
+
}
|
|
318
|
+
return array;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* DEVNOTE: 10/21/2018, 9:15:00 PM - using "archiver" package, this is too fast!.
|
|
324
|
+
*
|
|
325
|
+
* @param {string} scriptPath
|
|
326
|
+
* @param {string} comment
|
|
327
|
+
*/
|
|
328
|
+
function compressScript2(scriptPath, comment = "") {
|
|
329
|
+
// DEVNOTE: if want use "archiver" then install to npm global
|
|
330
|
+
const archiver = require("archiver");
|
|
331
|
+
const archive = archiver("zip", {
|
|
332
|
+
// comment, deplicated, unzip.min will fail decompress...
|
|
333
|
+
zlib: { level: 9 }, // Sets the compression level.
|
|
334
|
+
});
|
|
335
|
+
const pp = path.parse(scriptPath);
|
|
336
|
+
const output = fs.createWriteStream(`${pp.dir}/${pp.name}.zip`);
|
|
337
|
+
output.on("close", function () {
|
|
338
|
+
console.log(archive.pointer() + " total bytes");
|
|
339
|
+
console.log(
|
|
340
|
+
"archiver has been finalized and the output file descriptor has closed.",
|
|
341
|
+
);
|
|
342
|
+
});
|
|
343
|
+
output.on("end", function () {
|
|
344
|
+
console.log("Data has been drained");
|
|
345
|
+
});
|
|
346
|
+
// TODO: write code.
|
|
347
|
+
archive.on("progress", (progress) => {
|
|
348
|
+
console.log(progress.entries.processed);
|
|
349
|
+
});
|
|
350
|
+
archive.pipe(output);
|
|
351
|
+
// option name は必ず指定 (entry name となるため
|
|
352
|
+
archive.file(scriptPath, {
|
|
353
|
+
name: path.basename(scriptPath),
|
|
354
|
+
// DEVNOTE: "comment" are not entry at @types. however, it is entered in zip-stream.
|
|
355
|
+
// @ts-ignore ignore mistake of type definition
|
|
356
|
+
comment,
|
|
357
|
+
});
|
|
358
|
+
archive.finalize();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* it is bundled in webpack.js, other code becomes unnecessary.(at webpack
|
|
363
|
+
*
|
|
364
|
+
* + 📝 using "exec" internally
|
|
365
|
+
* * 🆗️ can use pipe command
|
|
366
|
+
*
|
|
367
|
+
* @param {string} command
|
|
368
|
+
* @param {string=} cwd 2025/2/1 current working directory
|
|
369
|
+
* @param {(result: string) => void} doneCallbackWithArgs gulp callback function.
|
|
370
|
+
*/
|
|
371
|
+
function execWithOutputResult(command, doneCallbackWithArgs, cwd) {
|
|
372
|
+
// const process = require("child_process");
|
|
373
|
+
console.log();
|
|
374
|
+
const { exec } = require("child_process");
|
|
375
|
+
return exec(command, { cwd }, (err, stdout /* , stderr */) => {
|
|
376
|
+
if (err) {
|
|
377
|
+
console.error(err);
|
|
378
|
+
} else {
|
|
379
|
+
doneCallbackWithArgs(stdout);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
*
|
|
386
|
+
* @param {string} list
|
|
387
|
+
*/
|
|
388
|
+
const NPM_INSTALL_SCRIPT = (list) => `
|
|
389
|
+
@echo off
|
|
390
|
+
rem REVISION LOG ENTRY
|
|
391
|
+
rem
|
|
392
|
+
rem File name : npm-upg.cmd
|
|
393
|
+
rem Revision By: Copyright 2020 Hiroyuki Tominaga, All Rights Reserved.
|
|
394
|
+
rem
|
|
395
|
+
rem 9:26 2018/06/27 When executed in batch - npm ERR! Maximum call stack size exceeded
|
|
396
|
+
rem
|
|
397
|
+
|
|
398
|
+
set opt=
|
|
399
|
+
if not "%1" == "" (
|
|
400
|
+
set opt=%1
|
|
401
|
+
) else (
|
|
402
|
+
set opt=i
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
rem workbox-cli@4 is too large
|
|
406
|
+
rem \`node-sass\` will complete more smoothly if installed separately
|
|
407
|
+
rem \`windows-build-tools\` - It is better to start PowerShell with administrator privileges and install
|
|
408
|
+
|
|
409
|
+
REM TODO: automation script by nodejs
|
|
410
|
+
REM + child_process("npm -g outdated") -> get output
|
|
411
|
+
REM + extract outdated packages by regex
|
|
412
|
+
REM + output install script
|
|
413
|
+
|
|
414
|
+
set LIST=${list}
|
|
415
|
+
|
|
416
|
+
echo packages="%LIST%"
|
|
417
|
+
npm %opt% -g %LIST%
|
|
418
|
+
`;
|
|
419
|
+
/**
|
|
420
|
+
* ### generate npm global package update script (windows command)
|
|
421
|
+
*
|
|
422
|
+
* ```js
|
|
423
|
+
* const utils = require("./utils");
|
|
424
|
+
* // ...
|
|
425
|
+
* // execute normally
|
|
426
|
+
* utils.genGlobalNpmUpdateScript("electron", "workbox-cli");
|
|
427
|
+
* // debug
|
|
428
|
+
* utils.genGlobalNpmUpdateScript("--debug", "electron", "workbox-cli");
|
|
429
|
+
* ```
|
|
430
|
+
*
|
|
431
|
+
* @param {string[]} excludes
|
|
432
|
+
*/
|
|
433
|
+
function genGlobalNpmUpdateScript(...excludes) {
|
|
434
|
+
let debug = false;
|
|
435
|
+
if (excludes.length && excludes[0] === "--debug") {
|
|
436
|
+
debug = true;
|
|
437
|
+
excludes.shift();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
console.log("run `npm -g outdated`");
|
|
441
|
+
// const progress = createProgressObject(aa, aa, aa);
|
|
442
|
+
// progress.run();
|
|
443
|
+
execWithOutputResult("npm -g outdated", (output) => {
|
|
444
|
+
console.log("done `npm -g outdated`");
|
|
445
|
+
/** @type {RegExpExecArray | null} */
|
|
446
|
+
let m;
|
|
447
|
+
/** @type {string[]} */
|
|
448
|
+
const packages = [];
|
|
449
|
+
const re = /^([\w-]+)/gm; // DEVNOTE: must use multi line flag
|
|
450
|
+
while ((m = re.exec(output))) {
|
|
451
|
+
const name = m[1];
|
|
452
|
+
if (name !== "Package" && !excludes.includes(name)) {
|
|
453
|
+
packages.push(name);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
const packageList = packages.join("^\n ");
|
|
457
|
+
const source = NPM_INSTALL_SCRIPT(packageList);
|
|
458
|
+
if (!debug) {
|
|
459
|
+
writeTextUTF8(source, "./tmp/npm-upg.cmd");
|
|
460
|
+
} else {
|
|
461
|
+
console.log(source);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
/* [simple test of `globalNpmUpdate`]
|
|
466
|
+
const dummy = (output: string) => {
|
|
467
|
+
let m: RegExpExecArray | null;
|
|
468
|
+
const packages: string[] = [];
|
|
469
|
+
const re = /^([\w-]+)/gm;
|
|
470
|
+
while (m = re.exec(output)) {
|
|
471
|
+
const name = m[1];
|
|
472
|
+
if (name !== "Package" && !excludes.includes(name)) {
|
|
473
|
+
packages.push(name);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const packageList = packages.join("^\n ");
|
|
477
|
+
const source = NPM_INSTALL_SCRIPT(packageList);
|
|
478
|
+
// if (!debug) {
|
|
479
|
+
// writeTextUTF8(source, "./tmp/npm-upg.cmd");
|
|
480
|
+
// } else {
|
|
481
|
+
// console.log(source);
|
|
482
|
+
// }
|
|
483
|
+
console.log(source);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
//
|
|
487
|
+
// for TEST code
|
|
488
|
+
//
|
|
489
|
+
const excludes = [
|
|
490
|
+
"electron", "workbox-cli"
|
|
491
|
+
];
|
|
492
|
+
const outdatedResult = `Package Current Wanted Latest Location
|
|
493
|
+
create-react-app 3.4.0 3.4.1 3.4.1 global
|
|
494
|
+
electron 8.0.1 8.2.0 8.2.0 global
|
|
495
|
+
firebase 7.12.0 7.13.1 7.13.1 global
|
|
496
|
+
firebase-tools 7.15.1 7.16.1 7.16.1 global
|
|
497
|
+
npm-check-updates 4.0.4 4.1.0 4.1.0 global
|
|
498
|
+
ts-node 8.7.0 8.8.1 8.8.1 global
|
|
499
|
+
typedoc 0.17.1 0.17.3 0.17.3 global
|
|
500
|
+
webpack 4.42.0 4.42.1 4.42.1 global
|
|
501
|
+
workbox-cli 4.3.1 4.3.1 5.1.2 global
|
|
502
|
+
`;
|
|
503
|
+
// run test
|
|
504
|
+
dummy(outdatedResult);
|
|
505
|
+
*/
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* ### command:
|
|
509
|
+
*
|
|
510
|
+
* + windows - chcp 65001 && clip
|
|
511
|
+
* + others - xclip
|
|
512
|
+
*
|
|
513
|
+
* @param {string} content the copy terget content as string.
|
|
514
|
+
* @param {string} [message] default: "text copied!"
|
|
515
|
+
* @param {boolean} [chcp65001] default `true`
|
|
516
|
+
*/
|
|
517
|
+
function copyText(content, message = "text copied!", chcp65001 = true) {
|
|
518
|
+
const os = require("os");
|
|
519
|
+
const cp = require("child_process");
|
|
520
|
+
const command =
|
|
521
|
+
os.platform() === "win32"
|
|
522
|
+
? `${chcp65001 ? "chcp 65001 && " : ""}clip`
|
|
523
|
+
: "xclip";
|
|
524
|
+
const clipTask = () => {
|
|
525
|
+
const childProc = cp.exec(command, (err, stdout) => {
|
|
526
|
+
if (err) {
|
|
527
|
+
console.error(err);
|
|
528
|
+
} else {
|
|
529
|
+
console.log(message, stdout);
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
// @ts-ignore
|
|
533
|
+
childProc.stdin.write(content, (error) => {
|
|
534
|
+
if (error) {
|
|
535
|
+
console.error(error);
|
|
536
|
+
}
|
|
537
|
+
// DEVNOTE: do noting...
|
|
538
|
+
// util.inspect("content_for_the_clipboard");
|
|
539
|
+
// @ts-ignore
|
|
540
|
+
childProc.stdin.end();
|
|
541
|
+
});
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
clipTask();
|
|
545
|
+
// if (os.platform() === "win32") {
|
|
546
|
+
// // clipTask();
|
|
547
|
+
// cp.exec("chcp", (err, stdout) => {
|
|
548
|
+
// if (err) {
|
|
549
|
+
// console.error(err);
|
|
550
|
+
// } else {
|
|
551
|
+
// if (!stdout.includes("65001")) {
|
|
552
|
+
// console.log("OKKKK");
|
|
553
|
+
// clipTask();
|
|
554
|
+
// }
|
|
555
|
+
// }
|
|
556
|
+
// }
|
|
557
|
+
// );
|
|
558
|
+
// } else {
|
|
559
|
+
// clipTask();
|
|
560
|
+
// }
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* use for gulp.dest(...)
|
|
565
|
+
*
|
|
566
|
+
* **useful when glob pattern can not be used (when path must be explicitly specified).**
|
|
567
|
+
*
|
|
568
|
+
* ```js
|
|
569
|
+
* gulp.src([
|
|
570
|
+
* "./src/app-config.ts",
|
|
571
|
+
* "./src/auth/{eve-sso,eve-sso-v2e}.php"
|
|
572
|
+
* ]).pipe(
|
|
573
|
+
* ...
|
|
574
|
+
* ).pipe(gulp.dest((vinyl) => {
|
|
575
|
+
* return convertRelativeDir(vinyl);
|
|
576
|
+
* })).on("end", () => {
|
|
577
|
+
* console.log("done");
|
|
578
|
+
* });
|
|
579
|
+
* ```
|
|
580
|
+
* @param {import("vinyl")} vinyl
|
|
581
|
+
* @param {string} dest default is "." -> node launched directory. (cwd?)
|
|
582
|
+
*/
|
|
583
|
+
function convertRelativeDir(vinyl, dest = ".") {
|
|
584
|
+
// NOTE: vinyl is https://github.com/gulpjs/vinyl
|
|
585
|
+
// if (false) {
|
|
586
|
+
// console.log("convertRelativeDir::debug log");
|
|
587
|
+
// console.log(vinyl.cwd);
|
|
588
|
+
// console.log(vinyl.base);
|
|
589
|
+
// }
|
|
590
|
+
let x = vinyl.cwd.length + 1;
|
|
591
|
+
let relative_dir = vinyl.base.substring(x);
|
|
592
|
+
return `${dest}/${relative_dir}`;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* prepend `content` to the beginning of each element of `str_array`
|
|
597
|
+
*
|
|
598
|
+
* form:
|
|
599
|
+
* ```js
|
|
600
|
+
* `${content}${suffix}${<str_array element>}`
|
|
601
|
+
* ```
|
|
602
|
+
*
|
|
603
|
+
* @param {string[]} str_array the string array
|
|
604
|
+
* @param {string} content prepend content
|
|
605
|
+
* @param {string} [suffix]
|
|
606
|
+
* @date 2020/2/16
|
|
607
|
+
* @version 2.0 rename `appendStringTo` -> `prependStringTo`
|
|
608
|
+
*/
|
|
609
|
+
function prependStringTo(str_array, content, suffix = "") {
|
|
610
|
+
/** @type {string} */
|
|
611
|
+
let target;
|
|
612
|
+
for (let i = 0; (target = str_array[i]); ) {
|
|
613
|
+
str_array[i++] = `${content}${suffix}${target}`;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
module.exports = {
|
|
618
|
+
prependStringTo,
|
|
619
|
+
|
|
620
|
+
extractVersion,
|
|
621
|
+
dateStringForFile,
|
|
622
|
+
getExtraArgs,
|
|
623
|
+
removeJsonComments,
|
|
624
|
+
writeTextUTF8,
|
|
625
|
+
readTextUTF8,
|
|
626
|
+
readJson,
|
|
627
|
+
walkDirSync,
|
|
628
|
+
|
|
629
|
+
compressScript,
|
|
630
|
+
compressScript2,
|
|
631
|
+
execWithOutputResult,
|
|
632
|
+
genGlobalNpmUpdateScript,
|
|
633
|
+
convertRelativeDir,
|
|
634
|
+
/**
|
|
635
|
+
*
|
|
636
|
+
* @param {string} content the copy terget content as string.
|
|
637
|
+
* @param {string} message default: "text copied!"
|
|
638
|
+
*/
|
|
639
|
+
copyText,
|
|
640
|
+
fireReplace,
|
|
641
|
+
CI,
|
|
642
|
+
log,
|
|
643
|
+
};
|