@gesslar/toolkit 1.9.1 → 1.10.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gesslar/toolkit",
3
- "version": "1.9.1",
3
+ "version": "1.10.0",
4
4
  "description": "Get in, bitches, we're going toolkitting.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -13,8 +13,10 @@ export {default as Util} from "./lib/Util.js"
13
13
 
14
14
  // Node-specific exports
15
15
  export {default as Cache} from "./lib/Cache.js"
16
+ export {default as CappedDirectoryObject} from "./lib/CappedDirectoryObject.js"
16
17
  export {default as Contract} from "./lib/Contract.js"
17
18
  export {default as DirectoryObject} from "./lib/DirectoryObject.js"
19
+ export {default as TempDirectoryObject} from "./lib/TempDirectoryObject.js"
18
20
  export {default as FileObject} from "./lib/FileObject.js"
19
21
  export {default as FS} from "./lib/FS.js"
20
22
  export {default as Glog} from "./lib/Glog.js"
@@ -0,0 +1,237 @@
1
+ /**
2
+ * @file CappedDirectoryObject.js
3
+ * @description Abstract base class for directory objects that are constrained
4
+ * to a specific directory tree (the "cap"). This provides security by ensuring
5
+ * all operations remain within the capped directory hierarchy.
6
+ *
7
+ * This class is not intended to be instantiated directly. Use subclasses like
8
+ * TempDirectoryObject that define specific caps.
9
+ */
10
+
11
+ import path from "node:path"
12
+
13
+ import {Data, Valid} from "../browser/index.js"
14
+ import DirectoryObject from "./DirectoryObject.js"
15
+ import FileObject from "./FileObject.js"
16
+ import Sass from "./Sass.js"
17
+
18
+ /**
19
+ * CappedDirectoryObject extends DirectoryObject with constraints that ensure
20
+ * all operations are restricted to a specific directory tree (the "cap").
21
+ *
22
+ * All path operations are validated to ensure they remain within the
23
+ * cap directory hierarchy for security.
24
+ *
25
+ * @augments DirectoryObject
26
+ */
27
+ export default class CappedDirectoryObject extends DirectoryObject {
28
+ #cap
29
+
30
+ /**
31
+ * Constructs a CappedDirectoryObject instance.
32
+ *
33
+ * This is an abstract base class - use subclasses like TempDirectoryObject
34
+ * that define specific caps.
35
+ *
36
+ * @param {string?} name - Base name for the directory (if empty/null, uses cap root)
37
+ * @param {string} cap - The root path that constrains this directory tree
38
+ * @param {CappedDirectoryObject?} [parent] - Optional parent capped directory
39
+ * @param {boolean} [temporary=false] - Whether this is a temporary directory
40
+ * @throws {Sass} If name is absolute
41
+ * @throws {Sass} If name is empty (when parent is provided)
42
+ * @throws {Sass} If name contains path separators
43
+ * @throws {Sass} If parent is not a capped directory
44
+ * @throws {Sass} If parent's lineage does not trace back to the cap
45
+ * @throws {Sass} If the resulting path would escape the cap
46
+ */
47
+ constructor(name, cap, parent=null, temporary=false) {
48
+ Valid.type(cap, "String")
49
+
50
+ // Validate parent using instanceof since TypeSpec doesn't understand inheritance
51
+ if(parent !== null && !(parent instanceof CappedDirectoryObject)) {
52
+ throw Sass.new(`Parent must be null or a CappedDirectoryObject instance, got ${Data.typeOf(parent)}`)
53
+ }
54
+
55
+ let dirPath
56
+
57
+ // Special case: empty name with no parent means use cap root
58
+ if(!name && !parent) {
59
+ dirPath = cap
60
+ } else {
61
+ Valid.type(name, "String")
62
+
63
+ // Security: Validate name before any processing
64
+ Valid.assert(
65
+ !path.isAbsolute(name),
66
+ "Capped directory name must not be an absolute path.",
67
+ )
68
+ Valid.assert(
69
+ name.length > 0,
70
+ "Capped directory name must not be empty.",
71
+ )
72
+ Valid.assert(
73
+ !name.includes("/") && !name.includes("\\") && !name.includes(path.sep),
74
+ "Capped directory name must not contain path separators.",
75
+ )
76
+
77
+ if(parent) {
78
+ // Ensure parent is capped
79
+ Valid.assert(parent.capped, "Parent must be a capped DirectoryObject.")
80
+
81
+ // Ensure parent has same cap
82
+ Valid.assert(
83
+ parent.cap === cap,
84
+ "Parent must have the same cap as this directory.",
85
+ )
86
+
87
+ const parentPath = parent.path
88
+
89
+ // Validate parent's lineage traces back to the cap
90
+ let found = false
91
+ if(parent.trail) {
92
+ for(const p of parent.walkUp) {
93
+ if(p.path === cap) {
94
+ found = true
95
+ break
96
+ }
97
+ }
98
+ }
99
+
100
+ Valid.assert(
101
+ found,
102
+ `The lineage of this directory must trace back to the cap '${cap}'.`,
103
+ )
104
+
105
+ dirPath = path.join(parentPath, name)
106
+ } else {
107
+ // No parent - this is a root-level capped directory
108
+ dirPath = path.join(cap, name)
109
+ }
110
+ }
111
+
112
+ // Call parent constructor with the path
113
+ // Pass through the temporary flag (subclasses control this)
114
+ super(dirPath, temporary)
115
+
116
+ // Store the cap AFTER calling super()
117
+ this.#cap = cap
118
+
119
+ // Validate that this path is within the cap
120
+ this.#validateCapPath()
121
+ }
122
+
123
+ /**
124
+ * Validates that the directory path is within the cap directory tree.
125
+ *
126
+ * @private
127
+ * @throws {Sass} If the path is not within the cap directory
128
+ */
129
+ #validateCapPath() {
130
+ const cap = this.#cap
131
+ const resolved = path.resolve(this.path)
132
+ const capResolved = path.resolve(cap)
133
+
134
+ // Check if the resolved path starts with the cap directory
135
+ if(!resolved.startsWith(capResolved)) {
136
+ throw Sass.new(
137
+ `Path '${this.path}' is not within the cap directory '${cap}'`
138
+ )
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Returns the cap path for this directory.
144
+ *
145
+ * @returns {string} The cap directory path
146
+ */
147
+ get cap() {
148
+ return this.#cap
149
+ }
150
+
151
+ /**
152
+ * Returns whether this directory is capped.
153
+ *
154
+ * @returns {boolean} Always true for CappedDirectoryObject instances
155
+ */
156
+ get capped() {
157
+ return true
158
+ }
159
+
160
+ /**
161
+ * Creates a new CappedDirectoryObject by extending this directory's path.
162
+ *
163
+ * Validates that the resulting path remains within the cap directory tree.
164
+ *
165
+ * @param {string} newPath - The path segment to append
166
+ * @returns {CappedDirectoryObject} A new CappedDirectoryObject with the extended path
167
+ * @throws {Sass} If the path would escape the cap directory
168
+ * @throws {Sass} If the path is absolute
169
+ * @throws {Sass} If the path contains traversal (..)
170
+ * @example
171
+ * const capped = new TempDirectoryObject("myapp")
172
+ * const subDir = capped.addDirectory("data")
173
+ * console.log(subDir.path) // "/tmp/myapp-ABC123/data"
174
+ */
175
+ addDirectory(newPath) {
176
+ Valid.type(newPath, "String")
177
+
178
+ // Prevent absolute paths
179
+ if(path.isAbsolute(newPath)) {
180
+ throw Sass.new("Absolute paths are not allowed in capped directories")
181
+ }
182
+
183
+ // Prevent path traversal attacks
184
+ const normalized = path.normalize(newPath)
185
+ if(normalized.includes("..")) {
186
+ throw Sass.new("Path traversal (..) is not allowed in capped directories")
187
+ }
188
+
189
+ // Use the constructor of the current class (supports subclassing)
190
+ // Pass this as parent so the child inherits the same cap
191
+ return new this.constructor(newPath, this)
192
+ }
193
+
194
+ /**
195
+ * Creates a new FileObject by extending this directory's path.
196
+ *
197
+ * Validates that the resulting path remains within the cap directory tree.
198
+ *
199
+ * @param {string} filename - The filename to append
200
+ * @returns {FileObject} A new FileObject with the extended path
201
+ * @throws {Sass} If the path would escape the cap directory
202
+ * @throws {Sass} If the path is absolute
203
+ * @throws {Sass} If the path contains traversal (..)
204
+ * @example
205
+ * const capped = new TempDirectoryObject("myapp")
206
+ * const file = capped.addFile("config.json")
207
+ * console.log(file.path) // "/tmp/myapp-ABC123/config.json"
208
+ */
209
+ addFile(filename) {
210
+ Valid.type(filename, "String")
211
+
212
+ // Prevent absolute paths
213
+ if(path.isAbsolute(filename)) {
214
+ throw Sass.new("Absolute paths are not allowed in capped directories")
215
+ }
216
+
217
+ // Prevent path traversal attacks
218
+ const normalized = path.normalize(filename)
219
+ if(normalized.includes("..")) {
220
+ throw Sass.new("Path traversal (..) is not allowed in capped directories")
221
+ }
222
+
223
+ // Create the file path by joining this directory with the filename
224
+ const filePath = path.join(this.path, filename)
225
+
226
+ return new FileObject(filePath)
227
+ }
228
+
229
+ /**
230
+ * Returns a string representation of the CappedDirectoryObject.
231
+ *
232
+ * @returns {string} string representation of the CappedDirectoryObject
233
+ */
234
+ toString() {
235
+ return `[CappedDirectoryObject: ${this.path}]`
236
+ }
237
+ }
@@ -9,10 +9,10 @@ import path from "node:path"
9
9
  import {URL} from "node:url"
10
10
  import util from "node:util"
11
11
 
12
+ import {Data, Valid} from "../browser/index.js"
12
13
  import FS from "./FS.js"
13
14
  import FileObject from "./FileObject.js"
14
15
  import Sass from "./Sass.js"
15
- import {Data, Valid} from "../browser/index.js"
16
16
 
17
17
  /**
18
18
  * DirectoryObject encapsulates metadata and operations for a directory,
@@ -64,10 +64,10 @@ export default class DirectoryObject extends FS {
64
64
  constructor(directory=null, temporary=false) {
65
65
  super()
66
66
 
67
- Valid.type(directory, "String|DirectoryObject|Null")
67
+ Valid.type(directory, "String|TempDirectoryObject|DirectoryObject|Null")
68
68
 
69
69
  // If passed a DirectoryObject, extract its path
70
- if(Data.isType(directory, "DirectoryObject"))
70
+ if(Data.isType(directory, "DirectoryObject") || Data.isType(directory, "TempDirectoryObject"))
71
71
  directory = directory.path
72
72
 
73
73
  const fixedDir = FS.fixSlashes(directory ?? ".")
@@ -231,7 +231,8 @@ export default class DirectoryObject extends FS {
231
231
  * @throws {Sass} If the directory is not marked as temporary
232
232
  * @throws {Sass} If the directory deletion fails
233
233
  * @example
234
- * const tempDir = await FS.tempDirectory("my-temp")
234
+ * const tempDir = new TempDirectoryObject("my-temp")
235
+ * await tempDir.assureExists()
235
236
  * // ... use the directory ...
236
237
  * await tempDir.remove() // Recursively deletes everything
237
238
  */
@@ -440,20 +441,19 @@ export default class DirectoryObject extends FS {
440
441
  }
441
442
 
442
443
  /**
443
- * Creates a new DirectoryObject by merging this directory's path with a new
444
- * path.
444
+ * Creates a new DirectoryObject by extending this directory's path.
445
445
  *
446
446
  * Uses overlapping path segment detection to intelligently combine paths.
447
447
  * Preserves the temporary flag from the current directory.
448
448
  *
449
- * @param {string} newPath - The path to merge with this directory's path.
450
- * @returns {DirectoryObject} A new DirectoryObject with the merged path.
449
+ * @param {string} newPath - The path to append to this directory's path.
450
+ * @returns {DirectoryObject} A new DirectoryObject with the extended path.
451
451
  * @example
452
452
  * const dir = new DirectoryObject("/projects/git/toolkit")
453
- * const subDir = dir.to("toolkit/src/lib")
453
+ * const subDir = dir.addDirectory("src/lib")
454
454
  * console.log(subDir.path) // "/projects/git/toolkit/src/lib"
455
455
  */
456
- to(newPath) {
456
+ addDirectory(newPath) {
457
457
  Valid.type(newPath, "String")
458
458
 
459
459
  const thisPath = this.path
@@ -461,4 +461,25 @@ export default class DirectoryObject extends FS {
461
461
 
462
462
  return new this.constructor(merged, this.temporary)
463
463
  }
464
+
465
+ /**
466
+ * Creates a new FileObject by extending this directory's path.
467
+ *
468
+ * Uses overlapping path segment detection to intelligently combine paths.
469
+ *
470
+ * @param {string} filename - The filename to append to this directory's path.
471
+ * @returns {FileObject} A new FileObject with the extended path.
472
+ * @example
473
+ * const dir = new DirectoryObject("/projects/git/toolkit")
474
+ * const file = dir.addFile("package.json")
475
+ * console.log(file.path) // "/projects/git/toolkit/package.json"
476
+ */
477
+ addFile(filename) {
478
+ Valid.type(filename, "String")
479
+
480
+ const thisPath = this.path
481
+ const merged = FS.mergeOverlappingPaths(thisPath, filename)
482
+
483
+ return new FileObject(merged)
484
+ }
464
485
  }
package/src/lib/FS.js CHANGED
@@ -8,13 +8,10 @@
8
8
  import {globby} from "globby"
9
9
  import path from "node:path"
10
10
  import url from "node:url"
11
- import fs from "node:fs/promises"
12
- import os from "node:os"
13
11
 
14
12
  import Collection from "../browser/lib/Collection.js"
15
13
  import Sass from "./Sass.js"
16
14
  import Valid from "./Valid.js"
17
- import DirectoryObject from "./DirectoryObject.js"
18
15
 
19
16
  /** @typedef {import("./FileObject.js").default} FileObject */
20
17
  /** @typedef {import("./DirectoryObject.js").default} DirectoryObject */
@@ -217,88 +214,4 @@ export default class FS {
217
214
  // join if no overlap
218
215
  return FS.mergeOverlappingPaths(from, normalizedTo)
219
216
  }
220
-
221
- /**
222
- * Creates a new temporary directory and wraps it in a DirectoryObject.
223
- *
224
- * When called without a parent, creates a new temporary directory in the OS
225
- * temp folder with a unique name. When called with a parent DirectoryObject,
226
- * creates a subdirectory within that parent.
227
- *
228
- * The parent directory (if provided) must:
229
- * - Be marked as temporary
230
- * - Actually exist on the filesystem
231
- * - Have lineage tracing back to the OS temp directory
232
- *
233
- * These validations ensure that only legitimately temporary directories can
234
- * be created and later removed with the remove() method.
235
- *
236
- * @static
237
- * @async
238
- * @param {string} name - The base name for the temporary directory. When creating a root temp directory, a random suffix will be appended for uniqueness.
239
- * @param {DirectoryObject|null} [parent] - Optional parent DirectoryObject to create this directory within. Must be a temporary directory itself.
240
- * @returns {Promise<DirectoryObject>} A DirectoryObject representing the created temporary directory, with the temporary flag set to true.
241
- * @throws {Sass} If name is not a string
242
- * @throws {Sass} If parent is provided but is not a DirectoryObject
243
- * @throws {Sass} If parent is not marked as temporary
244
- * @throws {Sass} If parent does not exist
245
- * @throws {Sass} If parent's lineage does not trace back to the OS temp directory
246
- * @example
247
- * // Create a standalone temporary directory
248
- * const tempDir = await FS.tempDirectory("my-temp")
249
- * console.log(tempDir.temporary) // true
250
- * console.log(tempDir.path) // /tmp/my-temp-abc123 (on Unix)
251
- *
252
- * @example
253
- * // Create nested temporary directories
254
- * const parent = await FS.tempDirectory("parent")
255
- * const child = await FS.tempDirectory("child", parent)
256
- * console.log(child.path.startsWith(parent.path)) // true
257
- * await parent.remove() // Removes both parent and child
258
- */
259
- static async tempDirectory(name, parent=null) {
260
- Valid.type(name, "String")
261
- Valid.type(parent, "Null|DirectoryObject")
262
-
263
- const temp = os.tmpdir()
264
-
265
- if(parent) {
266
- Valid.assert(parent.temporary, "Parent must be a temporary DirectoryObject.")
267
- Valid.assert(await parent.exists, "Parent must exist.")
268
-
269
- let found = false
270
- for(const p of parent.walkUp) {
271
- if(p.path === temp) {
272
- found = true
273
- break
274
- }
275
- }
276
-
277
- Valid.assert(found, "The lineage of this directory must be the OS temp directory.")
278
-
279
- // Security: Reject absolute paths, path traversal, and path separators
280
- Valid.assert(
281
- !path.isAbsolute(name),
282
- "Temporary directory name must not be an absolute path."
283
- )
284
- Valid.assert(
285
- !name.includes("/") && !name.includes("\\") && !name.includes(path.sep),
286
- "Temporary directory name must not contain path separators."
287
- )
288
- Valid.assert(
289
- name.length > 0,
290
- "Temporary directory name must not be empty."
291
- )
292
-
293
- const dir = new DirectoryObject(path.join(parent.path, name), true)
294
- await dir.assureExists()
295
-
296
- return dir
297
- }
298
-
299
- const prefix = name.endsWith("-") ? name : `${name}-`
300
- const dir = await fs.mkdtemp(path.join(temp, prefix))
301
-
302
- return new DirectoryObject(dir, true)
303
- }
304
217
  }
@@ -98,6 +98,7 @@ export default class FileObject extends FS {
98
98
  case "String":
99
99
  return new DirectoryObject(directory)
100
100
  case "DirectoryObject":
101
+ case "TempDirectoryObject":
101
102
  return directory
102
103
  default:
103
104
  return new DirectoryObject(dir)
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @file TempDirectoryObject.js
3
+ * @description Class representing a temporary directory that is constrained
4
+ * to the OS's temporary directory tree.
5
+ */
6
+
7
+ import fs from "node:fs"
8
+ import os from "node:os"
9
+
10
+ import CappedDirectoryObject from "./CappedDirectoryObject.js"
11
+ import Sass from "./Sass.js"
12
+
13
+ /**
14
+ * TempDirectoryObject extends CappedDirectoryObject with the cap set to
15
+ * the OS's temporary directory. Temporary directories are created
16
+ * synchronously during construction and exist immediately.
17
+ *
18
+ * All path operations are validated to ensure they remain within the temp
19
+ * directory hierarchy for security.
20
+ *
21
+ * @augments CappedDirectoryObject
22
+ */
23
+ export default class TempDirectoryObject extends CappedDirectoryObject {
24
+
25
+ /**
26
+ * Constructs a TempDirectoryObject instance and creates the directory.
27
+ *
28
+ * The directory is created synchronously during construction, so it will
29
+ * exist immediately after the constructor returns.
30
+ *
31
+ * If no name is provided, uses the OS temp directory directly. If a name
32
+ * is provided without a parent, creates a new directory with a unique suffix.
33
+ * If a parent is provided, creates a subdirectory within that parent.
34
+ *
35
+ * @param {string?} [name] - Base name for the temp directory (if empty/null, uses OS temp dir)
36
+ * @param {TempDirectoryObject?} [parent] - Optional parent temporary directory
37
+ * @throws {Sass} If name is absolute
38
+ * @throws {Sass} If name is empty (when parent is provided)
39
+ * @throws {Sass} If name contains path separators
40
+ * @throws {Sass} If parent is provided but not a temporary directory
41
+ * @throws {Sass} If parent's lineage does not trace back to the OS temp directory
42
+ * @throws {Sass} If directory creation fails
43
+ * @example
44
+ * // Use OS temp directory directly
45
+ * const temp = new TempDirectoryObject()
46
+ * console.log(temp.path) // "/tmp"
47
+ *
48
+ * @example
49
+ * // Create with unique name
50
+ * const temp = new TempDirectoryObject("myapp")
51
+ * console.log(temp.path) // "/tmp/myapp-ABC123"
52
+ *
53
+ * @example
54
+ * // Nested temp directories
55
+ * const parent = new TempDirectoryObject("parent")
56
+ * const child = new TempDirectoryObject("child", parent)
57
+ * await parent.remove() // Removes both parent and child
58
+ */
59
+ constructor(name, parent=null) {
60
+ let finalName = name
61
+
62
+ // Only generate unique suffix if we have a name and no parent
63
+ if(name && !parent) {
64
+ const prefix = name.endsWith("-") ? name : `${name}-`
65
+ const uniqueSuffix =
66
+ Math.random()
67
+ .toString(36)
68
+ .substring(2, 8)
69
+ .toUpperCase()
70
+ finalName = `${prefix}${uniqueSuffix}`
71
+ }
72
+
73
+ // Call parent constructor with the cap set to OS temp directory
74
+ // Mark as temporary=true so remove() works
75
+ super(finalName, os.tmpdir(), parent, true)
76
+
77
+ // Temp-specific behavior: create directory immediately
78
+ this.#createDirectory()
79
+ }
80
+
81
+ /**
82
+ * Creates the directory synchronously on the filesystem.
83
+ *
84
+ * @private
85
+ * @throws {Sass} If directory creation fails
86
+ */
87
+ #createDirectory() {
88
+ try {
89
+ fs.mkdirSync(this.path)
90
+ } catch(e) {
91
+ // EEXIST is fine - directory already exists
92
+ if(e.code !== "EEXIST") {
93
+ throw Sass.new(
94
+ `Unable to create temporary directory '${this.path}': ${e.message}`
95
+ )
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Creates a new TempDirectoryObject by extending this directory's path.
102
+ *
103
+ * Validates that the resulting path remains within the temp directory tree.
104
+ *
105
+ * @param {string} newPath - The path segment to append
106
+ * @returns {TempDirectoryObject} A new TempDirectoryObject with the extended path
107
+ * @throws {Sass} If the path would escape the temp directory
108
+ * @throws {Sass} If the path is absolute
109
+ * @throws {Sass} If the path contains traversal (..)
110
+ * @example
111
+ * const temp = new TempDirectoryObject("myapp")
112
+ * const subDir = temp.addDirectory("data")
113
+ * console.log(subDir.path) // "/tmp/myapp-ABC123/data"
114
+ */
115
+ addDirectory(newPath) {
116
+ // Delegate to base class addDirectory() which will call TempDirectoryObject constructor
117
+ return super.addDirectory(newPath)
118
+ }
119
+
120
+ /**
121
+ * Creates a new FileObject by extending this directory's path.
122
+ *
123
+ * Validates that the resulting path remains within the temp directory tree.
124
+ *
125
+ * @param {string} filename - The filename to append
126
+ * @returns {FileObject} A new FileObject with the extended path
127
+ * @throws {Sass} If the path would escape the temp directory
128
+ * @throws {Sass} If the path is absolute
129
+ * @throws {Sass} If the path contains traversal (..)
130
+ * @example
131
+ * const temp = new TempDirectoryObject("myapp")
132
+ * const file = temp.addFile("config.json")
133
+ * console.log(file.path) // "/tmp/myapp-ABC123/config.json"
134
+ */
135
+ addFile(filename) {
136
+ // Delegate to base class addFile() which handles security checks
137
+ return super.addFile(filename)
138
+ }
139
+
140
+ /**
141
+ * Returns a string representation of the TempDirectoryObject.
142
+ *
143
+ * @returns {string} string representation of the TempDirectoryObject
144
+ */
145
+ toString() {
146
+ return `[TempDirectoryObject: ${this.path}]`
147
+ }
148
+ }
@@ -6,8 +6,10 @@ export { default as Sass } from "./lib/Sass.js";
6
6
  export { default as Tantrum } from "./lib/Tantrum.js";
7
7
  export { default as Util } from "./lib/Util.js";
8
8
  export { default as Cache } from "./lib/Cache.js";
9
+ export { default as CappedDirectoryObject } from "./lib/CappedDirectoryObject.js";
9
10
  export { default as Contract } from "./lib/Contract.js";
10
11
  export { default as DirectoryObject } from "./lib/DirectoryObject.js";
12
+ export { default as TempDirectoryObject } from "./lib/TempDirectoryObject.js";
11
13
  export { default as FileObject } from "./lib/FileObject.js";
12
14
  export { default as FS } from "./lib/FS.js";
13
15
  export { default as Glog } from "./lib/Glog.js";
@@ -0,0 +1,60 @@
1
+ /**
2
+ * CappedDirectoryObject extends DirectoryObject with constraints that ensure
3
+ * all operations are restricted to a specific directory tree (the "cap").
4
+ *
5
+ * All path operations are validated to ensure they remain within the
6
+ * cap directory hierarchy for security.
7
+ *
8
+ * @augments DirectoryObject
9
+ */
10
+ export default class CappedDirectoryObject extends DirectoryObject {
11
+ /**
12
+ * Constructs a CappedDirectoryObject instance.
13
+ *
14
+ * This is an abstract base class - use subclasses like TempDirectoryObject
15
+ * that define specific caps.
16
+ *
17
+ * @param {string?} name - Base name for the directory (if empty/null, uses cap root)
18
+ * @param {string} cap - The root path that constrains this directory tree
19
+ * @param {CappedDirectoryObject?} [parent] - Optional parent capped directory
20
+ * @param {boolean} [temporary=false] - Whether this is a temporary directory
21
+ * @throws {Sass} If name is absolute
22
+ * @throws {Sass} If name is empty (when parent is provided)
23
+ * @throws {Sass} If name contains path separators
24
+ * @throws {Sass} If parent is not a capped directory
25
+ * @throws {Sass} If parent's lineage does not trace back to the cap
26
+ * @throws {Sass} If the resulting path would escape the cap
27
+ */
28
+ constructor(name: string | null, cap: string, parent?: CappedDirectoryObject | null, temporary?: boolean);
29
+ /**
30
+ * Returns the cap path for this directory.
31
+ *
32
+ * @returns {string} The cap directory path
33
+ */
34
+ get cap(): string;
35
+ /**
36
+ * Returns whether this directory is capped.
37
+ *
38
+ * @returns {boolean} Always true for CappedDirectoryObject instances
39
+ */
40
+ get capped(): boolean;
41
+ /**
42
+ * Creates a new CappedDirectoryObject by extending this directory's path.
43
+ *
44
+ * Validates that the resulting path remains within the cap directory tree.
45
+ *
46
+ * @param {string} newPath - The path segment to append
47
+ * @returns {CappedDirectoryObject} A new CappedDirectoryObject with the extended path
48
+ * @throws {Sass} If the path would escape the cap directory
49
+ * @throws {Sass} If the path is absolute
50
+ * @throws {Sass} If the path contains traversal (..)
51
+ * @example
52
+ * const capped = new TempDirectoryObject("myapp")
53
+ * const subDir = capped.addDirectory("data")
54
+ * console.log(subDir.path) // "/tmp/myapp-ABC123/data"
55
+ */
56
+ addDirectory(newPath: string): CappedDirectoryObject;
57
+ #private;
58
+ }
59
+ import DirectoryObject from "./DirectoryObject.js";
60
+ //# sourceMappingURL=CappedDirectoryObject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CappedDirectoryObject.d.ts","sourceRoot":"","sources":["../../lib/CappedDirectoryObject.js"],"names":[],"mappings":"AAiBA;;;;;;;;GAQG;AACH;IAGE;;;;;;;;;;;;;;;;OAgBG;IACH,kBAXW,MAAM,OAAC,OACP,MAAM,WACN,qBAAqB,OAAC,cACtB,OAAO,EAkFjB;IAqBD;;;;OAIG;IACH,WAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;OAcG;IACH,sBAVW,MAAM,GACJ,qBAAqB,CA0BjC;;CA6CF;4BA/N2B,sBAAsB"}
@@ -102,7 +102,8 @@ export default class DirectoryObject extends FS {
102
102
  * @throws {Sass} If the directory is not marked as temporary
103
103
  * @throws {Sass} If the directory deletion fails
104
104
  * @example
105
- * const tempDir = await FS.tempDirectory("my-temp")
105
+ * const tempDir = new TempDirectoryObject("my-temp")
106
+ * await tempDir.assureExists()
106
107
  * // ... use the directory ...
107
108
  * await tempDir.remove() // Recursively deletes everything
108
109
  */
@@ -190,20 +191,32 @@ export default class DirectoryObject extends FS {
190
191
  */
191
192
  hasDirectory(dirname: string): Promise<boolean>;
192
193
  /**
193
- * Creates a new DirectoryObject by merging this directory's path with a new
194
- * path.
194
+ * Creates a new DirectoryObject by extending this directory's path.
195
195
  *
196
196
  * Uses overlapping path segment detection to intelligently combine paths.
197
197
  * Preserves the temporary flag from the current directory.
198
198
  *
199
- * @param {string} newPath - The path to merge with this directory's path.
200
- * @returns {DirectoryObject} A new DirectoryObject with the merged path.
199
+ * @param {string} newPath - The path to append to this directory's path.
200
+ * @returns {DirectoryObject} A new DirectoryObject with the extended path.
201
201
  * @example
202
202
  * const dir = new DirectoryObject("/projects/git/toolkit")
203
- * const subDir = dir.to("toolkit/src/lib")
203
+ * const subDir = dir.addDirectory("src/lib")
204
204
  * console.log(subDir.path) // "/projects/git/toolkit/src/lib"
205
205
  */
206
- to(newPath: string): DirectoryObject;
206
+ addDirectory(newPath: string): DirectoryObject;
207
+ /**
208
+ * Creates a new FileObject by extending this directory's path.
209
+ *
210
+ * Uses overlapping path segment detection to intelligently combine paths.
211
+ *
212
+ * @param {string} filename - The filename to append to this directory's path.
213
+ * @returns {FileObject} A new FileObject with the extended path.
214
+ * @example
215
+ * const dir = new DirectoryObject("/projects/git/toolkit")
216
+ * const file = dir.addFile("package.json")
217
+ * console.log(file.path) // "/projects/git/toolkit/package.json"
218
+ */
219
+ addFile(filename: string): FileObject;
207
220
  #private;
208
221
  }
209
222
  import FS from "./FS.js";
@@ -1 +1 @@
1
- {"version":3,"file":"DirectoryObject.d.ts","sourceRoot":"","sources":["../../lib/DirectoryObject.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;GAaG;AACH;uBA4Fe,MAAM;IAjEnB;;;;;OAKG;IACH,yCAFW,OAAO,EA6BjB;IAWD;;;;OAIG;IACH,UAFa,MAAM,CAalB;IAWD;;;;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;;;;OAIG;IACH,iBAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;;OAeG;IACH,UARa,OAAO,CAAC,IAAI,CAAC,CAyBzB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAiBD;;;;OAIG;IACH,QAFa,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CAkBpF;IAED;;;;;;;;;;;;OAYG;IACH,uBARW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAqBzB;IA8BD;;;;;;;;;;;;;;;OAeG;IACH,cAZa,MAAM,CAclB;IAED;;;;;;;;;;;;;;OAcG;IACH,UARa,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAM5B;IAED;;;;;OAKG;IACH,sBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAO5B;IAED;;;;;;;;;;;;;OAaG;IACH,YAPW,MAAM,GACJ,eAAe,CAa3B;;CACF;eApcc,SAAS;uBACD,iBAAiB"}
1
+ {"version":3,"file":"DirectoryObject.d.ts","sourceRoot":"","sources":["../../lib/DirectoryObject.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;GAaG;AACH;uBA4Fe,MAAM;IAjEnB;;;;;OAKG;IACH,yCAFW,OAAO,EA6BjB;IAWD;;;;OAIG;IACH,UAFa,MAAM,CAalB;IAWD;;;;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;;;;OAIG;IACH,iBAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,UATa,OAAO,CAAC,IAAI,CAAC,CA0BzB;IAED;;;;OAIG;IACH,cAFa,OAAO,CAInB;IAED;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAiBD;;;;OAIG;IACH,QAFa,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,WAAW,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;KAAC,CAAC,CAkBpF;IAED;;;;;;;;;;;;OAYG;IACH,uBARW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAqBzB;IA8BD;;;;;;;;;;;;;;;OAeG;IACH,cAZa,MAAM,CAclB;IAED;;;;;;;;;;;;;;OAcG;IACH,UARa,OAAO,CAAC,IAAI,CAAC,CAkBzB;IAED;;;;;OAKG;IACH,kBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAM5B;IAED;;;;;OAKG;IACH,sBAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAO5B;IAED;;;;;;;;;;;;OAYG;IACH,sBAPW,MAAM,GACJ,eAAe,CAa3B;IAED;;;;;;;;;;;OAWG;IACH,kBAPW,MAAM,GACJ,UAAU,CAatB;;CACF;eAxdc,SAAS;uBACD,iBAAiB"}
@@ -71,47 +71,7 @@ export default class FS {
71
71
  * @returns {string} The resolved path
72
72
  */
73
73
  static resolvePath(fromPath: string, toPath: string): string;
74
- /**
75
- * Creates a new temporary directory and wraps it in a DirectoryObject.
76
- *
77
- * When called without a parent, creates a new temporary directory in the OS
78
- * temp folder with a unique name. When called with a parent DirectoryObject,
79
- * creates a subdirectory within that parent.
80
- *
81
- * The parent directory (if provided) must:
82
- * - Be marked as temporary
83
- * - Actually exist on the filesystem
84
- * - Have lineage tracing back to the OS temp directory
85
- *
86
- * These validations ensure that only legitimately temporary directories can
87
- * be created and later removed with the remove() method.
88
- *
89
- * @static
90
- * @async
91
- * @param {string} name - The base name for the temporary directory. When creating a root temp directory, a random suffix will be appended for uniqueness.
92
- * @param {DirectoryObject|null} [parent] - Optional parent DirectoryObject to create this directory within. Must be a temporary directory itself.
93
- * @returns {Promise<DirectoryObject>} A DirectoryObject representing the created temporary directory, with the temporary flag set to true.
94
- * @throws {Sass} If name is not a string
95
- * @throws {Sass} If parent is provided but is not a DirectoryObject
96
- * @throws {Sass} If parent is not marked as temporary
97
- * @throws {Sass} If parent does not exist
98
- * @throws {Sass} If parent's lineage does not trace back to the OS temp directory
99
- * @example
100
- * // Create a standalone temporary directory
101
- * const tempDir = await FS.tempDirectory("my-temp")
102
- * console.log(tempDir.temporary) // true
103
- * console.log(tempDir.path) // /tmp/my-temp-abc123 (on Unix)
104
- *
105
- * @example
106
- * // Create nested temporary directories
107
- * const parent = await FS.tempDirectory("parent")
108
- * const child = await FS.tempDirectory("child", parent)
109
- * console.log(child.path.startsWith(parent.path)) // true
110
- * await parent.remove() // Removes both parent and child
111
- */
112
- static tempDirectory(name: string, parent?: DirectoryObject | null): Promise<DirectoryObject>;
113
74
  }
114
75
  export type FileObject = import("./FileObject.js").default;
115
76
  export type DirectoryObject = import("./DirectoryObject.js").default;
116
- import DirectoryObject from "./DirectoryObject.js";
117
77
  //# sourceMappingURL=FS.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FS.d.ts","sourceRoot":"","sources":["../../lib/FS.js"],"names":[],"mappings":"AA2BA;;GAEG;AACH;IACE,kCAAwB;IACxB,uCAAkC;IAClC,mBAAsB;IAEtB;;;;;;OAMG;IACH,4BAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;OAQG;IACH,sBALW,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,GAClB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAmCtC;IAED;;;;;;;;;;OAUG;IACH,oCAJW,UAAU,GAAC,eAAe,MAC1B,UAAU,GAAC,eAAe,GACxB,MAAM,CAYlB;IAED;;;;;;;;OAQG;IACH,oCALW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,MAAM,CA2BlB;IAED;;;;;;;;OAQG;IACH,6BAJW,MAAM,UACN,MAAM,GACJ,MAAM,CAgClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACH,2BArBW,MAAM,WACN,eAAe,GAAC,IAAI,GAClB,OAAO,CAAC,eAAe,CAAC,CA+DpC;CACF;yBA7Ra,OAAO,iBAAiB,EAAE,OAAO;8BACjC,OAAO,sBAAsB,EAAE,OAAO;4BAHxB,sBAAsB"}
1
+ {"version":3,"file":"FS.d.ts","sourceRoot":"","sources":["../../lib/FS.js"],"names":[],"mappings":"AAwBA;;GAEG;AACH;IACE,kCAAwB;IACxB,uCAAkC;IAClC,mBAAsB;IAEtB;;;;;;OAMG;IACH,4BAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAUlB;IAED;;;;;;OAMG;IACH,2BAHW,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;OAQG;IACH,sBALW,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,GAClB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAmCtC;IAED;;;;;;;;;;OAUG;IACH,oCAJW,UAAU,GAAC,eAAe,MAC1B,UAAU,GAAC,eAAe,GACxB,MAAM,CAYlB;IAED;;;;;;;;OAQG;IACH,oCALW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,MAAM,CA2BlB;IAED;;;;;;;;OAQG;IACH,6BAJW,MAAM,UACN,MAAM,GACJ,MAAM,CAgClB;CACF;yBAzMa,OAAO,iBAAiB,EAAE,OAAO;8BACjC,OAAO,sBAAsB,EAAE,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileObject.d.ts","sourceRoot":"","sources":["../../lib/FileObject.js"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;;GAcG;AAEH;uBAsHe,MAAM;IArHnB;;;;;OAKG;IACH,yBAFU;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,KAAK,GAAG,OAAO,IAAI,CAAC,CAAA;KAAC,CAO1D;IA2BF;;;;;OAKG;IACH,sBAHW,MAAM,GAAG,UAAU,cACnB,eAAe,GAAC,MAAM,GAAC,IAAI,EA0CrC;IAWD;;;;OAIG;IACH,UAFa,MAAM,CAclB;IAWD;;;;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;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;OAcG;IACH,iBAFa,eAAe,CAI3B;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;IAsBD;;;;;OAKG;IACH,gBAHW,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAY3B;IAED;;;;;;;;;;;OAWG;IACH,cARa,OAAO,CAAC,MAAM,CAAC,CAkB3B;IAED;;;;;;;;;;;OAWG;IACH,eARW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAezB;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAXW,WAAW,GAAC,IAAI,GAAC,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAyBzB;IAED;;;;;;;;;;;;;;OAcG;IACH,gBAXW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAkC5B;IAED;;;;OAIG;IACH,UAFa,OAAO,CAAC,MAAM,CAAC,CAY3B;IAED;;;;;;;;;OASG;IACH,UAPa,OAAO,CAAC,IAAI,CAAC,CAiBzB;;CACF;eArgBc,SAAS;4BADI,sBAAsB;kBARhC,OAAO;iBAIR,MAAM"}
1
+ {"version":3,"file":"FileObject.d.ts","sourceRoot":"","sources":["../../lib/FileObject.js"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;;GAcG;AAEH;uBAuHe,MAAM;IAtHnB;;;;;OAKG;IACH,yBAFU;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,KAAK,GAAG,OAAO,IAAI,CAAC,CAAA;KAAC,CAO1D;IA2BF;;;;;OAKG;IACH,sBAHW,MAAM,GAAG,UAAU,cACnB,eAAe,GAAC,MAAM,GAAC,IAAI,EA2CrC;IAWD;;;;OAIG;IACH,UAFa,MAAM,CAclB;IAWD;;;;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;;;;OAIG;IACH,mBAFa,OAAO,CAInB;IAED;;;;;;;;;;;;;;OAcG;IACH,iBAFa,eAAe,CAI3B;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;IAsBD;;;;;OAKG;IACH,gBAHW,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAY3B;IAED;;;;;;;;;;;OAWG;IACH,cARa,OAAO,CAAC,MAAM,CAAC,CAkB3B;IAED;;;;;;;;;;;OAWG;IACH,eARW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAezB;IAED;;;;;;;;;;;;;;;OAeG;IACH,kBAXW,WAAW,GAAC,IAAI,GAAC,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAyBzB;IAED;;;;;;;;;;;;;;OAcG;IACH,gBAXW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAkC5B;IAED;;;;OAIG;IACH,UAFa,OAAO,CAAC,MAAM,CAAC,CAY3B;IAED;;;;;;;;;OASG;IACH,UAPa,OAAO,CAAC,IAAI,CAAC,CAiBzB;;CACF;eAtgBc,SAAS;4BADI,sBAAsB;kBARhC,OAAO;iBAIR,MAAM"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * TempDirectoryObject extends CappedDirectoryObject with the cap set to
3
+ * the OS's temporary directory. Temporary directories are created
4
+ * synchronously during construction and exist immediately.
5
+ *
6
+ * All path operations are validated to ensure they remain within the temp
7
+ * directory hierarchy for security.
8
+ *
9
+ * @augments CappedDirectoryObject
10
+ */
11
+ export default class TempDirectoryObject extends CappedDirectoryObject {
12
+ /**
13
+ * Constructs a TempDirectoryObject instance and creates the directory.
14
+ *
15
+ * The directory is created synchronously during construction, so it will
16
+ * exist immediately after the constructor returns.
17
+ *
18
+ * If no name is provided, uses the OS temp directory directly. If a name
19
+ * is provided without a parent, creates a new directory with a unique suffix.
20
+ * If a parent is provided, creates a subdirectory within that parent.
21
+ *
22
+ * @param {string?} [name] - Base name for the temp directory (if empty/null, uses OS temp dir)
23
+ * @param {TempDirectoryObject?} [parent] - Optional parent temporary directory
24
+ * @throws {Sass} If name is absolute
25
+ * @throws {Sass} If name is empty (when parent is provided)
26
+ * @throws {Sass} If name contains path separators
27
+ * @throws {Sass} If parent is provided but not a temporary directory
28
+ * @throws {Sass} If parent's lineage does not trace back to the OS temp directory
29
+ * @throws {Sass} If directory creation fails
30
+ * @example
31
+ * // Use OS temp directory directly
32
+ * const temp = new TempDirectoryObject()
33
+ * console.log(temp.path) // "/tmp"
34
+ *
35
+ * @example
36
+ * // Create with unique name
37
+ * const temp = new TempDirectoryObject("myapp")
38
+ * console.log(temp.path) // "/tmp/myapp-ABC123"
39
+ *
40
+ * @example
41
+ * // Nested temp directories
42
+ * const parent = new TempDirectoryObject("parent")
43
+ * const child = new TempDirectoryObject("child", parent)
44
+ * await parent.remove() // Removes both parent and child
45
+ */
46
+ constructor(name?: string | null, parent?: TempDirectoryObject | null);
47
+ /**
48
+ * Creates a new TempDirectoryObject by extending this directory's path.
49
+ *
50
+ * Validates that the resulting path remains within the temp directory tree.
51
+ *
52
+ * @param {string} newPath - The path segment to append
53
+ * @returns {TempDirectoryObject} A new TempDirectoryObject with the extended path
54
+ * @throws {Sass} If the path would escape the temp directory
55
+ * @throws {Sass} If the path is absolute
56
+ * @throws {Sass} If the path contains traversal (..)
57
+ * @example
58
+ * const temp = new TempDirectoryObject("myapp")
59
+ * const subDir = temp.addDirectory("data")
60
+ * console.log(subDir.path) // "/tmp/myapp-ABC123/data"
61
+ */
62
+ addDirectory(newPath: string): TempDirectoryObject;
63
+ /**
64
+ * Creates a new FileObject by extending this directory's path.
65
+ *
66
+ * Validates that the resulting path remains within the temp directory tree.
67
+ *
68
+ * @param {string} filename - The filename to append
69
+ * @returns {FileObject} A new FileObject with the extended path
70
+ * @throws {Sass} If the path would escape the temp directory
71
+ * @throws {Sass} If the path is absolute
72
+ * @throws {Sass} If the path contains traversal (..)
73
+ * @example
74
+ * const temp = new TempDirectoryObject("myapp")
75
+ * const file = temp.addFile("config.json")
76
+ * console.log(file.path) // "/tmp/myapp-ABC123/config.json"
77
+ */
78
+ addFile(filename: string): FileObject;
79
+ #private;
80
+ }
81
+ import CappedDirectoryObject from "./CappedDirectoryObject.js";
82
+ //# sourceMappingURL=TempDirectoryObject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TempDirectoryObject.d.ts","sourceRoot":"","sources":["../../lib/TempDirectoryObject.js"],"names":[],"mappings":"AAYA;;;;;;;;;GASG;AACH;IAEE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,mBAxBW,MAAM,OAAC,WACP,mBAAmB,OAAC,EA2C9B;IAqBD;;;;;;;;;;;;;;OAcG;IACH,sBAVW,MAAM,GACJ,mBAAmB,CAY/B;IAED;;;;;;;;;;;;;;OAcG;IACH,kBAVW,MAAM,GACJ,UAAU,CAYtB;;CAUF;kCA1IiC,4BAA4B"}