@gesslar/toolkit 3.12.3 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +5 -4
  2. package/package.json +2 -2
  3. package/src/{index.js → node/index.js} +11 -10
  4. package/src/{lib → node/lib}/DirectoryObject.js +47 -88
  5. package/src/{lib → node/lib}/FileObject.js +78 -179
  6. package/src/{lib/FS.js → node/lib/FileSystem.js} +7 -7
  7. package/src/{lib → node/lib}/Glog.js +2 -2
  8. package/src/{lib → node/lib}/Logger.js +1 -1
  9. package/src/{lib → node/lib}/Sass.js +1 -1
  10. package/src/{lib → node/lib}/Tantrum.js +1 -1
  11. package/src/{lib → node/lib}/TempDirectoryObject.js +9 -9
  12. package/src/{lib → node/lib}/Util.js +1 -1
  13. package/src/node/lib/VDirectoryObject.js +198 -0
  14. package/src/node/lib/VFileObject.js +61 -0
  15. package/src/{lib → node/lib}/Valid.js +11 -5
  16. package/src/lib/CappedDirectoryObject.js +0 -276
  17. package/src/types/browser/index.d.ts +0 -13
  18. package/src/types/browser/index.d.ts.map +0 -1
  19. package/src/types/browser/lib/Collection.d.ts +0 -248
  20. package/src/types/browser/lib/Collection.d.ts.map +0 -1
  21. package/src/types/browser/lib/Data.d.ts +0 -250
  22. package/src/types/browser/lib/Data.d.ts.map +0 -1
  23. package/src/types/browser/lib/Disposer.d.ts +0 -33
  24. package/src/types/browser/lib/Disposer.d.ts.map +0 -1
  25. package/src/types/browser/lib/HTML.d.ts +0 -40
  26. package/src/types/browser/lib/HTML.d.ts.map +0 -1
  27. package/src/types/browser/lib/Notify.d.ts +0 -60
  28. package/src/types/browser/lib/Notify.d.ts.map +0 -1
  29. package/src/types/browser/lib/Promised.d.ts +0 -119
  30. package/src/types/browser/lib/Promised.d.ts.map +0 -1
  31. package/src/types/browser/lib/Sass.d.ts +0 -63
  32. package/src/types/browser/lib/Sass.d.ts.map +0 -1
  33. package/src/types/browser/lib/Tantrum.d.ts +0 -52
  34. package/src/types/browser/lib/Tantrum.d.ts.map +0 -1
  35. package/src/types/browser/lib/Time.d.ts +0 -42
  36. package/src/types/browser/lib/Time.d.ts.map +0 -1
  37. package/src/types/browser/lib/TypeSpec.d.ts +0 -90
  38. package/src/types/browser/lib/TypeSpec.d.ts.map +0 -1
  39. package/src/types/browser/lib/Util.d.ts +0 -62
  40. package/src/types/browser/lib/Util.d.ts.map +0 -1
  41. package/src/types/browser/lib/Valid.d.ts +0 -33
  42. package/src/types/browser/lib/Valid.d.ts.map +0 -1
  43. package/src/types/browser/lib/vendor/dompurify.esm.d.ts +0 -29
  44. package/src/types/browser/lib/vendor/dompurify.esm.d.ts.map +0 -1
  45. package/src/types/index.d.ts +0 -20
  46. package/src/types/index.d.ts.map +0 -1
  47. package/src/types/lib/Cache.d.ts +0 -27
  48. package/src/types/lib/Cache.d.ts.map +0 -1
  49. package/src/types/lib/CappedDirectoryObject.d.ts +0 -144
  50. package/src/types/lib/CappedDirectoryObject.d.ts.map +0 -1
  51. package/src/types/lib/DirectoryObject.d.ts +0 -288
  52. package/src/types/lib/DirectoryObject.d.ts.map +0 -1
  53. package/src/types/lib/FS.d.ts +0 -188
  54. package/src/types/lib/FS.d.ts.map +0 -1
  55. package/src/types/lib/FileObject.d.ts +0 -245
  56. package/src/types/lib/FileObject.d.ts.map +0 -1
  57. package/src/types/lib/Glog.d.ts +0 -228
  58. package/src/types/lib/Glog.d.ts.map +0 -1
  59. package/src/types/lib/Logger.d.ts +0 -46
  60. package/src/types/lib/Logger.d.ts.map +0 -1
  61. package/src/types/lib/Notify.d.ts +0 -54
  62. package/src/types/lib/Notify.d.ts.map +0 -1
  63. package/src/types/lib/Sass.d.ts +0 -9
  64. package/src/types/lib/Sass.d.ts.map +0 -1
  65. package/src/types/lib/Tantrum.d.ts +0 -9
  66. package/src/types/lib/Tantrum.d.ts.map +0 -1
  67. package/src/types/lib/TempDirectoryObject.d.ts +0 -42
  68. package/src/types/lib/TempDirectoryObject.d.ts.map +0 -1
  69. package/src/types/lib/Term.d.ts +0 -127
  70. package/src/types/lib/Term.d.ts.map +0 -1
  71. package/src/types/lib/Util.d.ts +0 -100
  72. package/src/types/lib/Util.d.ts.map +0 -1
  73. package/src/types/lib/Valid.d.ts +0 -33
  74. package/src/types/lib/Valid.d.ts.map +0 -1
  75. /package/src/{lib → node/lib}/Cache.js +0 -0
  76. /package/src/{lib → node/lib}/Notify.js +0 -0
  77. /package/src/{lib → node/lib}/Term.js +0 -0
