@gesslar/toolkit 3.13.0 → 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 (76) 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 -56
  5. package/src/{lib → node/lib}/FileObject.js +76 -149
  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/{lib/CappedDirectoryObject.js → node/lib/VDirectoryObject.js} +37 -92
  14. package/src/node/lib/VFileObject.js +61 -0
  15. package/src/{lib → node/lib}/Valid.js +11 -5
  16. package/src/types/browser/index.d.ts +0 -13
  17. package/src/types/browser/index.d.ts.map +0 -1
  18. package/src/types/browser/lib/Collection.d.ts +0 -248
  19. package/src/types/browser/lib/Collection.d.ts.map +0 -1
  20. package/src/types/browser/lib/Data.d.ts +0 -250
  21. package/src/types/browser/lib/Data.d.ts.map +0 -1
  22. package/src/types/browser/lib/Disposer.d.ts +0 -33
  23. package/src/types/browser/lib/Disposer.d.ts.map +0 -1
  24. package/src/types/browser/lib/HTML.d.ts +0 -40
  25. package/src/types/browser/lib/HTML.d.ts.map +0 -1
  26. package/src/types/browser/lib/Notify.d.ts +0 -60
  27. package/src/types/browser/lib/Notify.d.ts.map +0 -1
  28. package/src/types/browser/lib/Promised.d.ts +0 -119
  29. package/src/types/browser/lib/Promised.d.ts.map +0 -1
  30. package/src/types/browser/lib/Sass.d.ts +0 -63
  31. package/src/types/browser/lib/Sass.d.ts.map +0 -1
  32. package/src/types/browser/lib/Tantrum.d.ts +0 -52
  33. package/src/types/browser/lib/Tantrum.d.ts.map +0 -1
  34. package/src/types/browser/lib/Time.d.ts +0 -42
  35. package/src/types/browser/lib/Time.d.ts.map +0 -1
  36. package/src/types/browser/lib/TypeSpec.d.ts +0 -90
  37. package/src/types/browser/lib/TypeSpec.d.ts.map +0 -1
  38. package/src/types/browser/lib/Util.d.ts +0 -62
  39. package/src/types/browser/lib/Util.d.ts.map +0 -1
  40. package/src/types/browser/lib/Valid.d.ts +0 -33
  41. package/src/types/browser/lib/Valid.d.ts.map +0 -1
  42. package/src/types/browser/lib/vendor/dompurify.esm.d.ts +0 -29
  43. package/src/types/browser/lib/vendor/dompurify.esm.d.ts.map +0 -1
  44. package/src/types/index.d.ts +0 -20
  45. package/src/types/index.d.ts.map +0 -1
  46. package/src/types/lib/Cache.d.ts +0 -27
  47. package/src/types/lib/Cache.d.ts.map +0 -1
  48. package/src/types/lib/CappedDirectoryObject.d.ts +0 -144
  49. package/src/types/lib/CappedDirectoryObject.d.ts.map +0 -1
  50. package/src/types/lib/DirectoryObject.d.ts +0 -277
  51. package/src/types/lib/DirectoryObject.d.ts.map +0 -1
  52. package/src/types/lib/FS.d.ts +0 -188
  53. package/src/types/lib/FS.d.ts.map +0 -1
  54. package/src/types/lib/FileObject.d.ts +0 -238
  55. package/src/types/lib/FileObject.d.ts.map +0 -1
  56. package/src/types/lib/Glog.d.ts +0 -228
  57. package/src/types/lib/Glog.d.ts.map +0 -1
  58. package/src/types/lib/Logger.d.ts +0 -46
  59. package/src/types/lib/Logger.d.ts.map +0 -1
  60. package/src/types/lib/Notify.d.ts +0 -54
  61. package/src/types/lib/Notify.d.ts.map +0 -1
  62. package/src/types/lib/Sass.d.ts +0 -9
  63. package/src/types/lib/Sass.d.ts.map +0 -1
  64. package/src/types/lib/Tantrum.d.ts +0 -9
  65. package/src/types/lib/Tantrum.d.ts.map +0 -1
  66. package/src/types/lib/TempDirectoryObject.d.ts +0 -42
  67. package/src/types/lib/TempDirectoryObject.d.ts.map +0 -1
  68. package/src/types/lib/Term.d.ts +0 -127
  69. package/src/types/lib/Term.d.ts.map +0 -1
  70. package/src/types/lib/Util.d.ts +0 -100
  71. package/src/types/lib/Util.d.ts.map +0 -1
  72. package/src/types/lib/Valid.d.ts +0 -33
  73. package/src/types/lib/Valid.d.ts.map +0 -1
  74. /package/src/{lib → node/lib}/Cache.js +0 -0
  75. /package/src/{lib → node/lib}/Notify.js +0 -0
  76. /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.13.0",
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,7 +140,7 @@ export default class DirectoryObject extends FS {
148
140
  * @returns {string} string representation of the DirectoryObject
149
141
  */
150
142
  toString() {
151
- return this.isCapped
143
+ return this.isVirtual
152
144
  ?`[${this.constructor.name}: ${this.path} → ${this.real.path}]`
153
145
  :`[${this.constructor.name}: ${this.path}]`
154
146
  }
@@ -266,15 +258,6 @@ export default class DirectoryObject extends FS {
266
258
  return this.#parent
267
259
  }
268
260
 
269
- /**
270
- * Returns false. Because this is a directory.
271
- *
272
- * @returns {boolean} Always false
273
- */
274
- get isFile() {
275
- return this.#meta.isFile
276
- }
277
-
278
261
  /**
279
262
  * We're a directory!
280
263
  *
@@ -290,9 +273,7 @@ export default class DirectoryObject extends FS {
290
273
  * @returns {Promise<boolean>} Whether the directory exists
291
274
  */
292
275
  async #directoryExists() {
293
- const path = this.isCapped
294
- ? this.cap?.real.path
295
- : this.path
276
+ const path = this.real?.path ?? this.path
296
277
 
297
278
  try {
298
279
  (await opendir(path)).close()
@@ -306,9 +287,12 @@ export default class DirectoryObject extends FS {
306
287
  /**
307
288
  * Lists the contents of a directory, optionally filtered by a glob pattern.
308
289
  *
290
+ * Returns FileObject and DirectoryObject instances for regular directories.
291
+ * Returns VFileObject and VDirectoryObject instances when called on virtual directories.
292
+ *
309
293
  * @async
310
294
  * @param {string} [pat=""] - Optional glob pattern to filter results (e.g., "*.txt", "test-*")
311
- * @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
312
296
  * @example
313
297
  * const dir = new DirectoryObject("./src")
314
298
  * const {files, directories} = await dir.read()
@@ -321,7 +305,7 @@ export default class DirectoryObject extends FS {
321
305
  */
322
306
  async read(pat="") {
323
307
  const withFileTypes = true
324
- const url = this.isCapped
308
+ const url = this.isVirtual
325
309
  ? this.real?.url
326
310
  : this.url
327
311
 
@@ -332,7 +316,7 @@ export default class DirectoryObject extends FS {
332
316
  ? await readdir(url, {withFileTypes})
333
317
  : await Array.fromAsync(
334
318
  glob(pat, {
335
- cwd: this.isCapped ? this.real?.path : this.path,
319
+ cwd: this.isVirtual ? this.real?.path : this.path,
336
320
  withFileTypes,
337
321
  // exclude: candidate => {
338
322
  // // Only allow entries within this directory's URL
@@ -346,7 +330,7 @@ export default class DirectoryObject extends FS {
346
330
 
347
331
  const files = found
348
332
  .filter(dirent => dirent.isFile())
349
- .map(dirent => new FileObject(dirent.name, this))
333
+ .map(dirent => this.getFile(dirent.name))
350
334
 
351
335
  const directories = found
352
336
  .filter(dirent => dirent.isDirectory())
@@ -376,15 +360,17 @@ export default class DirectoryObject extends FS {
376
360
  if(await this.exists)
377
361
  return
378
362
 
363
+ const path = this.real?.path ?? this.path
364
+
379
365
  try {
380
- await mkdir(this.path, options)
366
+ await mkdir(path, options)
381
367
  } catch(e) {
382
368
  if(e.code === "EEXIST") {
383
369
  // Directory already exists, ignore
384
370
  return
385
371
  }
386
372
 
387
- throw Sass.new(`Unable to create directory '${this.path}': ${e.message}`)
373
+ throw Sass.new(`Unable to create directory '${path}': ${e.message}`)
388
374
  }
389
375
  }
390
376
 
@@ -447,7 +433,7 @@ export default class DirectoryObject extends FS {
447
433
  * await dir.delete() // Only works if directory is empty
448
434
  */
449
435
  async delete() {
450
- const dirPath = this.path
436
+ const dirPath = this.real?.path ?? this.path
451
437
 
452
438
  if(!dirPath)
453
439
  throw Sass.new("This object does not represent a valid resource.")
@@ -455,7 +441,7 @@ export default class DirectoryObject extends FS {
455
441
  if(!(await this.exists))
456
442
  throw Sass.new(`No such resource '${this.url.href}'`)
457
443
 
458
- return await rmdir(this.path)
444
+ return await rmdir(dirPath)
459
445
  }
460
446
 
461
447
  /**
@@ -477,8 +463,8 @@ export default class DirectoryObject extends FS {
477
463
  * @returns {Promise<boolean>} True if the directory exists, false otherwise
478
464
  */
479
465
  async hasDirectory(dirname) {
480
- const resolved = FS.resolvePath(this.path, dirname)
481
- const directory = new DirectoryObject(resolved)
466
+ const dir = FS.resolvePath(this.real?.path ?? this.path, dirname)
467
+ const directory = new DirectoryObject(dir)
482
468
 
483
469
  return await directory.exists
484
470
  }
@@ -529,8 +515,11 @@ export default class DirectoryObject extends FS {
529
515
  * duplication. The resulting FileObject can be used for reading, writing,
530
516
  * and other file operations.
531
517
  *
518
+ * When called on a VDirectoryObject, returns a VFileObject to maintain
519
+ * virtual path semantics.
520
+ *
532
521
  * @param {string} file - The filename to append (can include subdirectories like "src/index.js")
533
- * @returns {FileObject} A new FileObject instance with the combined path
522
+ * @returns {FileObject|VFileObject} A new FileObject (or VFileObject if virtual)
534
523
  * @throws {Sass} If filename is not a string
535
524
  * @example
536
525
  * const dir = new DirectoryObject("/projects/git/toolkit")
@@ -549,6 +538,8 @@ export default class DirectoryObject extends FS {
549
538
 
550
539
  Valid.assert(this.#isLocal(newPath), `${newPath} would be out of bounds.`)
551
540
 
552
- return new FileObject(newPath, this)
541
+ return this.isVirtual
542
+ ? new VFileObject(file, this)
543
+ : new FileObject(file, this)
553
544
  }
554
545
  }