@gesslar/toolkit 5.1.0 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "gesslar",
6
6
  "url": "https://gesslar.dev"
7
7
  },
8
- "version": "5.1.0",
8
+ "version": "5.3.0",
9
9
  "license": "0BSD",
10
10
  "homepage": "https://github.com/gesslar/toolkit#readme",
11
11
  "repository": {
@@ -55,7 +55,7 @@
55
55
  "LICENSE.txt"
56
56
  ],
57
57
  "engines": {
58
- "node": ">=24.11.0"
58
+ "node": ">=24"
59
59
  },
60
60
  "scripts": {
61
61
  "preinstall": "node ./scripts/check-node-version.mjs",
@@ -86,8 +86,8 @@
86
86
  "@gesslar/uglier": "^2.4.1",
87
87
  "@rollup/plugin-node-resolve": "^16.0.3",
88
88
  "eslint": "^10.2.0",
89
- "happy-dom": "^20.8.9",
89
+ "happy-dom": "^20.9.0",
90
90
  "rollup": "^4.60.1",
91
- "typescript": "^6.0.2"
91
+ "typescript": "^6.0.3"
92
92
  }
93
93
  }
@@ -89,17 +89,15 @@ export default class Sass extends Error {
89
89
  )
90
90
  }
91
91
 