package/README.md CHANGED
@@ -35,10 +35,9 @@ Includes all browser functionality plus Node.js-specific modules for file I/O, l
35
35
  | Name | Description |
36
36
  | ---- | ----------- |
37
37
  | Cache | Cache management for file I/O operations |
38
- | CappedDirectoryObject | Directory operations constrained to a specific tree |
39
38
  | DirectoryObject | Directory metadata and operations including path resolution, existence checks, and traversal |
40
39
  | FileObject | File system wrapper for file operations |
41
- | FS | Base class for file system operations with static utilities |
40
+ | FileSystem | Base class for file system operations with static utilities |
42
41
  | Glog | Logging framework |
43
42
  | Notify | Event system wrapper for Node.js events |
44
43
  | Sass | Custom Error class with enhanced features |
@@ -47,6 +46,8 @@ Includes all browser functionality plus Node.js-specific modules for file I/O, l
47
46
  | Term | Terminal formatting and output utilities |
48
47
  | Util | General utility functions (Node-enhanced version) |
49
48
  | Valid | Validation and assertion methods |
49
+ | VDirectoryObject | Directory operations constrained to a specific tree |
50
+ | VFileObject | Virtual file operations for in-memory file handling |
50
51
 
51
52
  ## Installation
52
53
 
@@ -99,8 +100,8 @@ import { Data, Collection, Util } from '@gesslar/toolkit/browser'
99
100
 
100
101
  The browser version includes: Collection, Data, Disposer, HTML, Notify, Sass,
101
102
  Tantrum, Type (TypeSpec), Util, and Valid. Node-only modules (Cache,
102
- CappedDirectoryObject, DirectoryObject, FileObject, FS, Glog,
103
- TempDirectoryObject, Term) are not available in the browser version.
103
+ DirectoryObject, FileObject, FileSystem, Glog, TempDirectoryObject, Term,
104
+ VDirectoryObject, VFileObject) are not available in the browser version.
104
105
 
105
106
  ## Post Partum
106
107
 
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "gesslar",
6
6
  "url": "https://gesslar.dev"
7
7
  },
8
- "version": "3.12.3",
8
+ "version": "3.14.0",
9
9
  "license": "Unlicense",
10
10
  "homepage": "https://github.com/gesslar/toolkit#readme",
11
11
  "repository": {
@@ -63,7 +63,7 @@
63
63
  "typescript": "^5.9.3"
64
64
  },
