pwi-plata-type 0.4.166 → 0.4.167

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.
Files changed (101) hide show
  1. package/README.md +2 -2
  2. package/__BUILD__/libs/sql.js +4 -1
  3. package/__BUILD__/libs/sql.js.map +1 -1
  4. package/package.json +53 -53
  5. package/src/@types/build.d.ts +26 -26
  6. package/src/@types/cluster.actions.d.ts +27 -27
  7. package/src/@types/cluster.d.ts +55 -55
  8. package/src/@types/create-cli.d.ts +8 -8
  9. package/src/@types/exported.d.ts +31 -31
  10. package/src/@types/fs.d.ts +6 -6
  11. package/src/@types/global.d.ts +113 -113
  12. package/src/@types/knex.d.ts +13 -13
  13. package/src/@types/model.d.ts +143 -143
  14. package/src/@types/router.d.ts +107 -107
  15. package/src/@types/sql.d.ts +75 -75
  16. package/src/@types/swagger.d.ts +22 -22
  17. package/src/bin/extras/create-api-cli.ts +218 -218
  18. package/src/bin/extras/create-cluster-cli.ts +160 -160
  19. package/src/bin/extras/create-lib-cli.ts +84 -84
  20. package/src/bin/extras/plata-create-tools.ts +97 -97
  21. package/src/bin/plata-api.ts +189 -189
  22. package/src/bin/plata-build.ts +17 -17
  23. package/src/bin/plata-cluster.ts +42 -42
  24. package/src/bin/plata-cmd.ts +18 -18
  25. package/src/bin/plata-create.ts +49 -49
  26. package/src/bin/plata-runtime.ts +131 -131
  27. package/src/bin/plata-swagger.ts +99 -99
  28. package/src/bin/runtime/_setupRuntime.ts +48 -48
  29. package/src/bin/runtime/_types.d.ts +7 -7
  30. package/src/bin/runtime/class.ts +20 -20
  31. package/src/bin/runtime/dirs.ts +25 -25
  32. package/src/bin/runtime/effect.ts +60 -60
  33. package/src/bin/runtime/fs.ts +10 -10
  34. package/src/bin/runtime/promises.ts +18 -18
  35. package/src/bin/runtime/require.ts +113 -113
  36. package/src/bin/runtime/sql.ts +12 -12
  37. package/src/bin/runtime/switch.ts +60 -60
  38. package/src/index.ts +19 -19
  39. package/src/libs/axios.ts +51 -51
  40. package/src/libs/build.ts +162 -162
  41. package/src/libs/cluster/cluster-controller.ts +93 -93
  42. package/src/libs/cluster.ts +330 -330
  43. package/src/libs/custom.ts +15 -15
  44. package/src/libs/env.ts +10 -10
  45. package/src/libs/fs.ts +399 -399
  46. package/src/libs/hot-reload.ts +63 -63
  47. package/src/libs/models/index.ts +4 -4
  48. package/src/libs/models/model-template-combine.ts +93 -93
  49. package/src/libs/models/model-template-env.ts +58 -58
  50. package/src/libs/models/model-template-union.ts +83 -83
  51. package/src/libs/models/model-template.ts +107 -107
  52. package/src/libs/models/model-validations.ts +443 -443
  53. package/src/libs/models/tools.ts +194 -194
  54. package/src/libs/router.ts +185 -185
  55. package/src/libs/sql.ts +792 -788
  56. package/src/libs/swagger.ts +81 -81
  57. package/src/libs/tools.ts +240 -240
  58. package/src/scripts/post-install/api.ts +32 -32
  59. package/src/scripts/post-install/cluster.ts +28 -28
  60. package/src/scripts/post-install/lib.ts +25 -25
  61. package/src/scripts/post-install.ts +64 -64
  62. package/src/scripts/pre-test.ts +33 -33
  63. package/src/tests/assets/sql/example.sql +76 -76
  64. package/src/tests/config.test.ts +12 -12
  65. package/src/tests/effect.test.ts +62 -62
  66. package/src/tests/model.env.test.ts +66 -66
  67. package/src/tests/model.test.ts +141 -141
  68. package/src/tests/model.union.test.ts +160 -160
  69. package/src/tests/router.test.ts +44 -44
  70. package/src/tests/sql.test.ts +502 -502
  71. package/src/tests/switch.test.ts +76 -76
  72. package/templates/create-cli/class.ts +13 -13
  73. package/templates/create-cli/cluster.ts +14 -14
  74. package/templates/create-cli/cmd.ts +3 -3
  75. package/templates/create-cli/config.ts +2 -2
  76. package/templates/create-cli/lib.ts +3 -3
  77. package/templates/create-cli/model.ts +14 -14
  78. package/templates/create-cli/route.ts +8 -8
  79. package/templates/create-cli/task.ts +13 -13
  80. package/templates/postinstall/api/.vscode/launch.json +20 -20
  81. package/templates/postinstall/api/Dockerfile +24 -24
  82. package/templates/postinstall/api/configs/env.ts +2 -2
  83. package/templates/postinstall/api/envs/debug.env +15 -15
  84. package/templates/postinstall/api/envs/homolog.env +15 -15
  85. package/templates/postinstall/api/envs/prod.env +15 -15
  86. package/templates/postinstall/api/tsconfig.json +24 -24
  87. package/templates/postinstall/cluster/.vscode/launch.json +20 -20
  88. package/templates/postinstall/cluster/Dockerfile +24 -24
  89. package/templates/postinstall/cluster/configs/env.ts +2 -2
  90. package/templates/postinstall/cluster/envs/debug.env +10 -10
  91. package/templates/postinstall/cluster/envs/homolog.env +10 -10
  92. package/templates/postinstall/cluster/envs/prod.env +10 -10
  93. package/templates/postinstall/cluster/tsconfig.json +24 -24
  94. package/templates/postinstall/lib/postinstall-tools.mjs +111 -111
  95. package/templates/postinstall/lib/postinstall.js +33 -33
  96. package/templates/postinstall/lib/tsconfig.json +22 -22
  97. package/templates/swagger-cli/header.json +21 -21
  98. package/templates/swagger-cli/route/body.json +14 -14
  99. package/templates/swagger-cli/route/header.json +18 -18
  100. package/templates/swagger-cli/route/response.json +53 -53
  101. package/tsconfig.json +28 -28
