js-dev-tool 1.2.3 → 1.2.4

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/basic-types.d.ts CHANGED
@@ -106,6 +106,7 @@ type PickNumberProperties<T> = PickProperties<number, T>;
106
106
  type PickStringProperties<T> = PickProperties<string, T>;
107
107
  type NonFunctionPropertyNames<T> = { [K in keyof T]-?: T[K] extends Function ? never : K }[keyof T];
108
108
  type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
109
+ type ArrayToUnion<T extends readonly unknown[]> = T[number];
109
110
  /**
110
111
  * for lazy assign class.
111
112
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-dev-tool",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "bin": {
5
5
  "jstool": "tools.js"
6
6
  },
@@ -90,6 +90,6 @@
90
90
  "replace": "^1.2.2",
91
91
  "rm-cstyle-cmts": "^3.4.2",
92
92
  "terser": "^5.46.0",
93
- "tin-args": "^0.1.1"
93
+ "tin-args": "^0.1.3"
94
94
  }
95
95
  }
package/tools.js CHANGED
@@ -225,7 +225,7 @@ const ToolFunctions = {
225
225
  /** @type {string} */ (this.taskName),
226
226
  (data) => {
227
227
  let result = rmc(data);
228
- return preserveTsReferenceDirectives(result);
228
+ return preserveTsReferenceDirectives(result, params.debug);
229
229
  },