65
65
  "scripts": {
66
- "types:build": "node -e \"require('fs').rmSync('src/types',{recursive:true,force:true});\" && tsc -p tsconfig.types.json",
66
+ "types": "node -e \"require('fs').rmSync('types',{recursive:true,force:true});\" && tsc -p tsconfig.types.json",
67
67
  "lint": "eslint src/",
68
68
  "lint:fix": "eslint src/ --fix",
69
69
  "submit": "pnpm publish --access public --//registry.npmjs.org/:_authToken=\"${NPM_ACCESS_TOKEN}\"",
@@ -1,11 +1,11 @@
1
1
  // Browser-compatible utilities (pure JS)
2
- export {default as Collection} from "./browser/lib/Collection.js"
3
- export {default as Data} from "./browser/lib/Data.js"
4
- export {default as Disposer} from "./browser/lib/Disposer.js"
5
- export {Disposer as DisposerClass} from "./browser/lib/Disposer.js"
6
- export {default as Promised} from "./browser/lib/Promised.js"
7
- export {default as Time} from "./browser/lib/Time.js"
8
- export {default as Type} from "./browser/lib/TypeSpec.js"
2
+ export {default as Collection} from "../browser/lib/Collection.js"
3
+ export {default as Data} from "../browser/lib/Data.js"
4
+ export {default as Disposer} from "../browser/lib/Disposer.js"
5
+ export {Disposer as DisposerClass} from "../browser/lib/Disposer.js"
6
+ export {default as Promised} from "../browser/lib/Promised.js"
7
+ export {default as Time} from "../browser/lib/Time.js"
8
+ export {default as Type} from "../browser/lib/TypeSpec.js"
9
9
  export {default as Valid} from "./lib/Valid.js"
10
10
 
11
11
  // Node-enhanced versions (use Term for better formatting, crypto, etc.)
@@ -15,11 +15,12 @@ export {default as Util} from "./lib/Util.js"
15
15
 
16
16
  // Node-specific exports
17
17
  export {default as Cache} from "./lib/Cache.js"
18
- export {default as CappedDirectoryObject} from "./lib/CappedDirectoryObject.js"
19
18
  export {default as DirectoryObject} from "./lib/DirectoryObject.js"
20
- export {default as TempDirectoryObject} from "./lib/TempDirectoryObject.js"
21
19
  export {default as FileObject} from "./lib/FileObject.js"
22
- export {default as FS} from "./lib/FS.js"
20
+ export {default as FS} from "./lib/FileSystem.js"
23
21
  export {default as Glog} from "./lib/Glog.js"
24
22
  export {default as Notify} from "./lib/Notify.js"
23
+ export {default as TempDirectoryObject} from "./lib/TempDirectoryObject.js"
25
24
  export {default as Term} from "./lib/Term.js"
25
+ export {default as VFileObject} from "./lib/VFileObject.js"
26
+ export {default as VDirectoryObject} from "./lib/VDirectoryObject.js"
@@ -8,11 +8,12 @@ import {glob, mkdir, opendir, readdir, rmdir} from "node:fs/promises"
8
8
  import path from "node:path"
9
9
  import {URL} from "node:url"
10
10
 
11
- import Data from "../browser/lib/Data.js"
12
- import FS from "./FS.js"
11
+ import Data from "../../browser/lib/Data.js"
12
+ import FS from "./FileSystem.js"
13
13
  import FileObject from "./FileObject.js"
14
14
  import Sass from "./Sass.js"
15
15
  import Valid from "./Valid.js"
16
+ import VFileObject from "./VFileObject.js"
16
17
 
17
18
  /**
18
19
  * DirectoryObject encapsulates metadata and operations for a directory,
@@ -33,7 +34,6 @@ import Valid from "./Valid.js"
33
34
  * @property {string} extension - The directory extension (typically empty string)
34
35
  * @property {string} sep - Platform-specific path separator ('/' or '\\')
35
36
  * @property {Array<string>} trail - Path segments split by separator
36
- * @property {boolean} isFile - Always false (this is a directory)
37
37
  * @property {boolean} isDirectory - Always true
38
38
  * @property {DirectoryObject|null} parent - The parent directory (null if root)
39
39
  * @property {Promise<boolean>} exists - Whether the directory exists (async getter)
@@ -71,22 +71,18 @@ export default class DirectoryObject extends FS {
71
71
  * @property {string|null} name - The file name
72
72
  * @property {string|null} module - The file name without extension
73
73
  * @property {string|null} extension - The file extension
74
- * @property {boolean} isFile - Always false
75
74
  * @property {boolean} isDirectory - Always true
76
75
  */
77
76
  #meta = Object.seal({
78
- supplied: null,
79
- path: null,
80
- url: null,
81
- name: null,
82
- module: null,
83
- extension: null,
84
- isFile: false,
85
77
  isDirectory: true,
86
- trail: null,
87
- sep: null,
78
+ name: null,
88
79
  parent: undefined,
89
80
  parentPath: undefined,
81
+ path: null,
82
+ sep: null,
83
+ supplied: null,
84
+ trail: null,
85
+ url: null,
90
86
  })
91
87
 
92
88
  // Not in the meta, because it gets frozen, and these are lazily
