@gesslar/toolkit 3.13.0 → 3.14.1
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 +5 -4
- package/package.json +11 -10
- package/src/{index.js → node/index.js} +11 -10
- package/src/{lib → node/lib}/DirectoryObject.js +47 -56
- package/src/{lib → node/lib}/FileObject.js +76 -149
- package/src/{lib/FS.js → node/lib/FileSystem.js} +7 -7
- package/src/{lib → node/lib}/Glog.js +2 -2
- package/src/{lib → node/lib}/Logger.js +1 -1
- package/src/{lib → node/lib}/Sass.js +1 -1
- package/src/{lib → node/lib}/Tantrum.js +1 -1
- package/src/{lib → node/lib}/TempDirectoryObject.js +9 -9
- package/src/{lib → node/lib}/Util.js +1 -1
- package/src/{lib/CappedDirectoryObject.js → node/lib/VDirectoryObject.js} +37 -92
- package/src/node/lib/VFileObject.js +61 -0
- package/src/{lib → node/lib}/Valid.js +11 -5
- package/{src/types → types/browser}/index.d.ts.map +1 -1
- package/types/browser/lib/Collection.d.ts.map +1 -0
- package/types/browser/lib/Data.d.ts.map +1 -0
- package/types/browser/lib/Disposer.d.ts.map +1 -0
- package/types/browser/lib/HTML.d.ts.map +1 -0
- package/types/browser/lib/Notify.d.ts.map +1 -0
- package/types/browser/lib/Promised.d.ts.map +1 -0
- package/types/browser/lib/Sass.d.ts.map +1 -0
- package/types/browser/lib/Tantrum.d.ts.map +1 -0
- package/types/browser/lib/Time.d.ts.map +1 -0
- package/types/browser/lib/TypeSpec.d.ts.map +1 -0
- package/types/browser/lib/Util.d.ts.map +1 -0
- package/types/browser/lib/Valid.d.ts.map +1 -0
- package/types/browser/lib/vendor/dompurify.esm.d.ts.map +1 -0
- package/{src/types → types/node}/index.d.ts +10 -9
- package/{src/types/browser → types/node}/index.d.ts.map +1 -1
- package/types/node/lib/Cache.d.ts.map +1 -0
- package/{src/types → types/node}/lib/DirectoryObject.d.ts +15 -15
- package/types/node/lib/DirectoryObject.d.ts.map +1 -0
- package/{src/types → types/node}/lib/FileObject.d.ts +7 -36
- package/types/node/lib/FileObject.d.ts.map +1 -0
- package/{src/types/lib/FS.d.ts → types/node/lib/FileSystem.d.ts} +2 -2
- package/types/node/lib/FileSystem.d.ts.map +1 -0
- package/types/node/lib/Glog.d.ts.map +1 -0
- package/types/node/lib/Logger.d.ts.map +1 -0
- package/types/node/lib/Notify.d.ts.map +1 -0
- package/{src/types → types/node}/lib/Sass.d.ts +1 -1
- package/types/node/lib/Sass.d.ts.map +1 -0
- package/{src/types → types/node}/lib/Tantrum.d.ts +1 -1
- package/types/node/lib/Tantrum.d.ts.map +1 -0
- package/{src/types → types/node}/lib/TempDirectoryObject.d.ts +4 -4
- package/types/node/lib/TempDirectoryObject.d.ts.map +1 -0
- package/types/node/lib/Term.d.ts.map +1 -0
- package/{src/types → types/node}/lib/Util.d.ts +1 -1
- package/types/node/lib/Util.d.ts.map +1 -0
- package/{src/types/lib/CappedDirectoryObject.d.ts → types/node/lib/VDirectoryObject.d.ts} +36 -48
- package/types/node/lib/VDirectoryObject.d.ts.map +1 -0
- package/types/node/lib/VFileObject.d.ts +33 -0
- package/types/node/lib/VFileObject.d.ts.map +1 -0
- package/{src/types → types/node}/lib/Valid.d.ts +3 -1
- package/types/node/lib/Valid.d.ts.map +1 -0
- package/src/types/browser/lib/Collection.d.ts.map +0 -1
- package/src/types/browser/lib/Data.d.ts.map +0 -1
- package/src/types/browser/lib/Disposer.d.ts.map +0 -1
- package/src/types/browser/lib/HTML.d.ts.map +0 -1
- package/src/types/browser/lib/Notify.d.ts.map +0 -1
- package/src/types/browser/lib/Promised.d.ts.map +0 -1
- package/src/types/browser/lib/Sass.d.ts.map +0 -1
- package/src/types/browser/lib/Tantrum.d.ts.map +0 -1
- package/src/types/browser/lib/Time.d.ts.map +0 -1
- package/src/types/browser/lib/TypeSpec.d.ts.map +0 -1
- package/src/types/browser/lib/Util.d.ts.map +0 -1
- package/src/types/browser/lib/Valid.d.ts.map +0 -1
- package/src/types/browser/lib/vendor/dompurify.esm.d.ts.map +0 -1
- package/src/types/lib/Cache.d.ts.map +0 -1
- package/src/types/lib/CappedDirectoryObject.d.ts.map +0 -1
- package/src/types/lib/DirectoryObject.d.ts.map +0 -1
- package/src/types/lib/FS.d.ts.map +0 -1
- package/src/types/lib/FileObject.d.ts.map +0 -1
- package/src/types/lib/Glog.d.ts.map +0 -1
- package/src/types/lib/Logger.d.ts.map +0 -1
- package/src/types/lib/Notify.d.ts.map +0 -1
- package/src/types/lib/Sass.d.ts.map +0 -1
- package/src/types/lib/Tantrum.d.ts.map +0 -1
- package/src/types/lib/TempDirectoryObject.d.ts.map +0 -1
- package/src/types/lib/Term.d.ts.map +0 -1
- package/src/types/lib/Util.d.ts.map +0 -1
- package/src/types/lib/Valid.d.ts.map +0 -1
- /package/src/{lib → node/lib}/Cache.js +0 -0
- /package/src/{lib → node/lib}/Notify.js +0 -0
- /package/src/{lib → node/lib}/Term.js +0 -0
- /package/{src/types → types}/browser/index.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Collection.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Data.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Disposer.d.ts +0 -0
- /package/{src/types → types}/browser/lib/HTML.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Notify.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Promised.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Sass.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Tantrum.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Time.d.ts +0 -0
- /package/{src/types → types}/browser/lib/TypeSpec.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Util.d.ts +0 -0
- /package/{src/types → types}/browser/lib/Valid.d.ts +0 -0
- /package/{src/types → types}/browser/lib/vendor/dompurify.esm.d.ts +0 -0
- /package/{src/types → types/node}/lib/Cache.d.ts +0 -0
- /package/{src/types → types/node}/lib/Glog.d.ts +0 -0
- /package/{src/types → types/node}/lib/Logger.d.ts +0 -0
- /package/{src/types → types/node}/lib/Notify.d.ts +0 -0
- /package/{src/types → types/node}/lib/Term.d.ts +0 -0
|
@@ -10,9 +10,9 @@ import path from "node:path"
|
|
|
10
10
|
import YAML from "yaml"
|
|
11
11
|
import {URL} from "node:url"
|
|
12
12
|
|
|
13
|
-
import Data from "
|
|
13
|
+
import Data from "../../browser/lib/Data.js"
|
|
14
14
|
import DirectoryObject from "./DirectoryObject.js"
|
|
15
|
-
import FS from "./
|
|
15
|
+
import FS from "./FileSystem.js"
|
|
16
16
|
import Sass from "./Sass.js"
|
|
17
17
|
import Valid from "./Valid.js"
|
|
18
18
|
|
|
@@ -27,7 +27,6 @@ import Valid from "./Valid.js"
|
|
|
27
27
|
* @property {string} module - The file name without extension
|
|
28
28
|
* @property {string} extension - The file extension
|
|
29
29
|
* @property {boolean} isFile - Always true for files
|
|
30
|
-
* @property {boolean} isDirectory - Always false for files
|
|
31
30
|
* @property {DirectoryObject} parent - The parent directory object
|
|
32
31
|
* @property {Promise<boolean>} exists - Whether the file exists (async)
|
|
33
32
|
*/
|
|
@@ -56,7 +55,6 @@ export default class FileObject extends FS {
|
|
|
56
55
|
* @property {string|null} module - The file name without extension
|
|
57
56
|
* @property {string|null} extension - The file extension
|
|
58
57
|
* @property {boolean} isFile - Always true
|
|
59
|
-
* @property {boolean} isDirectory - Always false
|
|
60
58
|
* @property {DirectoryObject|null} parent - The parent directory object
|
|
61
59
|
*/
|
|
62
60
|
#meta = Object.seal({
|
|
@@ -67,7 +65,6 @@ export default class FileObject extends FS {
|
|
|
67
65
|
module: null,
|
|
68
66
|
extension: null,
|
|
69
67
|
isFile: true,
|
|
70
|
-
isDirectory: false,
|
|
71
68
|
parent: null,
|
|
72
69
|
parentPath: null,
|
|
73
70
|
})
|
|
@@ -75,55 +72,65 @@ export default class FileObject extends FS {
|
|
|
75
72
|
/**
|
|
76
73
|
* Constructs a FileObject instance.
|
|
77
74
|
*
|
|
78
|
-
* @param {string}
|
|
75
|
+
* @param {string} submitted - The file path
|
|
79
76
|
* @param {DirectoryObject|string|null} [parent] - The parent directory (object or string)
|
|
80
77
|
*/
|
|
81
|
-
constructor(
|
|
78
|
+
constructor(submitted, parent=null) {
|
|
82
79
|
super()
|
|
83
80
|
|
|
84
|
-
Valid.type(
|
|
81
|
+
Valid.type(submitted, "String", {allowEmpty: false})
|
|
85
82
|
Valid.type(parent, "Null|String|DirectoryObject", {allowEmpty: false})
|
|
86
83
|
|
|
87
|
-
const
|
|
88
|
-
const
|
|
84
|
+
const normalizedFile = FS.fixSlashes(submitted)
|
|
85
|
+
const absOrRel = path.isAbsolute(normalizedFile) && parent
|
|
86
|
+
? FS.absoluteToRelative(normalizedFile, true)
|
|
87
|
+
: normalizedFile
|
|
88
|
+
const {dir, base, ext, name} = FS.pathParts(absOrRel)
|
|
89
|
+
|
|
90
|
+
const [parentObject, fullPath] = (() => {
|
|
91
|
+
if(Data.isType(parent, "String")) {
|
|
92
|
+
const joined = FS.resolvePath(parent, absOrRel)
|
|
93
|
+
const {dir} = FS.pathParts(joined)
|
|
94
|
+
|
|
95
|
+
return [
|
|
96
|
+
new DirectoryObject(dir),
|
|
97
|
+
joined,
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if(Data.isType(parent, "DirectoryObject")) {
|
|
102
|
+
const joined = FS.resolvePath(parent.path, absOrRel)
|
|
103
|
+
const {dir} = FS.pathParts(joined)
|
|
89
104
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
105
|
+
return [
|
|
106
|
+
parent.path === dir
|
|
107
|
+
? parent
|
|
108
|
+
: new DirectoryObject(dir),
|
|
109
|
+
joined,
|
|
110
|
+
]
|
|
111
|
+
}
|
|
93
112
|
|
|
94
|
-
|
|
95
|
-
|
|
113
|
+
const directory = new DirectoryObject(dir)
|
|
114
|
+
const joined = FS.resolvePath(directory.path, absOrRel)
|
|
96
115
|
|
|
97
|
-
return
|
|
116
|
+
return [
|
|
117
|
+
directory,
|
|
118
|
+
joined,
|
|
119
|
+
]
|
|
98
120
|
})()
|
|
99
121
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const resolvedFilename = parent
|
|
103
|
-
? FS.absoluteToRelative(fixedFile, true)
|
|
104
|
-
: fixedFile
|
|
105
|
-
|
|
106
|
-
// Use real path if parent is capped, otherwise use path
|
|
107
|
-
const parentPath = parentObject.real?.path || parentObject.path
|
|
108
|
-
const resolved = FS.resolvePath(parentPath ?? ".", resolvedFilename)
|
|
109
|
-
const {dir: actualParent} = FS.pathParts(resolved)
|
|
122
|
+
const parentPath = parentObject.path
|
|
123
|
+
const resolved = FS.resolvePath(parentPath, fullPath)
|
|
110
124
|
const url = new URL(FS.pathToUrl(resolved))
|
|
111
125
|
|
|
112
|
-
this.#meta.supplied =
|
|
126
|
+
this.#meta.supplied = submitted
|
|
113
127
|
this.#meta.path = resolved
|
|
114
128
|
this.#meta.url = url
|
|
115
129
|
this.#meta.name = base
|
|
116
130
|
this.#meta.extension = ext
|
|
117
|
-
this.#meta.module =
|
|
118
|
-
this.#meta.parentPath =
|
|
119
|
-
|
|
120
|
-
const useCappedParent =
|
|
121
|
-
parentObject.isCapped ||
|
|
122
|
-
FS.fixSlashes(actualParent) === FS.fixSlashes(parentObject.path)
|
|
123
|
-
|
|
124
|
-
this.#meta.parent = useCappedParent
|
|
125
|
-
? parentObject
|
|
126
|
-
: new DirectoryObject(actualParent)
|
|
131
|
+
this.#meta.module = name
|
|
132
|
+
this.#meta.parentPath = parentPath
|
|
133
|
+
this.#meta.parent = parentObject
|
|
127
134
|
|
|
128
135
|
Object.freeze(this.#meta)
|
|
129
136
|
}
|
|
@@ -131,10 +138,10 @@ export default class FileObject extends FS {
|
|
|
131
138
|
/**
|
|
132
139
|
* Returns a string representation of the FileObject.
|
|
133
140
|
*
|
|
134
|
-
* @returns {string}
|
|
141
|
+
* @returns {string} String representation of the FileObject
|
|
135
142
|
*/
|
|
136
143
|
toString() {
|
|
137
|
-
return this.
|
|
144
|
+
return this.isVirtual
|
|
138
145
|
?`[${this.constructor.name}: ${this.path} → ${this.real.path}]`
|
|
139
146
|
:`[${this.constructor.name}: ${this.path}]`
|
|
140
147
|
}
|
|
@@ -158,44 +165,20 @@ export default class FileObject extends FS {
|
|
|
158
165
|
}
|
|
159
166
|
|
|
160
167
|
/**
|
|
161
|
-
* Returns the file path.
|
|
162
|
-
* virtual path relative to the cap. Otherwise returns the real filesystem
|
|
163
|
-
* path.
|
|
164
|
-
*
|
|
165
|
-
* Use `.real.path` to always get the actual filesystem path.
|
|
168
|
+
* Returns the file path.
|
|
166
169
|
*
|
|
167
|
-
* @returns {string} The file path
|
|
170
|
+
* @returns {string} The file path
|
|
168
171
|
*/
|
|
169
172
|
get path() {
|
|
170
|
-
|
|
171
|
-
const parent = this.#meta.parent
|
|
172
|
-
|
|
173
|
-
// If parent is capped, return virtual path
|
|
174
|
-
if(parent?.isCapped) {
|
|
175
|
-
const cap = parent.cap.real.path
|
|
176
|
-
const capResolved = path.resolve(cap)
|
|
177
|
-
const relativeRealPath = FS.absoluteToRelative(realPath)
|
|
178
|
-
const absolute = FS.resolvePath(capResolved, relativeRealPath)
|
|
179
|
-
|
|
180
|
-
// Return with leading slash to indicate it's cap-relative
|
|
181
|
-
return FS.absoluteToRelative(absolute)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Otherwise return real path
|
|
185
|
-
return realPath
|
|
173
|
+
return this.#meta.path
|
|
186
174
|
}
|
|
187
175
|
|
|
188
176
|
/**
|
|
189
|
-
* Returns the URL of the current file.
|
|
190
|
-
* returns a virtual URL relative to the cap. Otherwise returns the real URL.
|
|
177
|
+
* Returns the URL of the current file.
|
|
191
178
|
*
|
|
192
|
-
* @returns {URL} The file URL
|
|
179
|
+
* @returns {URL} The file URL
|
|
193
180
|
*/
|
|
194
181
|
get url() {
|
|
195
|
-
// If parent is capped, return virtual URL
|
|
196
|
-
if(this.parent?.isCapped)
|
|
197
|
-
return new URL(FS.pathToUrl(this.path))
|
|
198
|
-
|
|
199
182
|
return this.#meta.url
|
|
200
183
|
}
|
|
201
184
|
|
|
@@ -234,15 +217,6 @@ export default class FileObject extends FS {
|
|
|
234
217
|
return this.#meta.isFile
|
|
235
218
|
}
|
|
236
219
|
|
|
237
|
-
/**
|
|
238
|
-
* We're not masquerading as a directory! Nope.
|
|
239
|
-
*
|
|
240
|
-
* @returns {boolean} Always false
|
|
241
|
-
*/
|
|
242
|
-
get isDirectory() {
|
|
243
|
-
return this.#meta.isDirectory
|
|
244
|
-
}
|
|
245
|
-
|
|
246
220
|
/**
|
|
247
221
|
* Returns the directory containing this file. This does not necessarily
|
|
248
222
|
* mean that the directory exists. It could be theoretical, you will need
|
|
@@ -266,26 +240,6 @@ export default class FileObject extends FS {
|
|
|
266
240
|
return this.#meta.parentPath
|
|
267
241
|
}
|
|
268
242
|
|
|
269
|
-
/**
|
|
270
|
-
* Returns a plain FileObject representing the actual filesystem location.
|
|
271
|
-
* This provides an "escape hatch" when working with capped directories,
|
|
272
|
-
* allowing direct filesystem access when needed.
|
|
273
|
-
*
|
|
274
|
-
* @returns {FileObject} Uncapped file object at the real filesystem path
|
|
275
|
-
* @example
|
|
276
|
-
* const temp = new TempDirectoryObject("myapp")
|
|
277
|
-
* const file = temp.getFile("/config/app.json")
|
|
278
|
-
*
|
|
279
|
-
* // file.path shows virtual path
|
|
280
|
-
* console.log(file.path) // "/config/app.json"
|
|
281
|
-
* // file.real.path shows actual filesystem path
|
|
282
|
-
* console.log(file.real.path) // "/tmp/myapp-ABC123/config/app.json"
|
|
283
|
-
* file.real.parent.parent // Can traverse outside the cap
|
|
284
|
-
*/
|
|
285
|
-
get real() {
|
|
286
|
-
return new FileObject(this.path)
|
|
287
|
-
}
|
|
288
|
-
|
|
289
243
|
/**
|
|
290
244
|
* Check if a file can be read. Returns true if the file can be read, false
|
|
291
245
|
*
|
|
@@ -293,7 +247,7 @@ export default class FileObject extends FS {
|
|
|
293
247
|
*/
|
|
294
248
|
async canRead() {
|
|
295
249
|
try {
|
|
296
|
-
await fs.access(this
|
|
250
|
+
await fs.access(this.real?.path ?? this.path, fs.constants.R_OK)
|
|
297
251
|
|
|
298
252
|
return true
|
|
299
253
|
} catch {
|
|
@@ -308,7 +262,7 @@ export default class FileObject extends FS {
|
|
|
308
262
|
*/
|
|
309
263
|
async canWrite() {
|
|
310
264
|
try {
|
|
311
|
-
await fs.access(this
|
|
265
|
+
await fs.access(this.real?.path ?? this.path, fs.constants.W_OK)
|
|
312
266
|
|
|
313
267
|
return true
|
|
314
268
|
} catch {
|
|
@@ -323,7 +277,7 @@ export default class FileObject extends FS {
|
|
|
323
277
|
*/
|
|
324
278
|
async #fileExists() {
|
|
325
279
|
try {
|
|
326
|
-
await fs.access(this
|
|
280
|
+
await fs.access(this.real?.path ?? this.path, fs.constants.F_OK)
|
|
327
281
|
|
|
328
282
|
return true
|
|
329
283
|
} catch {
|
|
@@ -338,7 +292,7 @@ export default class FileObject extends FS {
|
|
|
338
292
|
*/
|
|
339
293
|
async size() {
|
|
340
294
|
try {
|
|
341
|
-
const stat = await fs.stat(this
|
|
295
|
+
const stat = await fs.stat(this.real?.path ?? this.path)
|
|
342
296
|
|
|
343
297
|
return stat.size
|
|
344
298
|
} catch {
|
|
@@ -354,7 +308,7 @@ export default class FileObject extends FS {
|
|
|
354
308
|
*/
|
|
355
309
|
async modified() {
|
|
356
310
|
try {
|
|
357
|
-
const stat = await fs.stat(this
|
|
311
|
+
const stat = await fs.stat(this.real?.path ?? this.path)
|
|
358
312
|
|
|
359
313
|
return stat.mtime
|
|
360
314
|
} catch {
|
|
@@ -369,15 +323,12 @@ export default class FileObject extends FS {
|
|
|
369
323
|
* @returns {Promise<string>} The file contents
|
|
370
324
|
*/
|
|
371
325
|
async read(encoding="utf8") {
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
if(!url)
|
|
375
|
-
throw Sass.new("No URL in file map")
|
|
326
|
+
const filePath = this.real?.path ?? this.path
|
|
376
327
|
|
|
377
328
|
if(!(await this.exists))
|
|
378
|
-
throw Sass.new(`No such file '${
|
|
329
|
+
throw Sass.new(`No such file '${filePath}'`)
|
|
379
330
|
|
|
380
|
-
return await fs.readFile(
|
|
331
|
+
return await fs.readFile(filePath, encoding)
|
|
381
332
|
}
|
|
382
333
|
|
|
383
334
|
/**
|
|
@@ -393,15 +344,12 @@ export default class FileObject extends FS {
|
|
|
393
344
|
* // Use the buffer (e.g., send in HTTP response, process image, etc.)
|
|
394
345
|
*/
|
|
395
346
|
async readBinary() {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
if(!url)
|
|
399
|
-
throw Sass.new("No URL in file map")
|
|
347
|
+
const filePath = this.real?.path ?? this.path
|
|
400
348
|
|
|
401
349
|
if(!(await this.exists))
|
|
402
|
-
throw Sass.new(`No such file '${
|
|
350
|
+
throw Sass.new(`No such file '${filePath}'`)
|
|
403
351
|
|
|
404
|
-
return await fs.readFile(
|
|
352
|
+
return await fs.readFile(filePath)
|
|
405
353
|
}
|
|
406
354
|
|
|
407
355
|
/**
|
|
@@ -417,29 +365,15 @@ export default class FileObject extends FS {
|
|
|
417
365
|
* await file.write(JSON.stringify({key: 'value'}))
|
|
418
366
|
*/
|
|
419
367
|
async write(content, encoding="utf8") {
|
|
420
|
-
const
|
|
421
|
-
if(!realPath)
|
|
422
|
-
throw Sass.new("No actual disk location detected.")
|
|
368
|
+
const filePath = this.real?.path ?? this.path
|
|
423
369
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if(process.platform === "win32") {
|
|
427
|
-
try {
|
|
428
|
-
const parentPath = path.dirname(realPath)
|
|
429
|
-
const normalizedParent = await fs.realpath(parentPath)
|
|
430
|
-
pathToWrite = path.join(normalizedParent, path.basename(realPath))
|
|
431
|
-
} catch {
|
|
432
|
-
// If normalization fails, use original path
|
|
433
|
-
}
|
|
434
|
-
}
|
|
370
|
+
if(!filePath)
|
|
371
|
+
throw Sass.new("No actual disk location detected.")
|
|
435
372
|
|
|
436
373
|
try {
|
|
437
|
-
await fs.writeFile(
|
|
374
|
+
await fs.writeFile(filePath, content, encoding)
|
|
438
375
|
} catch(error) {
|
|
439
|
-
|
|
440
|
-
throw Sass.new(`Invalid directory: ${path.dirname(pathToWrite)}`)
|
|
441
|
-
|
|
442
|
-
throw Sass.from(error, "Failed to write file")
|
|
376
|
+
throw Sass.new("Failed to write file.", error)
|
|
443
377
|
}
|
|
444
378
|
}
|
|
445
379
|
|
|
@@ -460,11 +394,10 @@ export default class FileObject extends FS {
|
|
|
460
394
|
* await file.writeBinary(buffer)
|
|
461
395
|
*/
|
|
462
396
|
async writeBinary(data) {
|
|
463
|
-
|
|
464
|
-
throw Sass.new("No URL in file")
|
|
397
|
+
const filePath = this.real?.path ?? this.path
|
|
465
398
|
|
|
466
399
|
const exists = await this.parent.exists
|
|
467
|
-
Valid.assert(exists, `Invalid directory
|
|
400
|
+
Valid.assert(exists, `Invalid directory writing ${filePath}`)
|
|
468
401
|
|
|
469
402
|
Valid.assert(Data.isBinary(data), "Data must be binary (ArrayBuffer, TypedArray, Blob, or Buffer)")
|
|
470
403
|
|
|
@@ -473,7 +406,7 @@ export default class FileObject extends FS {
|
|
|
473
406
|
|
|
474
407
|
// According to the internet, if it's already binary, I don't need
|
|
475
408
|
// an encoding. 🤷
|
|
476
|
-
return await fs.writeFile(
|
|
409
|
+
return await fs.writeFile(filePath, bufferData)
|
|
477
410
|
}
|
|
478
411
|
|
|
479
412
|
/**
|
|
@@ -524,15 +457,12 @@ export default class FileObject extends FS {
|
|
|
524
457
|
* @returns {Promise<object>} The file contents as a module.
|
|
525
458
|
*/
|
|
526
459
|
async import() {
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
if(!url)
|
|
530
|
-
throw Sass.new("No URL in file map")
|
|
460
|
+
const filePath = this.real?.path ?? this.path
|
|
531
461
|
|
|
532
462
|
if(!(await this.exists))
|
|
533
|
-
throw Sass.new(`No such file '${
|
|
463
|
+
throw Sass.new(`No such file '${filePath}'`)
|
|
534
464
|
|
|
535
|
-
return await import(
|
|
465
|
+
return await import(filePath)
|
|
536
466
|
}
|
|
537
467
|
|
|
538
468
|
/**
|
|
@@ -546,14 +476,11 @@ export default class FileObject extends FS {
|
|
|
546
476
|
* await file.delete()
|
|
547
477
|
*/
|
|
548
478
|
async delete() {
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
if(!url)
|
|
552
|
-
throw Sass.new("This object does not represent a valid resource.")
|
|
479
|
+
const filePath = this.real?.path ?? this.path
|
|
553
480
|
|
|
554
481
|
if(!(await this.exists))
|
|
555
|
-
throw Sass.new(`No such resource '${
|
|
482
|
+
throw Sass.new(`No such resource '${filePath}'`)
|
|
556
483
|
|
|
557
|
-
return await fs.unlink(
|
|
484
|
+
return await fs.unlink(filePath)
|
|
558
485
|
}
|
|
559
486
|
}
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
import path from "node:path"
|
|
12
12
|
import url from "node:url"
|
|
13
13
|
|
|
14
|
-
import Collection from "
|
|
15
|
-
import Data from "
|
|
14
|
+
import Collection from "../../browser/lib/Collection.js"
|
|
15
|
+
import Data from "../../browser/lib/Data.js"
|
|
16
16
|
import Valid from "./Valid.js"
|
|
17
17
|
|
|
18
18
|
/** @typedef {import("./FileObject.js").default} FileObject */
|
|
@@ -27,7 +27,7 @@ const fdType = Object.freeze(
|
|
|
27
27
|
/**
|
|
28
28
|
* File system utility class for path operations and file discovery.
|
|
29
29
|
*/
|
|
30
|
-
export default class
|
|
30
|
+
export default class FileSystem {
|
|
31
31
|
static fdTypes = fdTypes
|
|
32
32
|
static upperFdTypes = upperFdTypes
|
|
33
33
|
static fdType = fdType
|
|
@@ -49,7 +49,7 @@ export default class FS {
|
|
|
49
49
|
1
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
-
return
|
|
52
|
+
return FileSystem.relativeOrAbsolutePath(fileOrDirectoryObject, this)
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
@@ -193,7 +193,7 @@ export default class FS {
|
|
|
193
193
|
|
|
194
194
|
// Strategy 3: Try overlap-based merging, which will default to a basic
|
|
195
195
|
// join if no overlap
|
|
196
|
-
return
|
|
196
|
+
return FileSystem.mergeOverlappingPaths(from, to)
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
/**
|
|
@@ -339,14 +339,14 @@ export default class FS {
|
|
|
339
339
|
let target, cap
|
|
340
340
|
|
|
341
341
|
if(fileOrDirectoryObject.isFile) {
|
|
342
|
-
if(!fileOrDirectoryObject.parent.
|
|
342
|
+
if(!fileOrDirectoryObject.parent.isVirtual) {
|
|
343
343
|
return fileOrDirectoryObject.path
|
|
344
344
|
} else {
|
|
345
345
|
target = fileOrDirectoryObject.path
|
|
346
346
|
cap = fileOrDirectoryObject.parent.cap.real.path
|
|
347
347
|
}
|
|
348
348
|
} else {
|
|
349
|
-
if(!fileOrDirectoryObject.
|
|
349
|
+
if(!fileOrDirectoryObject.isVirtual) {
|
|
350
350
|
return fileOrDirectoryObject.path
|
|
351
351
|
} else {
|
|
352
352
|
target = fileOrDirectoryObject.path
|
|
@@ -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
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
import ErrorStackParser from "error-stack-parser"
|
|
27
27
|
import console from "node:console"
|
|
28
28
|
import {Environment} from "./Core.js"
|
|
29
|
-
import {FileObject, Util} from "
|
|
29
|
+
import {FileObject, Util} from "../../../types/node/index.js"
|
|
30
30
|
|
|
31
31
|
export const loggerColours = {
|
|
32
32
|
debug: [
|
|
@@ -8,24 +8,24 @@ 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 Data from "
|
|
12
|
-
import
|
|
11
|
+
import Data from "../../browser/lib/Data.js"
|
|
12
|
+
import VDirectoryObject from "./VDirectoryObject.js"
|
|
13
13
|
import DirectoryObject from "./DirectoryObject.js"
|
|
14
|
-
import
|
|
14
|
+
import FileSystem from "./FileSystem.js"
|
|
15
15
|
import Sass from "./Sass.js"
|
|
16
16
|
import Valid from "./Valid.js"
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* TempDirectoryObject extends
|
|
19
|
+
* TempDirectoryObject extends VDirectoryObject with the cap set to
|
|
20
20
|
* the OS's temporary directory. Temporary directories are created
|
|
21
21
|
* synchronously during construction and exist immediately.
|
|
22
22
|
*
|
|
23
23
|
* All path operations are validated to ensure they remain within the temp
|
|
24
24
|
* directory hierarchy for security.
|
|
25
25
|
*
|
|
26
|
-
* @augments
|
|
26
|
+
* @augments VDirectoryObject
|
|
27
27
|
*/
|
|
28
|
-
export default class TempDirectoryObject extends
|
|
28
|
+
export default class TempDirectoryObject extends VDirectoryObject {
|
|
29
29
|
#tmpReal
|
|
30
30
|
#tmpCap
|
|
31
31
|
|
|
@@ -62,7 +62,7 @@ export default class TempDirectoryObject extends CappedDirectoryObject {
|
|
|
62
62
|
const parentRealPath = source?.real.path ?? os.tmpdir()
|
|
63
63
|
|
|
64
64
|
if(source && path.isAbsolute(directory)) {
|
|
65
|
-
const {root} =
|
|
65
|
+
const {root} = FileSystem.pathParts(directory)
|
|
66
66
|
|
|
67
67
|
directory = Data.chopLeft(directory, root)
|
|
68
68
|
}
|
|
@@ -72,12 +72,12 @@ export default class TempDirectoryObject extends CappedDirectoryObject {
|
|
|
72
72
|
if(source) {
|
|
73
73
|
toSuper = `/${directory}`
|
|
74
74
|
realTempDirectoryPath =
|
|
75
|
-
|
|
75
|
+
FileSystem.mergeOverlappingPaths(parentRealPath, directory)
|
|
76
76
|
if(!fs.existsSync(realTempDirectoryPath))
|
|
77
77
|
mkdirSync(realTempDirectoryPath)
|
|
78
78
|
} else {
|
|
79
79
|
realTempDirectoryPath =
|
|
80
|
-
mkdtempSync(
|
|
80
|
+
mkdtempSync(FileSystem.mergeOverlappingPaths(os.tmpdir(), directory))
|
|
81
81
|
toSuper = path.resolve(path.sep)
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {createHash} from "node:crypto"
|
|
2
2
|
import {EventEmitter} from "node:events"
|
|
3
|
-
import {Util as BrowserUtil} from "
|
|
3
|
+
import {Util as BrowserUtil} from "../../browser/index.js"
|
|
4
4
|
import Sass from "./Sass.js"
|
|
5
5
|
import process from "node:process"
|
|
6
6
|
import JSON5 from "json5"
|