@naturalcycles/nodejs-lib 15.132.0 → 15.133.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.
@@ -18,15 +18,15 @@ export declare class CSVWriter {
18
18
  cfg: CSVWriterConfig & {
19
19
  delimiter: string;
20
20
  };
21
- writeRows(rows: AnyObject[]): string;
21
+ writeRows(rows: readonly AnyObject[]): string;
22
22
  writeHeader(): string;
23
23
  writeRow(row: AnyObject): string;
24
24
  private quoteIfNeeded;
25
25
  private quote;
26
26
  private shouldQuote;
27
27
  }
28
- export declare function arrayToCSVString(arr: AnyObject[], cfg?: CSVWriterConfig): string;
28
+ export declare function arrayToCSVString(arr: readonly AnyObject[], cfg?: CSVWriterConfig): string;
29
29
  /**
30
30
  * Iterates over the whole array and notes all possible columns.
31
31
  */
32
- export declare function arrayToCSVColumns(arr: AnyObject[]): string[];
32
+ export declare function arrayToCSVColumns(arr: readonly AnyObject[]): string[];
@@ -50,9 +50,9 @@ class Exec2 {
50
50
  */
51
51
  spawn(cmd, opt = {}) {
52
52
  const { shell = true, cwd, env, passProcessEnv = true, forceColor = hasColors, stdio = 'inherit', maxBuffer = defaultMaxBuffer, } = opt;
53
- opt.log ??= true; // by default log should be true, as we are printing the output
54
- opt.logStart ??= opt.log;
55
- opt.logFinish ??= opt.log;
53
+ const log = opt.log ?? true; // by default log should be true, as we are printing the output
54
+ // Copy, to not mutate the input options
55
+ opt = { ...opt, log, logStart: opt.logStart ?? log, logFinish: opt.logFinish ?? log };
56
56
  const started = Date.now();
57
57
  this.logStart(cmd, opt);
58
58
  const r = spawnSync(cmd, opt.args, {
@@ -92,8 +92,12 @@ class Exec2 {
92
92
  */
93
93
  exec(cmd, opt = {}) {
94
94
  const { cwd, env, passProcessEnv = true, timeout, stdio, maxBuffer = defaultMaxBuffer } = opt;
95
- opt.logStart ??= opt.log ?? false;
96
- opt.logFinish ??= opt.log ?? false;
95
+ // Copy, to not mutate the input options
96
+ opt = {
97
+ ...opt,
98
+ logStart: opt.logStart ?? opt.log ?? false,
99
+ logFinish: opt.logFinish ?? opt.log ?? false,
100
+ };
97
101
  const started = Date.now();
98
102
  this.logStart(cmd, opt);
99
103
  try {
@@ -141,9 +145,9 @@ class Exec2 {
141
145
  */
142
146
  async spawnAsync(cmd, opt = {}) {
143
147
  const { shell = true, cwd, env, passProcessEnv = true, forceColor = hasColors, stdio = 'inherit', } = opt;
144
- opt.log ??= true; // by default log should be true, as we are printing the output
145
- opt.logStart ??= opt.log;
146
- opt.logFinish ??= opt.log;
148
+ const log = opt.log ?? true; // by default log should be true, as we are printing the output
149
+ // Copy, to not mutate the input options
150
+ opt = { ...opt, log, logStart: opt.logStart ?? log, logFinish: opt.logFinish ?? log };
147
151
  const started = Date.now();
148
152
  this.logStart(cmd, opt);
149
153
  await new Promise((resolve, reject) => {
@@ -196,9 +200,9 @@ class Exec2 {
196
200
  */
197
201
  async spawnAsyncAndReturn(cmd, opt = {}) {
198
202
  const { shell = true, printWhileRunning = true, collectOutputWhileRunning = true, throwOnNonZeroCode = true, cwd, env, passProcessEnv = true, forceColor = hasColors, } = opt;
199
- opt.log ??= printWhileRunning; // by default log should be true, as we are printing the output
200
- opt.logStart ??= opt.log;
201
- opt.logFinish ??= opt.log;
203
+ const log = opt.log ?? printWhileRunning; // by default log should be true, as we are printing the output
204
+ // Copy, to not mutate the input options
205
+ opt = { ...opt, log, logStart: opt.logStart ?? log, logFinish: opt.logFinish ?? log };
202
206
  const started = Date.now();
203
207
  this.logStart(cmd, opt);
204
208
  let stdout = '';
package/dist/fs/kpy.js CHANGED
@@ -5,7 +5,7 @@ import { boldWhite, dimGrey, grey, yellow } from '../colors/colors.js';
5
5
  import { fs2 } from './fs2.js';
6
6
  export async function kpy(opt) {
7
7
  const started = localTime.nowUnixMillis();
8
- kpyPrepare(opt);
8
+ opt = kpyPrepare(opt);
9
9
  const filenames = await glob(opt.inputPatterns, {
10
10
  cwd: opt.baseDir,
11
11
  dot: opt.dotfiles,
@@ -34,7 +34,7 @@ export async function kpy(opt) {
34
34
  }
35
35
  export function kpySync(opt) {
36
36
  const started = localTime.nowUnixMillis();
37
- kpyPrepare(opt);
37
+ opt = kpyPrepare(opt);
38
38
  const filenames = globSync(opt.inputPatterns, {
39
39
  cwd: opt.baseDir,
40
40
  dot: opt.dotfiles,
@@ -59,16 +59,21 @@ export function kpySync(opt) {
59
59
  }
60
60
  kpyLogResult(opt, filenames, started);
61
61
  }
62
- function kpyPrepare(opt) {
63
- // Default pattern
64
- if (!opt.inputPatterns?.length)
65
- opt.inputPatterns = ['**'];
66
- // default to cwd
67
- opt.baseDir ||= '.';
68
- opt.outputDir ||= '.';
62
+ /**
63
+ * Returns normalized copy of the options. Does not mutate the input options.
64
+ */
65
+ function kpyPrepare(inputOpt) {
66
+ const opt = {
67
+ ...inputOpt,
68
+ // Default pattern
69
+ inputPatterns: inputOpt.inputPatterns?.length ? inputOpt.inputPatterns.slice() : ['**'],
70
+ // default to cwd
71
+ baseDir: inputOpt.baseDir || '.',
72
+ outputDir: inputOpt.outputDir || '.',
73
+ };
69
74
  if (!fs2.pathExists(opt.baseDir)) {
70
75
  console.log(`kpy: baseDir doesn't exist: ${boldWhite(opt.baseDir)}`);
71
- return;
76
+ return opt;
72
77
  }
73
78
  fs2.ensureDir(opt.outputDir);
74
79
  // Expand directories (ex-globby feature), experimental!
@@ -84,6 +89,7 @@ function kpyPrepare(opt) {
84
89
  console.log({ extraPatterns });
85
90
  }
86
91
  opt.inputPatterns.push(...extraPatterns);
92
+ return opt;
87
93
  }
88
94
  function kpyLogFilenames(opt, filenames) {
89
95
  if (opt.silent)
@@ -9,4 +9,4 @@ export interface DecryptCLIOptions {
9
9
  * Decrypts all files in given directory (*.enc), saves decrypted versions without ending `.enc`.
10
10
  * Using provided encKey.
11
11
  */
12
- export declare function secretsDecrypt(dir: string[], file: string | undefined, encKeyBuffer: Buffer, del?: boolean, jsonMode?: boolean): void;
12
+ export declare function secretsDecrypt(dir: readonly string[], file: string | undefined, encKeyBuffer: Buffer, del?: boolean, jsonMode?: boolean): void;
@@ -9,4 +9,4 @@ export interface EncryptCLIOptions {
9
9
  * Encrypts all files in given directory (except *.enc), saves encrypted versions as filename.ext.enc.
10
10
  * Using provided encKey.
11
11
  */
12
- export declare function secretsEncrypt(pattern: string[], file: string | undefined, encKeyBuffer: Buffer, del?: boolean, jsonMode?: boolean): void;
12
+ export declare function secretsEncrypt(pattern: readonly string[], file: string | undefined, encKeyBuffer: Buffer, del?: boolean, jsonMode?: boolean): void;
@@ -1,7 +1,7 @@
1
1
  export declare class NDJsonStats {
2
2
  static create(o?: Partial<NDJsonStats>): NDJsonStats;
3
3
  static empty(): NDJsonStats;
4
- static createCombined(stats: NDJsonStats[]): NDJsonStats;
4
+ static createCombined(stats: readonly NDJsonStats[]): NDJsonStats;
5
5
  tookMillis: number;
6
6
  rows: number;
7
7
  sizeBytes: number;
@@ -30,7 +30,7 @@ export declare class Pipeline<T = unknown> {
30
30
  * Technically same as `fromIterable` (since Array is Iterable),
31
31
  * but named a bit friendlier.
32
32
  */
33
- static fromArray<T>(input: T[]): Pipeline<T>;
33
+ static fromArray<T>(input: readonly T[]): Pipeline<T>;
34
34
  static fromIterable<T>(input: Iterable<T> | AsyncIterable<T>): Pipeline<T>;
35
35
  static fromNDJsonFile<T>(sourceFilePath: string): Pipeline<T>;
36
36
  static fromFile(sourceFilePath: string): Pipeline<Uint8Array>;
@@ -76,7 +76,7 @@ export declare class Pipeline<T = unknown> {
76
76
  * Helper method to add multiple transforms at once.
77
77
  * Not type safe! Prefer using singular `transform()` multiple times for type safety.
78
78
  */
79
- transformMany<TO>(transforms: Transform[]): Pipeline<TO>;
79
+ transformMany<TO>(transforms: readonly Transform[]): Pipeline<TO>;
80
80
  fork(fn: (pipeline: Pipeline<T>) => Promise<void>, opt?: TransformOptions): this;
81
81
  /**
82
82
  * Utility method just to conveniently type-cast the current Pipeline type.
@@ -12,8 +12,8 @@ import type { TransformOptions } from '../stream.model.js';
12
12
  * @experimental
13
13
  */
14
14
  export declare class ReadableCombined<T> extends Readable implements ReadableTyped<T> {
15
- inputs: Readable[];
16
- static create<T>(inputs: Readable[], opt?: TransformOptions): ReadableCombined<T>;
15
+ inputs: readonly Readable[];
16
+ static create<T>(inputs: readonly Readable[], opt?: TransformOptions): ReadableCombined<T>;
17
17
  private constructor();
18
18
  private logger;
19
19
  /**
@@ -7,4 +7,4 @@ import type { ReadableTyped } from '../stream.model.js';
7
7
  *
8
8
  * For simple cases use Readable.from(...) (Node.js 12+)
9
9
  */
10
- export declare function readableFromArray<IN, OUT>(items: IN[], mapper?: AbortableAsyncMapper<IN, OUT>, opt?: ReadableOptions): ReadableTyped<OUT>;
10
+ export declare function readableFromArray<IN, OUT>(items: readonly IN[], mapper?: AbortableAsyncMapper<IN, OUT>, opt?: ReadableOptions): ReadableTyped<OUT>;
@@ -5,4 +5,4 @@ import type { JsonSchema } from '../jSchema.js';
5
5
  *
6
6
  * `additionalProperties` is set to `true`, cause it's safer.
7
7
  */
8
- export declare function generateJsonSchemaFromData<T extends AnyObject = AnyObject>(rows: AnyObject[]): JsonSchema<T>;
8
+ export declare function generateJsonSchemaFromData<T extends AnyObject = AnyObject>(rows: readonly AnyObject[]): JsonSchema<T>;
@@ -1,15 +1,15 @@
1
1
  import type { AnyObject } from '@naturalcycles/js-lib/types';
2
2
  import type { JsonSchema } from './jSchema.js';
3
- export declare const JSON_SCHEMA_ORDER: string[];
3
+ export declare const JSON_SCHEMA_ORDER: readonly string[];
4
4
  /**
5
5
  * Merges s2 into s1 (mutates s1) and returns s1.
6
6
  * Does not mutate s2.
7
7
  * API similar to Object.assign(s1, s2)
8
8
  */
9
9
  export declare function mergeJsonSchemaObjects<T1 extends AnyObject, T2 extends AnyObject>(schema1: JsonSchema<T1>, schema2: JsonSchema<T2>): JsonSchema<T1 & T2>;
10
- export declare function isEveryItemString(arr: any[]): boolean;
11
- export declare function isEveryItemNumber(arr: any[]): boolean;
12
- export declare function isEveryItemPrimitive(arr: any[]): boolean;
10
+ export declare function isEveryItemString(arr: readonly any[]): boolean;
11
+ export declare function isEveryItemNumber(arr: readonly any[]): boolean;
12
+ export declare function isEveryItemPrimitive(arr: readonly any[]): boolean;
13
13
  /**
14
14
  * Values of the `format` keyword that `j` builders emit, named after the js-lib types they produce.
15
15
  * PascalCase on purpose, to never collide with standard, ajv-formats or OpenAPI formats (all lowercase),
@@ -66,11 +66,11 @@ declare class Zip2 {
66
66
  *
67
67
  * Returns the list of extracted entries.
68
68
  */
69
- extractZipFileToDirectory(zipFilePath: string, destDir: string): Promise<ZipEntry[]>;
69
+ extractZipFileToDirectory(zipFilePath: string, destDir: string): Promise<readonly ZipEntry[]>;
70
70
  /**
71
71
  * Create a zip archive on disk from a list of files and/or directories.
72
72
  */
73
- zipPaths(paths: string[], outputZipFilePath: string, opt?: ZipPathsOptions): Promise<void>;
73
+ zipPaths(paths: readonly string[], outputZipFilePath: string, opt?: ZipPathsOptions): Promise<void>;
74
74
  /**
75
75
  * Create a zip archive on disk, returning a {@link ZipWriter} that streams to it.
76
76
  *
@@ -90,7 +90,7 @@ declare class Zip2 {
90
90
  *
91
91
  * For large archives or streamed inputs prefer {@link createZip} / {@link ZipWriter}.
92
92
  */
93
- createZipBuffer(entries: ZipFileEntry[]): Promise<Buffer<ArrayBuffer>>;
93
+ createZipBuffer(entries: readonly ZipFileEntry[]): Promise<Buffer<ArrayBuffer>>;
94
94
  }
95
95
  export declare const zip2: Zip2;
96
96
  export {};
@@ -33,7 +33,7 @@ export declare class ZipReader implements AsyncDisposable {
33
33
  * All entries (files and directories) found in the archive,
34
34
  * in central-directory order.
35
35
  */
36
- readonly entries: ZipEntry[];
36
+ readonly entries: readonly ZipEntry[];
37
37
  /**
38
38
  * Archive-level comment (empty string if none).
39
39
  */
@@ -43,7 +43,7 @@ export declare class ZipReader implements AsyncDisposable {
43
43
  * All entries (files and directories) found in the archive,
44
44
  * in central-directory order.
45
45
  */
46
- entries: ZipEntry[],
46
+ entries: readonly ZipEntry[],
47
47
  /**
48
48
  * Archive-level comment (empty string if none).
49
49
  */
@@ -66,7 +66,7 @@ export declare class ZipReader implements AsyncDisposable {
66
66
  * Extract all entries into `destDir`, streaming each file to disk.
67
67
  * See {@link extractZip}.
68
68
  */
69
- extractAll(destDir: string): Promise<ZipEntry[]>;
69
+ extractAll(destDir: string): Promise<readonly ZipEntry[]>;
70
70
  /**
71
71
  * Close the underlying file handle. No-op for buffer-backed archives.
72
72
  * Safe to call multiple times.
@@ -19,13 +19,13 @@ import type { UnixTimestamp } from '@naturalcycles/js-lib/types';
19
19
  *
20
20
  * On failure the partially-written archive is removed.
21
21
  */
22
- export declare function zipPaths(paths: string[], outputZipFilePath: string, opt?: ZipPathsOptions): Promise<void>;
22
+ export declare function zipPaths(paths: readonly string[], outputZipFilePath: string, opt?: ZipPathsOptions): Promise<void>;
23
23
  /**
24
24
  * Build a zip archive entirely in memory and return it as a Buffer.
25
25
  *
26
26
  * For large archives or streamed inputs prefer {@link createZip} / {@link ZipWriter}.
27
27
  */
28
- export declare function createZipBuffer(entries: ZipFileEntry[]): Promise<Buffer<ArrayBuffer>>;
28
+ export declare function createZipBuffer(entries: readonly ZipFileEntry[]): Promise<Buffer<ArrayBuffer>>;
29
29
  /**
30
30
  * Options for {@link zipPaths}.
31
31
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.132.0",
4
+ "version": "15.133.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@standard-schema/spec": "^1",
@@ -14,7 +14,7 @@
14
14
  "yaml": "^2"
15
15
  },
16
16
  "devDependencies": {
17
- "@naturalcycles/dev-lib": "0.0.0",
17
+ "@naturalcycles/dev-lib": "20.68.0",
18
18
  "typescript": "^7"
19
19
  },
20
20
  "exports": {
@@ -31,7 +31,7 @@ export class CSVWriter {
31
31
 
32
32
  cfg: CSVWriterConfig & { delimiter: string }
33
33
 
34
- writeRows(rows: AnyObject[]): string {
34
+ writeRows(rows: readonly AnyObject[]): string {
35
35
  let s = ''
36
36
 
37
37
  // Detect columns based on content, if not defined upfront
@@ -68,7 +68,7 @@ export class CSVWriter {
68
68
  }
69
69
  }
70
70
 
71
- export function arrayToCSVString(arr: AnyObject[], cfg: CSVWriterConfig = {}): string {
71
+ export function arrayToCSVString(arr: readonly AnyObject[], cfg: CSVWriterConfig = {}): string {
72
72
  const writer = new CSVWriter(cfg)
73
73
  return writer.writeRows(arr)
74
74
  }
@@ -76,7 +76,7 @@ export function arrayToCSVString(arr: AnyObject[], cfg: CSVWriterConfig = {}): s
76
76
  /**
77
77
  * Iterates over the whole array and notes all possible columns.
78
78
  */
79
- export function arrayToCSVColumns(arr: AnyObject[]): string[] {
79
+ export function arrayToCSVColumns(arr: readonly AnyObject[]): string[] {
80
80
  const cols = new Set<string>()
81
81
  for (const row of arr) {
82
82
  for (const col of Object.keys(row)) {
@@ -66,9 +66,9 @@ class Exec2 {
66
66
  stdio = 'inherit',
67
67
  maxBuffer = defaultMaxBuffer,
68
68
  } = opt
69
- opt.log ??= true // by default log should be true, as we are printing the output
70
- opt.logStart ??= opt.log
71
- opt.logFinish ??= opt.log
69
+ const log = opt.log ?? true // by default log should be true, as we are printing the output
70
+ // Copy, to not mutate the input options
71
+ opt = { ...opt, log, logStart: opt.logStart ?? log, logFinish: opt.logFinish ?? log }
72
72
  const started = Date.now() as UnixTimestampMillis
73
73
  this.logStart(cmd, opt)
74
74
 
@@ -112,8 +112,12 @@ class Exec2 {
112
112
  */
113
113
  exec(cmd: string, opt: ExecOptions = {}): string {
114
114
  const { cwd, env, passProcessEnv = true, timeout, stdio, maxBuffer = defaultMaxBuffer } = opt
115
- opt.logStart ??= opt.log ?? false
116
- opt.logFinish ??= opt.log ?? false
115
+ // Copy, to not mutate the input options
116
+ opt = {
117
+ ...opt,
118
+ logStart: opt.logStart ?? opt.log ?? false,
119
+ logFinish: opt.logFinish ?? opt.log ?? false,
120
+ }
117
121
  const started = Date.now() as UnixTimestampMillis
118
122
  this.logStart(cmd, opt)
119
123
 
@@ -170,9 +174,9 @@ class Exec2 {
170
174
  forceColor = hasColors,
171
175
  stdio = 'inherit',
172
176
  } = opt
173
- opt.log ??= true // by default log should be true, as we are printing the output
174
- opt.logStart ??= opt.log
175
- opt.logFinish ??= opt.log
177
+ const log = opt.log ?? true // by default log should be true, as we are printing the output
178
+ // Copy, to not mutate the input options
179
+ opt = { ...opt, log, logStart: opt.logStart ?? log, logFinish: opt.logFinish ?? log }
176
180
  const started = Date.now() as UnixTimestampMillis
177
181
  this.logStart(cmd, opt)
178
182
 
@@ -238,9 +242,9 @@ class Exec2 {
238
242
  passProcessEnv = true,
239
243
  forceColor = hasColors,
240
244
  } = opt
241
- opt.log ??= printWhileRunning // by default log should be true, as we are printing the output
242
- opt.logStart ??= opt.log
243
- opt.logFinish ??= opt.log
245
+ const log = opt.log ?? printWhileRunning // by default log should be true, as we are printing the output
246
+ // Copy, to not mutate the input options
247
+ opt = { ...opt, log, logStart: opt.logStart ?? log, logFinish: opt.logFinish ?? log }
244
248
  const started = Date.now() as UnixTimestampMillis
245
249
  this.logStart(cmd, opt)
246
250
  let stdout = ''
package/src/fs/kpy.ts CHANGED
@@ -47,7 +47,7 @@ export interface KpyOptions {
47
47
  export async function kpy(opt: KpyOptions): Promise<void> {
48
48
  const started = localTime.nowUnixMillis()
49
49
 
50
- kpyPrepare(opt)
50
+ opt = kpyPrepare(opt)
51
51
 
52
52
  const filenames = await glob(opt.inputPatterns!, {
53
53
  cwd: opt.baseDir,
@@ -86,7 +86,7 @@ export async function kpy(opt: KpyOptions): Promise<void> {
86
86
  export function kpySync(opt: KpyOptions): void {
87
87
  const started = localTime.nowUnixMillis()
88
88
 
89
- kpyPrepare(opt)
89
+ opt = kpyPrepare(opt)
90
90
 
91
91
  const filenames = globSync(opt.inputPatterns!, {
92
92
  cwd: opt.baseDir,
@@ -118,17 +118,22 @@ export function kpySync(opt: KpyOptions): void {
118
118
  kpyLogResult(opt, filenames, started)
119
119
  }
120
120
 
121
- function kpyPrepare(opt: KpyOptions): void {
122
- // Default pattern
123
- if (!opt.inputPatterns?.length) opt.inputPatterns = ['**']
124
-
125
- // default to cwd
126
- opt.baseDir ||= '.'
127
- opt.outputDir ||= '.'
121
+ /**
122
+ * Returns normalized copy of the options. Does not mutate the input options.
123
+ */
124
+ function kpyPrepare(inputOpt: KpyOptions): KpyOptions {
125
+ const opt = {
126
+ ...inputOpt,
127
+ // Default pattern
128
+ inputPatterns: inputOpt.inputPatterns?.length ? inputOpt.inputPatterns.slice() : ['**'],
129
+ // default to cwd
130
+ baseDir: inputOpt.baseDir || '.',
131
+ outputDir: inputOpt.outputDir || '.',
132
+ }
128
133
 
129
134
  if (!fs2.pathExists(opt.baseDir)) {
130
135
  console.log(`kpy: baseDir doesn't exist: ${boldWhite(opt.baseDir)}`)
131
- return
136
+ return opt
132
137
  }
133
138
 
134
139
  fs2.ensureDir(opt.outputDir)
@@ -147,9 +152,10 @@ function kpyPrepare(opt: KpyOptions): void {
147
152
  console.log({ extraPatterns })
148
153
  }
149
154
  opt.inputPatterns.push(...extraPatterns)
155
+ return opt
150
156
  }
151
157
 
152
- function kpyLogFilenames(opt: KpyOptions, filenames: string[]): void {
158
+ function kpyLogFilenames(opt: KpyOptions, filenames: readonly string[]): void {
153
159
  if (opt.silent) return
154
160
 
155
161
  // console.log({filenames})
@@ -160,7 +166,11 @@ function kpyLogFilenames(opt: KpyOptions, filenames: string[]): void {
160
166
  )
161
167
  }
162
168
 
163
- function kpyLogResult(opt: KpyOptions, filenames: string[], started: UnixTimestampMillis): void {
169
+ function kpyLogResult(
170
+ opt: KpyOptions,
171
+ filenames: readonly string[],
172
+ started: UnixTimestampMillis,
173
+ ): void {
164
174
  if (opt.silent || filenames.length === 0) return
165
175
 
166
176
  console.log(
@@ -25,7 +25,7 @@ export interface DecryptCLIOptions {
25
25
  * Using provided encKey.
26
26
  */
27
27
  export function secretsDecrypt(
28
- dir: string[],
28
+ dir: readonly string[],
29
29
  file: string | undefined,
30
30
  encKeyBuffer: Buffer,
31
31
  del = false,
@@ -19,7 +19,7 @@ export interface EncryptCLIOptions {
19
19
  * Using provided encKey.
20
20
  */
21
21
  export function secretsEncrypt(
22
- pattern: string[],
22
+ pattern: readonly string[],
23
23
  file: string | undefined,
24
24
  encKeyBuffer: Buffer,
25
25
  del = false,
@@ -11,7 +11,7 @@ export class NDJsonStats {
11
11
  return new NDJsonStats()
12
12
  }
13
13
 
14
- static createCombined(stats: NDJsonStats[]): NDJsonStats {
14
+ static createCombined(stats: readonly NDJsonStats[]): NDJsonStats {
15
15
  // oxlint-disable-next-line unicorn/no-array-reduce
16
16
  return stats.reduce((statsTotal, stats) => statsTotal.add(stats), new NDJsonStats())
17
17
  }
@@ -93,7 +93,7 @@ export class Pipeline<T = unknown> {
93
93
  * Technically same as `fromIterable` (since Array is Iterable),
94
94
  * but named a bit friendlier.
95
95
  */
96
- static fromArray<T>(input: T[]): Pipeline<T> {
96
+ static fromArray<T>(input: readonly T[]): Pipeline<T> {
97
97
  return new Pipeline(Readable.from(input))
98
98
  }
99
99
 
@@ -265,7 +265,7 @@ export class Pipeline<T = unknown> {
265
265
  * Helper method to add multiple transforms at once.
266
266
  * Not type safe! Prefer using singular `transform()` multiple times for type safety.
267
267
  */
268
- transformMany<TO>(transforms: Transform[]): Pipeline<TO> {
268
+ transformMany<TO>(transforms: readonly Transform[]): Pipeline<TO> {
269
269
  this.transforms.push(...transforms)
270
270
  return this as any
271
271
  }
@@ -18,12 +18,12 @@ import type { TransformOptions } from '../stream.model.js'
18
18
  * @experimental
19
19
  */
20
20
  export class ReadableCombined<T> extends Readable implements ReadableTyped<T> {
21
- static create<T>(inputs: Readable[], opt: TransformOptions = {}): ReadableCombined<T> {
21
+ static create<T>(inputs: readonly Readable[], opt: TransformOptions = {}): ReadableCombined<T> {
22
22
  return new ReadableCombined<T>(inputs, opt)
23
23
  }
24
24
 
25
25
  private constructor(
26
- public inputs: Readable[],
26
+ public inputs: readonly Readable[],
27
27
  opt: TransformOptions,
28
28
  ) {
29
29
  const { objectMode = true, highWaterMark } = opt
@@ -11,7 +11,7 @@ import type { ReadableTyped } from '../stream.model.js'
11
11
  * For simple cases use Readable.from(...) (Node.js 12+)
12
12
  */
13
13
  export function readableFromArray<IN, OUT>(
14
- items: IN[],
14
+ items: readonly IN[],
15
15
  mapper: AbortableAsyncMapper<IN, OUT> = _passthroughMapper,
16
16
  opt?: ReadableOptions,
17
17
  ): ReadableTyped<OUT> {
@@ -5,7 +5,7 @@ export function transformFlatten<T>(): TransformTyped<T[], T> {
5
5
  return new Transform({
6
6
  objectMode: true,
7
7
  highWaterMark: 1,
8
- transform(chunk: T[], _, cb) {
8
+ transform(chunk: readonly T[], _, cb) {
9
9
  for (const item of chunk) {
10
10
  this.push(item)
11
11
  }
@@ -18,7 +18,7 @@ export function transformFlattenIfNeeded<T>(): TransformTyped<T[], T> {
18
18
  return new Transform({
19
19
  objectMode: true,
20
20
  highWaterMark: 1,
21
- transform(chunk: T[], _, cb) {
21
+ transform(chunk: readonly T[], _, cb) {
22
22
  if (Array.isArray(chunk)) {
23
23
  for (const item of chunk) {
24
24
  this.push(item)
@@ -12,12 +12,12 @@ type Type = PrimitiveType | 'array' | 'object'
12
12
  * `additionalProperties` is set to `true`, cause it's safer.
13
13
  */
14
14
  export function generateJsonSchemaFromData<T extends AnyObject = AnyObject>(
15
- rows: AnyObject[],
15
+ rows: readonly AnyObject[],
16
16
  ): JsonSchema<T> {
17
17
  return objectToJsonSchema<T>(rows)
18
18
  }
19
19
 
20
- function objectToJsonSchema<T extends AnyObject>(rows: AnyObject[]): JsonSchema<T> {
20
+ function objectToJsonSchema<T extends AnyObject>(rows: readonly AnyObject[]): JsonSchema<T> {
21
21
  const typesByKey: StringMap<Set<Type>> = {}
22
22
 
23
23
  rows.forEach(r => {
@@ -48,7 +48,7 @@ function objectToJsonSchema<T extends AnyObject>(rows: AnyObject[]): JsonSchema<
48
48
  return s
49
49
  }
50
50
 
51
- function mergeTypes(types: Type[], samples: any[]): JsonSchema | undefined {
51
+ function mergeTypes(types: readonly Type[], samples: readonly any[]): JsonSchema | undefined {
52
52
  // skip "undefined" types
53
53
  types = types.filter(t => t !== 'undefined')
54
54
 
@@ -456,7 +456,7 @@ export function createAjv(opt?: Options): Ajv2020 {
456
456
  errors: false,
457
457
  schemaType: 'array',
458
458
  validate: function validate(
459
- optionalValues: (string | number | boolean)[],
459
+ optionalValues: readonly (string | number | boolean)[],
460
460
  data: string | number | boolean,
461
461
  _schema,
462
462
  ctx,
@@ -549,7 +549,12 @@ export function createAjv(opt?: Options): Ajv2020 {
549
549
  modifying: false,
550
550
  errors: true,
551
551
  schemaType: 'array',
552
- validate: function validate(exclusiveProperties: string[][], data: AnyObject, _schema, ctx) {
552
+ validate: function validate(
553
+ exclusiveProperties: readonly string[][],
554
+ data: AnyObject,
555
+ _schema,
556
+ ctx,
557
+ ) {
553
558
  if (typeof data !== 'object') return true
554
559
 
555
560
  for (const props of exclusiveProperties) {
@@ -619,7 +624,7 @@ export function createAjv(opt?: Options): Ajv2020 {
619
624
  modifying: true,
620
625
  errors: true,
621
626
  schemaType: 'array',
622
- compile(schemas: JSchema<any, any>[], _parentSchema, _it) {
627
+ compile(schemas: readonly JSchema<any, any>[], _parentSchema, _it) {
623
628
  const validators = schemas.map(schema => ajv.compile(schema))
624
629
 
625
630
  function validate(data: AnyObject, ctx: any): boolean {
@@ -689,7 +694,12 @@ export function createAjv(opt?: Options): Ajv2020 {
689
694
  modifying: false,
690
695
  errors: true,
691
696
  schemaType: 'array',
692
- validate: function validate(customValidations: CustomValidatorFn[], data: any, _schema, ctx) {
697
+ validate: function validate(
698
+ customValidations: readonly CustomValidatorFn[],
699
+ data: any,
700
+ _schema,
701
+ ctx,
702
+ ) {
693
703
  if (!customValidations?.length) return true
694
704
 
695
705
  for (const validator of customValidations) {
@@ -715,7 +725,7 @@ export function createAjv(opt?: Options): Ajv2020 {
715
725
  errors: false,
716
726
  schemaType: 'array',
717
727
  validate: function validate(
718
- customConversions: CustomConverterFn<any>[],
728
+ customConversions: readonly CustomConverterFn<any>[],
719
729
  data: any,
720
730
  _schema,
721
731
  ctx,
@@ -3,7 +3,7 @@ import { _filterNullishValues } from '@naturalcycles/js-lib/object'
3
3
  import type { AnyObject } from '@naturalcycles/js-lib/types'
4
4
  import type { JsonSchema } from './jSchema.js'
5
5
 
6
- export const JSON_SCHEMA_ORDER = [
6
+ export const JSON_SCHEMA_ORDER: readonly string[] = [
7
7
  '$schema',
8
8
  '$id',
9
9
  'title',
@@ -79,21 +79,21 @@ export function mergeJsonSchemaObjects<T1 extends AnyObject, T2 extends AnyObjec
79
79
  return _filterNullishValues(s1, { mutate: true })
80
80
  }
81
81
 
82
- export function isEveryItemString(arr: any[]): boolean {
82
+ export function isEveryItemString(arr: readonly any[]): boolean {
83
83
  for (const item of arr) {
84
84
  if (typeof item !== 'string') return false
85
85
  }
86
86
  return true
87
87
  }
88
88
 
89
- export function isEveryItemNumber(arr: any[]): boolean {
89
+ export function isEveryItemNumber(arr: readonly any[]): boolean {
90
90
  for (const item of arr) {
91
91
  if (typeof item !== 'number') return false
92
92
  }
93
93
  return true
94
94
  }
95
95
 
96
- export function isEveryItemPrimitive(arr: any[]): boolean {
96
+ export function isEveryItemPrimitive(arr: readonly any[]): boolean {
97
97
  for (const item of arr) {
98
98
  if (typeof item !== 'number' && typeof item !== 'string' && typeof item !== 'symbol') {
99
99
  return false
package/src/zip/zip2.ts CHANGED
@@ -177,7 +177,10 @@ class Zip2 {
177
177
  *
178
178
  * Returns the list of extracted entries.
179
179
  */
180
- async extractZipFileToDirectory(zipFilePath: string, destDir: string): Promise<ZipEntry[]> {
180
+ async extractZipFileToDirectory(
181
+ zipFilePath: string,
182
+ destDir: string,
183
+ ): Promise<readonly ZipEntry[]> {
181
184
  const zip = await openZip(zipFilePath)
182
185
  try {
183
186
  return await zip.extractAll(destDir)
@@ -189,7 +192,11 @@ class Zip2 {
189
192
  /**
190
193
  * Create a zip archive on disk from a list of files and/or directories.
191
194
  */
192
- async zipPaths(paths: string[], outputZipFilePath: string, opt?: ZipPathsOptions): Promise<void> {
195
+ async zipPaths(
196
+ paths: readonly string[],
197
+ outputZipFilePath: string,
198
+ opt?: ZipPathsOptions,
199
+ ): Promise<void> {
193
200
  return await zipPaths(paths, outputZipFilePath, opt)
194
201
  }
195
202
 
@@ -215,7 +222,7 @@ class Zip2 {
215
222
  *
216
223
  * For large archives or streamed inputs prefer {@link createZip} / {@link ZipWriter}.
217
224
  */
218
- async createZipBuffer(entries: ZipFileEntry[]): Promise<Buffer<ArrayBuffer>> {
225
+ async createZipBuffer(entries: readonly ZipFileEntry[]): Promise<Buffer<ArrayBuffer>> {
219
226
  return await createZipBuffer(entries)
220
227
  }
221
228
  }
@@ -100,7 +100,7 @@ export class ZipReader implements AsyncDisposable {
100
100
  * All entries (files and directories) found in the archive,
101
101
  * in central-directory order.
102
102
  */
103
- readonly entries: ZipEntry[],
103
+ readonly entries: readonly ZipEntry[],
104
104
  /**
105
105
  * Archive-level comment (empty string if none).
106
106
  */
@@ -160,7 +160,7 @@ export class ZipReader implements AsyncDisposable {
160
160
  * Extract all entries into `destDir`, streaming each file to disk.
161
161
  * See {@link extractZip}.
162
162
  */
163
- async extractAll(destDir: string): Promise<ZipEntry[]> {
163
+ async extractAll(destDir: string): Promise<readonly ZipEntry[]> {
164
164
  const root = path.resolve(destDir)
165
165
  for (const entry of this.entries) {
166
166
  const targetPath = assertPathInside(root, entry.fileName)
@@ -402,7 +402,7 @@ function parseExtraFields(buf: Buffer): ExtraField[] {
402
402
  }
403
403
 
404
404
  function readZip64ExtraField(
405
- extraFields: ExtraField[],
405
+ extraFields: readonly ExtraField[],
406
406
  uncompressedSize: number,
407
407
  compressedSize: number,
408
408
  relativeOffsetOfLocalHeader: number,
@@ -431,7 +431,7 @@ function readZip64ExtraField(
431
431
  function decodeFileName(
432
432
  generalPurposeBitFlag: number,
433
433
  fileNameRaw: Buffer,
434
- extraFields: ExtraField[],
434
+ extraFields: readonly ExtraField[],
435
435
  ): string {
436
436
  // Info-ZIP Unicode Path Extra Field (0x7075): an authoritative UTF-8 name,
437
437
  // used only if its stored CRC-32 matches the raw name. See yauzl#33.
@@ -449,7 +449,11 @@ function decodeFileName(
449
449
  return normalizeZipEntryName(decodeBuffer(fileNameRaw, hasUtf8Flag))
450
450
  }
451
451
 
452
- function parseLastModified(date: number, time: number, extraFields: ExtraField[]): UnixTimestamp {
452
+ function parseLastModified(
453
+ date: number,
454
+ time: number,
455
+ extraFields: readonly ExtraField[],
456
+ ): UnixTimestamp {
453
457
  // Prefer the Info-ZIP "UT" extended timestamp (0x5455) if it carries mtime.
454
458
  // Its payload is already a Unix timestamp in seconds.
455
459
  const ut = extraFields.find(f => f.id === 0x5455)
@@ -76,7 +76,7 @@ const deflateRawAsync = promisify(zlib.deflateRaw.bind(zlib))
76
76
  * On failure the partially-written archive is removed.
77
77
  */
78
78
  export async function zipPaths(
79
- paths: string[],
79
+ paths: readonly string[],
80
80
  outputZipFilePath: string,
81
81
  opt: ZipPathsOptions = {},
82
82
  ): Promise<void> {
@@ -105,7 +105,9 @@ export async function zipPaths(
105
105
  *
106
106
  * For large archives or streamed inputs prefer {@link createZip} / {@link ZipWriter}.
107
107
  */
108
- export async function createZipBuffer(entries: ZipFileEntry[]): Promise<Buffer<ArrayBuffer>> {
108
+ export async function createZipBuffer(
109
+ entries: readonly ZipFileEntry[],
110
+ ): Promise<Buffer<ArrayBuffer>> {
109
111
  const chunks: Buffer[] = []
110
112
  const sink = new Writable({
111
113
  write(chunk: Buffer, _enc, cb) {
@@ -684,7 +686,10 @@ interface FileToZip {
684
686
  * Expand input paths (files and/or directories) into a flat list of files to add,
685
687
  * resolving each entry's archive name relative to `baseDir` (or each input's parent).
686
688
  */
687
- async function collectFiles(inputs: string[], baseDir: string | undefined): Promise<FileToZip[]> {
689
+ async function collectFiles(
690
+ inputs: readonly string[],
691
+ baseDir: string | undefined,
692
+ ): Promise<FileToZip[]> {
688
693
  const files: FileToZip[] = []
689
694
  for (const input of inputs) {
690
695
  const stats = await fsp.stat(input)