@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.
- package/README.md +35 -0
- package/package.json +22 -10
- package/src/browser/index.js +10 -0
- package/src/{lib → browser/lib}/Data.js +24 -0
- package/src/browser/lib/Sass.js +168 -0
- package/src/browser/lib/Tantrum.js +115 -0
- package/src/browser/lib/Util.js +257 -0
- package/src/browser/lib/Valid.js +76 -0
- package/src/index.js +14 -12
- package/src/lib/Cache.js +2 -3
- package/src/lib/Contract.js +3 -4
- package/src/lib/FS.js +15 -20
- package/src/lib/FileObject.js +71 -14
- package/src/lib/Glog.js +2 -2
- package/src/lib/Sass.js +2 -91
- package/src/lib/Schemer.js +2 -2
- package/src/lib/Tantrum.js +3 -70
- package/src/lib/Terms.js +2 -3
- package/src/lib/Util.js +2 -252
- package/src/lib/Valid.js +17 -20
- package/src/types/browser/index.d.ts +8 -0
- package/src/types/browser/index.d.ts.map +1 -0
- package/src/types/browser/lib/Collection.d.ts +246 -0
- package/src/types/browser/lib/Collection.d.ts.map +1 -0
- package/src/types/browser/lib/Data.d.ts +206 -0
- package/src/types/browser/lib/Data.d.ts.map +1 -0
- package/src/types/browser/lib/Sass.d.ts +62 -0
- package/src/types/browser/lib/Sass.d.ts.map +1 -0
- package/src/types/browser/lib/Tantrum.d.ts +51 -0
- package/src/types/browser/lib/Tantrum.d.ts.map +1 -0
- package/src/types/browser/lib/TypeSpec.d.ts +92 -0
- package/src/types/browser/lib/TypeSpec.d.ts.map +1 -0
- package/src/types/browser/lib/Util.d.ts +129 -0
- package/src/types/browser/lib/Util.d.ts.map +1 -0
- package/src/types/browser/lib/Valid.d.ts +33 -0
- package/src/types/browser/lib/Valid.d.ts.map +1 -0
- package/src/types/index.d.ts +10 -10
- package/src/types/lib/Data.d.ts +17 -0
- package/src/types/lib/Data.d.ts.map +1 -1
- package/src/types/lib/FS.d.ts +2 -2
- package/src/types/lib/FS.d.ts.map +1 -1
- package/src/types/lib/FileObject.d.ts +31 -1
- package/src/types/lib/FileObject.d.ts.map +1 -1
- package/src/types/lib/Sass.d.ts +2 -55
- package/src/types/lib/Sass.d.ts.map +1 -1
- package/src/types/lib/Tantrum.d.ts +3 -44
- package/src/types/lib/Tantrum.d.ts.map +1 -1
- package/src/types/lib/Util.d.ts +3 -124
- package/src/types/lib/Util.d.ts.map +1 -1
- package/src/types/lib/Valid.d.ts +1 -1
- package/src/types/lib/Valid.d.ts.map +1 -1
- /package/src/{lib → browser/lib}/Collection.js +0 -0
- /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
|
-
//
|
|
2
|
-
export {default as
|
|
3
|
-
export {default as
|
|
4
|
-
export {default as
|
|
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
|
-
//
|
|
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
|
|
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
|
*/
|
package/src/lib/Contract.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Sass from "./Sass.js"
|
|
2
2
|
import Schemer from "./Schemer.js"
|
|
3
|
-
import
|
|
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 "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
package/src/lib/FileObject.js
CHANGED
|
@@ -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 "
|
|
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
|
|
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(!
|
|
361
|
-
throw Sass.new("No
|
|
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 '${
|
|
388
|
+
throw Sass.new(`No such file '${url.href}'`)
|
|
365
389
|
|
|
366
|
-
return await fs.readFile(
|
|
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
|
|
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.
|
|
383
|
-
throw Sass.new("No
|
|
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.
|
|
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
|
|
519
|
+
const url = this.url
|
|
463
520
|
|
|
464
|
-
if(!
|
|
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 '${
|
|
525
|
+
throw Sass.new(`No such resource '${url.href}'`)
|
|
469
526
|
|
|
470
|
-
return await fs.unlink(
|
|
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 "
|
|
16
|
+
import Data from "../browser/lib/Data.js"
|
|
17
17
|
import Term from "./Term.js"
|
|
18
|
-
import Util from "
|
|
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
|
|
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
|
}
|
package/src/lib/Schemer.js
CHANGED
package/src/lib/Tantrum.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 "
|
|
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) {
|