@gesslar/toolkit 0.7.1 → 1.0.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.
Files changed (53) hide show
  1. package/README.md +35 -0
  2. package/package.json +22 -10
  3. package/src/browser/index.js +10 -0
  4. package/src/{lib → browser/lib}/Data.js +24 -0
  5. package/src/browser/lib/Sass.js +168 -0
  6. package/src/browser/lib/Tantrum.js +115 -0
  7. package/src/browser/lib/Util.js +257 -0
  8. package/src/browser/lib/Valid.js +76 -0
  9. package/src/index.js +14 -12
  10. package/src/lib/Cache.js +2 -3
  11. package/src/lib/Contract.js +3 -4
  12. package/src/lib/FS.js +15 -20
  13. package/src/lib/FileObject.js +71 -14
  14. package/src/lib/Glog.js +2 -2
  15. package/src/lib/Sass.js +2 -91
  16. package/src/lib/Schemer.js +2 -2
  17. package/src/lib/Tantrum.js +3 -70
  18. package/src/lib/Terms.js +2 -3
  19. package/src/lib/Util.js +2 -252
  20. package/src/lib/Valid.js +17 -20
  21. package/src/types/browser/index.d.ts +8 -0
  22. package/src/types/browser/index.d.ts.map +1 -0
  23. package/src/types/browser/lib/Collection.d.ts +246 -0
  24. package/src/types/browser/lib/Collection.d.ts.map +1 -0
  25. package/src/types/browser/lib/Data.d.ts +206 -0
  26. package/src/types/browser/lib/Data.d.ts.map +1 -0
  27. package/src/types/browser/lib/Sass.d.ts +62 -0
  28. package/src/types/browser/lib/Sass.d.ts.map +1 -0
  29. package/src/types/browser/lib/Tantrum.d.ts +51 -0
  30. package/src/types/browser/lib/Tantrum.d.ts.map +1 -0
  31. package/src/types/browser/lib/TypeSpec.d.ts +92 -0
  32. package/src/types/browser/lib/TypeSpec.d.ts.map +1 -0
  33. package/src/types/browser/lib/Util.d.ts +129 -0
  34. package/src/types/browser/lib/Util.d.ts.map +1 -0
  35. package/src/types/browser/lib/Valid.d.ts +33 -0
  36. package/src/types/browser/lib/Valid.d.ts.map +1 -0
  37. package/src/types/index.d.ts +10 -10
  38. package/src/types/lib/Data.d.ts +17 -0
  39. package/src/types/lib/Data.d.ts.map +1 -1
  40. package/src/types/lib/FS.d.ts +2 -2
  41. package/src/types/lib/FS.d.ts.map +1 -1
  42. package/src/types/lib/FileObject.d.ts +31 -1
  43. package/src/types/lib/FileObject.d.ts.map +1 -1
  44. package/src/types/lib/Sass.d.ts +2 -55
  45. package/src/types/lib/Sass.d.ts.map +1 -1
  46. package/src/types/lib/Tantrum.d.ts +3 -44
  47. package/src/types/lib/Tantrum.d.ts.map +1 -1
  48. package/src/types/lib/Util.d.ts +3 -124
  49. package/src/types/lib/Util.d.ts.map +1 -1
  50. package/src/types/lib/Valid.d.ts +1 -1
  51. package/src/types/lib/Valid.d.ts.map +1 -1
  52. /package/src/{lib → browser/lib}/Collection.js +0 -0
  53. /package/src/{lib → browser/lib}/TypeSpec.js +0 -0
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @file Valid.js
3
+ *
4
+ * Provides validation utilities for type checking and assertion.
5
+ * Includes prototype pollution protection for secure object manipulation.
6
+ */
7
+
8
+ import Sass from "./Sass.js"
9
+ import Data from "./Data.js"
10
+ import Collection from "./Collection.js"
11
+
12
+ /**
13
+ * Validation utility class providing type checking and assertion methods.
14
+ */
15
+ export default class Valid {
16
+ /**
17
+ * Validates a value against a type. Uses Data.isType.
18
+ *
19
+ * @param {unknown} value - The value to validate
20
+ * @param {string} type - The expected type in the form of "object", "object[]", "object|object[]"
21
+ * @param {object} [options] - Additional options for validation.
22
+ */
23
+ static type(value, type, options) {
24
+ Valid.assert(
25
+ Data.isType(value, type, options),
26
+ `Invalid type. Expected ${type}, got ${JSON.stringify(value)}`,
27
+ 1,
28
+ )
29
+ }
30
+
31
+ /**
32
+ * Asserts a condition
33
+ *
34
+ * @param {boolean} condition - The condition to assert
35
+ * @param {string} message - The message to display if the condition is not
36
+ * met
37
+ * @param {number} [arg] - The argument to display if the condition is not
38
+ * met (optional)
39
+ */
40
+ static assert(condition, message, arg = null) {
41
+ if(!Data.isType(condition, "boolean")) {
42
+ throw Sass.new(`Condition must be a boolean, got ${condition}`)
43
+ }
44
+
45
+ if(!Data.isType(message, "string")) {
46
+ throw Sass.new(`Message must be a string, got ${message}`)
47
+ }
48
+
49
+ if(!(arg === null || arg === undefined || typeof arg === "number")) {
50
+ throw Sass.new(`Arg must be a number, got ${arg}`)
51
+ }
52
+
53
+ if(!condition)
54
+ throw Sass.new(`${message}${arg ? `: ${arg}` : ""}`)
55
+ }
56
+
57
+ static #restrictedProto = ["__proto__", "constructor", "prototype"]
58
+
59
+ /**
60
+ * Protects against prototype pollution by checking keys for dangerous property names.
61
+ * Throws if any restricted prototype properties are found in the keys array.
62
+ *
63
+ * @param {Array<string>} keys - Array of property keys to validate
64
+ * @throws {Sass} If any key matches restricted prototype properties (__proto__, constructor, prototype)
65
+ */
66
+ static prototypePollutionProtection(keys) {
67
+ Valid.type(keys, "String[]")
68
+
69
+ const oopsIDidItAgain = Collection.intersection(this.#restrictedProto, keys)
70
+
71
+ Valid.assert(
72
+ oopsIDidItAgain.length === 0,
73
+ `We don't pee in your pool, don't pollute ours with your ${String(oopsIDidItAgain)}`
74
+ )
75
+ }
76
+ }
package/src/index.js CHANGED
@@ -1,19 +1,21 @@
1
- // Core file system abstractions
2
- export {default as FileObject} from "./lib/FileObject.js"
3
- export {default as DirectoryObject} from "./lib/DirectoryObject.js"
4
- export {default as FS} from "./lib/FS.js"
1
+ // Browser-compatible utilities (pure JS)
2
+ export {default as Collection} from "./browser/lib/Collection.js"
3
+ export {default as Data} from "./browser/lib/Data.js"
4
+ export {default as Type} from "./browser/lib/TypeSpec.js"
5
+ export {default as Valid} from "./lib/Valid.js"
6
+
7
+ // Node-enhanced versions (use Term for better formatting, crypto, etc.)
8
+ export {default as Sass} from "./lib/Sass.js"
9
+ export {default as Tantrum} from "./lib/Tantrum.js"
10
+ export {default as Util} from "./lib/Util.js"
5
11
 
6
- // Utility classes
12
+ // Node-specific exports
7
13
  export {default as Cache} from "./lib/Cache.js"
8
- export {default as Collection} from "./lib/Collection.js"
9
14
  export {default as Contract} from "./lib/Contract.js"
10
- export {default as Data} from "./lib/Data.js"
15
+ export {default as DirectoryObject} from "./lib/DirectoryObject.js"
16
+ export {default as FileObject} from "./lib/FileObject.js"
17
+ export {default as FS} from "./lib/FS.js"
11
18
  export {default as Glog} from "./lib/Glog.js"
12
- export {default as Sass} from "./lib/Sass.js"
13
19
  export {default as Schemer} from "./lib/Schemer.js"
14
- export {default as Tantrum} from "./lib/Tantrum.js"
15
20
  export {default as Term} from "./lib/Term.js"
16
21
  export {default as Terms} from "./lib/Terms.js"
17
- export {default as Type} from "./lib/TypeSpec.js"
18
- export {default as Util} from "./lib/Util.js"
19
- export {default as Valid} from "./lib/Valid.js"
package/src/lib/Cache.js CHANGED
@@ -1,4 +1,3 @@
1
- import FileObject from "./FileObject.js"
2
1
  import Sass from "./Sass.js"
3
2
 
4
3
  /**
@@ -22,7 +21,7 @@ export default class Cache {
22
21
  * maintained.
23
22
  *
24
23
  * @private
25
- * @param {FileObject} file - The file object to remove from cache
24
+ * @param {import("./FileObject.js").FileObject} file - The file object to remove from cache
26
25
  * @returns {void}
27
26
  */
28
27
  #cleanup(file) {
@@ -39,7 +38,7 @@ export default class Cache {
39
38
  * freshness while optimizing performance for repeated file access during
40
39
  * parallel processing.
41
40
  *
42
- * @param {FileObject} fileObject - The file object to load and cache
41
+ * @param {import("./FileObject.js").FileObject} fileObject - The file object to load and cache
43
42
  * @returns {Promise<unknown>} The parsed file data (JSON5 or YAML)
44
43
  * @throws {Sass} If the file cannot be found or accessed
45
44
  */
@@ -1,7 +1,6 @@
1
1
  import Sass from "./Sass.js"
2
2
  import Schemer from "./Schemer.js"
3
- import Terms from "./Terms.js"
4
- import Data from "./Data.js"
3
+ import Data from "../browser/lib/Data.js"
5
4
 
6
5
  /**
7
6
  * Contract represents a successful negotiation between Terms.
@@ -18,8 +17,8 @@ export default class Contract {
18
17
  /**
19
18
  * Creates a contract by negotiating between provider and consumer terms
20
19
  *
21
- * @param {Terms} providerTerms - What the provider offers
22
- * @param {Terms} consumerTerms - What the consumer expects
20
+ * @param {import("./Terms.js").Terms} providerTerms - What the provider offers
21
+ * @param {import("./Terms.js").Terms} consumerTerms - What the consumer expects
23
22
  * @param {object} options - Configuration options
24
23
  * @param {import('../types.js').DebugFunction} [options.debug] - Debug function
25
24
  */
package/src/lib/FS.js CHANGED
@@ -9,12 +9,13 @@ import {globby} from "globby"
9
9
  import path from "node:path"
10
10
  import url from "node:url"
11
11
 
12
- import Collection from "./Collection.js"
13
- import DirectoryObject from "./DirectoryObject.js"
14
- import FileObject from "./FileObject.js"
12
+ import Collection from "../browser/lib/Collection.js"
15
13
  import Sass from "./Sass.js"
16
14
  import Valid from "./Valid.js"
17
15
 
16
+ /** @typedef {import("./FileObject.js").default} FileObject */
17
+ /** @typedef {import("./DirectoryObject.js").default} DirectoryObject */
18
+
18
19
  const fdTypes = Object.freeze(["file", "directory"])
19
20
  const upperFdTypes = Object.freeze(fdTypes.map(type => type.toUpperCase()))
20
21
  const fdType = Object.freeze(
@@ -78,37 +79,31 @@ export default class FS {
78
79
  * @throws {Sass} If the glob pattern array is empty or for other search failures.
79
80
  */
80
81
  static async getFiles(glob) {
82
+ const isString = typeof glob === "string"
83
+ const isArray = Array.isArray(glob)
84
+ const isStringArray = isArray && glob.every(item => typeof item === "string")
85
+
81
86
  Valid.assert(
82
- (
83
- (typeof glob === "string" && glob.length > 0) ||
84
- (
85
- Collection.isArrayUniform(glob, "string") &&
86
- glob.length > 0
87
- )
88
- ),
87
+ (isString && glob.length > 0) ||
88
+ (isStringArray && glob.length > 0),
89
89
  "glob must be a non-empty string or array of strings.",
90
90
  1
91
91
  )
92
92
 
93
93
  const globbyArray = (
94
- typeof glob === "string"
95
- ? glob
96
- .split("|")
97
- .map(g => g.trim())
98
- .filter(Boolean)
94
+ isString
95
+ ? glob.split("|").map(g => g.trim()).filter(Boolean)
99
96
  : glob
100
97
  ).map(g => FS.fixSlashes(g))
101
98
 
102
- if(
103
- Array.isArray(globbyArray) &&
104
- Collection.isArrayUniform(globbyArray, "string") &&
105
- !globbyArray.length
106
- )
99
+ if(isArray && !globbyArray.length)
107
100
  throw Sass.new(
108
101
  `Invalid glob pattern: Array cannot be empty. Got ${JSON.stringify(glob)}`,
109
102
  )
110
103
 
111
104
  // Use Globby to fetch matching files
105
+ const {default: FileObject} = await import("./FileObject.js")
106
+
112
107
  const filesArray = await globby(globbyArray)
113
108
  const files = filesArray.map(file => new FileObject(file))
114
109
 
@@ -11,7 +11,7 @@ import util from "node:util"
11
11
  import YAML from "yaml"
12
12
  import {URL} from "node:url"
13
13
 
14
- import Data from "./Data.js"
14
+ import Data from "../browser/lib/Data.js"
15
15
  import DirectoryObject from "./DirectoryObject.js"
16
16
  import FS from "./FS.js"
17
17
  import Sass from "./Sass.js"
@@ -355,15 +355,39 @@ export default class FileObject extends FS {
355
355
  * @returns {Promise<string>} The file contents
356
356
  */
357
357
  async read(encoding="utf8") {
358
- const filePath = this.path
358
+ const url = this.url
359
+
360
+ if(!url)
361
+ throw Sass.new("No URL in file map")
362
+
363
+ if(!(await this.exists))
364
+ throw Sass.new(`No such file '${url.href}'`)
365
+
366
+ return await fs.readFile(url, encoding)
367
+ }
368
+
369
+ /**
370
+ * Reads binary data from a file asynchronously.
371
+ * Returns the file contents as a Buffer (Node.js binary data type).
372
+ *
373
+ * @returns {Promise<Buffer>} The file contents as a Buffer
374
+ * @throws {Sass} If the file URL is invalid
375
+ * @throws {Sass} If the file does not exist
376
+ * @example
377
+ * const file = new FileObject('./image.png')
378
+ * const buffer = await file.readBinary()
379
+ * // Use the buffer (e.g., send in HTTP response, process image, etc.)
380
+ */
381
+ async readBinary() {
382
+ const url = this.url
359
383
 
360
- if(!filePath)
361
- throw Sass.new("No absolute path in file map")
384
+ if(!url)
385
+ throw Sass.new("No URL in file map")
362
386
 
363
387
  if(!(await this.exists))
364
- throw Sass.new(`No such file '${filePath}'`)
388
+ throw Sass.new(`No such file '${url.href}'`)
365
389
 
366
- return await fs.readFile(filePath, encoding)
390
+ return await fs.readFile(url)
367
391
  }
368
392
 
369
393
  /**
@@ -373,22 +397,55 @@ export default class FileObject extends FS {
373
397
  * @param {string} content - The content to write
374
398
  * @param {string} [encoding] - The encoding in which to write (default: "utf8")
375
399
  * @returns {Promise<void>}
376
- * @throws {Sass} If the file path is invalid or the parent directory doesn't exist
400
+ * @throws {Sass} If the file URL is invalid or the parent directory doesn't exist
377
401
  * @example
378
402
  * const file = new FileObject('./output/data.json')
379
403
  * await file.write(JSON.stringify({key: 'value'}))
380
404
  */
381
405
  async write(content, encoding="utf8") {
382
- if(!this.path)
383
- throw Sass.new("No absolute path in file")
406
+ if(!this.url)
407
+ throw Sass.new("No URL in file")
384
408
 
385
409
  if(await this.directory.exists)
386
- await fs.writeFile(this.path, content, encoding)
410
+ await fs.writeFile(this.url, content, encoding)
387
411
 
388
412
  else
389
413
  throw Sass.new(`Invalid directory, ${this.directory.url.href}`)
390
414
  }
391
415
 
416
+ /**
417
+ * Writes binary data to a file asynchronously.
418
+ * Validates that the parent directory exists and that the data is valid binary format.
419
+ * Supports ArrayBuffer, TypedArrays (Uint8Array, etc.), Blob, and Node Buffer types.
420
+ *
421
+ * @param {ArrayBuffer|Blob|Buffer} data - The binary data to write
422
+ * @returns {Promise<void>}
423
+ * @throws {Sass} If the file URL is invalid
424
+ * @throws {Sass} If the parent directory doesn't exist
425
+ * @throws {Sass} If the data is not a valid binary type
426
+ * @example
427
+ * const file = new FileObject('./output/image.png')
428
+ * const response = await fetch('https://example.com/image.png')
429
+ * const buffer = await response.arrayBuffer()
430
+ * await file.writeBinary(buffer)
431
+ */
432
+ async writeBinary(data) {
433
+ if(!this.url)
434
+ throw Sass.new("No URL in file")
435
+
436
+ const exists = await this.directory.exists
437
+ Valid.assert(exists, `Invalid directory, ${this.directory.url.href}`)
438
+
439
+ Valid.assert(Data.isBinary(data), "Data must be binary (ArrayBuffer, TypedArray, Blob, or Buffer)")
440
+
441
+ // Convert ArrayBuffer to Buffer if needed (fs.writeFile doesn't accept ArrayBuffer directly)
442
+ const bufferData = data instanceof ArrayBuffer ? Buffer.from(data) : data
443
+
444
+ // According to the internet, if it's already binary, I don't need
445
+ // an encoding. 🤷
446
+ return await fs.writeFile(this.url, bufferData)
447
+ }
448
+
392
449
  /**
393
450
  * Loads an object from JSON or YAML file.
394
451
  * Attempts to parse content as JSON5 first, then falls back to YAML if specified.
@@ -459,14 +516,14 @@ export default class FileObject extends FS {
459
516
  * await file.delete()
460
517
  */
461
518
  async delete() {
462
- const filePath = this.path
519
+ const url = this.url
463
520
 
464
- if(!filePath)
521
+ if(!url)
465
522
  throw Sass.new("This object does not represent a valid resource.")
466
523
 
467
524
  if(!(await this.exists))
468
- throw Sass.new(`No such resource '${this.url.href}'`)
525
+ throw Sass.new(`No such resource '${url.href}'`)
469
526
 
470
- return await fs.unlink(this.path)
527
+ return await fs.unlink(url)
471
528
  }
472
529
  }
package/src/lib/Glog.js CHANGED
@@ -13,9 +13,9 @@
13
13
 
14
14
  import c from "@gesslar/colours"
15
15
 
16
- import Data from "./Data.js"
16
+ import Data from "../browser/lib/Data.js"
17
17
  import Term from "./Term.js"
18
- import Util from "./Util.js"
18
+ import Util from "../browser/lib/Util.js"
19
19
  // ErrorStackParser will be dynamically imported when needed
20
20
 
21
21
  // Enhanced color system using @gesslar/colours
package/src/lib/Sass.js CHANGED
@@ -11,61 +11,14 @@
11
11
  * debugging.
12
12
  */
13
13
 
14
+ import {Sass as BrowserSass} from "../browser/index.js"
14
15
  import Term from "./Term.js"
15
- import Tantrum from "./Tantrum.js"
16
16
 
17
17
  /**
18
18
  * Custom error class for toolkit errors.
19
19
  * Provides error chaining, trace management, and formatted error reporting.
20
20
  */
21
- export default class Sass extends Error {
22
- #trace = []
23
-
24
- /**
25
- * Creates a new Sass instance.
26
- *
27
- * @param {string} message - The error message
28
- * @param {...unknown} [arg] - Additional arguments passed to parent Error constructor
29
- */
30
- constructor(message, ...arg) {
31
- super(message, ...arg)
32
-
33
- this.trace = message
34
- }
35
-
36
- /**
37
- * Gets the error trace array.
38
- *
39
- * @returns {Array<string>} Array of trace messages
40
- */
41
- get trace() {
42
- return this.#trace
43
- }
44
-
45
- /**
46
- * Adds a message to the beginning of the trace array.
47
- *
48
- * @param {string} message - The trace message to add
49
- */
50
- set trace(message) {
51
- this.#trace.unshift(message)
52
- }
53
-
54
- /**
55
- * Adds a trace message and returns this instance for chaining.
56
- *
57
- * @param {string} message - The trace message to add
58
- * @returns {this} This Sass instance for method chaining
59
- */
60
- addTrace(message) {
61
- if(typeof message !== "string")
62
- throw Sass.new(`Sass.addTrace expected string, got ${JSON.stringify(message)}`)
63
-
64
- this.trace = message
65
-
66
- return this
67
- }
68
-
21
+ export default class Sass extends BrowserSass {
69
22
  /**
70
23
  * Reports the error to the terminal with formatted output.
71
24
  * Optionally includes detailed stack trace information.
@@ -124,46 +77,4 @@ export default class Sass extends Error {
124
77
 
125
78
  return lines.join("\n")
126
79
  }
127
-
128
- /**
129
- * Creates an Sass from an existing Error object with additional
130
- * trace message.
131
- *
132
- * @param {Error} error - The original error object
133
- * @param {string} message - Additional trace message to add
134
- * @returns {Sass} New Sass instance with trace from the original error
135
- * @throws {Sass} If the first parameter is not an Error instance
136
- */
137
- static from(error, message) {
138
- if(!(error instanceof Error))
139
- throw Sass.new("Sass.from must take an Error object.")
140
-
141
- const oldMessage = error.message
142
- const newError = new Sass(oldMessage, {cause: error}).addTrace(message)
143
-
144
- return newError
145
- }
146
-
147
- /**
148
- * Factory method to create or enhance Sass instances.
149
- * If error parameter is provided, enhances existing Sass or wraps
150
- * other errors. Otherwise creates a new Sass instance.
151
- *
152
- * @param {string} message - The error message
153
- * @param {Error|Sass|Tantrum} [error] - Optional existing error to wrap or enhance
154
- * @returns {Sass} New or enhanced Sass instance
155
- */
156
- static new(message, error) {
157
- if(error) {
158
- if(error instanceof Tantrum)
159
- return Tantrum.new(message, error)
160
-
161
- return error instanceof Sass
162
- ? error.addTrace(message)
163
- : Sass.from(error, message)
164
- } else {
165
-
166
- return new Sass(message)
167
- }
168
- }
169
80
  }
@@ -1,7 +1,7 @@
1
1
  import Ajv from "ajv"
2
2
 
3
- import Data from "./Data.js"
4
- import Util from "./Util.js"
3
+ import Data from "../browser/lib/Data.js"
4
+ import Util from "../browser/lib/Util.js"
5
5
  import Valid from "./Valid.js"
6
6
 
7
7
  /**
@@ -9,6 +9,7 @@
9
9
  * multiple error scenarios.
10
10
  */
11
11
 
12
+ import {Tantrum as BrowserTantrum} from "../browser/index.js"
12
13
  import Sass from "./Sass.js"
13
14
  import Term from "./Term.js"
14
15
 
@@ -16,63 +17,9 @@ import Term from "./Term.js"
16
17
  * Custom aggregate error class that extends AggregateError.
17
18
  * Automatically wraps plain errors in Sass instances for consistent reporting.
18
19
  */
19
- export default class Tantrum extends AggregateError {
20
- #trace = []
21
-
22
- /**
23
- * Creates a new Tantrum instance.
24
- *
25
- * @param {string} message - The aggregate error message
26
- * @param {Array<Error|Sass>} errors - Array of errors to aggregate
27
- */
20
+ export default class Tantrum extends BrowserTantrum {
28
21
  constructor(message, errors = []) {
29
- // Auto-wrap plain errors in Sass, keep existing Sass instances
30
- const wrappedErrors = errors.map(error => {
31
- if(error instanceof Sass)
32
- return error
33
-
34
- if(!(error instanceof Error))
35
- throw new TypeError(`All items in errors array must be Error instances, got: ${typeof error}`)
36
-
37
- return Sass.new(error.message, error)
38
- })
39
-
40
- super(wrappedErrors, message)
41
- this.name = "Tantrum"
42
- }
43
-
44
- /**
45
- * Adds a trace message and returns this instance for chaining.
46
- *
47
- * @param {string} message - The trace message to add
48
- * @param {Error|Sass} [_error] - Optional error (currently unused, reserved for future use)
49
- * @returns {this} This Tantrum instance for method chaining
50
- */
51
- addTrace(message, _error) {
52
- if(typeof message !== "string")
53
- throw Sass.new(`Tantrum.addTrace expected string, got ${JSON.stringify(message)}`)
54
-
55
- this.trace = message
56
-
57
- return this
58
- }
59
-
60
- /**
61
- * Gets the error trace array.
62
- *
63
- * @returns {Array<string>} Array of trace messages
64
- */
65
- get trace() {
66
- return this.#trace
67
- }
68
-
69
- /**
70
- * Adds a message to the beginning of the trace array.
71
- *
72
- * @param {string} message - The trace message to add
73
- */
74
- set trace(message) {
75
- this.#trace.unshift(message)
22
+ super(message, errors, Sass)
76
23
  }
77
24
 
78
25
  /**
@@ -95,18 +42,4 @@ export default class Tantrum extends AggregateError {
95
42
  error.report(nerdMode)
96
43
  })
97
44
  }
98
-
99
- /**
100
- * Factory method to create a Tantrum instance.
101
- *
102
- * @param {string} message - The aggregate error message
103
- * @param {Array<Error|Sass>} errors - Array of errors to aggregate
104
- * @returns {Tantrum} New Tantrum instance
105
- */
106
- static new(message, errors = []) {
107
- if(errors instanceof Tantrum)
108
- return errors.addTrace(message)
109
-
110
- return new Tantrum(message, errors)
111
- }
112
45
  }
package/src/lib/Terms.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import JSON5 from "json5"
2
2
  import yaml from "yaml"
3
3
 
4
- import Data from "./Data.js"
5
- import DirectoryObject from "./DirectoryObject.js"
4
+ import Data from "../browser/lib/Data.js"
6
5
  import FileObject from "./FileObject.js"
7
6
  import Sass from "./Sass.js"
8
7
  import Valid from "./Valid.js"
@@ -24,7 +23,7 @@ export default class Terms {
24
23
  * Parses terms data, handling file references
25
24
  *
26
25
  * @param {string|object} termsData - Terms data or reference
27
- * @param {DirectoryObject?} directoryObject - Directory context for file resolution
26
+ * @param {import("./DirectoryObject.js").DirectoryObject?} directoryObject - Directory context for file resolution
28
27
  * @returns {object} Parsed terms data
29
28
  */
30
29
  static async parse(termsData, directoryObject) {