@kikiutils/shared 20.1.0 → 20.1.1
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/dist/classes/path.d.ts.map +1 -1
- package/dist/classes/path.js +30 -30
- package/dist/classes/path.js.map +1 -1
- package/dist/enum.d.ts +4 -3
- package/dist/enum.d.ts.map +1 -1
- package/dist/enum.js +3 -2
- package/dist/enum.js.map +1 -1
- package/dist/event-awaiter.d.ts.map +1 -1
- package/dist/event-awaiter.js +6 -6
- package/dist/event-awaiter.js.map +1 -1
- package/dist/general.d.ts +3 -2
- package/dist/general.d.ts.map +1 -1
- package/dist/general.js.map +1 -1
- package/dist/logger/_internals/logger.d.ts.map +1 -1
- package/dist/logger/_internals/logger.js +3 -2
- package/dist/logger/_internals/logger.js.map +1 -1
- package/dist/logger/node/_internals/file-writer.js +7 -7
- package/dist/logger/node/_internals/file-writer.js.map +1 -1
- package/dist/logger/node/index.js +8 -8
- package/dist/logger/node/index.js.map +1 -1
- package/dist/storages/redis/keyed-store.d.ts.map +1 -1
- package/dist/storages/redis/keyed-store.js +10 -10
- package/dist/storages/redis/keyed-store.js.map +1 -1
- package/dist/storages/redis/msgpack.js +2 -2
- package/dist/storages/redis/msgpack.js.map +1 -1
- package/dist/time.d.ts.map +1 -1
- package/dist/time.js +4 -4
- package/dist/time.js.map +1 -1
- package/package.json +15 -11
- package/src/classes/path.ts +30 -30
- package/src/enum.ts +11 -5
- package/src/event-awaiter.ts +6 -6
- package/src/general.ts +5 -3
- package/src/logger/_internals/logger.ts +7 -2
- package/src/logger/node/_internals/file-writer.ts +7 -7
- package/src/logger/node/index.ts +9 -9
- package/src/storages/redis/keyed-store.ts +10 -10
- package/src/storages/redis/msgpack.ts +2 -2
- package/src/time.ts +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.d.ts","names":[],"sources":["../../src/classes/path.ts"],"mappings":";;;;;KAMK,oBAAoB,cAAc,qBAAqB,WAAW,0BAA0B,KAAK;;;;YAK1F,WAAW,GAAG,WAAW;;;;;;;;;;qBAWxB;;;;;;;EAWG,eAAG,OAAO;;;;;;MAoBlB,UAAM;;;;MAON;;;;;;;;;;SAeG,OAAO,YAAY,SAAS,wBAAqB;;;;;;;;;;;;;;SAiBjD,WAAW,OAAO,aAAU;GASlC,OAAO,aAAa;;;;;;;;EAYrB,SAAS;;;;;;;;EAWT,WAAO;;;;;;;;EAWP;;;;;;;;EAWA;;;;;;;;EAWA,aAAS;;;;;;;;;;EAaT,QAAQ,OAAO,aAAU;;;;;;;;EAWzB,SAAK,SAAA;;;;;;;;;;EAaL,SAAS,IAAI,WAAQ;;;;;;;;;;;EAcrB,WAAO;EAIP;;;;;;;;;EAYA;;;;EAOA;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"path.d.ts","names":[],"sources":["../../src/classes/path.ts"],"mappings":";;;;;KAMK,oBAAoB,cAAc,qBAAqB,WAAW,0BAA0B,KAAK;;;;YAK1F,WAAW,GAAG,WAAW;;;;;;;;;;qBAWxB;;;;;;;EAWG,eAAG,OAAO;;;;;;MAoBlB,UAAM;;;;MAON;;;;;;;;;;SAeG,OAAO,YAAY,SAAS,wBAAqB;;;;;;;;;;;;;;SAiBjD,WAAW,OAAO,aAAU;GASlC,OAAO,aAAa;;;;;;;;EAYrB,SAAS;;;;;;;;EAWT,WAAO;;;;;;;;EAWP;;;;;;;;EAWA;;;;;;;;EAWA,aAAS;;;;;;;;;;EAaT,QAAQ,OAAO,aAAU;;;;;;;;EAWzB,SAAK,SAAA;;;;;;;;;;EAaL,SAAS,IAAI,WAAQ;;;;;;;;;;;EAcrB,WAAO;EAIP;;;;;;;;;EAYA;;;;EAOA;;;;;;;;;EAYM,UAAU,MAAM,2BAA2B,IAAI,UAAO;;;;;;;;;EAYtD,cAAc,MAAM,2BAA2B,IAAI,cAAW;;;;;;;;;EAY9D,SAAS,MAAM,2BAA2B,IAAI,SAAM;;;;;;;;;EAYpD,SAAS,MAAM,2BAA2B,IAAI,SAAM;;;;;;;;;EAYpD,YAAY,MAAM,2BAA2B,IAAI,YAAS;;;;;;;;;;EAahE,MAAM,SAAS,GAAG;IAAyB;MAAoB;EAC/D,MACI,WACK,GAAG;IAAyB;OAC7B,GAAG,cAER;EACH,MAAM,UAAU,GAAG,uBAAuB,GAAG,cAAc;;;;;;;;;EAarD,QAAQ,MAAM,2BAA2B,IAAI,QAAK,QAAA,GAAA,SAAA;;;;;;;;;EAYxD,QACI,UACI,kBACC,GAAG;IACF;IACA;cAGP;EACH,QACI;IAGM;IACA;IACA;MAEP,QAAQ;EACX,QACI,UACI,kBACC,GAAG;IACF;IACA;cAGP,QAAQ;EACX,QACI,SAAS,GAAG;IACR;IACA;MAEL,QAAQ,GAAG;EACd,QACI;IACI;IACA;IACA;MAEL,QAAQ,MAAM,GAAG,OAAO;;;;;;;;;EAa3B,SACI,WACK;IACC;IACA,OAAO,GAAG;cAGjB,QAAQ;EACX,SACI,UACK;IACC,UAAU;IACV,OAAO,GAAG;OAEZ,iBACL;EACH,SACI,WAEQ,YACA,GAAG;IACD,OAAO,GAAG;OAEd,wBAEP,QAAQ;;;;;;;;;;;EAeL,OAAO,SAAS,WAAQ;;;;;;;;;EAYxB,MAAM,MAAM,2BAA2B,IAAI,MAAG;;;;;;;;;EAY9C,SAAS,MAAM,2BAA2B,IAAI,SAAM;;;;;;;;;;EAa1D,KACI,OAAO,GAAG;IACN;IACA;MAEL,QAAQ,GAAG;EACd,KACI,MAAM,GAAG;IACL;IACA;MAEL,QAAQ,GAAG;EACd,KACI,MAAM,GAAG;IACL;IACA;MAEL,QAAQ,GAAG;EACd,KACI,MAAM,GAAG;IACL;IACA;MAEL,QAAQ,GAAG;EACd,KAAK,MAAM,GAAG;IAAgB;MAA0B,QAAQ,GAAG,cAAc,GAAG;EACpF,KAAK,OAAO,GAAG,cAAc,QAAQ,GAAG,cAAc,GAAG;;;;;;;;;EAwBnD,YAAY,MAAM,2BAA2B,IAAI,YAAS;;;;;;;;;EAY1D,UAAM;;;;;;;;;EAYN,aAAa,MAAM,2BAA2B,IAAI,aAAU"}
|
package/dist/classes/path.js
CHANGED
|
@@ -200,8 +200,8 @@ var Path = class Path {
|
|
|
200
200
|
*
|
|
201
201
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.access}
|
|
202
202
|
*/
|
|
203
|
-
access(...args) {
|
|
204
|
-
return fsp.access(this.#value, ...args);
|
|
203
|
+
async access(...args) {
|
|
204
|
+
return await fsp.access(this.#value, ...args);
|
|
205
205
|
}
|
|
206
206
|
/**
|
|
207
207
|
* Appends data to the file at the stored path.
|
|
@@ -211,8 +211,8 @@ var Path = class Path {
|
|
|
211
211
|
*
|
|
212
212
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.appendFile}
|
|
213
213
|
*/
|
|
214
|
-
appendFile(...args) {
|
|
215
|
-
return fsp.appendFile(this.#value, ...args);
|
|
214
|
+
async appendFile(...args) {
|
|
215
|
+
return await fsp.appendFile(this.#value, ...args);
|
|
216
216
|
}
|
|
217
217
|
/**
|
|
218
218
|
* Changes the permissions of the stored path.
|
|
@@ -222,8 +222,8 @@ var Path = class Path {
|
|
|
222
222
|
*
|
|
223
223
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chmod}
|
|
224
224
|
*/
|
|
225
|
-
chmod(...args) {
|
|
226
|
-
return fsp.chmod(this.#value, ...args);
|
|
225
|
+
async chmod(...args) {
|
|
226
|
+
return await fsp.chmod(this.#value, ...args);
|
|
227
227
|
}
|
|
228
228
|
/**
|
|
229
229
|
* Changes the owner and group of the stored path.
|
|
@@ -233,8 +233,8 @@ var Path = class Path {
|
|
|
233
233
|
*
|
|
234
234
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chown}
|
|
235
235
|
*/
|
|
236
|
-
chown(...args) {
|
|
237
|
-
return fsp.chown(this.#value, ...args);
|
|
236
|
+
async chown(...args) {
|
|
237
|
+
return await fsp.chown(this.#value, ...args);
|
|
238
238
|
}
|
|
239
239
|
/**
|
|
240
240
|
* Copies the file at the stored path to a destination.
|
|
@@ -244,11 +244,11 @@ var Path = class Path {
|
|
|
244
244
|
*
|
|
245
245
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.copyFile}
|
|
246
246
|
*/
|
|
247
|
-
copyFile(...args) {
|
|
248
|
-
return fsp.copyFile(this.#value, ...args);
|
|
247
|
+
async copyFile(...args) {
|
|
248
|
+
return await fsp.copyFile(this.#value, ...args);
|
|
249
249
|
}
|
|
250
|
-
mkdir(...args) {
|
|
251
|
-
return fsp.mkdir(this.#value, ...args);
|
|
250
|
+
async mkdir(...args) {
|
|
251
|
+
return await fsp.mkdir(this.#value, ...args);
|
|
252
252
|
}
|
|
253
253
|
/**
|
|
254
254
|
* Opens the file at the stored path.
|
|
@@ -258,14 +258,14 @@ var Path = class Path {
|
|
|
258
258
|
*
|
|
259
259
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.open}
|
|
260
260
|
*/
|
|
261
|
-
open(...args) {
|
|
262
|
-
return fsp.open(this.#value, ...args);
|
|
261
|
+
async open(...args) {
|
|
262
|
+
return await fsp.open(this.#value, ...args);
|
|
263
263
|
}
|
|
264
|
-
readdir(...args) {
|
|
265
|
-
return fsp.readdir(this.#value, ...args);
|
|
264
|
+
async readdir(...args) {
|
|
265
|
+
return await fsp.readdir(this.#value, ...args);
|
|
266
266
|
}
|
|
267
|
-
readFile(...args) {
|
|
268
|
-
return fsp.readFile(this.#value, ...args);
|
|
267
|
+
async readFile(...args) {
|
|
268
|
+
return await fsp.readFile(this.#value, ...args);
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
271
|
* Renames or moves the file or directory at the stored path.
|
|
@@ -277,8 +277,8 @@ var Path = class Path {
|
|
|
277
277
|
*
|
|
278
278
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rename}
|
|
279
279
|
*/
|
|
280
|
-
rename(newPath) {
|
|
281
|
-
return fsp.rename(this.#value, newPath.toString());
|
|
280
|
+
async rename(newPath) {
|
|
281
|
+
return await fsp.rename(this.#value, newPath.toString());
|
|
282
282
|
}
|
|
283
283
|
/**
|
|
284
284
|
* Removes the file or directory at the stored path.
|
|
@@ -288,8 +288,8 @@ var Path = class Path {
|
|
|
288
288
|
*
|
|
289
289
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rm}
|
|
290
290
|
*/
|
|
291
|
-
rm(...args) {
|
|
292
|
-
return fsp.rm(this.#value, ...args);
|
|
291
|
+
async rm(...args) {
|
|
292
|
+
return await fsp.rm(this.#value, ...args);
|
|
293
293
|
}
|
|
294
294
|
/**
|
|
295
295
|
* Removes the directory at the stored path.
|
|
@@ -299,8 +299,8 @@ var Path = class Path {
|
|
|
299
299
|
*
|
|
300
300
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rmdir}
|
|
301
301
|
*/
|
|
302
|
-
rmdir(...args) {
|
|
303
|
-
return fsp.rmdir(this.#value, ...args);
|
|
302
|
+
async rmdir(...args) {
|
|
303
|
+
return await fsp.rmdir(this.#value, ...args);
|
|
304
304
|
}
|
|
305
305
|
async stat(opts) {
|
|
306
306
|
try {
|
|
@@ -318,8 +318,8 @@ var Path = class Path {
|
|
|
318
318
|
*
|
|
319
319
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.truncate}
|
|
320
320
|
*/
|
|
321
|
-
truncate(...args) {
|
|
322
|
-
return fsp.truncate(this.#value, ...args);
|
|
321
|
+
async truncate(...args) {
|
|
322
|
+
return await fsp.truncate(this.#value, ...args);
|
|
323
323
|
}
|
|
324
324
|
/**
|
|
325
325
|
* Deletes the file or symbolic link at the stored path.
|
|
@@ -329,8 +329,8 @@ var Path = class Path {
|
|
|
329
329
|
*
|
|
330
330
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.unlink}
|
|
331
331
|
*/
|
|
332
|
-
unlink() {
|
|
333
|
-
return fsp.unlink(this.#value);
|
|
332
|
+
async unlink() {
|
|
333
|
+
return await fsp.unlink(this.#value);
|
|
334
334
|
}
|
|
335
335
|
/**
|
|
336
336
|
* Writes data to the file at the stored path.
|
|
@@ -340,8 +340,8 @@ var Path = class Path {
|
|
|
340
340
|
*
|
|
341
341
|
* @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.writeFile}
|
|
342
342
|
*/
|
|
343
|
-
writeFile(...args) {
|
|
344
|
-
return fsp.writeFile(this.#value, ...args);
|
|
343
|
+
async writeFile(...args) {
|
|
344
|
+
return await fsp.writeFile(this.#value, ...args);
|
|
345
345
|
}
|
|
346
346
|
};
|
|
347
347
|
export { Path };
|
package/dist/classes/path.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path.js","names":[],"sources":["../../src/classes/path.ts"],"sourcesContent":["import type { Buffer } from 'node:buffer';\nimport type { Abortable } from 'node:events';\nimport type * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as nodePath from 'node:path';\n\ntype DropFirstParameters<T extends (...args: any) => any> = Parameters<T> extends [any, ...infer R] ? R : never;\n\n/**\n * Values accepted by the `Path` constructor and path-composition methods.\n */\nexport type PathLike = fs.PathLike | Path;\n\n/**\n * An immutable file system path with Node.js path and file operations.\n *\n * @remarks\n * Path-composition methods return new instances and leave this instance unchanged.\n * File operations act on the stored path and forward Node.js defaults and promise rejections.\n * They do not update the stored path, including after a successful rename.\n * The constructor joins stringified inputs using the platform-specific Node.js path rules.\n */\nexport class Path {\n // Private instance properties\n readonly #value: string;\n\n // Constructor\n\n /**\n * Creates a normalized path value by joining the provided path segments.\n *\n * @param paths - Path segments accepted by Node.js `path.join` or another `Path` instance.\n */\n constructor(...paths: PathLike[]) {\n this.#value = nodePath.join(...this.#toStrings(paths));\n }\n\n // Private instance methods\n #newInstance(...paths: PathLike[]) {\n return new Path(...paths);\n }\n\n #toStrings(paths: PathLike[]) {\n return paths.map((path) => path.toString());\n }\n\n // Public instance accessors\n\n /**\n * The parent directory as a new `Path`; this instance is unchanged.\n *\n * @see {@link Path.dirname}\n */\n get parent() {\n return this.dirname();\n }\n\n /**\n * The normalized path string stored by this instance.\n */\n get value() {\n return this.#value;\n }\n\n // Public static methods\n\n /**\n * Creates a new path from a Node.js path object.\n *\n * @param pathObject - The path components to format.\n *\n * @returns A new normalized `Path`.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.format}\n */\n static format(pathObject: nodePath.FormatInputPathObject) {\n return new Path(nodePath.format(pathObject));\n }\n\n /**\n * Resolves joined path segments to an absolute path.\n *\n * @remarks\n * Inputs are joined before resolution; unlike Node.js `path.resolve`,\n * later absolute segments do not reset the path.\n *\n * @param paths - The stringified path segments to join.\n *\n * @returns A new absolute `Path`.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.resolve}\n */\n static resolve(...paths: PathLike[]) {\n return new this(...paths).resolve();\n }\n\n // Public instance methods\n [Symbol.for('nodejs.util.inspect.custom')]() {\n return this.#value;\n }\n\n [Symbol.toPrimitive](hint: string) {\n if (hint === 'number') throw new TypeError('Cannot convert a Path to a number');\n return this.#value;\n }\n\n /**\n * Returns the final component of this path.\n *\n * @param suffix - An optional exact suffix to remove.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.basename}\n */\n basename(suffix?: string) {\n return nodePath.basename(this.#value, suffix);\n }\n\n /**\n * Returns the parent directory of this path.\n *\n * @returns A new `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.dirname}\n */\n dirname() {\n return this.#newInstance(nodePath.dirname(this.#value));\n }\n\n /**\n * Returns the extension of the final path component.\n *\n * @returns The extension including its leading dot, or an empty string when absent.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.extname}\n */\n extname() {\n return nodePath.extname(this.#value);\n }\n\n /**\n * Checks whether this path is absolute on the current platform.\n *\n * @returns Whether this path is absolute.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.isAbsolute}\n */\n isAbsolute() {\n return nodePath.isAbsolute(this.#value);\n }\n\n /**\n * Normalizes separators and relative segments in this path.\n *\n * @returns A new `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.normalize}\n */\n normalize() {\n return this.#newInstance(nodePath.normalize(this.#value));\n }\n\n /**\n * Joins additional segments onto this path.\n *\n * @param paths - The stringified path segments to append.\n *\n * @returns A new normalized `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.join}\n */\n join(...paths: PathLike[]) {\n return this.#newInstance(this.#value, ...this.#toStrings(paths));\n }\n\n /**\n * Parses this path into its root, directory, basename, extension, and name.\n *\n * @returns A new object containing the path components.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.parse}\n */\n parse() {\n return nodePath.parse(this.#value);\n }\n\n /**\n * Computes a relative path from this path to the destination.\n *\n * @param to - The destination path.\n *\n * @returns A new `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.relative}\n */\n relative(to: PathLike) {\n return this.#newInstance(nodePath.relative(this.#value, to.toString()));\n }\n\n /**\n * Resolves this path to an absolute path using the current working directory.\n *\n * @remarks\n * Relative paths use the current working directory. This instance is unchanged.\n *\n * @returns A new absolute `Path`.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.resolve}\n */\n resolve() {\n return this.#newInstance(nodePath.resolve(this.#value));\n }\n\n toJSON() {\n return this.#value;\n }\n\n /**\n * Converts this path to the Windows namespace form when applicable.\n *\n * @returns The namespace-converted path string; this instance is unchanged.\n * On non-Windows platforms, the path text is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.toNamespacedPath}\n */\n toNamespacedPath() {\n return nodePath.toNamespacedPath(this.#value);\n }\n\n /**\n * Returns the stored path as a string.\n */\n toString() {\n return this.#value;\n }\n\n /**\n * Checks access permissions for the stored path.\n *\n * @remarks\n * The promise resolves when the access check succeeds and rejects if access is denied or the path is missing.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.access}\n */\n access(...args: DropFirstParameters<typeof fsp.access>) {\n return fsp.access(this.#value, ...args);\n }\n\n /**\n * Appends data to the file at the stored path.\n *\n * @remarks\n * The promise resolves when appending completes; a missing file is created according to the supplied options.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.appendFile}\n */\n appendFile(...args: DropFirstParameters<typeof fsp.appendFile>) {\n return fsp.appendFile(this.#value, ...args);\n }\n\n /**\n * Changes the permissions of the stored path.\n *\n * @remarks\n * The promise resolves when the permissions are changed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chmod}\n */\n chmod(...args: DropFirstParameters<typeof fsp.chmod>) {\n return fsp.chmod(this.#value, ...args);\n }\n\n /**\n * Changes the owner and group of the stored path.\n *\n * @remarks\n * The promise resolves when the ownership is changed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chown}\n */\n chown(...args: DropFirstParameters<typeof fsp.chown>) {\n return fsp.chown(this.#value, ...args);\n }\n\n /**\n * Copies the file at the stored path to a destination.\n *\n * @remarks\n * The promise resolves when copying completes. The stored path remains the source path.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.copyFile}\n */\n copyFile(...args: DropFirstParameters<typeof fsp.copyFile>) {\n return fsp.copyFile(this.#value, ...args);\n }\n\n /**\n * Creates a directory at the stored path.\n *\n * @remarks\n * The promise resolves after creation. Recursive mode resolves to the first created directory path, or\n * `undefined` if no directory is created; nonrecursive mode resolves without a value.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.mkdir}\n */\n mkdir(options: fs.MakeDirectoryOptions & { recursive: true }): Promise<string | undefined>;\n mkdir(\n options?:\n | (fs.MakeDirectoryOptions & { recursive?: false })\n | fs.Mode\n | null,\n ): Promise<void>;\n mkdir(options?: fs.MakeDirectoryOptions | fs.Mode | null): Promise<string | undefined>;\n mkdir(...args: any): any {\n return fsp.mkdir(this.#value, ...args);\n }\n\n /**\n * Opens the file at the stored path.\n *\n * @remarks\n * The promise resolves to a new file handle. The caller must close the handle when it is no longer needed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.open}\n */\n open(...args: DropFirstParameters<typeof fsp.open>) {\n return fsp.open(this.#value, ...args);\n }\n\n /**\n * Reads the entries of the directory at the stored path.\n *\n * @remarks\n * The promise resolves to names, buffers, or directory entries according to the options.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.readdir}\n */\n readdir(\n options?:\n | BufferEncoding\n | (fs.ObjectEncodingOptions & {\n recursive?: boolean;\n withFileTypes?: false;\n })\n | null,\n ): Promise<string[]>;\n readdir(\n options:\n | 'buffer'\n | {\n encoding: 'buffer';\n recursive?: boolean;\n withFileTypes?: false;\n },\n ): Promise<Buffer[]>;\n readdir(\n options?:\n | BufferEncoding\n | (fs.ObjectEncodingOptions & {\n recursive?: boolean;\n withFileTypes?: false;\n })\n | null,\n ): Promise<Buffer[] | string[]>;\n readdir(\n options: fs.ObjectEncodingOptions & {\n recursive?: boolean;\n withFileTypes: true;\n },\n ): Promise<fs.Dirent[]>;\n readdir(\n options: {\n encoding: 'buffer';\n recursive?: boolean;\n withFileTypes: true;\n },\n ): Promise<Array<fs.Dirent<Buffer>>>;\n readdir(...args: any): any {\n return fsp.readdir(this.#value, ...args);\n }\n\n /**\n * Reads the entire file at the stored path.\n *\n * @remarks\n * The promise resolves to a string when a text encoding is supplied, or a `Buffer` otherwise.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.readFile}\n */\n readFile(\n options?:\n | (Abortable & {\n encoding?: null;\n flag?: fs.OpenMode;\n })\n | null,\n ): Promise<Buffer>;\n readFile(\n options:\n | (Abortable & {\n encoding: BufferEncoding;\n flag?: fs.OpenMode;\n })\n | BufferEncoding,\n ): Promise<string>;\n readFile(\n options?:\n | (\n & Abortable\n & fs.ObjectEncodingOptions\n & { flag?: fs.OpenMode }\n )\n | BufferEncoding\n | null,\n ): Promise<Buffer | string>;\n readFile(...args: any): any {\n return fsp.readFile(this.#value, ...args);\n }\n\n /**\n * Renames or moves the file or directory at the stored path.\n *\n * @remarks\n * The promise resolves when the rename completes. This instance retains its original stored path.\n *\n * @param newPath - The destination path; this instance retains its original value.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rename}\n */\n rename(newPath: PathLike) {\n return fsp.rename(this.#value, newPath.toString());\n }\n\n /**\n * Removes the file or directory at the stored path.\n *\n * @remarks\n * The promise resolves after removal according to the supplied options.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rm}\n */\n rm(...args: DropFirstParameters<typeof fsp.rm>) {\n return fsp.rm(this.#value, ...args);\n }\n\n /**\n * Removes the directory at the stored path.\n *\n * @remarks\n * The promise resolves after directory removal.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rmdir}\n */\n rmdir(...args: DropFirstParameters<typeof fsp.rmdir>) {\n return fsp.rmdir(this.#value, ...args);\n }\n\n /**\n * Reads file system metadata for the stored path.\n *\n * @remarks\n * The promise resolves to `Stats`, or `BigIntStats` when `bigint` is enabled.\n * If `throwIfNoEntry` is `false`, a missing path resolves to `undefined` instead of rejecting.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.stat}\n */\n stat(\n opts?: fs.StatOptions & {\n bigint?: false;\n throwIfNoEntry?: true;\n },\n ): Promise<fs.Stats>;\n stat(\n opts: fs.StatOptions & {\n bigint: true;\n throwIfNoEntry?: true;\n },\n ): Promise<fs.BigIntStats>;\n stat(\n opts: fs.StatOptions & {\n bigint?: false;\n throwIfNoEntry: false;\n },\n ): Promise<fs.Stats | undefined>;\n stat(\n opts: fs.StatOptions & {\n bigint: true;\n throwIfNoEntry: false;\n },\n ): Promise<fs.BigIntStats | undefined>;\n stat(opts: fs.StatOptions & { throwIfNoEntry?: true }): Promise<fs.BigIntStats | fs.Stats>;\n stat(opts?: fs.StatOptions): Promise<fs.BigIntStats | fs.Stats | undefined>;\n async stat(opts?: fs.StatOptions): Promise<fs.BigIntStats | fs.Stats | undefined> {\n try {\n return await fsp.stat(this.#value, opts);\n } catch (error) {\n if (\n opts?.throwIfNoEntry === false\n && error instanceof Error\n && 'code' in error\n && error.code === 'ENOENT'\n ) return undefined;\n\n throw error;\n }\n }\n\n /**\n * Truncates or extends the file at the stored path.\n *\n * @remarks\n * The promise resolves when the file reaches the requested length in bytes; the default length is `0`.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.truncate}\n */\n truncate(...args: DropFirstParameters<typeof fsp.truncate>) {\n return fsp.truncate(this.#value, ...args);\n }\n\n /**\n * Deletes the file or symbolic link at the stored path.\n *\n * @remarks\n * The promise resolves after deletion; directories are not removed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.unlink}\n */\n unlink() {\n return fsp.unlink(this.#value);\n }\n\n /**\n * Writes data to the file at the stored path.\n *\n * @remarks\n * The promise resolves when writing completes; the default flag replaces existing file contents.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.writeFile}\n */\n writeFile(...args: DropFirstParameters<typeof fsp.writeFile>) {\n return fsp.writeFile(this.#value, ...args);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAsBA,IAAa,OAAb,MAAa,KAAK;CAEd;;;;;;CASA,YAAY,GAAG,OAAmB;EAC9B,KAAK,SAAS,SAAS,KAAK,GAAG,KAAK,WAAW,KAAK,CAAC;CACzD;CAGA,aAAa,GAAG,OAAmB;EAC/B,OAAO,IAAI,KAAK,GAAG,KAAK;CAC5B;CAEA,WAAW,OAAmB;EAC1B,OAAO,MAAM,KAAK,SAAS,KAAK,SAAS,CAAC;CAC9C;;;;;;CASA,IAAI,SAAS;EACT,OAAO,KAAK,QAAQ;CACxB;;;;CAKA,IAAI,QAAQ;EACR,OAAO,KAAK;CAChB;;;;;;;;;;CAaA,OAAO,OAAO,YAA4C;EACtD,OAAO,IAAI,KAAK,SAAS,OAAO,UAAU,CAAC;CAC/C;;;;;;;;;;;;;;CAeA,OAAO,QAAQ,GAAG,OAAmB;EACjC,OAAO,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,QAAQ;CACtC;CAGA,CAAC,OAAO,IAAI,4BAA4B,KAAK;EACzC,OAAO,KAAK;CAChB;CAEA,CAAC,OAAO,aAAa,MAAc;EAC/B,IAAI,SAAS,UAAU,MAAM,IAAI,UAAU,mCAAmC;EAC9E,OAAO,KAAK;CAChB;;;;;;;;CASA,SAAS,QAAiB;EACtB,OAAO,SAAS,SAAS,KAAK,QAAQ,MAAM;CAChD;;;;;;;;CASA,UAAU;EACN,OAAO,KAAK,aAAa,SAAS,QAAQ,KAAK,MAAM,CAAC;CAC1D;;;;;;;;CASA,UAAU;EACN,OAAO,SAAS,QAAQ,KAAK,MAAM;CACvC;;;;;;;;CASA,aAAa;EACT,OAAO,SAAS,WAAW,KAAK,MAAM;CAC1C;;;;;;;;CASA,YAAY;EACR,OAAO,KAAK,aAAa,SAAS,UAAU,KAAK,MAAM,CAAC;CAC5D;;;;;;;;;;CAWA,KAAK,GAAG,OAAmB;EACvB,OAAO,KAAK,aAAa,KAAK,QAAQ,GAAG,KAAK,WAAW,KAAK,CAAC;CACnE;;;;;;;;CASA,QAAQ;EACJ,OAAO,SAAS,MAAM,KAAK,MAAM;CACrC;;;;;;;;;;CAWA,SAAS,IAAc;EACnB,OAAO,KAAK,aAAa,SAAS,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAC,CAAC;CAC1E;;;;;;;;;;;CAYA,UAAU;EACN,OAAO,KAAK,aAAa,SAAS,QAAQ,KAAK,MAAM,CAAC;CAC1D;CAEA,SAAS;EACL,OAAO,KAAK;CAChB;;;;;;;;;CAUA,mBAAmB;EACf,OAAO,SAAS,iBAAiB,KAAK,MAAM;CAChD;;;;CAKA,WAAW;EACP,OAAO,KAAK;CAChB;;;;;;;;;CAUA,OAAO,GAAG,MAA8C;EACpD,OAAO,IAAI,OAAO,KAAK,QAAQ,GAAG,IAAI;CAC1C;;;;;;;;;CAUA,WAAW,GAAG,MAAkD;EAC5D,OAAO,IAAI,WAAW,KAAK,QAAQ,GAAG,IAAI;CAC9C;;;;;;;;;CAUA,MAAM,GAAG,MAA6C;EAClD,OAAO,IAAI,MAAM,KAAK,QAAQ,GAAG,IAAI;CACzC;;;;;;;;;CAUA,MAAM,GAAG,MAA6C;EAClD,OAAO,IAAI,MAAM,KAAK,QAAQ,GAAG,IAAI;CACzC;;;;;;;;;CAUA,SAAS,GAAG,MAAgD;EACxD,OAAO,IAAI,SAAS,KAAK,QAAQ,GAAG,IAAI;CAC5C;CAmBA,MAAM,GAAG,MAAgB;EACrB,OAAO,IAAI,MAAM,KAAK,QAAQ,GAAG,IAAI;CACzC;;;;;;;;;CAUA,KAAK,GAAG,MAA4C;EAChD,OAAO,IAAI,KAAK,KAAK,QAAQ,GAAG,IAAI;CACxC;CAkDA,QAAQ,GAAG,MAAgB;EACvB,OAAO,IAAI,QAAQ,KAAK,QAAQ,GAAG,IAAI;CAC3C;CAoCA,SAAS,GAAG,MAAgB;EACxB,OAAO,IAAI,SAAS,KAAK,QAAQ,GAAG,IAAI;CAC5C;;;;;;;;;;;CAYA,OAAO,SAAmB;EACtB,OAAO,IAAI,OAAO,KAAK,QAAQ,QAAQ,SAAS,CAAC;CACrD;;;;;;;;;CAUA,GAAG,GAAG,MAA0C;EAC5C,OAAO,IAAI,GAAG,KAAK,QAAQ,GAAG,IAAI;CACtC;;;;;;;;;CAUA,MAAM,GAAG,MAA6C;EAClD,OAAO,IAAI,MAAM,KAAK,QAAQ,GAAG,IAAI;CACzC;CAqCA,MAAM,KAAK,MAAuE;EAC9E,IAAI;GACA,OAAO,MAAM,IAAI,KAAK,KAAK,QAAQ,IAAI;EAC3C,SAAS,OAAO;GACZ,IACI,MAAM,mBAAmB,SACtB,iBAAiB,SACjB,UAAU,SACV,MAAM,SAAS,UACpB,OAAO,KAAA;GAET,MAAM;EACV;CACJ;;;;;;;;;CAUA,SAAS,GAAG,MAAgD;EACxD,OAAO,IAAI,SAAS,KAAK,QAAQ,GAAG,IAAI;CAC5C;;;;;;;;;CAUA,SAAS;EACL,OAAO,IAAI,OAAO,KAAK,MAAM;CACjC;;;;;;;;;CAUA,UAAU,GAAG,MAAiD;EAC1D,OAAO,IAAI,UAAU,KAAK,QAAQ,GAAG,IAAI;CAC7C;AACJ"}
|
|
1
|
+
{"version":3,"file":"path.js","names":[],"sources":["../../src/classes/path.ts"],"sourcesContent":["import type { Buffer } from 'node:buffer';\nimport type { Abortable } from 'node:events';\nimport type * as fs from 'node:fs';\nimport * as fsp from 'node:fs/promises';\nimport * as nodePath from 'node:path';\n\ntype DropFirstParameters<T extends (...args: any) => any> = Parameters<T> extends [any, ...infer R] ? R : never;\n\n/**\n * Values accepted by the `Path` constructor and path-composition methods.\n */\nexport type PathLike = fs.PathLike | Path;\n\n/**\n * An immutable file system path with Node.js path and file operations.\n *\n * @remarks\n * Path-composition methods return new instances and leave this instance unchanged.\n * File operations act on the stored path and forward Node.js defaults and promise rejections.\n * They do not update the stored path, including after a successful rename.\n * The constructor joins stringified inputs using the platform-specific Node.js path rules.\n */\nexport class Path {\n // Private instance properties\n readonly #value: string;\n\n // Constructor\n\n /**\n * Creates a normalized path value by joining the provided path segments.\n *\n * @param paths - Path segments accepted by Node.js `path.join` or another `Path` instance.\n */\n constructor(...paths: PathLike[]) {\n this.#value = nodePath.join(...this.#toStrings(paths));\n }\n\n // Private instance methods\n #newInstance(...paths: PathLike[]) {\n return new Path(...paths);\n }\n\n #toStrings(paths: PathLike[]) {\n return paths.map((path) => path.toString());\n }\n\n // Public instance accessors\n\n /**\n * The parent directory as a new `Path`; this instance is unchanged.\n *\n * @see {@link Path.dirname}\n */\n get parent() {\n return this.dirname();\n }\n\n /**\n * The normalized path string stored by this instance.\n */\n get value() {\n return this.#value;\n }\n\n // Public static methods\n\n /**\n * Creates a new path from a Node.js path object.\n *\n * @param pathObject - The path components to format.\n *\n * @returns A new normalized `Path`.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.format}\n */\n static format(pathObject: nodePath.FormatInputPathObject) {\n return new Path(nodePath.format(pathObject));\n }\n\n /**\n * Resolves joined path segments to an absolute path.\n *\n * @remarks\n * Inputs are joined before resolution; unlike Node.js `path.resolve`,\n * later absolute segments do not reset the path.\n *\n * @param paths - The stringified path segments to join.\n *\n * @returns A new absolute `Path`.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.resolve}\n */\n static resolve(...paths: PathLike[]) {\n return new this(...paths).resolve();\n }\n\n // Public instance methods\n [Symbol.for('nodejs.util.inspect.custom')]() {\n return this.#value;\n }\n\n [Symbol.toPrimitive](hint: string) {\n if (hint === 'number') throw new TypeError('Cannot convert a Path to a number');\n return this.#value;\n }\n\n /**\n * Returns the final component of this path.\n *\n * @param suffix - An optional exact suffix to remove.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.basename}\n */\n basename(suffix?: string) {\n return nodePath.basename(this.#value, suffix);\n }\n\n /**\n * Returns the parent directory of this path.\n *\n * @returns A new `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.dirname}\n */\n dirname() {\n return this.#newInstance(nodePath.dirname(this.#value));\n }\n\n /**\n * Returns the extension of the final path component.\n *\n * @returns The extension including its leading dot, or an empty string when absent.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.extname}\n */\n extname() {\n return nodePath.extname(this.#value);\n }\n\n /**\n * Checks whether this path is absolute on the current platform.\n *\n * @returns Whether this path is absolute.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.isAbsolute}\n */\n isAbsolute() {\n return nodePath.isAbsolute(this.#value);\n }\n\n /**\n * Normalizes separators and relative segments in this path.\n *\n * @returns A new `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.normalize}\n */\n normalize() {\n return this.#newInstance(nodePath.normalize(this.#value));\n }\n\n /**\n * Joins additional segments onto this path.\n *\n * @param paths - The stringified path segments to append.\n *\n * @returns A new normalized `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.join}\n */\n join(...paths: PathLike[]) {\n return this.#newInstance(this.#value, ...this.#toStrings(paths));\n }\n\n /**\n * Parses this path into its root, directory, basename, extension, and name.\n *\n * @returns A new object containing the path components.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.parse}\n */\n parse() {\n return nodePath.parse(this.#value);\n }\n\n /**\n * Computes a relative path from this path to the destination.\n *\n * @param to - The destination path.\n *\n * @returns A new `Path`; this instance is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.relative}\n */\n relative(to: PathLike) {\n return this.#newInstance(nodePath.relative(this.#value, to.toString()));\n }\n\n /**\n * Resolves this path to an absolute path using the current working directory.\n *\n * @remarks\n * Relative paths use the current working directory. This instance is unchanged.\n *\n * @returns A new absolute `Path`.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.resolve}\n */\n resolve() {\n return this.#newInstance(nodePath.resolve(this.#value));\n }\n\n toJSON() {\n return this.#value;\n }\n\n /**\n * Converts this path to the Windows namespace form when applicable.\n *\n * @returns The namespace-converted path string; this instance is unchanged.\n * On non-Windows platforms, the path text is unchanged.\n *\n * @see {@link https://nodejs.org/api/path.html | Node.js path.toNamespacedPath}\n */\n toNamespacedPath() {\n return nodePath.toNamespacedPath(this.#value);\n }\n\n /**\n * Returns the stored path as a string.\n */\n toString() {\n return this.#value;\n }\n\n /**\n * Checks access permissions for the stored path.\n *\n * @remarks\n * The promise resolves when the access check succeeds and rejects if access is denied or the path is missing.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.access}\n */\n async access(...args: DropFirstParameters<typeof fsp.access>) {\n return await fsp.access(this.#value, ...args);\n }\n\n /**\n * Appends data to the file at the stored path.\n *\n * @remarks\n * The promise resolves when appending completes; a missing file is created according to the supplied options.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.appendFile}\n */\n async appendFile(...args: DropFirstParameters<typeof fsp.appendFile>) {\n return await fsp.appendFile(this.#value, ...args);\n }\n\n /**\n * Changes the permissions of the stored path.\n *\n * @remarks\n * The promise resolves when the permissions are changed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chmod}\n */\n async chmod(...args: DropFirstParameters<typeof fsp.chmod>) {\n return await fsp.chmod(this.#value, ...args);\n }\n\n /**\n * Changes the owner and group of the stored path.\n *\n * @remarks\n * The promise resolves when the ownership is changed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.chown}\n */\n async chown(...args: DropFirstParameters<typeof fsp.chown>) {\n return await fsp.chown(this.#value, ...args);\n }\n\n /**\n * Copies the file at the stored path to a destination.\n *\n * @remarks\n * The promise resolves when copying completes. The stored path remains the source path.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.copyFile}\n */\n async copyFile(...args: DropFirstParameters<typeof fsp.copyFile>) {\n return await fsp.copyFile(this.#value, ...args);\n }\n\n /**\n * Creates a directory at the stored path.\n *\n * @remarks\n * The promise resolves after creation. Recursive mode resolves to the first created directory path, or\n * `undefined` if no directory is created; nonrecursive mode resolves without a value.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.mkdir}\n */\n mkdir(options: fs.MakeDirectoryOptions & { recursive: true }): Promise<string | undefined>;\n mkdir(\n options?:\n | (fs.MakeDirectoryOptions & { recursive?: false })\n | fs.Mode\n | null,\n ): Promise<void>;\n mkdir(options?: fs.MakeDirectoryOptions | fs.Mode | null): Promise<string | undefined>;\n async mkdir(...args: any): Promise<any> {\n return await fsp.mkdir(this.#value, ...args);\n }\n\n /**\n * Opens the file at the stored path.\n *\n * @remarks\n * The promise resolves to a new file handle. The caller must close the handle when it is no longer needed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.open}\n */\n async open(...args: DropFirstParameters<typeof fsp.open>) {\n return await fsp.open(this.#value, ...args);\n }\n\n /**\n * Reads the entries of the directory at the stored path.\n *\n * @remarks\n * The promise resolves to names, buffers, or directory entries according to the options.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.readdir}\n */\n readdir(\n options?:\n | BufferEncoding\n | (fs.ObjectEncodingOptions & {\n recursive?: boolean;\n withFileTypes?: false;\n })\n | null,\n ): Promise<string[]>;\n readdir(\n options:\n | 'buffer'\n | {\n encoding: 'buffer';\n recursive?: boolean;\n withFileTypes?: false;\n },\n ): Promise<Buffer[]>;\n readdir(\n options?:\n | BufferEncoding\n | (fs.ObjectEncodingOptions & {\n recursive?: boolean;\n withFileTypes?: false;\n })\n | null,\n ): Promise<Buffer[] | string[]>;\n readdir(\n options: fs.ObjectEncodingOptions & {\n recursive?: boolean;\n withFileTypes: true;\n },\n ): Promise<fs.Dirent[]>;\n readdir(\n options: {\n encoding: 'buffer';\n recursive?: boolean;\n withFileTypes: true;\n },\n ): Promise<Array<fs.Dirent<Buffer>>>;\n async readdir(...args: any): Promise<any> {\n return await fsp.readdir(this.#value, ...args);\n }\n\n /**\n * Reads the entire file at the stored path.\n *\n * @remarks\n * The promise resolves to a string when a text encoding is supplied, or a `Buffer` otherwise.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.readFile}\n */\n readFile(\n options?:\n | (Abortable & {\n encoding?: null;\n flag?: fs.OpenMode;\n })\n | null,\n ): Promise<Buffer>;\n readFile(\n options:\n | (Abortable & {\n encoding: BufferEncoding;\n flag?: fs.OpenMode;\n })\n | BufferEncoding,\n ): Promise<string>;\n readFile(\n options?:\n | (\n & Abortable\n & fs.ObjectEncodingOptions\n & { flag?: fs.OpenMode }\n )\n | BufferEncoding\n | null,\n ): Promise<Buffer | string>;\n async readFile(...args: any): Promise<any> {\n return await fsp.readFile(this.#value, ...args);\n }\n\n /**\n * Renames or moves the file or directory at the stored path.\n *\n * @remarks\n * The promise resolves when the rename completes. This instance retains its original stored path.\n *\n * @param newPath - The destination path; this instance retains its original value.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rename}\n */\n async rename(newPath: PathLike) {\n return await fsp.rename(this.#value, newPath.toString());\n }\n\n /**\n * Removes the file or directory at the stored path.\n *\n * @remarks\n * The promise resolves after removal according to the supplied options.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rm}\n */\n async rm(...args: DropFirstParameters<typeof fsp.rm>) {\n return await fsp.rm(this.#value, ...args);\n }\n\n /**\n * Removes the directory at the stored path.\n *\n * @remarks\n * The promise resolves after directory removal.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.rmdir}\n */\n async rmdir(...args: DropFirstParameters<typeof fsp.rmdir>) {\n return await fsp.rmdir(this.#value, ...args);\n }\n\n /**\n * Reads file system metadata for the stored path.\n *\n * @remarks\n * The promise resolves to `Stats`, or `BigIntStats` when `bigint` is enabled.\n * If `throwIfNoEntry` is `false`, a missing path resolves to `undefined` instead of rejecting.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.stat}\n */\n stat(\n opts?: fs.StatOptions & {\n bigint?: false;\n throwIfNoEntry?: true;\n },\n ): Promise<fs.Stats>;\n stat(\n opts: fs.StatOptions & {\n bigint: true;\n throwIfNoEntry?: true;\n },\n ): Promise<fs.BigIntStats>;\n stat(\n opts: fs.StatOptions & {\n bigint?: false;\n throwIfNoEntry: false;\n },\n ): Promise<fs.Stats | undefined>;\n stat(\n opts: fs.StatOptions & {\n bigint: true;\n throwIfNoEntry: false;\n },\n ): Promise<fs.BigIntStats | undefined>;\n stat(opts: fs.StatOptions & { throwIfNoEntry?: true }): Promise<fs.BigIntStats | fs.Stats>;\n stat(opts?: fs.StatOptions): Promise<fs.BigIntStats | fs.Stats | undefined>;\n async stat(opts?: fs.StatOptions): Promise<fs.BigIntStats | fs.Stats | undefined> {\n try {\n return await fsp.stat(this.#value, opts);\n } catch (error) {\n if (\n opts?.throwIfNoEntry === false\n && error instanceof Error\n && 'code' in error\n && error.code === 'ENOENT'\n ) return undefined;\n\n throw error;\n }\n }\n\n /**\n * Truncates or extends the file at the stored path.\n *\n * @remarks\n * The promise resolves when the file reaches the requested length in bytes; the default length is `0`.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.truncate}\n */\n async truncate(...args: DropFirstParameters<typeof fsp.truncate>) {\n return await fsp.truncate(this.#value, ...args);\n }\n\n /**\n * Deletes the file or symbolic link at the stored path.\n *\n * @remarks\n * The promise resolves after deletion; directories are not removed.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.unlink}\n */\n async unlink() {\n return await fsp.unlink(this.#value);\n }\n\n /**\n * Writes data to the file at the stored path.\n *\n * @remarks\n * The promise resolves when writing completes; the default flag replaces existing file contents.\n *\n * @see {@link https://nodejs.org/api/fs.html | Node.js fsPromises.writeFile}\n */\n async writeFile(...args: DropFirstParameters<typeof fsp.writeFile>) {\n return await fsp.writeFile(this.#value, ...args);\n }\n}\n"],"mappings":"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"}
|
package/dist/enum.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ValueOf } from "type-fest";
|
|
1
2
|
/**
|
|
2
3
|
* Extracts only the numeric values from an enumeration-like object.
|
|
3
4
|
*
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
* console.log(getEnumNumberValues(RecordType)); // => [0, 1]
|
|
23
24
|
* ```
|
|
24
25
|
*/
|
|
25
|
-
export declare function getEnumNumberValues<T extends Record<string, any>>(enumObject: T): Array<Extract<T
|
|
26
|
+
export declare function getEnumNumberValues<T extends Record<string, any>>(enumObject: T): Array<Extract<ValueOf<T>, number>>;
|
|
26
27
|
/**
|
|
27
28
|
* Extracts only the string values from an enumeration-like object.
|
|
28
29
|
*
|
|
@@ -47,7 +48,7 @@ export declare function getEnumNumberValues<T extends Record<string, any>>(enumO
|
|
|
47
48
|
* console.log(getEnumStringValues(RecordType)); // => ['unknown']
|
|
48
49
|
* ```
|
|
49
50
|
*/
|
|
50
|
-
export declare function getEnumStringValues<T extends Record<string, any>>(enumObject: T): Array<Extract<T
|
|
51
|
+
export declare function getEnumStringValues<T extends Record<string, any>>(enumObject: T): Array<Extract<ValueOf<T>, string>>;
|
|
51
52
|
/**
|
|
52
53
|
* Extracts all values from an enumeration-like object.
|
|
53
54
|
*
|
|
@@ -96,5 +97,5 @@ export declare function getEnumStringValues<T extends Record<string, any>>(enumO
|
|
|
96
97
|
* console.log(getEnumValues(RecordType)); // => [0, 1, 'unknown']
|
|
97
98
|
* ```
|
|
98
99
|
*/
|
|
99
|
-
export declare function getEnumValues<T extends Record<string, any>>(enumObject: T): Array<T
|
|
100
|
+
export declare function getEnumValues<T extends Record<string, any>>(enumObject: T): Array<ValueOf<T>>;
|
|
100
101
|
//# sourceMappingURL=enum.d.ts.map
|
package/dist/enum.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enum.d.ts","names":[],"sources":["../src/enum.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"enum.d.ts","names":[],"sources":["../src/enum.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;wBA8BgB,oBAAoB,UAAU,qBAAqB,YAAY,IAAI,MAAM,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;wBA4BzF,oBAAoB,UAAU,qBAAqB,YAAY,IAAI,MAAM,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAoDzF,cAAc,UAAU,qBAAqB,YAAY,IAAI,MAAM,QAAQ"}
|
package/dist/enum.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { objectKeys, objectValues } from "ts-extras";
|
|
1
2
|
// src/enum.ts
|
|
2
3
|
/**
|
|
3
4
|
* Extracts only the numeric values from an enumeration-like object.
|
|
@@ -102,9 +103,9 @@ function getEnumStringValues(enumObject) {
|
|
|
102
103
|
* ```
|
|
103
104
|
*/
|
|
104
105
|
function getEnumValues(enumObject) {
|
|
105
|
-
const values =
|
|
106
|
+
const values = objectValues(enumObject);
|
|
106
107
|
if (!values.some((value) => typeof value === "number")) return values;
|
|
107
|
-
return
|
|
108
|
+
return objectKeys(enumObject).filter((key) => Number.isNaN(Number(key))).map((key) => enumObject[key]);
|
|
108
109
|
}
|
|
109
110
|
export { getEnumNumberValues, getEnumStringValues, getEnumValues };
|
|
110
111
|
|
package/dist/enum.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enum.js","names":[],"sources":["../src/enum.ts"],"sourcesContent":["/**\n * Extracts only the numeric values from an enumeration-like object.\n *\n * @typeParam T - The type of the enum object.\n *\n * @param enumObject - The enumeration-like object to extract numeric values from,\n * the object can contain numeric values, string values, or both.\n *\n * @returns An array of numeric values extracted from the enum object.\n *\n * @example\n *\n * ```ts\n * import { getEnumNumberValues } from '@kikiutils/shared/enum';\n *\n * enum RecordType {\n * Receive = 0,\n * Send = 1,\n * Unknown = 'unknown',\n * }\n *\n * console.log(getEnumNumberValues(RecordType)); // => [0, 1]\n * ```\n */\nexport function getEnumNumberValues<T extends Record<string, any>>(enumObject: T): Array<Extract<T
|
|
1
|
+
{"version":3,"file":"enum.js","names":[],"sources":["../src/enum.ts"],"sourcesContent":["import {\n objectKeys,\n objectValues,\n} from 'ts-extras';\nimport type { ValueOf } from 'type-fest';\n\n/**\n * Extracts only the numeric values from an enumeration-like object.\n *\n * @typeParam T - The type of the enum object.\n *\n * @param enumObject - The enumeration-like object to extract numeric values from,\n * the object can contain numeric values, string values, or both.\n *\n * @returns An array of numeric values extracted from the enum object.\n *\n * @example\n *\n * ```ts\n * import { getEnumNumberValues } from '@kikiutils/shared/enum';\n *\n * enum RecordType {\n * Receive = 0,\n * Send = 1,\n * Unknown = 'unknown',\n * }\n *\n * console.log(getEnumNumberValues(RecordType)); // => [0, 1]\n * ```\n */\nexport function getEnumNumberValues<T extends Record<string, any>>(enumObject: T): Array<Extract<ValueOf<T>, number>> {\n return getEnumValues(enumObject).filter((value) => typeof value === 'number');\n}\n\n/**\n * Extracts only the string values from an enumeration-like object.\n *\n * @typeParam T - The type of the enum object.\n *\n * @param enumObject - The enumeration-like object to extract string values from,\n * the object can contain numeric values, string values, or both.\n *\n * @returns An array of string values extracted from the enum object.\n *\n * @example\n *\n * ```ts\n * import { getEnumStringValues } from '@kikiutils/shared/enum';\n *\n * enum RecordType {\n * Receive = 0,\n * Send = 1,\n * Unknown = 'unknown',\n * }\n *\n * console.log(getEnumStringValues(RecordType)); // => ['unknown']\n * ```\n */\nexport function getEnumStringValues<T extends Record<string, any>>(enumObject: T): Array<Extract<ValueOf<T>, string>> {\n return getEnumValues(enumObject).filter((value) => typeof value === 'string');\n}\n\n/**\n * Extracts all values from an enumeration-like object.\n *\n * @remarks\n * This function handles TypeScript enums correctly by accounting for the reverse mapping\n * that occurs with numeric enums. It works with pure numeric enums, pure string enums,\n * and mixed enums.\n *\n * @typeParam T - The type of the enum object.\n *\n * @param enumObject - The enumeration-like object to extract values from,\n * the object can contain numeric values, string values, or both.\n *\n * @returns An array containing all the values from the enum object.\n *\n * @example\n *\n * ```ts\n * import { getEnumValues } from '@kikiutils/shared/enum';\n *\n * // Numeric enum\n * enum Status {\n * Active = 0,\n * Inactive = 1,\n * Pending = 2,\n * }\n *\n * console.log(getEnumValues(Status)); // => [0, 1, 2]\n *\n * // String enum\n * enum Color {\n * Red = 'RED',\n * Green = 'GREEN',\n * Blue = 'BLUE',\n * }\n *\n * console.log(getEnumValues(Color)); // => ['RED', 'GREEN', 'BLUE']\n *\n * // Mixed enum\n * enum RecordType {\n * Receive = 0,\n * Send = 1,\n * Unknown = 'unknown',\n * }\n *\n * console.log(getEnumValues(RecordType)); // => [0, 1, 'unknown']\n * ```\n */\nexport function getEnumValues<T extends Record<string, any>>(enumObject: T): Array<ValueOf<T>> {\n const values = objectValues(enumObject);\n const hasNumberValues = values.some((value) => typeof value === 'number');\n if (!hasNumberValues) return values;\n return objectKeys(enumObject).filter((key) => Number.isNaN(Number(key))).map((key) => enumObject[key]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,oBAAmD,YAAmD;CAClH,OAAO,cAAc,UAAU,CAAC,CAAC,QAAQ,UAAU,OAAO,UAAU,QAAQ;AAChF;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,oBAAmD,YAAmD;CAClH,OAAO,cAAc,UAAU,CAAC,CAAC,QAAQ,UAAU,OAAO,UAAU,QAAQ;AAChF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,SAAgB,cAA6C,YAAkC;CAC3F,MAAM,SAAS,aAAa,UAAU;CAEtC,IAAI,CADoB,OAAO,MAAM,UAAU,OAAO,UAAU,QAC7C,GAAG,OAAO;CAC7B,OAAO,WAAW,UAAU,CAAC,CAAC,QAAQ,QAAQ,OAAO,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,WAAW,IAAI;AACzG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-awaiter.d.ts","names":[],"sources":["../src/event-awaiter.ts"],"mappings":";;;;;;;;;;;qBAWa,aAAa;;;;;;;;EAYtB,QAAQ,aAAa,OAAO;;;;;;EAa5B,WAAW,QAAO;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"event-awaiter.d.ts","names":[],"sources":["../src/event-awaiter.ts"],"mappings":";;;;;;;;;;;qBAWa,aAAa;;;;;;;;EAYtB,QAAQ,aAAa,OAAO;;;;;;EAa5B,WAAW,QAAO;;;;;;;;;;;;;;;;;;;;EAwBZ,KAAK,aAAa,oBAAoB,8BAA8B,SAAS,cAAW,QAAA;;;;;;;;;;;;;;EAgExF,cAAc,aAAa,oBAAoB,SAAS,cAAW,QAAA;;;;;;;;;;;;;;;EAkBnE,WAAW,aAAa,oBAAoB,SAAS,cAAW,QAAA"}
|
package/dist/event-awaiter.js
CHANGED
|
@@ -53,8 +53,8 @@ var EventAwaiter = class {
|
|
|
53
53
|
*
|
|
54
54
|
* @throws Error through promise rejection if `strict` mode encounters an existing waiter.
|
|
55
55
|
*/
|
|
56
|
-
wait(key, timeoutMs, mode, signal) {
|
|
57
|
-
return new Promise((resolve) => {
|
|
56
|
+
async wait(key, timeoutMs, mode, signal) {
|
|
57
|
+
return await new Promise((resolve) => {
|
|
58
58
|
const resolvers = this.#promiseResolvers.get(key) || [];
|
|
59
59
|
if (resolvers.length) switch (mode) {
|
|
60
60
|
case "override":
|
|
@@ -99,8 +99,8 @@ var EventAwaiter = class {
|
|
|
99
99
|
*
|
|
100
100
|
* @see {@link EventAwaiter.wait}
|
|
101
101
|
*/
|
|
102
|
-
waitExclusive(key, timeoutMs, signal) {
|
|
103
|
-
return this.wait(key, timeoutMs, "strict", signal);
|
|
102
|
+
async waitExclusive(key, timeoutMs, signal) {
|
|
103
|
+
return await this.wait(key, timeoutMs, "strict", signal);
|
|
104
104
|
}
|
|
105
105
|
/**
|
|
106
106
|
* Replaces existing waiters for a key and waits for its next trigger.
|
|
@@ -116,8 +116,8 @@ var EventAwaiter = class {
|
|
|
116
116
|
*
|
|
117
117
|
* @see {@link EventAwaiter.wait}
|
|
118
118
|
*/
|
|
119
|
-
waitLatest(key, timeoutMs, signal) {
|
|
120
|
-
return this.wait(key, timeoutMs, "override", signal);
|
|
119
|
+
async waitLatest(key, timeoutMs, signal) {
|
|
120
|
+
return await this.wait(key, timeoutMs, "override", signal);
|
|
121
121
|
}
|
|
122
122
|
};
|
|
123
123
|
export { EventAwaiter };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-awaiter.js","names":[],"sources":["../src/event-awaiter.ts"],"sourcesContent":["/**\n * An asynchronous keyed event rendezvous for one or more waiting consumers.\n *\n * @remarks\n * Triggers resolve the currently registered waiters; values are not retained for future waits.\n * Timeouts and subsequent abort events resolve affected waiters with `undefined`.\n * Use `triggerAll` to resolve pending waits during cleanup. Timers and abort listeners are not proactively\n * removed by triggers, so they may remain until their timeout or abort event occurs.\n *\n * @typeParam T - The value delivered to waiting consumers.\n */\nexport class EventAwaiter<T> {\n // Private instance properties\n #promiseResolvers = new Map<string, Array<(value: PromiseLike<T | undefined> | T | undefined) => void>>();\n\n // Public instance methods\n\n /**\n * Resolves all currently pending waits for a key with the supplied value.\n *\n * @param key - The event identifier; a key without pending waits has no effect.\n * @param value - The delivered value; `undefined` indicates no result.\n */\n trigger(key: string, value: T | undefined) {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers) {\n this.#promiseResolvers.delete(key);\n resolvers?.forEach((resolve) => resolve(value));\n }\n }\n\n /**\n * Resolves all currently pending waits and clears their registrations.\n *\n * @param value - The delivered value; omission resolves all pending waits with `undefined`.\n */\n triggerAll(value: T | undefined = undefined) {\n for (const [_, resolvers] of this.#promiseResolvers.entries()) resolvers.forEach((resolve) => resolve(value));\n this.#promiseResolvers.clear();\n }\n\n /**\n * Waits for a trigger associated with a key.\n *\n * @remarks\n * By default, multiple waiters share a key and all receive the next trigger value.\n * `strict` mode rejects duplicate waits; `override` mode resolves existing waits with `undefined` before\n * registering the new wait. Timeout and abort remove only the affected waiter's registration.\n * An already aborted signal is not checked; only an abort event emitted after registration ends the wait.\n * Without a timeout or subsequent abort, the wait remains pending until a trigger arrives.\n *\n * @param key - The event identifier to wait for.\n * @param timeoutMs - The optional timeout in milliseconds, using native `setTimeout` timing rules.\n * @param mode - The policy for existing waiters; omission allows multiple waiters.\n * @param signal - A signal whose subsequent abort event ends this wait.\n *\n * @returns A promise resolving to the triggered value, or `undefined` after timeout, abort, or replacement.\n *\n * @throws Error through promise rejection if `strict` mode encounters an existing waiter.\n */\n wait(key: string, timeoutMs?: number, mode?: 'override' | 'strict', signal?: AbortSignal) {\n return new Promise<T | undefined>((resolve) => {\n const resolvers = this.#promiseResolvers.get(key) || [];\n if (resolvers.length) {\n switch (mode) {\n case 'override':\n resolvers.forEach((r) => r(undefined));\n resolvers.length = 0;\n break;\n case 'strict':\n throw new Error(`Duplicate wait detected for key: ${key}`);\n case undefined:\n break;\n }\n }\n\n resolvers.push(resolve);\n this.#promiseResolvers.set(key, resolvers);\n if (timeoutMs != null) {\n setTimeout(\n () => {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers?.includes(resolve)) {\n resolve(undefined);\n const newResolvers = resolvers.filter((r) => r !== resolve);\n if (newResolvers.length) this.#promiseResolvers.set(key, newResolvers);\n else this.#promiseResolvers.delete(key);\n }\n },\n timeoutMs,\n );\n }\n\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers?.includes(resolve)) {\n resolve(undefined);\n const newResolvers = resolvers.filter((r) => r !== resolve);\n if (newResolvers.length) this.#promiseResolvers.set(key, newResolvers);\n else this.#promiseResolvers.delete(key);\n }\n },\n { once: true },\n );\n }\n });\n }\n\n /**\n * Waits for a key while rejecting duplicate registrations.\n *\n * @param key - The event identifier to wait for.\n * @param timeoutMs - The optional timeout in milliseconds.\n * @param signal - A signal whose subsequent abort event ends this wait; an already aborted signal is not checked.\n *\n * @returns A promise resolving to the triggered value, or `undefined` on timeout or subsequent abort.\n *\n * @throws Error through promise rejection if the key already has a pending waiter.\n *\n * @see {@link EventAwaiter.wait}\n */\n waitExclusive(key: string, timeoutMs?: number, signal?: AbortSignal) {\n return this.wait(key, timeoutMs, 'strict', signal);\n }\n\n /**\n * Replaces existing waiters for a key and waits for its next trigger.\n *\n * @remarks\n * Existing waiters resolve with `undefined` before the new waiter is registered.\n *\n * @param key - The event identifier to wait for.\n * @param timeoutMs - The optional timeout in milliseconds.\n * @param signal - A signal whose subsequent abort event ends this wait; an already aborted signal is not checked.\n *\n * @returns A promise resolving to the triggered value, or `undefined` on timeout, subsequent abort, or replacement.\n *\n * @see {@link EventAwaiter.wait}\n */\n waitLatest(key: string, timeoutMs?: number, signal?: AbortSignal) {\n return this.wait(key, timeoutMs, 'override', signal);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAa,eAAb,MAA6B;CAEzB,oCAAoB,IAAI,IAAgF;;;;;;;CAUxG,QAAQ,KAAa,OAAsB;EACvC,MAAM,YAAY,KAAK,kBAAkB,IAAI,GAAG;EAChD,IAAI,WAAW;GACX,KAAK,kBAAkB,OAAO,GAAG;GACjC,WAAW,SAAS,YAAY,QAAQ,KAAK,CAAC;EAClD;CACJ;;;;;;CAOA,WAAW,QAAuB,KAAA,GAAW;EACzC,KAAK,MAAM,CAAC,GAAG,cAAc,KAAK,kBAAkB,QAAQ,GAAG,UAAU,SAAS,YAAY,QAAQ,KAAK,CAAC;EAC5G,KAAK,kBAAkB,MAAM;CACjC;;;;;;;;;;;;;;;;;;;;CAqBA,KAAK,KAAa,WAAoB,MAA8B,QAAsB;
|
|
1
|
+
{"version":3,"file":"event-awaiter.js","names":[],"sources":["../src/event-awaiter.ts"],"sourcesContent":["/**\n * An asynchronous keyed event rendezvous for one or more waiting consumers.\n *\n * @remarks\n * Triggers resolve the currently registered waiters; values are not retained for future waits.\n * Timeouts and subsequent abort events resolve affected waiters with `undefined`.\n * Use `triggerAll` to resolve pending waits during cleanup. Timers and abort listeners are not proactively\n * removed by triggers, so they may remain until their timeout or abort event occurs.\n *\n * @typeParam T - The value delivered to waiting consumers.\n */\nexport class EventAwaiter<T> {\n // Private instance properties\n #promiseResolvers = new Map<string, Array<(value: PromiseLike<T | undefined> | T | undefined) => void>>();\n\n // Public instance methods\n\n /**\n * Resolves all currently pending waits for a key with the supplied value.\n *\n * @param key - The event identifier; a key without pending waits has no effect.\n * @param value - The delivered value; `undefined` indicates no result.\n */\n trigger(key: string, value: T | undefined) {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers) {\n this.#promiseResolvers.delete(key);\n resolvers?.forEach((resolve) => resolve(value));\n }\n }\n\n /**\n * Resolves all currently pending waits and clears their registrations.\n *\n * @param value - The delivered value; omission resolves all pending waits with `undefined`.\n */\n triggerAll(value: T | undefined = undefined) {\n for (const [_, resolvers] of this.#promiseResolvers.entries()) resolvers.forEach((resolve) => resolve(value));\n this.#promiseResolvers.clear();\n }\n\n /**\n * Waits for a trigger associated with a key.\n *\n * @remarks\n * By default, multiple waiters share a key and all receive the next trigger value.\n * `strict` mode rejects duplicate waits; `override` mode resolves existing waits with `undefined` before\n * registering the new wait. Timeout and abort remove only the affected waiter's registration.\n * An already aborted signal is not checked; only an abort event emitted after registration ends the wait.\n * Without a timeout or subsequent abort, the wait remains pending until a trigger arrives.\n *\n * @param key - The event identifier to wait for.\n * @param timeoutMs - The optional timeout in milliseconds, using native `setTimeout` timing rules.\n * @param mode - The policy for existing waiters; omission allows multiple waiters.\n * @param signal - A signal whose subsequent abort event ends this wait.\n *\n * @returns A promise resolving to the triggered value, or `undefined` after timeout, abort, or replacement.\n *\n * @throws Error through promise rejection if `strict` mode encounters an existing waiter.\n */\n async wait(key: string, timeoutMs?: number, mode?: 'override' | 'strict', signal?: AbortSignal) {\n return await new Promise<T | undefined>((resolve) => {\n const resolvers = this.#promiseResolvers.get(key) || [];\n if (resolvers.length) {\n switch (mode) {\n case 'override':\n resolvers.forEach((r) => r(undefined));\n resolvers.length = 0;\n break;\n case 'strict':\n throw new Error(`Duplicate wait detected for key: ${key}`);\n case undefined:\n break;\n }\n }\n\n resolvers.push(resolve);\n this.#promiseResolvers.set(key, resolvers);\n if (timeoutMs != null) {\n setTimeout(\n () => {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers?.includes(resolve)) {\n resolve(undefined);\n const newResolvers = resolvers.filter((r) => r !== resolve);\n if (newResolvers.length) this.#promiseResolvers.set(key, newResolvers);\n else this.#promiseResolvers.delete(key);\n }\n },\n timeoutMs,\n );\n }\n\n if (signal) {\n signal.addEventListener(\n 'abort',\n () => {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers?.includes(resolve)) {\n resolve(undefined);\n const newResolvers = resolvers.filter((r) => r !== resolve);\n if (newResolvers.length) this.#promiseResolvers.set(key, newResolvers);\n else this.#promiseResolvers.delete(key);\n }\n },\n { once: true },\n );\n }\n });\n }\n\n /**\n * Waits for a key while rejecting duplicate registrations.\n *\n * @param key - The event identifier to wait for.\n * @param timeoutMs - The optional timeout in milliseconds.\n * @param signal - A signal whose subsequent abort event ends this wait; an already aborted signal is not checked.\n *\n * @returns A promise resolving to the triggered value, or `undefined` on timeout or subsequent abort.\n *\n * @throws Error through promise rejection if the key already has a pending waiter.\n *\n * @see {@link EventAwaiter.wait}\n */\n async waitExclusive(key: string, timeoutMs?: number, signal?: AbortSignal) {\n return await this.wait(key, timeoutMs, 'strict', signal);\n }\n\n /**\n * Replaces existing waiters for a key and waits for its next trigger.\n *\n * @remarks\n * Existing waiters resolve with `undefined` before the new waiter is registered.\n *\n * @param key - The event identifier to wait for.\n * @param timeoutMs - The optional timeout in milliseconds.\n * @param signal - A signal whose subsequent abort event ends this wait; an already aborted signal is not checked.\n *\n * @returns A promise resolving to the triggered value, or `undefined` on timeout, subsequent abort, or replacement.\n *\n * @see {@link EventAwaiter.wait}\n */\n async waitLatest(key: string, timeoutMs?: number, signal?: AbortSignal) {\n return await this.wait(key, timeoutMs, 'override', signal);\n }\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAa,eAAb,MAA6B;CAEzB,oCAAoB,IAAI,IAAgF;;;;;;;CAUxG,QAAQ,KAAa,OAAsB;EACvC,MAAM,YAAY,KAAK,kBAAkB,IAAI,GAAG;EAChD,IAAI,WAAW;GACX,KAAK,kBAAkB,OAAO,GAAG;GACjC,WAAW,SAAS,YAAY,QAAQ,KAAK,CAAC;EAClD;CACJ;;;;;;CAOA,WAAW,QAAuB,KAAA,GAAW;EACzC,KAAK,MAAM,CAAC,GAAG,cAAc,KAAK,kBAAkB,QAAQ,GAAG,UAAU,SAAS,YAAY,QAAQ,KAAK,CAAC;EAC5G,KAAK,kBAAkB,MAAM;CACjC;;;;;;;;;;;;;;;;;;;;CAqBA,MAAM,KAAK,KAAa,WAAoB,MAA8B,QAAsB;EAC5F,OAAO,MAAM,IAAI,SAAwB,YAAY;GACjD,MAAM,YAAY,KAAK,kBAAkB,IAAI,GAAG,KAAK,CAAC;GACtD,IAAI,UAAU,QACV,QAAQ,MAAR;IACI,KAAK;KACD,UAAU,SAAS,MAAM,EAAE,KAAA,CAAS,CAAC;KACrC,UAAU,SAAS;KACnB;IACJ,KAAK,UACD,MAAM,IAAI,MAAM,oCAAoC,KAAK;IAC7D,KAAK,KAAA;GAET;GAGJ,UAAU,KAAK,OAAO;GACtB,KAAK,kBAAkB,IAAI,KAAK,SAAS;GACzC,IAAI,aAAa,MACb,iBACU;IACF,MAAM,YAAY,KAAK,kBAAkB,IAAI,GAAG;IAChD,IAAI,WAAW,SAAS,OAAO,GAAG;KAC9B,QAAQ,KAAA,CAAS;KACjB,MAAM,eAAe,UAAU,QAAQ,MAAM,MAAM,OAAO;KAC1D,IAAI,aAAa,QAAQ,KAAK,kBAAkB,IAAI,KAAK,YAAY;UAChE,KAAK,kBAAkB,OAAO,GAAG;IAC1C;GACJ,GACA,SACJ;GAGJ,IAAI,QACA,OAAO,iBACH,eACM;IACF,MAAM,YAAY,KAAK,kBAAkB,IAAI,GAAG;IAChD,IAAI,WAAW,SAAS,OAAO,GAAG;KAC9B,QAAQ,KAAA,CAAS;KACjB,MAAM,eAAe,UAAU,QAAQ,MAAM,MAAM,OAAO;KAC1D,IAAI,aAAa,QAAQ,KAAK,kBAAkB,IAAI,KAAK,YAAY;UAChE,KAAK,kBAAkB,OAAO,GAAG;IAC1C;GACJ,GACA,EAAE,MAAM,KAAK,CACjB;EAER,CAAC;CACL;;;;;;;;;;;;;;CAeA,MAAM,cAAc,KAAa,WAAoB,QAAsB;EACvE,OAAO,MAAM,KAAK,KAAK,KAAK,WAAW,UAAU,MAAM;CAC3D;;;;;;;;;;;;;;;CAgBA,MAAM,WAAW,KAAa,WAAoB,QAAsB;EACpE,OAAO,MAAM,KAAK,KAAK,KAAK,WAAW,YAAY,MAAM;CAC7D;AACJ"}
|
package/dist/general.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Arrayable } from "type-fest";
|
|
1
2
|
/**
|
|
2
3
|
* Returns the first array element or the input value, with a nullish fallback.
|
|
3
4
|
*
|
|
@@ -29,6 +30,6 @@
|
|
|
29
30
|
* console.log(extractFirstValue(undefined, 'fallback')); // => 'fallback'
|
|
30
31
|
* ```
|
|
31
32
|
*/
|
|
32
|
-
export declare function extractFirstValue<T>(value: T
|
|
33
|
-
export declare function extractFirstValue<T, D>(value: T
|
|
33
|
+
export declare function extractFirstValue<T>(value: Arrayable<T>): T | undefined;
|
|
34
|
+
export declare function extractFirstValue<T, D>(value: Arrayable<T>, defaultValue: D): D | NonNullable<T>;
|
|
34
35
|
//# sourceMappingURL=general.d.ts.map
|
package/dist/general.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"general.d.ts","names":[],"sources":["../src/general.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"general.d.ts","names":[],"sources":["../src/general.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAmCgB,kBAAkB,GAAG,OAAO,UAAU,KAAK;wBAC3C,kBAAkB,GAAG,GAAG,OAAO,UAAU,IAAI,cAAc,IAAI,IAAI,YAAY"}
|
package/dist/general.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"general.js","names":[],"sources":["../src/general.ts"],"sourcesContent":["/* eslint-disable jsdoc/check-param-names */\n\n/**\n * Returns the first array element or the input value, with a nullish fallback.\n *\n * @remarks\n * An empty array, `null`, or `undefined` selects the fallback; omission of a fallback yields `undefined`.\n * The input and selected values are not copied or changed.\n *\n * @typeParam T - The input value or array element type.\n * @typeParam D - The fallback type when the fallback overload is used.\n *\n * @param value - A single value or an array of values.\n * @param defaultValue - The fallback returned when the selected value is nullish.\n *\n * @returns The selected non-nullish value, or the fallback without copying either value.\n *\n * @example\n *\n * ```ts\n * import { extractFirstValue } from '@kikiutils/shared/general';\n *\n * console.log(extractFirstValue([\n * 1,\n * 2,\n * 3,\n * ])); // => 1\n *\n * console.log(extractFirstValue('hello')); // => 'hello'\n * console.log(extractFirstValue([], 'default')); // => 'default'\n * console.log(extractFirstValue(undefined, 'fallback')); // => 'fallback'\n * ```\n */\nexport function extractFirstValue<T>(value: T
|
|
1
|
+
{"version":3,"file":"general.js","names":[],"sources":["../src/general.ts"],"sourcesContent":["import type { Arrayable } from 'type-fest';\n\n/* eslint-disable jsdoc/check-param-names */\n\n/**\n * Returns the first array element or the input value, with a nullish fallback.\n *\n * @remarks\n * An empty array, `null`, or `undefined` selects the fallback; omission of a fallback yields `undefined`.\n * The input and selected values are not copied or changed.\n *\n * @typeParam T - The input value or array element type.\n * @typeParam D - The fallback type when the fallback overload is used.\n *\n * @param value - A single value or an array of values.\n * @param defaultValue - The fallback returned when the selected value is nullish.\n *\n * @returns The selected non-nullish value, or the fallback without copying either value.\n *\n * @example\n *\n * ```ts\n * import { extractFirstValue } from '@kikiutils/shared/general';\n *\n * console.log(extractFirstValue([\n * 1,\n * 2,\n * 3,\n * ])); // => 1\n *\n * console.log(extractFirstValue('hello')); // => 'hello'\n * console.log(extractFirstValue([], 'default')); // => 'default'\n * console.log(extractFirstValue(undefined, 'fallback')); // => 'fallback'\n * ```\n */\nexport function extractFirstValue<T>(value: Arrayable<T>): T | undefined;\nexport function extractFirstValue<T, D>(value: Arrayable<T>, defaultValue: D): D | NonNullable<T>;\nexport function extractFirstValue<T, D>(value: Arrayable<T>, defaultValue?: D) {\n return (Array.isArray(value) ? value[0] : value) ?? defaultValue;\n}\n\n/* eslint-enable jsdoc/check-param-names */\n"],"mappings":";AAqCA,SAAgB,kBAAwB,OAAqB,cAAkB;CAC3E,QAAQ,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,UAAU;AACxD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","names":[],"sources":["../../../src/logger/_internals/logger.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"logger.d.ts","names":[],"sources":["../../../src/logger/_internals/logger.ts"],"mappings":";;UAgBU;;;;EAIN,SAAS,OAAO;EAChB,QAAQ,QAAQ,iBAAiB;;;;;wBAoBrB,yBACZ,WAAW,OAAO,SAAS,4BAC3B,YAAY,4BACZ,OAAO;wBAkEK,iBAAiB,SAAS,eAAe,OAAO,cAAc,SAAS"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { loggerMethods } from "./levels.js";
|
|
2
|
+
import { objectHasOwn, objectKeys } from "ts-extras";
|
|
2
3
|
// src/logger/_internals/logger.ts
|
|
3
4
|
const booleanPresentationKeys = [
|
|
4
5
|
"console",
|
|
@@ -108,7 +109,7 @@ function createLoggerCore(options, hooks) {
|
|
|
108
109
|
else refreshLevel();
|
|
109
110
|
}
|
|
110
111
|
};
|
|
111
|
-
for (const type of
|
|
112
|
+
for (const type of objectKeys(loggerMethods)) logger[type] = async (...args) => {
|
|
112
113
|
try {
|
|
113
114
|
refreshLevel();
|
|
114
115
|
if (loggerMethods[type].severity < getLevelSeverity(currentLevel)) return;
|
|
@@ -132,7 +133,7 @@ function getLevelSeverity(level) {
|
|
|
132
133
|
return level === "silent" ? Number.POSITIVE_INFINITY : loggerMethods[level].severity;
|
|
133
134
|
}
|
|
134
135
|
function isLevel(value) {
|
|
135
|
-
return typeof value === "string" && (value === "silent" || value !== "success" &&
|
|
136
|
+
return typeof value === "string" && (value === "silent" || value !== "success" && objectHasOwn(loggerMethods, value));
|
|
136
137
|
}
|
|
137
138
|
function readEnvironmentLevel() {
|
|
138
139
|
return globalThis.process?.env?.LOG_LEVEL;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","names":[],"sources":["../../../src/logger/_internals/logger.ts"],"sourcesContent":["import type {\n Logger,\n LoggerDiagnostic,\n LoggerLevel,\n LoggerMethod,\n LoggerOptions,\n} from '../types';\n\nimport { loggerMethods } from './levels';\nimport type { LoggerRecord } from './types';\n\ninterface LoggerHooks {\n /**\n * A non-throwing reporter created by createDiagnosticReporter.\n */\n report: (event: LoggerDiagnostic) => void;\n write: (record: LoggerRecord) => Promise<void> | void;\n}\n\n// Constants/Variables\nconst booleanPresentationKeys = [\n 'console',\n 'icons',\n 'timestamp',\n] as const;\n\nconst stringPresentationKeys = [\n 'prefix',\n 'suffix',\n] as const;\n\n// Functions\n\n/**\n * A non-recursive, rate-limited diagnostic boundary shared by server and browser adapters.\n */\nexport function createDiagnosticReporter(\n onError?: (event: Readonly<LoggerDiagnostic>) => void,\n fallback?: (message: string) => void,\n): (event: LoggerDiagnostic) => void {\n let reporting = false;\n let callbackPending = false;\n const stateByType = new Map<LoggerDiagnostic['type'], { lastReportedAt: number; suppressedCount: number }>();\n\n return (event) => {\n if (reporting) return;\n try {\n const now = Date.now();\n const state = stateByType.get(event.type);\n if (state && now - state.lastReportedAt < 1000) {\n state.suppressedCount++;\n return;\n }\n\n reporting = true;\n const suppressedCount = state?.suppressedCount ?? 0;\n if (suppressedCount) {\n event = {\n ...event,\n suppressedCount,\n };\n }\n\n stateByType.set(\n event.type,\n {\n lastReportedAt: now,\n suppressedCount: 0,\n },\n );\n\n try {\n const summary = suppressedCount ? ` (${suppressedCount} similar diagnostics suppressed)` : '';\n fallback?.(`[logger] ${event.message}${summary}\\n`);\n } catch {\n // Diagnostics must never re-enter the normal logging pipeline.\n }\n\n if (!callbackPending) {\n try {\n callbackPending = true;\n const result: unknown = onError?.(Object.freeze({ ...event }));\n if (result !== null && (typeof result === 'object' || typeof result === 'function')) {\n void Promise.resolve(result).then(\n () => {\n callbackPending = false;\n },\n () => {\n callbackPending = false;\n },\n );\n } else {\n callbackPending = false;\n }\n } catch {\n callbackPending = false;\n // User diagnostic callbacks have the same non-throwing boundary.\n }\n }\n } catch { /* Diagnostics must never escape into the logging pipeline. */ } finally {\n reporting = false;\n }\n };\n}\n\nexport function createLoggerCore(options: LoggerOptions, hooks: LoggerHooks): Readonly<Logger> {\n validateLevel(options.level);\n validatePresentation(options);\n if (options.onError !== undefined && typeof options.onError !== 'function') {\n throw new TypeError('Logger onError must be a function');\n }\n\n const presentation = {\n console: options.console ?? true,\n icons: options.icons ?? true,\n prefix: options.prefix ?? '',\n suffix: options.suffix ?? '',\n timestamp: options.timestamp ?? true,\n };\n\n const { report } = hooks;\n\n let override = options.level === 'env' ? undefined : options.level;\n let previousEnvironment: string | undefined;\n let currentLevel: LoggerLevel = override ?? 'info';\n let environmentRead = false;\n\n function refreshLevel() {\n if (override !== undefined) return;\n const input = readEnvironmentLevel();\n if (environmentRead && input === previousEnvironment) return;\n environmentRead = true;\n previousEnvironment = input;\n const normalized = input?.trim().toLowerCase() || undefined;\n currentLevel = isLevel(normalized) ? normalized : 'info';\n if (normalized !== undefined && !isLevel(normalized)) {\n report({\n message: 'Invalid LOG_LEVEL; using info',\n type: 'invalid-level',\n });\n }\n }\n\n const logger = {\n configure(configuration) {\n validatePresentation(configuration);\n for (const name of booleanPresentationKeys) {\n const value = configuration[name];\n if (value !== undefined) presentation[name] = value;\n }\n\n for (const name of stringPresentationKeys) {\n const value = configuration[name];\n if (value !== undefined) presentation[name] = value;\n }\n },\n isLevelEnabled(level) {\n if (level !== 'success' && !isLevel(level)) throw new TypeError('Invalid logger level');\n refreshLevel();\n return level !== 'silent' && getLevelSeverity(level) >= getLevelSeverity(currentLevel);\n },\n setLevel(level) {\n validateLevel(level);\n if (level === undefined) throw new TypeError('Invalid logger level');\n override = level === 'env' ? undefined : level;\n environmentRead = false;\n if (override !== undefined) {\n currentLevel = override;\n } else {\n refreshLevel();\n }\n },\n } as Logger;\n\n for (const type of Object.keys(loggerMethods) as LoggerMethod[]) {\n logger[type] = async (...args: unknown[]) => {\n try {\n refreshLevel();\n if (loggerMethods[type].severity < getLevelSeverity(currentLevel)) return;\n await hooks.write({\n ...presentation,\n args,\n date: new Date(),\n type,\n });\n } catch (error) {\n report({\n error,\n message: 'Logger output failed',\n type: 'format',\n });\n }\n };\n }\n\n return Object.freeze(logger);\n}\n\nfunction getLevelSeverity(level: LoggerLevel | LoggerMethod): number {\n return level === 'silent' ? Number.POSITIVE_INFINITY : loggerMethods[level].severity;\n}\n\nfunction isLevel(value: unknown): value is LoggerLevel {\n return typeof value === 'string'\n && (value === 'silent' || (value !== 'success' && Object.hasOwn(loggerMethods, value)));\n}\n\nfunction readEnvironmentLevel(): string | undefined {\n return (globalThis as { process?: { env?: { LOG_LEVEL?: string } } }).process?.env?.LOG_LEVEL;\n}\n\nfunction validateLevel(value: unknown): asserts value is 'env' | LoggerLevel | undefined {\n if (value !== undefined && value !== 'env' && !isLevel(value)) throw new TypeError('Invalid logger level');\n}\n\nfunction validatePresentation(options: Pick<LoggerOptions, 'console' | 'icons' | 'prefix' | 'suffix' | 'timestamp'>) {\n for (const name of booleanPresentationKeys) {\n if (options[name] !== undefined && typeof options[name] !== 'boolean') {\n throw new TypeError(`Logger ${name} must be a boolean`);\n }\n }\n\n for (const name of stringPresentationKeys) {\n if (options[name] !== undefined && typeof options[name] !== 'string') {\n throw new TypeError(`Logger ${name} must be a string`);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"logger.js","names":[],"sources":["../../../src/logger/_internals/logger.ts"],"sourcesContent":["import {\n objectHasOwn,\n objectKeys,\n} from 'ts-extras';\n\nimport type {\n Logger,\n LoggerDiagnostic,\n LoggerLevel,\n LoggerMethod,\n LoggerOptions,\n} from '../types';\n\nimport { loggerMethods } from './levels';\nimport type { LoggerRecord } from './types';\n\ninterface LoggerHooks {\n /**\n * A non-throwing reporter created by createDiagnosticReporter.\n */\n report: (event: LoggerDiagnostic) => void;\n write: (record: LoggerRecord) => Promise<void> | void;\n}\n\n// Constants/Variables\nconst booleanPresentationKeys = [\n 'console',\n 'icons',\n 'timestamp',\n] as const;\n\nconst stringPresentationKeys = [\n 'prefix',\n 'suffix',\n] as const;\n\n// Functions\n\n/**\n * A non-recursive, rate-limited diagnostic boundary shared by server and browser adapters.\n */\nexport function createDiagnosticReporter(\n onError?: (event: Readonly<LoggerDiagnostic>) => void,\n fallback?: (message: string) => void,\n): (event: LoggerDiagnostic) => void {\n let reporting = false;\n let callbackPending = false;\n const stateByType = new Map<LoggerDiagnostic['type'], { lastReportedAt: number; suppressedCount: number }>();\n\n return (event) => {\n if (reporting) return;\n try {\n const now = Date.now();\n const state = stateByType.get(event.type);\n if (state && now - state.lastReportedAt < 1000) {\n state.suppressedCount++;\n return;\n }\n\n reporting = true;\n const suppressedCount = state?.suppressedCount ?? 0;\n if (suppressedCount) {\n event = {\n ...event,\n suppressedCount,\n };\n }\n\n stateByType.set(\n event.type,\n {\n lastReportedAt: now,\n suppressedCount: 0,\n },\n );\n\n try {\n const summary = suppressedCount ? ` (${suppressedCount} similar diagnostics suppressed)` : '';\n fallback?.(`[logger] ${event.message}${summary}\\n`);\n } catch {\n // Diagnostics must never re-enter the normal logging pipeline.\n }\n\n if (!callbackPending) {\n try {\n callbackPending = true;\n const result: unknown = onError?.(Object.freeze({ ...event }));\n if (result !== null && (typeof result === 'object' || typeof result === 'function')) {\n void Promise.resolve(result).then(\n () => {\n callbackPending = false;\n },\n () => {\n callbackPending = false;\n },\n );\n } else {\n callbackPending = false;\n }\n } catch {\n callbackPending = false;\n // User diagnostic callbacks have the same non-throwing boundary.\n }\n }\n } catch { /* Diagnostics must never escape into the logging pipeline. */ } finally {\n reporting = false;\n }\n };\n}\n\nexport function createLoggerCore(options: LoggerOptions, hooks: LoggerHooks): Readonly<Logger> {\n validateLevel(options.level);\n validatePresentation(options);\n if (options.onError !== undefined && typeof options.onError !== 'function') {\n throw new TypeError('Logger onError must be a function');\n }\n\n const presentation = {\n console: options.console ?? true,\n icons: options.icons ?? true,\n prefix: options.prefix ?? '',\n suffix: options.suffix ?? '',\n timestamp: options.timestamp ?? true,\n };\n\n const { report } = hooks;\n\n let override = options.level === 'env' ? undefined : options.level;\n let previousEnvironment: string | undefined;\n let currentLevel: LoggerLevel = override ?? 'info';\n let environmentRead = false;\n\n function refreshLevel() {\n if (override !== undefined) return;\n const input = readEnvironmentLevel();\n if (environmentRead && input === previousEnvironment) return;\n environmentRead = true;\n previousEnvironment = input;\n const normalized = input?.trim().toLowerCase() || undefined;\n currentLevel = isLevel(normalized) ? normalized : 'info';\n if (normalized !== undefined && !isLevel(normalized)) {\n report({\n message: 'Invalid LOG_LEVEL; using info',\n type: 'invalid-level',\n });\n }\n }\n\n const logger = {\n configure(configuration) {\n validatePresentation(configuration);\n for (const name of booleanPresentationKeys) {\n const value = configuration[name];\n if (value !== undefined) presentation[name] = value;\n }\n\n for (const name of stringPresentationKeys) {\n const value = configuration[name];\n if (value !== undefined) presentation[name] = value;\n }\n },\n isLevelEnabled(level) {\n if (level !== 'success' && !isLevel(level)) throw new TypeError('Invalid logger level');\n refreshLevel();\n return level !== 'silent' && getLevelSeverity(level) >= getLevelSeverity(currentLevel);\n },\n setLevel(level) {\n validateLevel(level);\n if (level === undefined) throw new TypeError('Invalid logger level');\n override = level === 'env' ? undefined : level;\n environmentRead = false;\n if (override !== undefined) {\n currentLevel = override;\n } else {\n refreshLevel();\n }\n },\n } as Logger;\n\n for (const type of objectKeys(loggerMethods) as LoggerMethod[]) {\n logger[type] = async (...args: unknown[]) => {\n try {\n refreshLevel();\n if (loggerMethods[type].severity < getLevelSeverity(currentLevel)) return;\n await hooks.write({\n ...presentation,\n args,\n date: new Date(),\n type,\n });\n } catch (error) {\n report({\n error,\n message: 'Logger output failed',\n type: 'format',\n });\n }\n };\n }\n\n return Object.freeze(logger);\n}\n\nfunction getLevelSeverity(level: LoggerLevel | LoggerMethod): number {\n return level === 'silent' ? Number.POSITIVE_INFINITY : loggerMethods[level].severity;\n}\n\nfunction isLevel(value: unknown): value is LoggerLevel {\n return typeof value === 'string'\n && (value === 'silent' || (value !== 'success' && objectHasOwn(loggerMethods, value)));\n}\n\nfunction readEnvironmentLevel(): string | undefined {\n return (globalThis as { process?: { env?: { LOG_LEVEL?: string } } }).process?.env?.LOG_LEVEL;\n}\n\nfunction validateLevel(value: unknown): asserts value is 'env' | LoggerLevel | undefined {\n if (value !== undefined && value !== 'env' && !isLevel(value)) throw new TypeError('Invalid logger level');\n}\n\nfunction validatePresentation(options: Pick<LoggerOptions, 'console' | 'icons' | 'prefix' | 'suffix' | 'timestamp'>) {\n for (const name of booleanPresentationKeys) {\n if (options[name] !== undefined && typeof options[name] !== 'boolean') {\n throw new TypeError(`Logger ${name} must be a boolean`);\n }\n }\n\n for (const name of stringPresentationKeys) {\n if (options[name] !== undefined && typeof options[name] !== 'string') {\n throw new TypeError(`Logger ${name} must be a string`);\n }\n }\n}\n"],"mappings":";;;AAyBA,MAAM,0BAA0B;CAC5B;CACA;CACA;AACJ;AAEA,MAAM,yBAAyB,CAC3B,UACA,QACJ;;;;AAOA,SAAgB,yBACZ,SACA,UACiC;CACjC,IAAI,YAAY;CAChB,IAAI,kBAAkB;CACtB,MAAM,8BAAc,IAAI,IAAmF;CAE3G,QAAQ,UAAU;EACd,IAAI,WAAW;EACf,IAAI;GACA,MAAM,MAAM,KAAK,IAAI;GACrB,MAAM,QAAQ,YAAY,IAAI,MAAM,IAAI;GACxC,IAAI,SAAS,MAAM,MAAM,iBAAiB,KAAM;IAC5C,MAAM;IACN;GACJ;GAEA,YAAY;GACZ,MAAM,kBAAkB,OAAO,mBAAmB;GAClD,IAAI,iBACA,QAAQ;IACJ,GAAG;IACH;GACJ;GAGJ,YAAY,IACR,MAAM,MACN;IACI,gBAAgB;IAChB,iBAAiB;GACrB,CACJ;GAEA,IAAI;IACA,MAAM,UAAU,kBAAkB,KAAK,gBAAgB,oCAAoC;IAC3F,WAAW,YAAY,MAAM,UAAU,QAAQ,GAAG;GACtD,QAAQ,CAER;GAEA,IAAI,CAAC,iBACD,IAAI;IACA,kBAAkB;IAClB,MAAM,SAAkB,UAAU,OAAO,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;IAC7D,IAAI,WAAW,SAAS,OAAO,WAAW,YAAY,OAAO,WAAW,aACpE,QAAa,QAAQ,MAAM,CAAC,CAAC,WACnB;KACF,kBAAkB;IACtB,SACM;KACF,kBAAkB;IACtB,CACJ;SAEA,kBAAkB;GAE1B,QAAQ;IACJ,kBAAkB;GAEtB;EAER,QAAQ,CAAiE,UAAU;GAC/E,YAAY;EAChB;CACJ;AACJ;AAEA,SAAgB,iBAAiB,SAAwB,OAAsC;CAC3F,cAAc,QAAQ,KAAK;CAC3B,qBAAqB,OAAO;CAC5B,IAAI,QAAQ,YAAY,KAAA,KAAa,OAAO,QAAQ,YAAY,YAC5D,MAAM,IAAI,UAAU,mCAAmC;CAG3D,MAAM,eAAe;EACjB,SAAS,QAAQ,WAAW;EAC5B,OAAO,QAAQ,SAAS;EACxB,QAAQ,QAAQ,UAAU;EAC1B,QAAQ,QAAQ,UAAU;EAC1B,WAAW,QAAQ,aAAa;CACpC;CAEA,MAAM,EAAE,WAAW;CAEnB,IAAI,WAAW,QAAQ,UAAU,QAAQ,KAAA,IAAY,QAAQ;CAC7D,IAAI;CACJ,IAAI,eAA4B,YAAY;CAC5C,IAAI,kBAAkB;CAEtB,SAAS,eAAe;EACpB,IAAI,aAAa,KAAA,GAAW;EAC5B,MAAM,QAAQ,qBAAqB;EACnC,IAAI,mBAAmB,UAAU,qBAAqB;EACtD,kBAAkB;EAClB,sBAAsB;EACtB,MAAM,aAAa,OAAO,KAAK,CAAC,CAAC,YAAY,KAAK,KAAA;EAClD,eAAe,QAAQ,UAAU,IAAI,aAAa;EAClD,IAAI,eAAe,KAAA,KAAa,CAAC,QAAQ,UAAU,GAC/C,OAAO;GACH,SAAS;GACT,MAAM;EACV,CAAC;CAET;CAEA,MAAM,SAAS;EACX,UAAU,eAAe;GACrB,qBAAqB,aAAa;GAClC,KAAK,MAAM,QAAQ,yBAAyB;IACxC,MAAM,QAAQ,cAAc;IAC5B,IAAI,UAAU,KAAA,GAAW,aAAa,QAAQ;GAClD;GAEA,KAAK,MAAM,QAAQ,wBAAwB;IACvC,MAAM,QAAQ,cAAc;IAC5B,IAAI,UAAU,KAAA,GAAW,aAAa,QAAQ;GAClD;EACJ;EACA,eAAe,OAAO;GAClB,IAAI,UAAU,aAAa,CAAC,QAAQ,KAAK,GAAG,MAAM,IAAI,UAAU,sBAAsB;GACtF,aAAa;GACb,OAAO,UAAU,YAAY,iBAAiB,KAAK,KAAK,iBAAiB,YAAY;EACzF;EACA,SAAS,OAAO;GACZ,cAAc,KAAK;GACnB,IAAI,UAAU,KAAA,GAAW,MAAM,IAAI,UAAU,sBAAsB;GACnE,WAAW,UAAU,QAAQ,KAAA,IAAY;GACzC,kBAAkB;GAClB,IAAI,aAAa,KAAA,GACb,eAAe;QAEf,aAAa;EAErB;CACJ;CAEA,KAAK,MAAM,QAAQ,WAAW,aAAa,GACvC,OAAO,QAAQ,OAAO,GAAG,SAAoB;EACzC,IAAI;GACA,aAAa;GACb,IAAI,cAAc,KAAK,CAAC,WAAW,iBAAiB,YAAY,GAAG;GACnE,MAAM,MAAM,MAAM;IACd,GAAG;IACH;IACA,sBAAM,IAAI,KAAK;IACf;GACJ,CAAC;EACL,SAAS,OAAO;GACZ,OAAO;IACH;IACA,SAAS;IACT,MAAM;GACV,CAAC;EACL;CACJ;CAGJ,OAAO,OAAO,OAAO,MAAM;AAC/B;AAEA,SAAS,iBAAiB,OAA2C;CACjE,OAAO,UAAU,WAAW,OAAO,oBAAoB,cAAc,MAAM,CAAC;AAChF;AAEA,SAAS,QAAQ,OAAsC;CACnD,OAAO,OAAO,UAAU,aAClB,UAAU,YAAa,UAAU,aAAa,aAAa,eAAe,KAAK;AACzF;AAEA,SAAS,uBAA2C;CAChD,OAAQ,WAA8D,SAAS,KAAK;AACxF;AAEA,SAAS,cAAc,OAAkE;CACrF,IAAI,UAAU,KAAA,KAAa,UAAU,SAAS,CAAC,QAAQ,KAAK,GAAG,MAAM,IAAI,UAAU,sBAAsB;AAC7G;AAEA,SAAS,qBAAqB,SAAuF;CACjH,KAAK,MAAM,QAAQ,yBACf,IAAI,QAAQ,UAAU,KAAA,KAAa,OAAO,QAAQ,UAAU,WACxD,MAAM,IAAI,UAAU,UAAU,KAAK,mBAAmB;CAI9D,KAAK,MAAM,QAAQ,wBACf,IAAI,QAAQ,UAAU,KAAA,KAAa,OAAO,QAAQ,UAAU,UACxD,MAAM,IAAI,UAAU,UAAU,KAAK,kBAAkB;AAGjE"}
|
|
@@ -86,8 +86,8 @@ async function createFileWriter(options, report) {
|
|
|
86
86
|
initializing = false;
|
|
87
87
|
}
|
|
88
88
|
return Object.freeze({
|
|
89
|
-
close() {
|
|
90
|
-
if (closePromise) return closePromise;
|
|
89
|
+
async close() {
|
|
90
|
+
if (closePromise) return await closePromise;
|
|
91
91
|
closing = true;
|
|
92
92
|
closePromise = new Promise((resolveClosed) => {
|
|
93
93
|
if (closed) {
|
|
@@ -101,20 +101,20 @@ async function createFileWriter(options, report) {
|
|
|
101
101
|
fail(error);
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
|
-
return closePromise;
|
|
104
|
+
return await closePromise;
|
|
105
105
|
},
|
|
106
106
|
getStats: () => Object.freeze({
|
|
107
107
|
droppedCount,
|
|
108
108
|
pendingBytes,
|
|
109
109
|
writeErrorCount
|
|
110
110
|
}),
|
|
111
|
-
write(text) {
|
|
111
|
+
async write(text) {
|
|
112
112
|
if (closing || closed || failed) {
|
|
113
113
|
report({
|
|
114
114
|
message: "File output is closed or unavailable.",
|
|
115
115
|
type: "closed"
|
|
116
116
|
});
|
|
117
|
-
return Promise.resolve();
|
|
117
|
+
return await Promise.resolve();
|
|
118
118
|
}
|
|
119
119
|
const bytes = Buffer.byteLength(text);
|
|
120
120
|
if (bytes > maxPendingBytes - pendingBytes) {
|
|
@@ -124,10 +124,10 @@ async function createFileWriter(options, report) {
|
|
|
124
124
|
message: "File output queue is full; the newest record was discarded.",
|
|
125
125
|
type: "overflow"
|
|
126
126
|
});
|
|
127
|
-
return Promise.resolve();
|
|
127
|
+
return await Promise.resolve();
|
|
128
128
|
}
|
|
129
129
|
pendingBytes += bytes;
|
|
130
|
-
return new Promise((resolveWritten) => {
|
|
130
|
+
return await new Promise((resolveWritten) => {
|
|
131
131
|
let settled = false;
|
|
132
132
|
const settle = () => {
|
|
133
133
|
if (settled) return;
|