package/src/libs/fs.ts CHANGED
@@ -1,400 +1,400 @@
1
- import nodeFS from 'node:fs/promises'
2
- import path from 'node:path'
3
- import nodeFSCallBack, { PathLike } from 'node:fs'
4
- import readline from 'node:readline'
5
- import glob from 'glob'
6
-
7
- export namespace PlataFs {
8
- export const constants = nodeFS.constants
9
-
10
- export const fs = nodeFS
11
-
12
- /**
13
- * Tests a user's permissions for the file or directory specified by `path`.
14
- * The `mode` argument is an optional integer that specifies the accessibility
15
- * checks to be performed. `mode` should be either the value `fs.constants.F_OK`or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`,`fs.constants.W_OK`, and `fs.constants.X_OK`
16
- * (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for
17
- * possible values of `mode`.
18
- *
19
- * If the accessibility check is successful, the promise is resolved with no
20
- * value. If any of the accessibility checks fail, the promise is rejected
21
- * with an [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object. The following example checks if the file`/etc/passwd` can be read and
22
- * written by the current process.
23
- *
24
- * ```js
25
- * import { access } from 'fs/promises';
26
- * import { constants } from 'fs';
27
- *
28
- * try {
29
- * await access('/etc/passwd', constants.R_OK | constants.W_OK);
30
- * console.log('can access');
31
- * } catch {
32
- * console.error('cannot access');
33
- * }
34
- * ```
35
- *
36
- * Using `fsPromises.access()` to check for the accessibility of a file before
37
- * calling `fsPromises.open()` is not recommended. Doing so introduces a race
38
- * condition, since other processes may change the file's state between the two
39
- * calls. Instead, user code should open/read/write the file directly and handle
40
- * the error raised if the file is not accessible.
41
- * @since v10.0.0
42
- * @param [mode=fs.constants.F_OK]
43
- * @return Fulfills with `undefined` upon success.
44
- */
45
- export function access(path: PathLike, mode?: number): Promise<boolean> {
46
- return fs.access(path, mode).then(
47
- () => true,
48
- () => false
49
- )
50
- }
51
-
52
- /**
53
- * `options` may also include a `start` option to allow writing data at some
54
- * position past the beginning of the file, allowed values are in the
55
- * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than
56
- * replacing it may require the `flags` option to be set to `r+` rather than the
57
- * default `w`. The `encoding` can be any one of those accepted by `Buffer`.
58
- *
59
- * If `autoClose` is set to true (default behavior) on `'error'` or `'finish'`the file descriptor will be closed automatically. If `autoClose` is false,
60
- * then the file descriptor won't be closed, even if there's an error.
61
- * It is the application's responsibility to close it and make sure there's no
62
- * file descriptor leak.
63
- *
64
- * By default, the stream will emit a `'close'` event after it has been
65
- * destroyed. Set the `emitClose` option to `false` to change this behavior.
66
- *
67
- * By providing the `fs` option it is possible to override the corresponding `fs`implementations for `open`, `write`, `writev` and `close`. Overriding `write()`without `writev()` can reduce
68
- * performance as some optimizations (`_writev()`)
69
- * will be disabled. When providing the `fs` option, overrides for at least one of`write` and `writev` are required. If no `fd` option is supplied, an override
70
- * for `open` is also required. If `autoClose` is `true`, an override for `close`is also required.
71
- *
72
- * Like `fs.ReadStream`, if `fd` is specified, `fs.WriteStream` will ignore the`path` argument and will use the specified file descriptor. This means that no`'open'` event will be
73
- * emitted. `fd` should be blocking; non-blocking `fd`s
74
- * should be passed to `net.Socket`.
75
- *
76
- * If `options` is a string, then it specifies the encoding.
77
- * @since v0.1.31
78
- */
79
- export const createWriteStream: typeof nodeFSCallBack.createWriteStream = nodeFSCallBack.createWriteStream
80
- /**
81
- * Unlike the 16 kb default `highWaterMark` for a `stream.Readable`, the stream
82
- * returned by this method has a default `highWaterMark` of 64 kb.
83
- *
84
- * `options` can include `start` and `end` values to read a range of bytes from
85
- * the file instead of the entire file. Both `start` and `end` are inclusive and
86
- * start counting at 0, allowed values are in the
87
- * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. If `fd` is specified and `start` is
88
- * omitted or `undefined`, `fs.createReadStream()` reads sequentially from the
89
- * current file position. The `encoding` can be any one of those accepted by `Buffer`.
90
- *
91
- * If `fd` is specified, `ReadStream` will ignore the `path` argument and will use
92
- * the specified file descriptor. This means that no `'open'` event will be
93
- * emitted. `fd` should be blocking; non-blocking `fd`s should be passed to `net.Socket`.
94
- *
95
- * If `fd` points to a character device that only supports blocking reads
96
- * (such as keyboard or sound card), read operations do not finish until data is
97
- * available. This can prevent the process from exiting and the stream from
98
- * closing naturally.
99
- *
100
- * By default, the stream will emit a `'close'` event after it has been
101
- * destroyed. Set the `emitClose` option to `false` to change this behavior.
102
- *
103
- * By providing the `fs` option, it is possible to override the corresponding `fs`implementations for `open`, `read`, and `close`. When providing the `fs` option,
104
- * an override for `read` is required. If no `fd` is provided, an override for`open` is also required. If `autoClose` is `true`, an override for `close` is
105
- * also required.
106
- *
107
- * ```js
108
- * import { createReadStream } from 'fs';
109
- *
110
- * // Create a stream from some character device.
111
- * const stream = createReadStream('/dev/input/event0');
112
- * setTimeout(() => {
113
- * stream.close(); // This may not close the stream.
114
- * // Artificially marking end-of-stream, as if the underlying resource had
115
- * // indicated end-of-file by itself, allows the stream to close.
116
- * // This does not cancel pending read operations, and if there is such an
117
- * // operation, the process may still not be able to exit successfully
118
- * // until it finishes.
119
- * stream.push(null);
120
- * stream.read(0);
121
- * }, 100);
122
- * ```
123
- *
124
- * If `autoClose` is false, then the file descriptor won't be closed, even if
125
- * there's an error. It is the application's responsibility to close it and make
126
- * sure there's no file descriptor leak. If `autoClose` is set to true (default
127
- * behavior), on `'error'` or `'end'` the file descriptor will be closed
128
- * automatically.
129
- *
130
- * `mode` sets the file mode (permission and sticky bits), but only if the
131
- * file was created.
132
- *
133
- * An example to read the last 10 bytes of a file which is 100 bytes long:
134
- *
135
- * ```js
136
- * import { createReadStream } from 'fs';
137
- *
138
- * createReadStream('sample.txt', { start: 90, end: 99 });
139
- * ```
140
- *
141
- * If `options` is a string, then it specifies the encoding.
142
- * @since v0.1.31
143
- */
144
- export const createReadStream: typeof nodeFSCallBack.createReadStream = nodeFSCallBack.createReadStream
145
-
146
- export async function ReadEnvFileToPromise(p: string): PlataPromise<Dictionary<string | undefined>> {
147
- const envFile = Object.create(null)
148
-
149
- const result = await ReadFileAsync(p, async line => {
150
- if (line[0] === '#') return
151
-
152
- if (line !== '') {
153
- const env = line.split('=')
154
-
155
- if (env.length >= 2) {
156
- const [ key, ...v ] = env
157
- let value = v.join('=')
158
-
159
- if (value[0] === '{' && value.slice(-1) === '}')
160
- value = process.env[value.slice(1, -1)] ?? ''
161
- ;
162
-
163
- if (value !== '')
164
- envFile[key] = value
165
- ;
166
- }
167
- }
168
- })
169
-
170
- if (result !== null) {
171
- return result
172
- }
173
-
174
- return envFile as any
175
- }
176
-
177
- export const cp: PlataFunctionWrapperReturn<typeof nodeFS.cp, Promise<MaybePlataError>> = (source, destination, opts) => {
178
- return nodeFS.cp(source, destination, opts).then(
179
- () => null,
180
- err => {
181
- return {
182
- errorID: 'PLFS001',
183
- msg: err.message,
184
- error: {
185
- message: err?.toString(),
186
- stack: err?.stack ?? new Error().stack
187
- }
188
- }
189
- }
190
- )
191
- }
192
-
193
- export function ReadFileSync(file: string, callback: (line: string) => string): PlataPromise<string> {
194
- return new Promise(resolve => {
195
- try {
196
- const content: string[] = []
197
- const stream = readline.createInterface({
198
- input: createReadStream(file),
199
- crlfDelay: Infinity
200
- })
201
-
202
- stream.on('close', () => {
203
- resolve(content.join('\n'))
204
- })
205
-
206
- stream.on('line', (line) => {
207
- content.push(callback(line))
208
- })
209
-
210
- } catch(err) {
211
- resolve({
212
- errorID: 'PLTRF0004',
213
- msg: `Error while reading file: ${file}`,
214
- error: {
215
- message: err?.toString(),
216
- stack: err?.stack ?? new Error().stack
217
- }
218
- })
219
- }
220
- })
221
- }
222
-
223
- export function ReadFileAsync(file: string, callback: (line: string) => Promise<void>): Promise<MaybePlataError> {
224
- return new Promise(resolve => {
225
- try {
226
- const promises: any = []
227
-
228
- const stream = readline.createInterface({
229
- input: createReadStream(file),
230
- crlfDelay: Infinity
231
- })
232
-
233
- stream.on('close', () => {
234
- Promise.all(promises).then(
235
- () => resolve(null),
236
- err => resolve({
237
- errorID: 'PPFRFA0002',
238
- msg: `Unexpected error while reading file: ${file}`,
239
- error: {
240
- message: err?.toString(),
241
- stack: err?.stack ?? new Error().stack
242
- }
243
- }),
244
- )
245
- })
246
-
247
- stream.on('line', line => {
248
- promises.push(Plata.FastPromise(() => callback(line)))
249
- })
250
-
251
- } catch (err) {
252
- return resolve({
253
- errorID: 'PPFRFA0001',
254
- msg: `Unexpected error while reading file: ${file}`,
255
- error: {
256
- message: err?.toString(),
257
- stack: err?.stack ?? new Error().stack
258
- }
259
- })
260
- }
261
- })
262
- }
263
-
264
- export async function FindFiles(folders: string[], file: string): Promise<string[]> {
265
- const files: string[] = []
266
-
267
- for (const folder of folders) {
268
- files.push(...glob.sync(`${folder.replace(/\\/g, '/')}/**/${file}`))
269
- }
270
-
271
- return files
272
- }
273
-
274
- export class CliTools {
275
- public readonly sourcePath: PathLike
276
- public readonly destPath: PathLike
277
-
278
- constructor(sourcePath: PathLike, destPath: PathLike) {
279
- this.destPath = destPath
280
- this.sourcePath = sourcePath
281
- }
282
-
283
- public async mkdirIfNotExists(dir: PathLike) {
284
- try {
285
- const p = path.resolve(dir.toString())
286
-
287
- if (!(await access(p))) {
288
- await nodeFS.mkdir(p, { recursive: true })
289
- }
290
- } catch (err) {
291
- console.error(err)
292
- process.exit(1)
293
- }
294
- }
295
-
296
- public async createFolderToDest(folder: string) {
297
- const destinationPath = path.join(this.destPath.toString(), folder)
298
-
299
- await this.mkdirIfNotExists(destinationPath)
300
- }
301
-
302
- public async forEachFileInFolder(folder: PathLike, callback: (file: string, filePath: PathLike) => Promise<void>) {
303
- try {
304
- const folderPath = path.resolve(folder.toString())
305
- const files = await nodeFS.readdir(folder)
306
-
307
- const promises: Promise<void>[] = []
308
-
309
- files.forEach(file => {
310
- const filePath = path.join(folderPath, file)
311
-
312
- promises.push(
313
- Promise.resolve().then(() => callback(file, filePath))
314
- )
315
- })
316
-
317
- await Promise.all(promises)
318
- } catch (err) {
319
- console.error(err)
320
- process.exit(1)
321
- }
322
- }
323
-
324
- public async copyFile(sourcePath: PathLike, destinationPath: PathLike) {
325
- try {
326
- const s = path.resolve(sourcePath.toString())
327
- const d = path.resolve(destinationPath.toString())
328
-
329
- if (!(await access(d))) {
330
- await nodeFS.copyFile(s, d)
331
- }
332
- } catch (err) {
333
- console.error(err)
334
- process.exit(1)
335
- }
336
- }
337
-
338
- public async copyFileIfNotExists(sourcePath: PathLike, destinationPath: PathLike) {
339
- try {
340
- const s = path.resolve(sourcePath.toString())
341
- const d = path.resolve(destinationPath.toString())
342
-
343
- if (!(await access(d))) {
344
- await this.copyFile(s, d)
345
- }
346
- } catch (err) {
347
- console.error(err)
348
- process.exit(1)
349
- }
350
- }
351
-
352
- public async copyFolderToDest(folder: string) {
353
- const sourcePath = path.join(this.sourcePath.toString(), folder)
354
- const destinationPath = path.join(this.destPath.toString(), folder)
355
-
356
- await this.mkdirIfNotExists(destinationPath)
357
-
358
- await this.forEachFileInFolder(sourcePath, (file, filePath) =>
359
- this.copyFileIfNotExists(
360
- filePath,
361
- path.join(destinationPath, file)
362
- )
363
- )
364
- }
365
-
366
- public async syncFolder(folder: string) {
367
- const sourcePath = path.join(this.sourcePath.toString(), folder)
368
- const destinationPath = path.join(this.destPath.toString(), folder)
369
-
370
- await this.mkdirIfNotExists(destinationPath)
371
-
372
- await this.forEachFileInFolder(sourcePath, (file, filePath) =>
373
- this.copyFile(
374
- filePath,
375
- path.join(destinationPath, file)
376
- )
377
- )
378
- }
379
-
380
- public async copyFileToDest(file: string) {
381
- const sourcePath = path.join(this.sourcePath.toString(), file)
382
- const destinationPath = path.join(this.destPath.toString(), file)
383
-
384
- await this.copyFileIfNotExists(sourcePath, destinationPath)
385
- }
386
-
387
- public async syncFileToDest(file: string) {
388
- const sourcePath = path.join(this.sourcePath.toString(), file)
389
- const destinationPath = path.join(this.destPath.toString(), file)
390
-
391
- await this.copyFile(sourcePath, destinationPath)
392
- }
393
-
394
- public async createFileToDest(file: string, content: Parameters<typeof nodeFS.writeFile>[1]) {
395
- const destinationPath = path.join(this.destPath.toString(), file)
396
-
397
- await nodeFS.writeFile(destinationPath, content)
398
- }
399
- }
1
+ import nodeFS from 'node:fs/promises'
2
+ import path from 'node:path'
3
+ import nodeFSCallBack, { PathLike } from 'node:fs'
4
+ import readline from 'node:readline'
5
+ import glob from 'glob'
6
+
7
+ export namespace PlataFs {
8
+ export const constants = nodeFS.constants
9
+
10
+ export const fs = nodeFS
11
+
12
+ /**
13
+ * Tests a user's permissions for the file or directory specified by `path`.
14
+ * The `mode` argument is an optional integer that specifies the accessibility
15
+ * checks to be performed. `mode` should be either the value `fs.constants.F_OK`or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`,`fs.constants.W_OK`, and `fs.constants.X_OK`
16
+ * (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for
17
+ * possible values of `mode`.
18
+ *
19
+ * If the accessibility check is successful, the promise is resolved with no
20
+ * value. If any of the accessibility checks fail, the promise is rejected
21
+ * with an [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object. The following example checks if the file`/etc/passwd` can be read and
22
+ * written by the current process.
23
+ *
24
+ * ```js
25
+ * import { access } from 'fs/promises';
26
+ * import { constants } from 'fs';
27
+ *
28
+ * try {
29
+ * await access('/etc/passwd', constants.R_OK | constants.W_OK);
30
+ * console.log('can access');
31
+ * } catch {
32
+ * console.error('cannot access');
33
+ * }
34
+ * ```
35
+ *
36
+ * Using `fsPromises.access()` to check for the accessibility of a file before
37
+ * calling `fsPromises.open()` is not recommended. Doing so introduces a race
38
+ * condition, since other processes may change the file's state between the two
39
+ * calls. Instead, user code should open/read/write the file directly and handle
40
+ * the error raised if the file is not accessible.
41
+ * @since v10.0.0
42
+ * @param [mode=fs.constants.F_OK]
43
+ * @return Fulfills with `undefined` upon success.
44
+ */
45
+ export function access(path: PathLike, mode?: number): Promise<boolean> {
46
+ return fs.access(path, mode).then(
47
+ () => true,
48
+ () => false
49
+ )
50
+ }
51
+
52
+ /**
53
+ * `options` may also include a `start` option to allow writing data at some
54
+ * position past the beginning of the file, allowed values are in the
55
+ * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than
56
+ * replacing it may require the `flags` option to be set to `r+` rather than the
57
+ * default `w`. The `encoding` can be any one of those accepted by `Buffer`.
58
+ *
59
+ * If `autoClose` is set to true (default behavior) on `'error'` or `'finish'`the file descriptor will be closed automatically. If `autoClose` is false,
60
+ * then the file descriptor won't be closed, even if there's an error.
61
+ * It is the application's responsibility to close it and make sure there's no
62
+ * file descriptor leak.
63
+ *
64
+ * By default, the stream will emit a `'close'` event after it has been
65
+ * destroyed. Set the `emitClose` option to `false` to change this behavior.
66
+ *
67
+ * By providing the `fs` option it is possible to override the corresponding `fs`implementations for `open`, `write`, `writev` and `close`. Overriding `write()`without `writev()` can reduce
68
+ * performance as some optimizations (`_writev()`)
69
+ * will be disabled. When providing the `fs` option, overrides for at least one of`write` and `writev` are required. If no `fd` option is supplied, an override
70
+ * for `open` is also required. If `autoClose` is `true`, an override for `close`is also required.
71
+ *
72
+ * Like `fs.ReadStream`, if `fd` is specified, `fs.WriteStream` will ignore the`path` argument and will use the specified file descriptor. This means that no`'open'` event will be
73
+ * emitted. `fd` should be blocking; non-blocking `fd`s
74
+ * should be passed to `net.Socket`.
75
+ *
76
+ * If `options` is a string, then it specifies the encoding.
77
+ * @since v0.1.31
78
+ */
79
+ export const createWriteStream: typeof nodeFSCallBack.createWriteStream = nodeFSCallBack.createWriteStream
80
+ /**
81
+ * Unlike the 16 kb default `highWaterMark` for a `stream.Readable`, the stream
82
+ * returned by this method has a default `highWaterMark` of 64 kb.
83
+ *
84
+ * `options` can include `start` and `end` values to read a range of bytes from
85
+ * the file instead of the entire file. Both `start` and `end` are inclusive and
86
+ * start counting at 0, allowed values are in the
87
+ * \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. If `fd` is specified and `start` is
88
+ * omitted or `undefined`, `fs.createReadStream()` reads sequentially from the
89
+ * current file position. The `encoding` can be any one of those accepted by `Buffer`.
90
+ *
91
+ * If `fd` is specified, `ReadStream` will ignore the `path` argument and will use
92
+ * the specified file descriptor. This means that no `'open'` event will be
93
+ * emitted. `fd` should be blocking; non-blocking `fd`s should be passed to `net.Socket`.
94
+ *
95
+ * If `fd` points to a character device that only supports blocking reads
96
+ * (such as keyboard or sound card), read operations do not finish until data is
97
+ * available. This can prevent the process from exiting and the stream from
98
+ * closing naturally.
99
+ *
100
+ * By default, the stream will emit a `'close'` event after it has been
101
+ * destroyed. Set the `emitClose` option to `false` to change this behavior.
102
+ *
103
+ * By providing the `fs` option, it is possible to override the corresponding `fs`implementations for `open`, `read`, and `close`. When providing the `fs` option,
104
+ * an override for `read` is required. If no `fd` is provided, an override for`open` is also required. If `autoClose` is `true`, an override for `close` is
105
+ * also required.
106
+ *
107
+ * ```js
108
+ * import { createReadStream } from 'fs';
109
+ *
110
+ * // Create a stream from some character device.
111
+ * const stream = createReadStream('/dev/input/event0');
112
+ * setTimeout(() => {
113
+ * stream.close(); // This may not close the stream.
114
+ * // Artificially marking end-of-stream, as if the underlying resource had
115
+ * // indicated end-of-file by itself, allows the stream to close.
116
+ * // This does not cancel pending read operations, and if there is such an
117
+ * // operation, the process may still not be able to exit successfully
118
+ * // until it finishes.
119
+ * stream.push(null);
120
+ * stream.read(0);
121
+ * }, 100);
122
+ * ```
123
+ *
124
+ * If `autoClose` is false, then the file descriptor won't be closed, even if
125
+ * there's an error. It is the application's responsibility to close it and make
126
+ * sure there's no file descriptor leak. If `autoClose` is set to true (default
127
+ * behavior), on `'error'` or `'end'` the file descriptor will be closed
128
+ * automatically.
129
+ *
130
+ * `mode` sets the file mode (permission and sticky bits), but only if the
131
+ * file was created.
132
+ *
133
+ * An example to read the last 10 bytes of a file which is 100 bytes long:
134
+ *
135
+ * ```js
136
+ * import { createReadStream } from 'fs';
137
+ *
138
+ * createReadStream('sample.txt', { start: 90, end: 99 });
139
+ * ```
140
+ *
141
+ * If `options` is a string, then it specifies the encoding.
142
+ * @since v0.1.31
143
+ */
144
+ export const createReadStream: typeof nodeFSCallBack.createReadStream = nodeFSCallBack.createReadStream
145
+
146
+ export async function ReadEnvFileToPromise(p: string): PlataPromise<Dictionary<string | undefined>> {
147
+ const envFile = Object.create(null)
148
+
149
+ const result = await ReadFileAsync(p, async line => {
150
+ if (line[0] === '#') return
151
+
152
+ if (line !== '') {
153
+ const env = line.split('=')
154
+
155
+ if (env.length >= 2) {
156
+ const [ key, ...v ] = env
157
+ let value = v.join('=')
158
+
159
+ if (value[0] === '{' && value.slice(-1) === '}')
160
+ value = process.env[value.slice(1, -1)] ?? ''
161
+ ;
162
+
163
+ if (value !== '')
164
+ envFile[key] = value
165
+ ;
166
+ }
167
+ }
168
+ })
169
+
170
+ if (result !== null) {
171
+ return result
172
+ }
173
+
174
+ return envFile as any
175
+ }
176
+
177
+ export const cp: PlataFunctionWrapperReturn<typeof nodeFS.cp, Promise<MaybePlataError>> = (source, destination, opts) => {
178
+ return nodeFS.cp(source, destination, opts).then(
179
+ () => null,
180
+ err => {
181
+ return {
182
+ errorID: 'PLFS001',
183
+ msg: err.message,
184
+ error: {
185
+ message: err?.toString(),
186
+ stack: err?.stack ?? new Error().stack
187
+ }
188
+ }
189
+ }
190
+ )
191
+ }
192
+
193
+ export function ReadFileSync(file: string, callback: (line: string) => string): PlataPromise<string> {
194
+ return new Promise(resolve => {
195
+ try {
196
+ const content: string[] = []
197
+ const stream = readline.createInterface({
198
+ input: createReadStream(file),
199
+ crlfDelay: Infinity
200
+ })
201
+
202
+ stream.on('close', () => {
203
+ resolve(content.join('\n'))
204
+ })
205
+
206
+ stream.on('line', (line) => {
207
+ content.push(callback(line))
208
+ })
209
+
210
+ } catch(err) {
211
+ resolve({
212
+ errorID: 'PLTRF0004',
213
+ msg: `Error while reading file: ${file}`,
214
+ error: {
215
+ message: err?.toString(),
216
+ stack: err?.stack ?? new Error().stack
217
+ }
218
+ })
219
+ }
220
+ })
221
+ }
222
+
223
+ export function ReadFileAsync(file: string, callback: (line: string) => Promise<void>): Promise<MaybePlataError> {
224
+ return new Promise(resolve => {
225
+ try {
226
+ const promises: any = []
227
+
228
+ const stream = readline.createInterface({
229
+ input: createReadStream(file),
230
+ crlfDelay: Infinity
231
+ })
232
+
233
+ stream.on('close', () => {
234
+ Promise.all(promises).then(
235
+ () => resolve(null),
236
+ err => resolve({
237
+ errorID: 'PPFRFA0002',
238
+ msg: `Unexpected error while reading file: ${file}`,
239
+ error: {
240
+ message: err?.toString(),
241
+ stack: err?.stack ?? new Error().stack
242
+ }
243
+ }),
244
+ )
245
+ })
246
+
247
+ stream.on('line', line => {
248
+ promises.push(Plata.FastPromise(() => callback(line)))
249
+ })
250
+
251
+ } catch (err) {
252
+ return resolve({
253
+ errorID: 'PPFRFA0001',
254
+ msg: `Unexpected error while reading file: ${file}`,
255
+ error: {
256
+ message: err?.toString(),
257
+ stack: err?.stack ?? new Error().stack
258
+ }
259
+ })
260
+ }
261
+ })
262
+ }
263
+
264
+ export async function FindFiles(folders: string[], file: string): Promise<string[]> {
265
+ const files: string[] = []
266
+
267
+ for (const folder of folders) {
268
+ files.push(...glob.sync(`${folder.replace(/\\/g, '/')}/**/${file}`))
269
+ }
270
+
271
+ return files
272
+ }
273
+
274
+ export class CliTools {
275
+ public readonly sourcePath: PathLike
276
+ public readonly destPath: PathLike
277
+
278
+ constructor(sourcePath: PathLike, destPath: PathLike) {
279
+ this.destPath = destPath
280
+ this.sourcePath = sourcePath
281
+ }
282
+
283
+ public async mkdirIfNotExists(dir: PathLike) {
284
+ try {
285
+ const p = path.resolve(dir.toString())
286
+
287
+ if (!(await access(p))) {
288
+ await nodeFS.mkdir(p, { recursive: true })
289
+ }
290
+ } catch (err) {
291
+ console.error(err)
292
+ process.exit(1)
293
+ }
294
+ }
295
+
296
+ public async createFolderToDest(folder: string) {
297
+ const destinationPath = path.join(this.destPath.toString(), folder)
298
+
299
+ await this.mkdirIfNotExists(destinationPath)
300
+ }
301
+
302
+ public async forEachFileInFolder(folder: PathLike, callback: (file: string, filePath: PathLike) => Promise<void>) {
303
+ try {
304
+ const folderPath = path.resolve(folder.toString())
305
+ const files = await nodeFS.readdir(folder)
306
+
307
+ const promises: Promise<void>[] = []
308
+
309
+ files.forEach(file => {
310
+ const filePath = path.join(folderPath, file)
311
+
312
+ promises.push(
313
+ Promise.resolve().then(() => callback(file, filePath))
314
+ )
315
+ })
316
+
317
+ await Promise.all(promises)
318
+ } catch (err) {
319
+ console.error(err)
320
+ process.exit(1)
321
+ }
322
+ }
323
+
324
+ public async copyFile(sourcePath: PathLike, destinationPath: PathLike) {
325
+ try {
326
+ const s = path.resolve(sourcePath.toString())
327
+ const d = path.resolve(destinationPath.toString())
328
+
329
+ if (!(await access(d))) {
330
+ await nodeFS.copyFile(s, d)
331
+ }
332
+ } catch (err) {
333
+ console.error(err)
334
+ process.exit(1)
335
+ }
336
+ }
337
+
338
+ public async copyFileIfNotExists(sourcePath: PathLike, destinationPath: PathLike) {
339
+ try {
340
+ const s = path.resolve(sourcePath.toString())
341
+ const d = path.resolve(destinationPath.toString())
342
+
343
+ if (!(await access(d))) {
344
+ await this.copyFile(s, d)
345
+ }
346
+ } catch (err) {
347
+ console.error(err)
348
+ process.exit(1)
349
+ }
350
+ }
351
+
352
+ public async copyFolderToDest(folder: string) {
353
+ const sourcePath = path.join(this.sourcePath.toString(), folder)
354
+ const destinationPath = path.join(this.destPath.toString(), folder)
355
+
356
+ await this.mkdirIfNotExists(destinationPath)
357
+
358
+ await this.forEachFileInFolder(sourcePath, (file, filePath) =>
359
+ this.copyFileIfNotExists(
360
+ filePath,
361
+ path.join(destinationPath, file)
362
+ )
363
+ )
364
+ }
365
+
366
+ public async syncFolder(folder: string) {
367
+ const sourcePath = path.join(this.sourcePath.toString(), folder)
368
+ const destinationPath = path.join(this.destPath.toString(), folder)
369
+
370
+ await this.mkdirIfNotExists(destinationPath)
371
+
372
+ await this.forEachFileInFolder(sourcePath, (file, filePath) =>
373
+ this.copyFile(
374
+ filePath,
375
+ path.join(destinationPath, file)
376
+ )
377
+ )
378
+ }
379
+
380
+ public async copyFileToDest(file: string) {
381
+ const sourcePath = path.join(this.sourcePath.toString(), file)
382
+ const destinationPath = path.join(this.destPath.toString(), file)
383
+
384
+ await this.copyFileIfNotExists(sourcePath, destinationPath)
385
+ }
386
+
387
+ public async syncFileToDest(file: string) {
388
+ const sourcePath = path.join(this.sourcePath.toString(), file)
389
+ const destinationPath = path.join(this.destPath.toString(), file)
390
+
391
+ await this.copyFile(sourcePath, destinationPath)
392
+ }
393
+
394
+ public async createFileToDest(file: string, content: Parameters<typeof nodeFS.writeFile>[1]) {
395
+ const destinationPath = path.join(this.destPath.toString(), file)
396
+
397
+ await nodeFS.writeFile(destinationPath, content)
398
+ }
399
+ }
400
400
  }