92
- if(this.cause) {
92
+ if(this.cause && nerdMode) {
93
93
  if(typeof this.cause.report === "function") {
94
- if(nerdMode) {
95
- console.error(
96
- "\n" +
97
- `[error] Caused By`
98
- )
99
- }
94
+ console.error(
95
+ "\n" +
96
+ `[error] Caused By`
97
+ )
100
98
 
101
99
  this.cause.report(nerdMode, true)
102
- } else if(nerdMode && this.cause.stack) {
100
+ } else if(this.cause.stack) {
103
101
  console.error()
104
102
  console.group()
105
103
  console.error(
@@ -77,7 +77,9 @@ export default class Valid {
77
77
  static prototypePollutionProtection(keys) {
78
78
  this.type(keys, "String[]")
79
79
 
80
- const oopsIDidItAgain = Collection.intersection(Valid.#restrictedProto, keys)
80
+ const oopsIDidItAgain = Collection.intersection(
81
+ Valid.#restrictedProto, keys
82
+ )
81
83
 
82
84
  this.assert(
83
85
  oopsIDidItAgain.length === 0,
@@ -4,7 +4,7 @@
4
4
  * resolution and existence checks.
5
5
  */
6
6
 
7
- import {glob, mkdir, opendir, readdir, rmdir, stat} from "node:fs/promises"
7
+ import {glob, lstat, mkdir, readdir, rmdir, stat} from "node:fs/promises"
8
8
  import path, {relative} from "node:path"
9
9
  import {URL} from "node:url"
10
10
  import {inspect} from "node:util"
@@ -59,6 +59,7 @@ import Valid from "./Valid.js"
59
59
  * @property {boolean} isDirectory - Always true
60
60
  * @property {DirectoryObject|null} parent - The parent directory (null if root)
61
61
  * @property {Promise<boolean>} exists - Whether the directory exists (async getter)
62
+ * @property {Promise<("none"|"symbolic"|null)>} linkType - The link kind at this path (async)
62
63
  *
63
64
  * @example
64
65
  * // Basic usage
@@ -225,6 +226,28 @@ export default class DirectoryObject extends FS {
225
226
  return this.#directoryExists()
226
227
  }
227
228
 
229
+ /**
230
+ * Reports the link kind at this path. Reads the filesystem on every
231
+ * access, like {@link DirectoryObject#exists}, and throws under the
232
+ * same conditions: if the path exists but is not a directory (broken
233
+ * symlink, symlink to a non-directory, or a regular file), this throws
234
+ * a {@link Sass} error rather than returning a misleading value.
235
+ *
236
+ * - `"symbolic"` - a symlink whose target is a directory that exists
237
+ * - `"none"` - a regular directory
238
+ * - `null` - the path does not exist at all
239
+ *
240
+ * Hard links are not reported for directories: most filesystems do not
241
+ * allow hard-linked directories at all, and `nlink` on a directory is
242
+ * not a usable signal (it counts `.` and each subdirectory's `..`).
243
+ *
244
+ * @returns {Promise<"none"|"symbolic"|null>} The link kind
245
+ * @throws {Sass} If the path exists but does not resolve to a directory
246
+ */
247
+ get linkType() {
248
+ return this.#directoryLinkType()
249
+ }
250
+
228
251
  /**
229
252
  * Return the path as passed to the constructor.
230
253
  *
@@ -342,16 +365,58 @@ export default class DirectoryObject extends FS {
342
365
  * Check if a directory exists
343
366
  *
344
367
  * @returns {Promise<boolean>} Whether the directory exists
368
+ * @throws {Sass} If the path exists but is not a directory
345
369
  */
346
370
  async #directoryExists() {
347
- const path = this.path
348
-
349
371
  try {
350
- (await opendir(path)).close()
372
+ const stats = await stat(this.path).catch(error => error.code === "ENOENT" ? null : error)
373
+
374
+ if(stats instanceof Error)
375
+ throw stats
376
+
377
+ if(stats === null)
378
+ return false
379
+
380
+ if(!stats.isDirectory())
381
+ throw Sass.new(`Path exists but is not a directory: '${this.path}'`)
351
382
 
352
383
  return true
353
- } catch {
354
- return false
384
+ } catch(error) {
385
+ throw Sass.new(`Determining status of '${this.path}'`, error)
386
+ }
387
+ }
388
+
389
+ /**
390
+ * Resolves the link kind at this path.
391
+ *
392
+ * @private
393
+ * @returns {Promise<"none"|"symbolic"|null>} The link kind
394
+ */
395
+ async #directoryLinkType() {
396
+ try {
397
+ const linkStats = await lstat(this.path).catch(error => error.code === "ENOENT" ? null : error)
398
+
399
+ if(linkStats instanceof Error)
400
+ throw linkStats
401
+
402
+ if(linkStats === null)
403
+ return null
404
+
405
+ if(linkStats.isSymbolicLink()) {
406
+ const targetStats = await stat(this.path)
407
+
408
+ if(!targetStats.isDirectory())
409
+ throw Sass.new(`Path exists but is not a directory: '${this.path}'`)
410
+
411
+ return "symbolic"
412
+ }
413
+
414
+ if(!linkStats.isDirectory())
415
+ throw Sass.new(`Path exists but is not a directory: '${this.path}'`)
416
+
417
+ return "none"
418
+ } catch(error) {
419
+ throw Sass.new(`Determining link type of '${this.path}'`, error)
355
420
  }
356
421
  }
357
422
 
@@ -360,8 +425,8 @@ export default class DirectoryObject extends FS {
360
425
  *
361
426
  * Returns FileObject and DirectoryObject instances. Symbolic links are
362
427
  * resolved to their target type: links to files appear in `files`, links
363
- * to directories appear in `directories`. Broken symlinks propagate the
364
- * stat error to the caller.
428
+ * to directories appear in `directories`. Broken symlinks (where the
429
+ * target does not exist) appear in `files` so they can be unlinked.
365
430
  *
366
431
  * @async
367
432
  * @param {string} [pat=""] - Optional glob pattern to filter results (e.g., "*.txt", "test-*")
@@ -407,8 +472,8 @@ export default class DirectoryObject extends FS {
407
472
  *
408
473
  * Returns FileObject and DirectoryObject instances. Symbolic links are
409
474
  * resolved to their target type: links to files appear in `files`, links
410
- * to directories appear in `directories`. Broken symlinks propagate the
411
- * stat error to the caller.
475
+ * to directories appear in `directories`. Broken symlinks (where the
476
+ * target does not exist) appear in `files` so they can be unlinked.
412
477
  *
413
478
  * @async
414
479
  * @param {string} [pat=""] - Glob pattern to filter results
@@ -443,7 +508,8 @@ export default class DirectoryObject extends FS {
443
508
  /**
444
509
  * Categorizes an array of Dirent objects into files and directories.
445
510
  * Resolves symbolic links to their target type via `fs.stat()`. Broken
446
- * symlinks propagate the stat error to the caller.
511
+ * symlinks (where the target does not exist) are categorized as files
512
+ * so they can be unlinked.
447
513
  *
448
514
  * @private
449
515
  * @param {Array<import("node:fs").Dirent>} dirents - Directory entries to categorize
@@ -463,12 +529,19 @@ export default class DirectoryObject extends FS {
463
529
  } else if(dirent.isDirectory()) {
464
530
  result.directories.push(new this.constructor(fullPath))
465
531
  } else if(dirent.isSymbolicLink()) {
466
- const stats = await stat(fullPath)
467
-
468
- if(stats.isFile())
469
- result.files.push(new FileObject(fullPath, this))
470
- else if(stats.isDirectory())
471
- result.directories.push(new this.constructor(fullPath))
532
+ try {
533
+ const stats = await stat(fullPath)
534
+
535
+ if(stats.isFile())
536
+ result.files.push(new FileObject(fullPath, this))
537
+ else if(stats.isDirectory())
538
+ result.directories.push(new this.constructor(fullPath))
539
+ } catch(error) {
540
+ if(error.code === "ENOENT")
541
+ result.files.push(new FileObject(fullPath, this))
542
+ else
543
+ throw error
544
+ }
472
545
  }
473
546
  }
474
547
 
@@ -583,9 +656,9 @@ export default class DirectoryObject extends FS {
583
656
  * @returns {Promise<boolean>} True if the file exists, false otherwise
584
657
  */
585
658
  async hasFile(filename) {
586
- const file = new FileObject(filename, this)
659
+ const file = this.getFile(filename)
587
660
 
588
- return await file.exists
661
+ return await file.exists.catch(() => false)
589
662
  }
590
663
 
591
664
  /**
@@ -595,10 +668,9 @@ export default class DirectoryObject extends FS {
595
668
  * @returns {Promise<boolean>} True if the directory exists, false otherwise
596
669
  */
597
670
  async hasDirectory(dirname) {
598
- const dir = FS.resolvePath(this.path, dirname)
599
- const directory = new DirectoryObject(dir)
671
+ const dir = this.getDirectory(dirname)
600
672
 
601
- return await directory.exists
673
+ return await dir.exists.catch(() => false)
602
674
  }
603
675
 
604
676
  /**
@@ -29,6 +29,7 @@ import Valid from "./Valid.js"
29
29
  * @property {boolean} isFile - Always true for files
30
30
  * @property {DirectoryObject} parent - The parent directory object
31
31
  * @property {Promise<boolean>} exists - Whether the file exists (async)
32
+ * @property {Promise<("none"|"symbolic"|"broken"|"hard"|null)>} linkType - The link kind at this path (async)
32
33
  */
33
34
 
34
35
  export default class FileObject extends FS {
@@ -200,6 +201,24 @@ export default class FileObject extends FS {
200
201
  return this.#fileExists()
201
202
  }
202
203
 
204
+ /**
205
+ * Reports the link kind at this path. Reads the filesystem on every
206
+ * access, like {@link FileObject#exists}.
207
+ *
208
+ * - `"symbolic"` - a symlink whose target exists
209
+ * - `"broken"` - a symlink whose target does not exist
210
+ * - `"hard"` - a regular file with additional hard links (`nlink > 1`).
211
+ * Hard links are inode-level and indistinguishable from each other,
212
+ * so this only reports that *some* other entry shares the inode.
213
+ * - `"none"` - a regular file with no links
214
+ * - `null` - the path does not exist
215
+ *
216
+ * @returns {Promise<"none"|"symbolic"|"broken"|"hard"|null>} The link kind
217
+ */
218
+ get linkType() {
219
+ return this.#fileLinkType()
220
+ }
221
+
203
222
  /**
204
223
  * Return the normalized path that was provided to the constructor.
205
224
  *
@@ -324,14 +343,65 @@ export default class FileObject extends FS {
324
343
  * Check if a file exists
325
344
  *
326
345
  * @returns {Promise<boolean>} Whether the file exists
346
+ * @throws {Sass} If the path exists but is not a file
327
347
  */
328
348
  async #fileExists() {
329
349
  try {
330
- await fs.access(this.path, fs.constants.F_OK)
350
+ const stats = await fs.lstat(this.path).catch(error => error.code === "ENOENT" ? null : error)
351
+
352
+ if(stats instanceof Error)
353
+ throw stats
354
+
355
+ if(stats === null)
356
+ return false
357
+
358
+ if(!stats.isFile() && !stats.isSymbolicLink())
359
+ throw Sass.new(`Path exists but is not a file: '${this.path}'`)
331
360
 
332
361
  return true
333
- } catch {
334
- return false
362
+ } catch(error) {
363
+ throw Sass.new(`Determining status of '${this.path}'`, error)
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Resolves the link kind at this path.
369
+ *
370
+ * @private
371
+ * @returns {Promise<"none"|"symbolic"|"broken"|"hard"|null>} The link kind
372
+ */
373
+ async #fileLinkType() {
374
+ try {
375
+ const stats = await fs.lstat(this.path).catch(error => error.code === "ENOENT" ? null : error)
376
+
377
+ if(stats instanceof Error)
378
+ throw stats
379
+
380
+ if(stats === null)
381
+ return null
382
+
383
+ if(stats.isSymbolicLink()) {
384
+ try {
385
+ await fs.stat(this.path)
386
+
387
+ return "symbolic"
388
+ } catch(error) {
389
+ if(error.code === "ENOENT")
390
+ return "broken"
391
+
392
+ throw error
393
+ }
394
+ }
395
+
396
+ if(!stats.isFile())
397
+ throw Sass.new(`Path exists but is not a file: '${this.path}'`)
398
+
399
+ if(stats.nlink > 1)
400
+ return "hard"
401
+
402
+ return "none"
403
+ } catch(error) {
404
+ throw Sass.new(`Determining link type of '${this.path}'`, error)
335
405
  }
336
406
  }
337
407
 
@@ -40,17 +40,15 @@ export default class Sass extends BrowserSass {
40
40
  )
41
41
  }
42
42
 
43
- if(this.cause) {
43
+ if(this.cause && nerdMode) {
44
44
  if(typeof this.cause.report === "function") {
45
- if(nerdMode) {
46
- Term.error(
47
- "\n" +
48
- `${Term.terminalBracket(["error", "Caused By"])}`
49
- )
50
- }
45
+ Term.error(
46
+ "\n" +
47
+ `${Term.terminalBracket(["error", "Caused By"])}`
48
+ )
51
49
 
52
50
  this.cause.report(nerdMode, true)
53
- } else if(nerdMode && this.cause.stack) {
51
+ } else if(this.cause.stack) {
54
52
  Term.error()
55
53
  Term.group()
56
54
  Term.error(
@@ -1 +1 @@
1
- {"version":3,"file":"Sass.d.ts","sourceRoot":"","sources":["../../../src/browser/lib/Sass.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH;IAgIE;;;;;;;;OAQG;IACH,mBALW,KAAK,WACL,MAAM,GACJ,IAAI,CAahB;IAED;;;;;;;;OAQG;IACH,sBAJW,MAAM,UACN,KAAK,GAAC,IAAI,GAAC,OAAO,GAChB,IAAI,CAchB;IAvKD;;;;;OAKG;IACH,qBAHW,MAAM,WACH,OAAO,EAAA,EAMpB;IAWD;;;;OAIG;IACH,mBAFW,MAAM,EAIhB;IAhBD;;;;OAIG;IACH,aAFa,KAAK,CAAC,MAAM,CAAC,CAIzB;IAWD;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,IAAI,CAShB;IAED;;;;;;OAMG;IACH,kBAHW,OAAO,aACP,OAAO,QAyCjB;;CA6EF;oBAjLmB,cAAc"}
1
+ {"version":3,"file":"Sass.d.ts","sourceRoot":"","sources":["../../../src/browser/lib/Sass.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH;IA8HE;;;;;;;;OAQG;IACH,mBALW,KAAK,WACL,MAAM,GACJ,IAAI,CAahB;IAED;;;;;;;;OAQG;IACH,sBAJW,MAAM,UACN,KAAK,GAAC,IAAI,GAAC,OAAO,GAChB,IAAI,CAchB;IArKD;;;;;OAKG;IACH,qBAHW,MAAM,WACH,OAAO,EAAA,EAMpB;IAWD;;;;OAIG;IACH,mBAFW,MAAM,EAIhB;IAhBD;;;;OAIG;IACH,aAFa,KAAK,CAAC,MAAM,CAAC,CAIzB;IAWD;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,IAAI,CAShB;IAED;;;;;;OAMG;IACH,kBAHW,OAAO,aACP,OAAO,QAuCjB;;CA6EF;oBA/KmB,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"Valid.d.ts","sourceRoot":"","sources":["../../../src/browser/lib/Valid.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AAEH;;GAEG;AACH;IACE,0BAA0B;IAC1B,cADW,OAAO,IAAI,CACH;IAEnB;;;;;;OAMG;IACH,mBAJW,OAAO,QACP,MAAM,YACN,qBAAqB,QAY/B;IAED;;;;;;;;OAQG;IACH,yBANW,OAAO,WACP,MAAM,QAEN,MAAM,QAehB;IAED,2CAAkF;IAElF;;;;;;OAMG;IACH,0CAHW,KAAK,CAAC,MAAM,CAAC,QAYvB;CACF;;;;;;;;iBAvEa,OAAO;;iBARJ,WAAW"}
1
+ {"version":3,"file":"Valid.d.ts","sourceRoot":"","sources":["../../../src/browser/lib/Valid.js"],"names":[],"mappings":"AAWA;;;;;GAKG;AAEH;;GAEG;AACH;IACE,0BAA0B;IAC1B,cADW,OAAO,IAAI,CACH;IAEnB;;;;;;OAMG;IACH,mBAJW,OAAO,QACP,MAAM,YACN,qBAAqB,QAY/B;IAED;;;;;;;;OAQG;IACH,yBANW,OAAO,WACP,MAAM,QAEN,MAAM,QAehB;IAED,2CAAkF;IAElF;;;;;;OAMG;IACH,0CAHW,KAAK,CAAC,MAAM,CAAC,QAcvB;CACF;;;;;;;;iBAzEa,OAAO;;iBARJ,WAAW"}
@@ -40,6 +40,7 @@
40
40
  * @property {boolean} isDirectory - Always true
41
41
  * @property {DirectoryObject|null} parent - The parent directory (null if root)
42
42
  * @property {Promise<boolean>} exists - Whether the directory exists (async getter)
43
+ * @property {Promise<("none"|"symbolic"|null)>} linkType - The link kind at this path (async)
43
44
  *
44
45
  * @example
45
46
  * // Basic usage
@@ -100,6 +101,25 @@ export default class DirectoryObject extends FS {
100
101
  * @returns {Promise<boolean>} - A Promise that resolves to true or false
101
102
  */
102
103
  get exists(): Promise<boolean>;
104
+ /**
105
+ * Reports the link kind at this path. Reads the filesystem on every
106
+ * access, like {@link DirectoryObject#exists}, and throws under the
107
+ * same conditions: if the path exists but is not a directory (broken
108
+ * symlink, symlink to a non-directory, or a regular file), this throws
109
+ * a {@link Sass} error rather than returning a misleading value.
110
+ *
111
+ * - `"symbolic"` - a symlink whose target is a directory that exists
112
+ * - `"none"` - a regular directory
113
+ * - `null` - the path does not exist at all
114
+ *
115
+ * Hard links are not reported for directories: most filesystems do not
116
+ * allow hard-linked directories at all, and `nlink` on a directory is
117
+ * not a usable signal (it counts `.` and each subdirectory's `..`).
118
+ *
119
+ * @returns {Promise<"none"|"symbolic"|null>} The link kind
120
+ * @throws {Sass} If the path exists but does not resolve to a directory
121
+ */
122
+ get linkType(): Promise<"none" | "symbolic" | null>;
103
123
  /**
104
124
  * Return the path as passed to the constructor.
105
125
  *
@@ -176,8 +196,8 @@ export default class DirectoryObject extends FS {
176
196
  *
177
197
  * Returns FileObject and DirectoryObject instances. Symbolic links are
178
198
  * resolved to their target type: links to files appear in `files`, links
179
- * to directories appear in `directories`. Broken symlinks propagate the
180
- * stat error to the caller.
199
+ * to directories appear in `directories`. Broken symlinks (where the
200
+ * target does not exist) appear in `files` so they can be unlinked.
181
201
  *
182
202
  * @async
183
203
  * @param {string} [pat=""] - Optional glob pattern to filter results (e.g., "*.txt", "test-*")
@@ -202,8 +222,8 @@ export default class DirectoryObject extends FS {
202
222
  *
203
223
  * Returns FileObject and DirectoryObject instances. Symbolic links are
204
224
  * resolved to their target type: links to files appear in `files`, links
205
- * to directories appear in `directories`. Broken symlinks propagate the
206
- * stat error to the caller.
225
+ * to directories appear in `directories`. Broken symlinks (where the
226
+ * target does not exist) appear in `files` so they can be unlinked.
207
227
  *
208
228
  * @async
209
229
  * @param {string} [pat=""] - Glob pattern to filter results
@@ -1 +1 @@
1
- {"version":3,"file":"DirectoryObject.d.ts","sourceRoot":"","sources":["../../../src/node/lib/DirectoryObject.js"],"names":[],"mappings":"AAiBA;;;;GAIG;AAEH;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH;yBAoGa,MAAM,WACN,MAAM,oBAEJ,MAAM;IAhDnB;;;;;;;;;OASG;IACH,kBALa,eAAe,CAO3B;IA7CD;;;;OAIG;IACH,uBAFW,MAAM,OAAC,EA4BjB;IAyBD;;;;OAIG;IACH,UAFa,MAAM,CAclB;IA8BD;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;OAIG;IACH,gBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,GAAG,CAIf;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,aALa,KAAK,CAAC,MAAM,CAAC,CAOzB;IAED;;;;;;;;;;;;OAYG;IACH,cARa,eAAe,GAAC,IAAI,CAsBhC;IAED;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAmBD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAZW,MAAM,iBACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CAkCpF;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAXW,MAAM,iBACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CA0BpF;IAqCD;;;;;;;;;;;;OAYG;IACH,uBARW,MAAM,GACJ,OAAO,CAAC,SAAS,CAAC,CAuB9B;IAyBD;;;;;;;;;;;;;;;OAeG;IACH,cAZa,eAAe,CAc3B;IAED;;;;;;;;;;;;;;OAcG;IACH,UARa,OAAO,CAAC,SAAS,CAAC,CAkB9B;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAM5B;IAED;;;;;OAKG;IACH,sBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAO5B;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,sBAbW,MAAM,GACJ,eAAe,CAgC3B;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,kBAbW,MAAM,GACJ,UAAU,CAgCtB;IAxfD;;;;;;;OAOG;IACH,2BAHW,QAAQ,GAAC,QAAQ,GAAC,SAAS,GACzB,MAAM,GAAC,MAAM,CAQzB;;CA2eF;;UAvqBa,MAAY;QAAC,KAAK,EAAE,eAAe,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAC;eACnD,MAAY,aAAa;;;;;;iBAMzB,OAAO;;;;eACP,MAAM,GAAC,IAAI;;;;YACX,MAAM,GAAC,IAAI;;;;UACX,MAAM,GAAC,IAAI;;;;YACX,eAAe,GAAC,SAAS;;;;gBACzB,MAAM,GAAC,IAAI;;;;UACX,MAAM,GAAC,IAAI;;;;SACX,MAAM,GAAC,IAAI;;;;cACX,MAAM,GAAC,IAAI;;;;WACX,KAAK,CAAC,MAAM,CAAC,GAAC,IAAI;;;;SAClB,GAAG,GAAC,IAAI;;eAvBP,iBAAiB;uBADT,iBAAiB"}
1
+ {"version":3,"file":"DirectoryObject.d.ts","sourceRoot":"","sources":["../../../src/node/lib/DirectoryObject.js"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@
11
11
  * @property {boolean} isFile - Always true for files
12
12
  * @property {DirectoryObject} parent - The parent directory object
13
13
  * @property {Promise<boolean>} exists - Whether the file exists (async)
14
+ * @property {Promise<("none"|"symbolic"|"broken"|"hard"|null)>} linkType - The link kind at this path (async)
14
15
  */
15
16
  export default class FileObject extends FS {
16
17
  [x: number]: (depth: number, options: object, ins: Function) => string;
@@ -52,6 +53,21 @@ export default class FileObject extends FS {
52
53
  * @returns {Promise<boolean>} - A Promise that resolves to true or false
53
54
  */
54
55
  get exists(): Promise<boolean>;
56
+ /**
57
+ * Reports the link kind at this path. Reads the filesystem on every
58
+ * access, like {@link FileObject#exists}.
59
+ *
60
+ * - `"symbolic"` - a symlink whose target exists
61
+ * - `"broken"` - a symlink whose target does not exist
62
+ * - `"hard"` - a regular file with additional hard links (`nlink > 1`).
63
+ * Hard links are inode-level and indistinguishable from each other,
64
+ * so this only reports that *some* other entry shares the inode.
65
+ * - `"none"` - a regular file with no links
66
+ * - `null` - the path does not exist
67
+ *
68
+ * @returns {Promise<"none"|"symbolic"|"broken"|"hard"|null>} The link kind
69
+ */
70
+ get linkType(): Promise<"none" | "symbolic" | "broken" | "hard" | null>;
55
71
  /**
56
72
  * Return the normalized path that was provided to the constructor.
57
73
  *
@@ -1 +1 @@
1
- {"version":3,"file":"FileObject.d.ts","sourceRoot":"","sources":["../../../src/node/lib/FileObject.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;GAaG;AAEH;yBA8Ha,MAAM,WACN,MAAM,oBAEJ,MAAM;IAsfnB;;;;;;;;;;;OAWG;IACH,kBAPa,UAAU,CAsCtB;IAvoBD;;;;;OAKG;IACH,uBAHW,MAAM,WACN,eAAe,GAAC,MAAM,GAAC,IAAI,EA+DrC;IAWD;;;;OAIG;IACH,UAFa,MAAM,CAalB;IA8BD;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;OAIG;IACH,gBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,GAAG,CAIf;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAFa,MAAM,CAIlB;IACD;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;OAcG;IACH,cAFa,eAAe,CAI3B;IAED;;;;OAIG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,OAAO,CAAC,OAAO,CAAC,CAU5B;IAED;;;;OAIG;IACH,YAFa,OAAO,CAAC,OAAO,CAAC,CAU5B;IAiBD;;;;OAIG;IACH,QAFa,OAAO,CAAC,MAAM,OAAC,CAAC,CAU5B;IAED;;;;;OAKG;IACH,YAFa,OAAO,CAAC,IAAI,OAAC,CAAC,CAU1B;IAED;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;;;;OAOG;IACH,kBAJW,KAAK,GACH,UAAU,CAYtB;IAED;;;;OAIG;IACH,eAFa,UAAU,CAOtB;IAED;;;;OAIG;IACH,cAFa,UAAU,CAMtB;IAED;;;;;;;OAOG;IACH,+BAJG;QAAyB,QAAQ,GAAzB,MAAM;QACY,SAAS,GAA3B,OAAO;KACf,GAAU,OAAO,CAAC,MAAM,CAAC,CAa3B;IAED;;;;;;;;;;;OAWG;IACH,cARa,OAAO,CAAC,MAAM,CAAC,CAe3B;IAED;;;;;;;;;;;OAWG;IACH,eARW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,SAAS,CAAC,CAiB9B;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAXW,WAAW,GAAC,IAAI,GAAC,MAAM,GACrB,OAAO,CAAC,SAAS,CAAC,CAwB9B;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,yCAZG;QAAyB,IAAI,GAArB,MAAM;QACW,QAAQ,GAAzB,MAAM;QACY,SAAS,GAA3B,OAAO;KACf,GAAU,OAAO,CAAC,OAAO,CAAC,CAqB5B;IAED;;;;OAIG;IACH,UAFa,OAAO,CAAC,MAAM,CAAC,CAS3B;IAED;;;;;;;;;;;;OAYG;IACH,kBATW,MAAM,GACJ,OAAO,CAAC,UAAU,CAAC,CAyB/B;IAED;;;;;;;;;;;;;OAaG;IACH,kBATW,MAAM,GACJ,OAAO,CAAC,UAAU,CAAC,CA0C/B;IAED;;;;;;;;;OASG;IACH,UAPa,OAAO,CAAC,SAAS,CAAC,CAc9B;IA9eD;;;;;;;OAOG;IACH,2BAHW,QAAQ,GAAC,QAAQ,GAAC,SAAS,GACzB,MAAM,GAAC,MAAM,CAQzB;;CA8gBF;eAtrBc,iBAAiB;4BADJ,sBAAsB;kBAFhC,YAAY"}
1
+ {"version":3,"file":"FileObject.d.ts","sourceRoot":"","sources":["../../../src/node/lib/FileObject.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;GAcG;AAEH;yBA8Ha,MAAM,WACN,MAAM,oBAEJ,MAAM;IA2jBnB;;;;;;;;;;;OAWG;IACH,kBAPa,UAAU,CAsCtB;IA5sBD;;;;;OAKG;IACH,uBAHW,MAAM,WACN,eAAe,GAAC,MAAM,GAAC,IAAI,EA+DrC;IAWD;;;;OAIG;IACH,UAFa,MAAM,CAalB;IA8BD;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;;;;;;;;;;OAaG;IACH,gBAFa,OAAO,CAAC,MAAM,GAAC,UAAU,GAAC,QAAQ,GAAC,MAAM,GAAC,IAAI,CAAC,CAI3D;IAED;;;;OAIG;IACH,gBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,GAAG,CAIf;IAED;;;;OAIG;IACH,YAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,iBAFa,MAAM,CAIlB;IACD;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;OAcG;IACH,cAFa,eAAe,CAI3B;IAED;;;;OAIG;IACH,kBAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,OAAO,CAAC,OAAO,CAAC,CAU5B;IAED;;;;OAIG;IACH,YAFa,OAAO,CAAC,OAAO,CAAC,CAU5B;IAoED;;;;OAIG;IACH,QAFa,OAAO,CAAC,MAAM,OAAC,CAAC,CAU5B;IAED;;;;;OAKG;IACH,YAFa,OAAO,CAAC,IAAI,OAAC,CAAC,CAU1B;IAED;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;;;;OAOG;IACH,kBAJW,KAAK,GACH,UAAU,CAYtB;IAED;;;;OAIG;IACH,eAFa,UAAU,CAOtB;IAED;;;;OAIG;IACH,cAFa,UAAU,CAMtB;IAED;;;;;;;OAOG;IACH,+BAJG;QAAyB,QAAQ,GAAzB,MAAM;QACY,SAAS,GAA3B,OAAO;KACf,GAAU,OAAO,CAAC,MAAM,CAAC,CAa3B;IAED;;;;;;;;;;;OAWG;IACH,cARa,OAAO,CAAC,MAAM,CAAC,CAe3B;IAED;;;;;;;;;;;OAWG;IACH,eARW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,SAAS,CAAC,CAiB9B;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAXW,WAAW,GAAC,IAAI,GAAC,MAAM,GACrB,OAAO,CAAC,SAAS,CAAC,CAwB9B;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,yCAZG;QAAyB,IAAI,GAArB,MAAM;QACW,QAAQ,GAAzB,MAAM;QACY,SAAS,GAA3B,OAAO;KACf,GAAU,OAAO,CAAC,OAAO,CAAC,CAqB5B;IAED;;;;OAIG;IACH,UAFa,OAAO,CAAC,MAAM,CAAC,CAS3B;IAED;;;;;;;;;;;;OAYG;IACH,kBATW,MAAM,GACJ,OAAO,CAAC,UAAU,CAAC,CAyB/B;IAED;;;;;;;;;;;;;OAaG;IACH,kBATW,MAAM,GACJ,OAAO,CAAC,UAAU,CAAC,CA0C/B;IAED;;;;;;;;;OASG;IACH,UAPa,OAAO,CAAC,SAAS,CAAC,CAc9B;IAnjBD;;;;;;;OAOG;IACH,2BAHW,QAAQ,GAAC,QAAQ,GAAC,SAAS,GACzB,MAAM,GAAC,MAAM,CAQzB;;CAmlBF;eA5vBc,iBAAiB;4BADJ,sBAAsB;kBAFhC,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sass.d.ts","sourceRoot":"","sources":["../../../src/node/lib/Sass.js"],"names":[],"mappings":"AAgBA;;;GAGG;AACH;IACE;;;;;OAKG;IACH,kBAFW,OAAO,QAuCjB;;CAiCF;wBApFuB,2BAA2B"}
1
+ {"version":3,"file":"Sass.d.ts","sourceRoot":"","sources":["../../../src/node/lib/Sass.js"],"names":[],"mappings":"AAgBA;;;GAGG;AACH;IACE;;;;;OAKG;IACH,kBAFW,OAAO,QAqCjB;;CAiCF;wBAlFuB,2BAA2B"}
@@ -1,4 +1,4 @@
1
- // @gesslar/toolkit v5.1.0 - ES module bundle
1
+ // @gesslar/toolkit v5.3.0 - ES module bundle
2
2
  /**
3
3
  * @file Tantrum.js
4
4
  *
@@ -208,17 +208,15 @@ class Sass extends Error {
208
208
  );
209
209
  }
210
210
 
211
- if(this.cause) {
211
+ if(this.cause && nerdMode) {
212
212
  if(typeof this.cause.report === "function") {
213
- if(nerdMode) {
214
- console.error(
215
- "\n" +
216
- `[error] Caused By`
217
- );
218
- }
213
+ console.error(
214
+ "\n" +
215
+ `[error] Caused By`
216
+ );
219
217
 
220
218
  this.cause.report(nerdMode, true);
221
- } else if(nerdMode && this.cause.stack) {
219
+ } else if(this.cause.stack) {
222
220
  console.error();
223
221
  console.group();
224
222
  console.error(
@@ -385,7 +383,9 @@ class Valid {
385
383
  static prototypePollutionProtection(keys) {
386
384
  this.type(keys, "String[]");
387
385
 
388
- const oopsIDidItAgain = Collection.intersection(Valid.#restrictedProto, keys);
386
+ const oopsIDidItAgain = Collection.intersection(
387
+ Valid.#restrictedProto, keys
388
+ );
389
389
 
390
390
  this.assert(
391
391
  oopsIDidItAgain.length === 0,
@@ -1,4 +1,4 @@
1
- // @gesslar/toolkit v5.1.0 - UMD bundle
1
+ // @gesslar/toolkit v5.3.0 - UMD bundle
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -214,17 +214,15 @@
214
214
  );
215
215
  }
216
216
 
217
- if(this.cause) {
217
+ if(this.cause && nerdMode) {
218
218
  if(typeof this.cause.report === "function") {
219
- if(nerdMode) {
220
- console.error(
221
- "\n" +
222
- `[error] Caused By`
223
- );
224
- }
219
+ console.error(
220
+ "\n" +
221
+ `[error] Caused By`
222
+ );
225
223
 
226
224
  this.cause.report(nerdMode, true);
227
- } else if(nerdMode && this.cause.stack) {
225
+ } else if(this.cause.stack) {
228
226
  console.error();
229
227
  console.group();
230
228
  console.error(
@@ -391,7 +389,9 @@
391
389
  static prototypePollutionProtection(keys) {
392
390
  this.type(keys, "String[]");
393
391
 
394
- const oopsIDidItAgain = Collection.intersection(Valid.#restrictedProto, keys);
392
+ const oopsIDidItAgain = Collection.intersection(
393
+ Valid.#restrictedProto, keys
394
+ );
395
395
 
396
396
  this.assert(
397
397
  oopsIDidItAgain.length === 0,