@gesslar/toolkit 3.8.0 → 3.12.3

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.
@@ -4,13 +4,16 @@
4
4
  * to the OS's temporary directory tree.
5
5
  */
6
6
 
7
- import fs from "node:fs"
7
+ import fs, {mkdirSync, mkdtempSync} from "node:fs"
8
8
  import os from "node:os"
9
9
  import path from "node:path"
10
10
 
11
- import CappedDirectoryObject from "./CappedDirectoryObject.js"
12
11
  import Data from "../browser/lib/Data.js"
12
+ import CappedDirectoryObject from "./CappedDirectoryObject.js"
13
+ import DirectoryObject from "./DirectoryObject.js"
14
+ import FS from "./FS.js"
13
15
  import Sass from "./Sass.js"
16
+ import Valid from "./Valid.js"
14
17
 
15
18
  /**
16
19
  * TempDirectoryObject extends CappedDirectoryObject with the cap set to
@@ -23,6 +26,8 @@ import Sass from "./Sass.js"
23
26
  * @augments CappedDirectoryObject
24
27
  */
25
28
  export default class TempDirectoryObject extends CappedDirectoryObject {
29
+ #tmpReal
30
+ #tmpCap
26
31
 
27
32
  /**
28
33
  * Constructs a TempDirectoryObject instance and creates the directory.
@@ -34,7 +39,7 @@ export default class TempDirectoryObject extends CappedDirectoryObject {
34
39
  * is provided without a parent, creates a new directory with a unique suffix.
35
40
  * If a parent is provided, creates a subdirectory within that parent.
36
41
  *
37
- * @param {string?} [name] - Base name for the temp directory (if empty/null, uses OS temp dir)
42
+ * @param {string?} [directory] - Base name for the temp directory (if empty/null, uses OS temp dir)
38
43
  * @param {TempDirectoryObject?} [parent] - Optional parent temporary directory
39
44
  * @throws {Sass} If name is absolute
40
45
  * @throws {Sass} If name is empty (when parent is provided)
@@ -43,159 +48,118 @@ export default class TempDirectoryObject extends CappedDirectoryObject {
43
48
  * @throws {Sass} If parent's lineage does not trace back to the OS temp directory
44
49
  * @throws {Sass} If directory creation fails
45
50
  * @example
46
- * // Use OS temp directory directly
47
- * const temp = new TempDirectoryObject()
48
- * console.log(temp.path) // "/tmp"
49
- *
50
- * @example
51
51
  * // Create with unique name
52
52
  * const temp = new TempDirectoryObject("myapp")
53
- * console.log(temp.path) // "/tmp/myapp-ABC123"
54
- *
55
- * @example
56
- * // Nested temp directories
57
- * const parent = new TempDirectoryObject("parent")
58
- * const child = new TempDirectoryObject("child", parent)
59
- * await parent.remove() // Removes both parent and child
53
+ * console.log(temp.path) // "/"
54
+ * console.log(temp.real.path) // "/tmp/myapp-ABC123"
60
55
  */
61
- constructor(name, parent=null) {
62
- let dirPath
63
- let cappedParent = parent
64
-
65
- if(!parent) {
66
- // No parent: need to create a capped parent at tmpdir first
67
- cappedParent = new CappedDirectoryObject(os.tmpdir(), null, true)
68
-
69
- if(name) {
70
- // Check if name is a simple name (no separators, not absolute)
71
- const isSimpleName = !path.isAbsolute(name) &&
72
- !name.includes("/") &&
73
- !name.includes("\\") &&
74
- !name.includes(path.sep)
75
-
76
- if(isSimpleName) {
77
- // Simple name: add unique suffix
78
- const prefix = name.endsWith("-") ? name : `${name}-`
79
- const uniqueSuffix =
80
- Math.random()
81
- .toString(36)
82
- .substring(2, 8)
83
- .toUpperCase()
84
- dirPath = `${prefix}${uniqueSuffix}`
85
- } else {
86
- // Complex path: use as-is, let CappedDirectoryObject handle coercion
87
- dirPath = name
88
- }
89
- } else {
90
- // No name: use tmpdir itself (no parent)
91
- dirPath = os.tmpdir()
92
- cappedParent = null
93
- }
94
- } else {
95
- // With parent: validate it's a proper temp directory parent
96
- if(!Data.isType(parent, "CappedDirectoryObject")) {
97
- throw Sass.new(
98
- "Parent must be a CappedDirectoryObject or TempDirectoryObject."
99
- )
100
- }
101
-
102
- // SECURITY: Ensure parent's cap is within tmpdir (prevent escape to other caps)
103
- const tmpdir = path.resolve(os.tmpdir())
104
- const parentCap = path.resolve(parent.cap)
105
-
106
- if(!parentCap.startsWith(tmpdir)) {
107
- throw Sass.new(
108
- `Parent must be capped to OS temp directory (${tmpdir}) or a subdirectory thereof, ` +
109
- `got cap: ${parent.cap}`
110
- )
111
- }
112
-
113
- dirPath = name || ""
114
- if(!dirPath) {
115
- throw Sass.new("Name must not be empty when parent is provided.")
116
- }
117
- }
56
+ constructor(directory, source=null) {
57
+ Valid.type(source, "Null|TempDirectoryObject")
118
58
 
119
- // Call parent constructor with new signature
120
- super(dirPath, cappedParent, true)
59
+ directory ||= "temp"
60
+ directory = Data.append(directory, source ? "" : "-")
121
61
 
122
- // Temp-specific behavior: create directory immediately
123
- this.#createDirectory()
62
+ const parentRealPath = source?.real.path ?? os.tmpdir()
124
63
 
125
- // Re-cap to the temp directory itself for consistent behavior with CappedDirectoryObject
126
- // This makes temp.cap === temp.real.path and temp.parent === null
127
- if(!parent) {
128
- // Only re-cap if this is a root temp directory (no TempDirectoryObject parent)
129
- this._recapToSelf()
64
+ if(source && path.isAbsolute(directory)) {
65
+ const {root} = FS.pathParts(directory)
66
+
67
+ directory = Data.chopLeft(directory, root)
130
68
  }
131
- }
132
69
 
133
- /**
134
- * Creates the directory synchronously on the filesystem.
135
- *
136
- * @private
137
- * @throws {Sass} If directory creation fails
138
- */
139
- #createDirectory() {
140
- try {
141
- // Use recursive: true to create parent directories as needed
142
- fs.mkdirSync(this.realPath, {recursive: true})
143
- } catch(e) {
144
- // EEXIST is fine - directory already exists
145
- if(e.code !== "EEXIST") {
146
- throw Sass.new(
147
- `Unable to create temporary directory '${this.realPath}': ${e.message}`
148
- )
149
- }
70
+ let realTempDirectoryPath, toSuper
71
+
72
+ if(source) {
73
+ toSuper = `/${directory}`
74
+ realTempDirectoryPath =
75
+ FS.mergeOverlappingPaths(parentRealPath, directory)
76
+ if(!fs.existsSync(realTempDirectoryPath))
77
+ mkdirSync(realTempDirectoryPath)
78
+ } else {
79
+ realTempDirectoryPath =
80
+ mkdtempSync(FS.mergeOverlappingPaths(os.tmpdir(), directory))
81
+ toSuper = path.resolve(path.sep)
150
82
  }
83
+
84
+ super(toSuper, source)
85
+
86
+ this.#tmpReal = new DirectoryObject(realTempDirectoryPath)
87
+ this.#tmpCap = source?.cap ?? this
88
+ }
89
+
90
+ get isTemporary() {
91
+ return true
151
92
  }
152
93
 
153
94
  /**
154
- * Creates a new TempDirectoryObject by extending this directory's path.
95
+ * Returns a plain DirectoryObject representing the actual filesystem location.
96
+ * This provides an "escape hatch" from the capped environment to interact
97
+ * with the real filesystem when needed.
155
98
  *
156
- * Validates that the resulting path remains within the temp directory tree.
157
- *
158
- * @param {string} newPath - The path segment to append
159
- * @returns {TempDirectoryObject} A new TempDirectoryObject with the extended path
160
- * @throws {Sass} If the path would escape the temp directory
161
- * @throws {Sass} If the path is absolute
162
- * @throws {Sass} If the path contains traversal (..)
99
+ * @returns {DirectoryObject} Uncapped directory object at the real filesystem path
163
100
  * @example
164
101
  * const temp = new TempDirectoryObject("myapp")
165
- * const subDir = temp.getDirectory("data")
166
- * console.log(subDir.path) // "/tmp/myapp-ABC123/data"
102
+ * const subdir = temp.getDirectory("data")
103
+ *
104
+ * // Work within the capped environment (virtual paths)
105
+ * console.log(subdir.path) // "/data" (virtual)
106
+ * subdir.getFile("config.json") // Stays within cap
107
+ *
108
+ * // Break out to real filesystem when needed
109
+ * console.log(subdir.real.path) // "/tmp/myapp-ABC123/data" (real)
110
+ * subdir.real.parent // Can traverse outside the cap
167
111
  */
168
- getDirectory(newPath) {
169
- // Delegate to base class getDirectory() which will call TempDirectoryObject constructor
170
- return super.getDirectory(newPath)
112
+ get real() {
113
+ return this.#tmpReal
114
+ }
115
+
116
+ get cap() {
117
+ return this.#tmpCap
171
118
  }
172
119
 
173
120
  /**
174
- * Creates a new FileObject by extending this directory's path.
121
+ * Recursively removes a temporary directory and all its contents.
175
122
  *
176
- * Validates that the resulting path remains within the temp directory tree.
123
+ * This method will delete all files and subdirectories within this directory,
124
+ * then delete the directory itself. It only works on directories explicitly
125
+ * marked as temporary for safety.
177
126
  *
178
- * @param {string} filename - The filename to append
179
- * @returns {FileObject} A new FileObject with the extended path
180
- * @throws {Sass} If the path would escape the temp directory
181
- * @throws {Sass} If the path is absolute
182
- * @throws {Sass} If the path contains traversal (..)
127
+ * @async
128
+ * @returns {Promise<void>}
129
+ * @throws {Sass} If the directory is not marked as temporary
130
+ * @throws {Sass} If the directory deletion fails
183
131
  * @example
184
- * const temp = new TempDirectoryObject("myapp")
185
- * const file = temp.getFile("config.json")
186
- * console.log(file.path) // "/tmp/myapp-ABC123/config.json"
132
+ * const tempDir = new TempDirectoryObject("my-temp")
133
+ * await tempDir.assureExists()
134
+ * // ... use the directory ...
135
+ * await tempDir.remove() // Recursively deletes everything
187
136
  */
188
- getFile(filename) {
189
- // Delegate to base class getFile() which handles security checks
190
- return super.getFile(filename)
137
+ async remove() {
138
+ await this.#recurseDelete(this.real)
139
+ }
140
+
141
+ async #recurseDelete(directory) {
142
+ const {files, directories} = await directory.read()
143
+
144
+ // files first
145
+ for(const file of files)
146
+ await file.delete()
147
+
148
+ // now dir-ty dirs
149
+ for(const dir of directories)
150
+ await this.#recurseDelete(dir)
151
+
152
+ // byebyebyeeee 🕺🏾
153
+ await directory.delete()
191
154
  }
192
155
 
193
156
  /**
194
- * Returns a string representation of the TempDirectoryObject.
157
+ * TempDirectoryObject does not support fromCwd() since it is specifically
158
+ * designed to work within the OS temporary directory tree.
195
159
  *
196
- * @returns {string} string representation of the TempDirectoryObject
160
+ * @throws {Sass} Always throws an error
197
161
  */
198
- toString() {
199
- return `[TempDirectoryObject: ${this.path}]`
162
+ static fromCwd() {
163
+ throw Sass.new("TempDirectoryObject.fromCwd() is not supported.")
200
164
  }
201
165
  }
package/src/lib/Valid.js CHANGED
@@ -25,7 +25,7 @@ export default class Valid {
25
25
  static type(value, type, options) {
26
26
  Valid.assert(
27
27
  Data.isType(value, type, options),
28
- `Invalid type. Expected ${type}, got ${JSON.stringify(value)}`,
28
+ `Invalid type. Expected ${type}, got ${Data.typeOf(value)}`,
29
29
  1,
30
30
  )
31
31
  }
@@ -36,7 +36,7 @@ export default class Data {
36
36
  * @param {string} append - The string to append
37
37
  * @returns {string} The appended string
38
38
  */
39
- static appendString(string: string, append: string): string;
39
+ static append(string: string, append: string): string;
40
40
  /**
41
41
  * Prepends a string to another string if it does not already start with it.
42
42
  *
@@ -44,7 +44,51 @@ export default class Data {
44
44
  * @param {string} prepend - The string to prepend
45
45
  * @returns {string} The prepended string
46
46
  */
47
- static prependString(string: string, prepend: string): string;
47
+ static prepend(string: string, prepend: string): string;
48
+ /**
49
+ * Remove a suffix from the end of a string if present.
50
+ *
51
+ * @param {string} string - The string to process
52
+ * @param {string} toChop - The suffix to remove from the end
53
+ * @param {boolean} [caseInsensitive=false] - Whether to perform case-insensitive matching
54
+ * @returns {string} The string with suffix removed, or original if suffix not found
55
+ * @example
56
+ * Data.chopRight("hello.txt", ".txt") // "hello"
57
+ * Data.chopRight("Hello", "o") // "Hell"
58
+ * Data.chopRight("HELLO", "lo", true) // "HEL"
59
+ */
60
+ static chopRight(string: string, toChop: string, caseInsensitive?: boolean): string;
61
+ /**
62
+ * Remove a prefix from the beginning of a string if present.
63
+ *
64
+ * @param {string} string - The string to process
65
+ * @param {string} toChop - The prefix to remove from the beginning
66
+ * @param {boolean} [caseInsensitive=false] - Whether to perform case-insensitive matching
67
+ * @returns {string} The string with prefix removed, or original if prefix not found
68
+ * @example
69
+ * Data.chopLeft("hello.txt", "hello") // ".txt"
70
+ * Data.chopLeft("Hello", "H") // "ello"
71
+ * Data.chopLeft("HELLO", "he", true) // "LLO"
72
+ */
73
+ static chopLeft(string: string, toChop: string, caseInsensitive?: boolean): string;
74
+ /**
75
+ * Chop a string after the first occurence of another string.
76
+ *
77
+ * @param {string} string - The string to search
78
+ * @param {string} needle - The bit to chop after
79
+ * @param {boolean} caseInsensitive - Whether to search insensitive to case
80
+ * @returns {string} The remaining string
81
+ */
82
+ static chopAfter(string: string, needle: string, caseInsensitive?: boolean): string;
83
+ /**
84
+ * Chop a string before the first occurrence of another string.
85
+ *
86
+ * @param {string} string - The string to search
87
+ * @param {string} needle - The bit to chop before
88
+ * @param {boolean} caseInsensitive - Whether to search insensitive to case
89
+ * @returns {string} The remaining string
90
+ */
91
+ static chopBefore(string: string, needle: string, caseInsensitive?: boolean): string;
48
92
  /**
49
93
  * Creates a type spec from a string. A type spec is an array of objects
50
94
  * defining the type of a value and whether an array is expected.
@@ -1 +1 @@
1
- {"version":3,"file":"Data.d.ts","sourceRoot":"","sources":["../../../browser/lib/Data.js"],"names":[],"mappings":"AAUA;IACA;;;;;OAKG;IACD,mBAFQ,KAAK,CAAC,MAAM,CAAC,CAgBnB;IAEF;;;;;OAKG;IACH,qBAFU,KAAK,CAAC,MAAM,CAAC,CAmBrB;IAEF;;;;;;;OAOG;IACH,kBAFU,KAAK,CAAC,MAAM,CAAC,CAKrB;IAEF;;;;;OAKG;IACH,uBAFU,KAAK,CAAC,MAAM,CAAC,CAE6C;IAEpE;;;;;;OAMG;IACH,4BAJW,MAAM,UACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,6BAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,2BAJW,MAAM,WACN,MAAM,GACJ,KAAK,CAAC,MAAM,CAAC,CAIzB;IAED;;;;;;;OAOG;IACH,qBALW,OAAO,QACP,MAAM,GAAC,QAAQ,YACf,MAAM,GACJ,OAAO,CAQnB;IAED;;;;;OAKG;IACH,yBAHW,MAAM,GACJ,OAAO,CASnB;IAED;;;;;;;;OAQG;IACH,yBAJW,OAAO,QACP,MAAM,GACJ,OAAO,CAwBnB;IAED;;;;;OAKG;IACH,qBAHW,OAAO,GACL,MAAM,CAclB;IAED;;;;;OAKG;IACH,wBAHW,OAAO,GACL,OAAO,CAInB;IAED;;;;;;;;OAQG;IACH,sBALW,OAAO,oBACP,OAAO,GAEL,OAAO,CA2BnB;IAED;;;;;OAKG;IACH,6BAHW,MAAM,GACJ,MAAM,CAmBlB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,QACN,KAAK,CAAC,MAAM,CAAC,GACX,MAAM,CAiBlB;IAED;;;;;;;OAOG;IACH,2BAJW,MAAM,QACN,KAAK,CAAC,MAAM,CAAC,SACb,OAAO,QAMjB;IAED;;;;;OAKG;IACH,+BAHc,MAAM,EAAA,GACP,MAAM,CAqBlB;IAED;;;;;;;OAOG;IACH,wBAJW,KAAK,CAAC,OAAO,CAAC,aACd,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAClC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAMnC;IAED;;;;;;;OAOG;IACH,kBALW,MAAM,OACN,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,oBALW,MAAM,OACN,MAAM,OACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,4BAbW,OAAO,GACL,OAAO,CA+BnB;IAED;;;;;;;;;;;;;;;OAeG;IACH,uBAXW,OAAO,GACL,OAAO,CAgBnB;CACF;qBA5aoB,eAAe"}
1
+ {"version":3,"file":"Data.d.ts","sourceRoot":"","sources":["../../../browser/lib/Data.js"],"names":[],"mappings":"AAUA;IACA;;;;;OAKG;IACD,mBAFQ,KAAK,CAAC,MAAM,CAAC,CAgBnB;IAEF;;;;;OAKG;IACH,qBAFU,KAAK,CAAC,MAAM,CAAC,CAmBrB;IAEF;;;;;;;OAOG;IACH,kBAFU,KAAK,CAAC,MAAM,CAAC,CAKrB;IAEF;;;;;OAKG;IACH,uBAFU,KAAK,CAAC,MAAM,CAAC,CAE2D;IAElF;;;;;;OAMG;IACH,sBAJW,MAAM,UACN,MAAM,GACJ,MAAM,CAMlB;IAED;;;;;;OAMG;IACH,uBAJW,MAAM,WACN,MAAM,GACJ,MAAM,CAMlB;IAED;;;;;;;;;;;OAWG;IACH,yBATW,MAAM,UACN,MAAM,oBACN,OAAO,GACL,MAAM,CAWlB;IAED;;;;;;;;;;;OAWG;IACH,wBATW,MAAM,UACN,MAAM,oBACN,OAAO,GACL,MAAM,CAWlB;IAED;;;;;;;OAOG;IACH,yBALW,MAAM,UACN,MAAM,oBACN,OAAO,GACL,MAAM,CAWlB;IAED;;;;;;;OAOG;IACH,0BALW,MAAM,UACN,MAAM,oBACN,OAAO,GACL,MAAM,CAYlB;IAED;;;;;;;OAOG;IACH,2BAJW,MAAM,WACN,MAAM,GACJ,KAAK,CAAC,MAAM,CAAC,CAIzB;IAED;;;;;;;OAOG;IACH,qBALW,OAAO,QACP,MAAM,GAAC,QAAQ,YACf,MAAM,GACJ,OAAO,CAQnB;IAED;;;;;OAKG;IACH,yBAHW,MAAM,GACJ,OAAO,CASnB;IAED;;;;;;;;OAQG;IACH,yBAJW,OAAO,QACP,MAAM,GACJ,OAAO,CAwBnB;IAED;;;;;OAKG;IACH,qBAHW,OAAO,GACL,MAAM,CAclB;IAED;;;;;OAKG;IACH,wBAHW,OAAO,GACL,OAAO,CAInB;IAED;;;;;;;;OAQG;IACH,sBALW,OAAO,oBACP,OAAO,GAEL,OAAO,CA8BnB;IAED;;;;;OAKG;IACH,6BAHW,MAAM,GACJ,MAAM,CAmBlB;IAED;;;;;;;OAOG;IACH,6BAJW,MAAM,QACN,KAAK,CAAC,MAAM,CAAC,GACX,MAAM,CAiBlB;IAED;;;;;;;OAOG;IACH,2BAJW,MAAM,QACN,KAAK,CAAC,MAAM,CAAC,SACb,OAAO,QAMjB;IAED;;;;;OAKG;IACH,+BAHc,MAAM,EAAA,GACP,MAAM,CAqBlB;IAED;;;;;;;OAOG;IACH,wBAJW,KAAK,CAAC,OAAO,CAAC,aACd,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAClC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAMnC;IAED;;;;;;;OAOG;IACH,kBALW,MAAM,OACN,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,oBALW,MAAM,OACN,MAAM,OACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,4BAbW,OAAO,GACL,OAAO,CA+BnB;IAED;;;;;;;;;;;;;;;OAeG;IACH,uBAXW,OAAO,GACL,OAAO,CAgBnB;CACF;qBAhgBoB,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"TypeSpec.d.ts","sourceRoot":"","sources":["../../../browser/lib/TypeSpec.js"],"names":[],"mappings":"AAWA;;;GAGG;AACH;IAGE;;;;;OAKG;IACH,oBAHW,MAAM,WACN,OAAO,EAUjB;IAJC,aAAwB;IACxB,eAAgC;IAChC,6BAA2C;IAI7C;;;;OAIG;IACH,YAFa,MAAM,CAQlB;IAED;;;;OAIG;IACH,UAFa,OAAO,CASnB;IAED;;;;OAIG;IACH,kBAFW,CAAS,IAAO,EAAP,OAAO,KAAG,IAAI,QAIjC;IAED;;;;;OAKG;IACH,gBAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,OAAO,CAInB;IAED;;;;;OAKG;IACH,eAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,OAAO,CAInB;IAED;;;;;OAKG;IACH,iBAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,KAAK,CAAC,OAAO,CAAC,CAI1B;IAED;;;;;OAKG;IACH,cAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,KAAK,CAAC,OAAO,CAAC,CAI1B;IAED;;;;;;OAMG;IACH,iBAJW,CAAS,IAAO,EAAP,OAAO,EAAE,IAAO,EAAP,OAAO,KAAG,OAAO,gBACnC,OAAO,GACL,OAAO,CAInB;IAED;;;;;OAKG;IACH,eAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,MAAM,GAAC,SAAS,CAI5B;IAED;;;;;;;;OAQG;IACH,eALW,OAAO,WACP,OAAO,GAEL,OAAO,CAInB;IAED,2CA2DC;;CAmDF"}
1
+ {"version":3,"file":"TypeSpec.d.ts","sourceRoot":"","sources":["../../../browser/lib/TypeSpec.js"],"names":[],"mappings":"AAWA;;;GAGG;AACH;IAGE;;;;;OAKG;IACH,oBAHW,MAAM,WACN,OAAO,EAUjB;IAJC,aAAwB;IACxB,eAAgC;IAChC,6BAA2C;IAI7C;;;;OAIG;IACH,YAFa,MAAM,CAQlB;IAED;;;;OAIG;IACH,UAFa,OAAO,CASnB;IAED;;;;OAIG;IACH,kBAFW,CAAS,IAAO,EAAP,OAAO,KAAG,IAAI,QAIjC;IAED;;;;;OAKG;IACH,gBAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,OAAO,CAInB;IAED;;;;;OAKG;IACH,eAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,OAAO,CAInB;IAED;;;;;OAKG;IACH,iBAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,KAAK,CAAC,OAAO,CAAC,CAI1B;IAED;;;;;OAKG;IACH,cAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,KAAK,CAAC,OAAO,CAAC,CAI1B;IAED;;;;;;OAMG;IACH,iBAJW,CAAS,IAAO,EAAP,OAAO,EAAE,IAAO,EAAP,OAAO,KAAG,OAAO,gBACnC,OAAO,GACL,OAAO,CAInB;IAED;;;;;OAKG;IACH,eAHW,CAAS,IAAO,EAAP,OAAO,KAAG,OAAO,GACxB,MAAM,GAAC,SAAS,CAI5B;IAED;;;;;;;;OAQG;IACH,eALW,OAAO,WACP,OAAO,GAEL,OAAO,CAInB;IAED,2CA6DC;;CAmDF"}
@@ -8,6 +8,19 @@
8
8
  * @augments DirectoryObject
9
9
  */
10
10
  export default class CappedDirectoryObject extends DirectoryObject {
11
+ /**
12
+ * Creates a CappedDirectoryObject from the current working directory.
13
+ * This is useful when working with pnpx or other tools where you need to
14
+ * cap at the project's root directory determined at runtime.
15
+ *
16
+ * @returns {CappedDirectoryObject} A CappedDirectoryObject capped at the current working directory
17
+ * @example
18
+ * // When using pnpx or similar tools
19
+ * const projectRoot = CappedDirectoryObject.fromCwd()
20
+ * const srcDir = projectRoot.getDirectory("src")
21
+ * // srcDir is capped at the project root
22
+ */
23
+ static fromCwd(): CappedDirectoryObject;
11
24
  /**
12
25
  * Constructs a CappedDirectoryObject instance.
13
26
  *
@@ -15,13 +28,16 @@ export default class CappedDirectoryObject extends DirectoryObject {
15
28
  * (virtual root). With a parent, the path is resolved relative to the parent's
16
29
  * cap using virtual path semantics (absolute paths treated as cap-relative).
17
30
  *
18
- * @param {string} dirPath - Directory path (becomes cap if no parent, else relative to parent's cap)
31
+ * @param {string} [directory="."] - Directory path (becomes cap if no parent, else relative to parent's cap, defaults to current directory)
19
32
  * @param {CappedDirectoryObject?} [parent] - Optional parent capped directory
20
- * @param {boolean} [temporary=false] - Whether this is a temporary directory
21
- * @throws {Sass} If path is empty
22
33
  * @throws {Sass} If parent is provided but not a CappedDirectoryObject
23
34
  * @throws {Sass} If the resulting path would escape the cap
24
35
  * @example
36
+ * // Create new capped directory at current directory
37
+ * const cwd = new CappedDirectoryObject()
38
+ * // path: process.cwd(), cap: process.cwd()
39
+ *
40
+ * @example
25
41
  * // Create new capped directory
26
42
  * const cache = new CappedDirectoryObject("/home/user/.cache")
27
43
  * // path: /home/user/.cache, cap: /home/user/.cache
@@ -36,33 +52,34 @@ export default class CappedDirectoryObject extends DirectoryObject {
36
52
  * const config = new CappedDirectoryObject("/etc/config", cache)
37
53
  * // path: /home/user/.cache/etc/config, cap: /home/user/.cache
38
54
  */
39
- constructor(dirPath: string, parent?: CappedDirectoryObject | null, temporary?: boolean);
55
+ constructor(directory?: string, source?: any);
40
56
  /**
41
- * Re-caps this directory to itself, making it the new root of the capped tree.
42
- * This is a protected method intended for use by subclasses like TempDirectoryObject.
57
+ * Indicates whether this directory is capped (constrained to a specific tree).
58
+ * Always returns true for CappedDirectoryObject instances.
43
59
  *
44
- * @protected
45
- */
46
- protected _recapToSelf(): void;
47
- /**
48
- * Returns the cap path for this directory.
60
+ * @returns {boolean} True for all CappedDirectoryObject instances
61
+ * @example
62
+ * const capped = new TempDirectoryObject("myapp")
63
+ * console.log(capped.isCapped) // true
49
64
  *
50
- * @returns {string} The cap directory path
65
+ * const regular = new DirectoryObject("/tmp")
66
+ * console.log(regular.isCapped) // false
51
67
  */
52
- get cap(): string;
68
+ get isCapped(): boolean;
53
69
  /**
54
- * Returns whether this directory is capped.
70
+ * Returns the cap (root) of the capped directory tree.
71
+ * For root CappedDirectoryObject instances, returns itself.
72
+ * For children, returns the inherited cap from the parent chain.
55
73
  *
56
- * @returns {boolean} Always true for CappedDirectoryObject instances
57
- */
58
- get capped(): boolean;
59
- /**
60
- * Returns the real filesystem path (for internal and subclass use).
74
+ * @returns {CappedDirectoryObject} The cap directory object (root of the capped tree)
75
+ * @example
76
+ * const temp = new TempDirectoryObject("myapp")
77
+ * console.log(temp.cap === temp) // true (root is its own cap)
61
78
  *
62
- * @protected
63
- * @returns {string} The actual filesystem path
79
+ * const subdir = temp.getDirectory("data")
80
+ * console.log(subdir.cap === temp) // true (child inherits parent's cap)
64
81
  */
65
- protected get realPath(): string;
82
+ get cap(): CappedDirectoryObject;
66
83
  /**
67
84
  * Returns a plain DirectoryObject representing the actual filesystem location.
68
85
  * This provides an "escape hatch" from the capped environment to interact
@@ -98,50 +115,25 @@ export default class CappedDirectoryObject extends DirectoryObject {
98
115
  */
99
116
  get parent(): CappedDirectoryObject | null;
100
117
  /**
101
- * Returns the URL with virtual path (cap-relative).
102
- *
103
- * @returns {URL} Virtual URL
104
- */
105
- get url(): URL;
106
- /**
107
- * Returns a generator that walks up to the cap.
108
- *
109
- * @returns {Generator<DirectoryObject>} Generator yielding parent directories
110
- */
111
- get walkUp(): Generator<DirectoryObject>;
112
- /**
113
- * Creates a new CappedDirectoryObject by extending this directory's path.
114
- *
115
- * All paths are coerced to remain within the cap directory tree:
116
- * - Absolute paths (e.g., "/foo") are treated as relative to the cap
117
- * - Parent traversal ("..") is allowed but clamped at the cap boundary
118
- * - The cap acts as the virtual root directory
119
- *
120
- * @param {string} newPath - The path to resolve (can be absolute or contain ..)
121
- * @returns {CappedDirectoryObject} A new CappedDirectoryObject with the coerced path
122
- * @example
123
- * const capped = new TempDirectoryObject("myapp")
124
- * const subDir = capped.getDirectory("data")
125
- * console.log(subDir.path) // "/tmp/myapp-ABC123/data"
118
+ * Returns the path of the parent directory.
119
+ * Returns null if this directory is at the cap root (no parent).
126
120
  *
121
+ * @returns {string|null} The parent directory path, or null if at cap root
127
122
  * @example
128
- * // Absolute paths are relative to cap
129
- * const abs = capped.getDirectory("/foo/bar")
130
- * console.log(abs.path) // "/tmp/myapp-ABC123/foo/bar"
123
+ * const temp = new TempDirectoryObject("myapp")
124
+ * console.log(temp.parentPath) // null (at cap root)
131
125
  *
132
- * @example
133
- * // Excessive .. traversal clamps to cap
134
- * const up = capped.getDirectory("../../../etc/passwd")
135
- * console.log(up.path) // "/tmp/myapp-ABC123" (clamped to cap)
126
+ * const subdir = temp.getDirectory("data")
127
+ * console.log(subdir.parentPath) // "/data" or similar (parent's virtual path)
136
128
  */
137
- getDirectory(newPath: string): CappedDirectoryObject;
129
+ get parentPath(): string | null;
138
130
  /**
139
131
  * Override read to use real filesystem path and return capped objects.
140
132
  *
141
133
  * @param {string} [pat=""] - Optional glob pattern
142
134
  * @returns {Promise<{files: Array<FileObject>, directories: Array}>} Directory contents
143
135
  */
144
- read(pat?: string): Promise<{
136
+ read(...arg: any[]): Promise<{
145
137
  files: Array<FileObject>;
146
138
  directories: any[];
147
139
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"CappedDirectoryObject.d.ts","sourceRoot":"","sources":["../../lib/CappedDirectoryObject.js"],"names":[],"mappings":"AAkBA;;;;;;;;GAQG;AACH;IAGE;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,qBArBW,MAAM,WACN,qBAAqB,OAAC,cACtB,OAAO,EA0EjB;IAqBD;;;;;OAKG;IACH,+BAEC;IAED;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;;OAKG;IACH,0BAFa,MAAM,CAIlB;IAqCD;;;;;;;;;;;;;;;;;OAiBG;IACH,YAba,eAAe,CAe3B;IAED;;;;;;;;;;;;;OAaG;IACH,cAPa,qBAAqB,GAAC,IAAI,CA0BtC;IAED;;;;OAIG;IACH,WAFa,GAAG,CAIf;IAqFD;;;;OAIG;IACH,cAFa,SAAS,CAAC,eAAe,CAAC,CAItC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,sBAjBW,MAAM,GACJ,qBAAqB,CAiEjC;IAsID;;;;;OAKG;IACH,WAHW,MAAM,GACJ,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,QAAO;KAAC,CAAC,CAgBnE;;CA8DF;4BAloB2B,sBAAsB;uBAC3B,iBAAiB"}
1
+ {"version":3,"file":"CappedDirectoryObject.d.ts","sourceRoot":"","sources":["../../lib/CappedDirectoryObject.js"],"names":[],"mappings":"AAiBA;;;;;;;;GAQG;AACH;IAoEE;;;;;;;;;;;OAWG;IACH,kBAPa,qBAAqB,CASjC;IA5ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,wBAxBW,MAAM,gBAqDhB;IAkBD;;;;;;;;;;;OAWG;IACH,gBARa,OAAO,CAUnB;IAED;;;;;;;;;;;;OAYG;IACH,WARa,qBAAqB,CAUjC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,YAba,eAAe,CAe3B;IAED;;;;;;;;;;;;;OAaG;IACH,cAPa,qBAAqB,GAAC,IAAI,CAStC;IAED;;;;;;;;;;;OAWG;IACH,kBARa,MAAM,GAAC,IAAI,CAUvB;IAkCD;;;;;OAKG;IACH,qBAFa,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,QAAO;KAAC,CAAC,CAUnE;;CA8BF;4BAvQ2B,sBAAsB;uBAC3B,iBAAiB"}