@@ -96,34 +92,30 @@ export default class DirectoryObject extends FS {
96
92
  /**
97
93
  * Constructs a DirectoryObject instance.
98
94
  *
99
- * @param {string?} [directory="."] - The directory path or DirectoryObject (defaults to current directory)
95
+ * @param {string?} [supplied="."] - The directory path (defaults to current directory)
100
96
  */
101
- constructor(directory) {
102
- directory ||= "."
97
+ constructor(supplied) {
98
+ const fixedDir = supplied || "."
103
99
 
104
- Valid.type(directory, "String")
100
+ Valid.type(fixedDir, "String")
105
101
 
106
102
  super()
107
103
 
108
- const fixedDir = FS.fixSlashes(directory)
109
- const resolved = path.resolve(fixedDir)
104
+ const normalizedDir = FS.fixSlashes(fixedDir)
105
+ const resolved = path.resolve(normalizedDir)
106
+ const {dir, name, root} = FS.pathParts(resolved)
110
107
  const url = new URL(FS.pathToUrl(resolved))
111
- const baseName = path.basename(resolved) || ""
112
108
  const trail = resolved.split(path.sep)
113
- const sep = path.sep
114
- const pathParts = FS.pathParts(resolved)
115
109
 
116
- this.#meta.supplied = fixedDir
110
+ this.#meta.name = name
111
+ this.#meta.parentPath = dir == root
112
+ ? null
113
+ : dir
117
114
  this.#meta.path = resolved
118
- this.#meta.url = url
119
- this.#meta.name = baseName
120
- this.#meta.extension = ""
121
- this.#meta.module = baseName !== "." ? baseName : ""
115
+ this.#meta.sep = path.sep
116
+ this.#meta.supplied = supplied
122
117
  this.#meta.trail = trail
123
- this.#meta.sep = sep
124
- this.#meta.parentPath = pathParts.dir === pathParts.root
125
- ? null
126
- : pathParts.dir
118
+ this.#meta.url = url
127
119
 
128
120
  Object.freeze(this.#meta)
129
121
  }
@@ -148,43 +140,11 @@ export default class DirectoryObject extends FS {
148
140
  * @returns {string} string representation of the DirectoryObject
149
141
  */
150
142
  toString() {
151
- return this.isCapped
152
- ?`[${this.constructor.name}: ${this.path} → ${this.real.path}]`
153
- :`[${this.constructor.name}: ${this.path}]`
154
-
155
- return this.isCapped
143
+ return this.isVirtual
156
144
  ?`[${this.constructor.name}: ${this.path} → ${this.real.path}]`
157
145
  :`[${this.constructor.name}: ${this.path}]`
158
146
  }
159
147
 
160
- /**
161
- * Returns a JSON representation of the DirectoryObject.
162
- *
163
- * @returns {object} JSON representation of the DirectoryObject
164
- */
165
- toJSON() {
166
- return {
167
- supplied: this.supplied,
168
- path: this.path,
169
- url: this.url.toString(),
170
- name: this.name,
171
- module: this.module,
172
- extension: this.extension,
173
- isFile: this.isFile,
174
- isDirectory: this.isDirectory,
175
- parent: this.parent?.path ?? null,
176
- }
177
- }
178
-
179
- /**
180
- * Custom inspect method for Node.js console.
181
- *
182
- * @returns {object} JSON representation of this object.
183
- */
184
- // [util.inspect.custom]() {
185
- // return this.toJSON()
186
- // }
187
-
188
148
  /**
189
149
  * Checks if the directory exists (async).
190
150
  *
@@ -298,15 +258,6 @@ export default class DirectoryObject extends FS {
298
258
  return this.#parent
299
259
  }
300
260
 
301
- /**
302
- * Returns false. Because this is a directory.
303
- *
304
- * @returns {boolean} Always false
305
- */
306
- get isFile() {
307
- return this.#meta.isFile
308
- }
309
-
310
261
  /**
311
262
  * We're a directory!
312
263
  *
@@ -322,9 +273,7 @@ export default class DirectoryObject extends FS {
322
273
  * @returns {Promise<boolean>} Whether the directory exists
323
274
  */
324
275
  async #directoryExists() {
325
- const path = this.isCapped
326
- ? this.cap?.real.path
327
- : this.path
276
+ const path = this.real?.path ?? this.path
328
277
 
329
278
  try {
330
279
  (await opendir(path)).close()
@@ -338,9 +287,12 @@ export default class DirectoryObject extends FS {
338
287
  /**
339
288
  * Lists the contents of a directory, optionally filtered by a glob pattern.
340
289
  *
290
+ * Returns FileObject and DirectoryObject instances for regular directories.
291
+ * Returns VFileObject and VDirectoryObject instances when called on virtual directories.
292
+ *
341
293
  * @async
342
294
  * @param {string} [pat=""] - Optional glob pattern to filter results (e.g., "*.txt", "test-*")
343
- * @returns {Promise<{files: Array<FileObject>, directories: Array<DirectoryObject>}>} Object containing arrays of files and directories
295
+ * @returns {Promise<{files: Array<FileObject|VFileObject>, directories: Array<DirectoryObject|VDirectoryObject>}>} Object containing arrays of files and directories
344
296
  * @example
345
297
  * const dir = new DirectoryObject("./src")
346
298
  * const {files, directories} = await dir.read()
@@ -353,7 +305,7 @@ export default class DirectoryObject extends FS {
353
305
  */
354
306
  async read(pat="") {
355
307
  const withFileTypes = true
356
- const url = this.isCapped
308
+ const url = this.isVirtual
357
309
  ? this.real?.url
358
310
  : this.url
359
311
 
@@ -364,7 +316,7 @@ export default class DirectoryObject extends FS {
364
316
  ? await readdir(url, {withFileTypes})
365
317
  : await Array.fromAsync(
366
318
  glob(pat, {
367
- cwd: this.isCapped ? this.real?.path : this.path,
319
+ cwd: this.isVirtual ? this.real?.path : this.path,
368
320
  withFileTypes,
369
321
  // exclude: candidate => {
370
322
  // // Only allow entries within this directory's URL
@@ -378,7 +330,7 @@ export default class DirectoryObject extends FS {
378
330
 
379
331
  const files = found
380
332
  .filter(dirent => dirent.isFile())
381
- .map(dirent => new FileObject(dirent.name, this))
333
+ .map(dirent => this.getFile(dirent.name))
382
334
 
383
335
  const directories = found
384
336
  .filter(dirent => dirent.isDirectory())
@@ -408,15 +360,17 @@ export default class DirectoryObject extends FS {
408
360
  if(await this.exists)
409
361
  return
410
362
 
363
+ const path = this.real?.path ?? this.path
364
+
411
365
  try {
412
- await mkdir(this.path, options)
366
+ await mkdir(path, options)
413
367
  } catch(e) {
414
368
  if(e.code === "EEXIST") {
415
369
  // Directory already exists, ignore
416
370
  return
417
371
  }
418
372
 
419
- throw Sass.new(`Unable to create directory '${this.path}': ${e.message}`)
373
+ throw Sass.new(`Unable to create directory '${path}': ${e.message}`)
420
374
  }
421
375
  }
422
376
 
@@ -479,7 +433,7 @@ export default class DirectoryObject extends FS {
479
433
  * await dir.delete() // Only works if directory is empty
480
434
  */
481
435
  async delete() {
482
- const dirPath = this.path
436
+ const dirPath = this.real?.path ?? this.path
483
437
 
484
438
  if(!dirPath)
485
439
  throw Sass.new("This object does not represent a valid resource.")
@@ -487,7 +441,7 @@ export default class DirectoryObject extends FS {
487
441
  if(!(await this.exists))
488
442
  throw Sass.new(`No such resource '${this.url.href}'`)
489
443
 
490
- return await rmdir(this.path)
444
+ return await rmdir(dirPath)
491
445
  }
492
446
 
493
447
  /**
@@ -509,8 +463,8 @@ export default class DirectoryObject extends FS {
509
463
  * @returns {Promise<boolean>} True if the directory exists, false otherwise
510
464
  */
511
465
  async hasDirectory(dirname) {
512
- const resolved = FS.resolvePath(this.path, dirname)
513
- const directory = new DirectoryObject(resolved)
466
+ const dir = FS.resolvePath(this.real?.path ?? this.path, dirname)
467
+ const directory = new DirectoryObject(dir)
514
468
 
515
469
  return await directory.exists
516
470
  }
@@ -561,8 +515,11 @@ export default class DirectoryObject extends FS {
561
515
  * duplication. The resulting FileObject can be used for reading, writing,
562
516
  * and other file operations.
563
517
  *
518
+ * When called on a VDirectoryObject, returns a VFileObject to maintain
519
+ * virtual path semantics.
520
+ *
564
521
  * @param {string} file - The filename to append (can include subdirectories like "src/index.js")
565
- * @returns {FileObject} A new FileObject instance with the combined path
522
+ * @returns {FileObject|VFileObject} A new FileObject (or VFileObject if virtual)
566
523
  * @throws {Sass} If filename is not a string
567
524
  * @example
568
525
  * const dir = new DirectoryObject("/projects/git/toolkit")
@@ -581,6 +538,8 @@ export default class DirectoryObject extends FS {
581
538
 
582
539
  Valid.assert(this.#isLocal(newPath), `${newPath} would be out of bounds.`)
583
540
 
584
- return new FileObject(newPath, this)
541
+ return this.isVirtual
542
+ ? new VFileObject(file, this)
543
+ : new FileObject(file, this)
585
544
  }
586
545
  }