230
230
  {
231
231
  bases: basePaths,
@@ -268,8 +268,7 @@ function preserveTsReferenceDirectives(jsSource, debug) {
268
268
  const usLine = jsSource.slice(m.index, usLen);
269
269
  /** @type {string[]} */
270
270
  const knownDirectives = [];
271
- const reReferenceDirectiveChecker = /^\/\/\/\s*<reference.+[\r\n]/gm;
272
- let purgedSource = jsSource.slice(usLen).replace(reReferenceDirectiveChecker, (match) => {
271
+ let purgedSource = jsSource.slice(usLen).replace(/^\/\/\/\s*<reference.+[\r\n]/gm, (match) => {
273
272
  knownDirectives.push(match);
274
273
  return "";
275
274
  });
package/utils.d.ts CHANGED
@@ -25,9 +25,9 @@ export type TExtraArgsValue = string | boolean | RegExp | string[];
25
25
  * `${content}${suffix}${<str_array element>}`
26
26
  * ```
27
27
  *
28
- * @param {string[]} str_array the string array
29
- * @param {string} content prepend content
30
- * @param {string} [suffix]
28
+ * @param str_array the string array
29
+ * @param content prepend content
30
+ * @param [suffix]
31
31
  * @date 2020/2/16
32
32
  * @version 2.0 rename `appendStringTo` -> `prependStringTo`
33
33
  */
@@ -44,7 +44,7 @@ export function prependStringTo(str_array: string[], content: string, suffix?: s
44
44
  * console.log(nv); // => {major: 10, minor: 9, patch: 0}
45
45
  * ```
46
46
  *
47
- * @param {string} versionString default is process.version
47
+ * @param versionString default is process.version
48
48
  */
49
49
  export function extractVersion(versionString?: string): {
50
50
  major: number;
@@ -53,54 +53,54 @@ export function extractVersion(versionString?: string): {
53
53
  };
54
54
  /**
55
55
  * use toLocaleString
56
- * @param {any} ymd use simple year month day formant? default `false`
56
+ * @param ymd use simple year month day formant? default `false`
57
57
  * + should be truthy/falsy value
58
58
  */
59
59
  export function dateStringForFile(ymd?: any): string;
60
60
  /**
61
61
  * use "rm-cstyle-cmts"
62
62
  *
63
- * @param {string} source
63
+ * @param source
64
64
  */
65
65
  export function removeJsonComments(source: string): string;
66
66
  /**
67
67
  * write text content to dest path.
68
68
  * when not exists parent directory, creat it.
69
69
  *
70
- * @param {string|NodeJS.ReadableStream|Buffer} content text? content.
71
- * @param {string} dest content output path
72
- * @param {() => void} [callback] the callback function
70
+ * @param content text? content.
71
+ * @param dest content output path
72
+ * @param [callback] the callback function
73
73
  */
74
74
  export function writeText(content: string | NodeJS.ReadableStream | Buffer, dest: string, callback?: () => void): void;
75
75
  /**
76
- * @param {string} from file path.
76
+ * @param from file path.
77
77
  * @param [callback]
78
78
  */
79
79
  export function readText<C extends TBD<TFsCallback>, R extends undefined extends C ? string : void>(from: string, callback?: C): R;
80
80
  /**
81
81
  * NOTE: when callback specified, returns undefined
82
82
  *
83
- * @param {string} path
83
+ * @param path
84
84
  * @param [callback]
85
85
  */
86
86
  export function readJson<T, C extends TBD<TReadJsonCallback<string>>, R extends undefined extends C ? TypedRecord<T> : void>(path: string, callback?: C): R;
87
87
  /**
88
- * @param {string} path
89
- * @param {(dirent: Dirent) => void} handler
88
+ * @param path
89
+ * @param handler
90
90
  */
91
91
  export function walkDirSync(path: string, handler: (dirent: Dirent) => void): void;
92
92
  /**
93
93
  * create sourceName zip. (using zip.min.js
94
94
  *
95
- * @param {string} scriptPath simple script file name. e.g - webpack (original path are "./lib/webpack.js")
96
- * @param {string} comment the zip file comment.
95
+ * @param scriptPath simple script file name. e.g - webpack (original path are "./lib/webpack.js")
96
+ * @param comment the zip file comment.
97
97
  */
98
98
  export function compressScript(scriptPath: string, comment?: string): void;
99
99
  /**
100
100
  * DEVNOTE: 10/21/2018, 9:15:00 PM - using "archiver" package, this is too fast!.
101
101
  *
102
- * @param {string} scriptPath
103
- * @param {string} comment
102
+ * @param scriptPath
103
+ * @param comment
104
104
  */
105
105
  export function compressScript2(scriptPath: string, comment?: string): void;
106
106
  /**
@@ -109,9 +109,9 @@ export function compressScript2(scriptPath: string, comment?: string): void;
109
109
  * + 📝 using "exec" internally
110
110
  * * 🆗️ can use pipe command
111
111
  *
112
- * @param {string} command
113
- * @param {(result: string) => void} doneCallbackWithArgs gulp callback function.
114
- * @param {string=} cwd 2025/2/1 current working directory
112
+ * @param command
113
+ * @param doneCallbackWithArgs gulp callback function.
114
+ * @param cwd 2025/2/1 current working directory
115
115
  */
116
116
  export function execWithOutputResult(command: string, doneCallbackWithArgs: (result: string) => void, cwd?: string): any;
117
117
  /**
@@ -131,26 +131,26 @@ export function execWithOutputResult(command: string, doneCallbackWithArgs: (res
131
131
  * console.log("done");
132
132
  * });
133
133
  * ```
134
- * @param {import("vinyl")} vinyl
135
- * @param {string} dest default is "." -> node launched directory. (cwd?)
134
+ * @param vinyl
135
+ * @param dest default is "." -> node launched directory. (cwd?)
136
136
  */
137
- export function convertRelativeDir(vinyl: any, dest?: string): string;
137
+ export function convertRelativeDir(vinyl: import("vinyl"), dest?: string): string;
138
138
  /**
139
139
  * ### command:
140
140
  *
141
141
  * + windows - chcp 65001 && clip
142
142
  * + others - xclip
143
143
  *
144
- * @param {string} content the copy terget content as string.
145
- * @param {string} [message] default: "text copied!"
146
- * @param {boolean} [chcp65001] default `true`
144
+ * @param content the copy terget content as string.
145
+ * @param [message] default: "text copied!"
146
+ * @param [chcp65001] default `true`
147
147
  */
148
148
  export function copyText(content: string, message?: string, chcp65001?: boolean): void;
149
149
  /**
150
- * @param {RegExp} regex
151
- * @param {string | Function} replacement
152
- * @param {string[]} paths Paths that do not exist are ignored
153
- * @param {boolean} [async]
150
+ * @param regex
151
+ * @param replacement
152
+ * @param paths Paths that do not exist are ignored
153
+ * @param [async]
154
154
  *
155
155
  * @date 2019-4-26
156
156
  */
@@ -160,4 +160,54 @@ export const CI: boolean;
160
160
  * Nothing is logged in a CI environment.
161
161
  */
162
162
  export const log: typeof console.log;
163
- export const listDependenciesOf: typeof import("./extras/list-deps-of").listDependenciesOf;
163
+ export const listDependenciesOf: typeof import("./extras/list-deps-of").listDependenciesOf;
164
+ export type TCSVParseOpt = {
165
+ /**
166
+ * Zero-based column index to use as the map key.
167
+ * @default 0
168
+ */
169
+ mapKeyCol: number;
170
+ /**
171
+ * Zero-based column index to sort by (omit to keep original order).
172
+ * @default undefined
173
+ */
174
+ sortByCol?: number;
175
+ /**
176
+ * @default /\t/
177
+ */
178
+ separator?: string | RegExp;
179
+ };
180
+ /**
181
+ * Builds a key -> row index from a delimited text source (TSV by default).
182
+ * Alias: {@link parseDelimitedToIndex}.
183
+ *
184
+ * @template TKey - The key type used to identify each row.
185
+ * @template TProp - The property-name type for each row field.
186
+ * @template Entry - A parsed row (key column is omitted).
187
+ * @template R - The resulting index type.
188
+ *
189
+ * @param tsvSource - Delimited text to parse (expects a header row).
190
+ * @param opt - Parsing options (separator, key column, optional sort column).
191
+ *
192
+ * @returns A key-to-row index.
193
+ *
194
+ * @example
195
+ * // Key by the 3rd column (marketGroupName) and sort by name.
196
+ * const map = indexByCol(_data, { mapKeyCol: 2, sortByCol: 2 });
197
+ * console.log(map["Gunnery"].description);
198
+ *
199
+ * @remarks
200
+ * - The first line is treated as the header (property names).
201
+ * - The key column is used only as the map key and is omitted from each Entry.
202
+ * - Numeric-looking values are coerced to numbers when finite.
203
+ *
204
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries Object.entries (MDN)}
205
+ * @date 2026/02/05 19:46:19
206
+ */
207
+ export declare function indexByCol<
208
+ TKey extends string,
209
+ TProp extends string,
210
+ Entry extends Partial<Record<TProp, string | number>>,
211
+ R extends Record<TKey, Entry>
212
+ >(tsvSource: string, opt?: TCSVParseOpt): R;
213
+ export const parseDelimitedToIndex: typeof indexByCol;
package/utils.js CHANGED
@@ -303,6 +303,84 @@ function execWithOutputResult(command, doneCallbackWithArgs, cwd) {
303
303
  }
304
304
  });
305
305
  }
306
+ /**
307
+ * @import { TCSVParseOpt } from "./utils";
308
+ */
309
+ /**
310
+ * Builds a key -> row index from a delimited text source (TSV by default).
311
+ * Alias: {@link parseDelimitedToIndex}.
312
+ *
313
+ * @template {string} TKey - The key type used to identify each row.
314
+ * @template {string} TProp - The property-name type for each row field.
315
+ * @template {Partial<Record<TProp, string | number>>} Entry - A parsed row (key column is omitted).
316
+ * @template {Record<TKey, Entry>} R - The resulting index type.
317
+ *
318
+ * @param {string} tsvSource - Delimited text to parse (expects a header row).
319
+ * @param {TCSVParseOpt=} opt - Parsing options (separator, key column, optional sort column).
320
+ *
321
+ * @returns {R} A key-to-row index.
322
+ *
323
+ * @example
324
+ * // Key by the 3rd column (marketGroupName) and sort by name.
325
+ * const map = indexByCol(_data, { mapKeyCol: 2, sortByCol: 2 });
326
+ * console.log(map["Gunnery"].description);
327
+ *
328
+ * @remarks
329
+ * - The first line is treated as the header (property names).
330
+ * - The key column is used only as the map key and is omitted from each Entry.
331
+ * - Numeric-looking values are coerced to numbers when finite.
332
+ *
333
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries Object.entries (MDN)}
334
+ * @date 2026/02/05 19:46:19
335
+ */
336
+ function indexByCol(tsvSource, opt) {
337
+ const lines = tsvSource.split(/[\r\n]+/);
338
+ const linesLen = lines.length;
339
+ if (linesLen === 0) return /** @type {R} */({});
340
+ const {
341
+ separator = /\t/,
342
+ mapKeyCol = 0,
343
+ sortByCol
344
+ } = opt || {};
345
+ const propertyList = /** @type {TProp[]} */(lines[0].split(separator));
346
+ let mapData = /** @type {R} */(Object.create(null));
347
+ for (let idx = 1; idx < linesLen;) {
348
+ const line = lines[idx++];
349
+ if (!line) continue;
350
+ const cols = /** @type {string[]} */(line.split(separator));
351
+ const key = /** @type {TKey} */(cols[mapKeyCol]);
352
+ const currentMap = /** @type {Entry} */({});
353
+ for (let _idx = 0, pListLen = propertyList.length; _idx < pListLen; _idx++) {
354
+ if (_idx === mapKeyCol) continue;
355
+ const val = cols[_idx];
356
+ const n = +val;
357
+ currentMap[
358
+ propertyList[_idx]
359
+ ] = /** @type {Entry[TProp]} */((val !== "" && Number.isFinite(n)) ? n : val);
360
+ }
361
+ mapData[key] = /** @type {R[TKey]} */(currentMap);
362
+ }
363
+ if (typeof sortByCol === "number") {
364
+ const _mapData = /** @type {R} */(Object.create(null));
365
+ if (mapKeyCol === sortByCol) {
366
+ const keys = /** @type {TKey[]} */(Object.keys(mapData).sort());
367
+ for (const key of keys) _mapData[key] = mapData[key];
368
+ } else {
369
+ const propName = propertyList[sortByCol];
370
+ /*const sortedEntries =*/
371
+ /** @type {[TKey, Entry][]} */(Object.entries(mapData)).sort(([, a], [, b]) => {
372
+ const av = a[propName];
373
+ const bv = b[propName];
374
+ // @ts-expect-error bv type are same as `av`
375
+ return typeof av === "string" ? av.localeCompare(bv) : av - bv;
376
+ }).forEach(entry => {
377
+ _mapData[entry[0]] = /** @type {R[TKey]} */(entry[1]);
378
+ });
379
+ }
380
+ mapData = _mapData;
381
+ }
382
+ return mapData;
383
+ }
306
384
  /**
307
385
  * ### command:
308
386
  *
@@ -408,5 +486,7 @@ module.exports = {
408
486
  fireReplace,
409
487
  CI,
410
488
  log,
411
- listDependenciesOf
489
+ listDependenciesOf,
490
+ indexByCol,
491
+ parseDelimitedToIndex: indexByCol
412
492
  };