@zthun/crumbtrail-fs 2.3.3 → 2.4.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.
@@ -27,13 +27,35 @@ export interface IZFileSystemNode {
27
27
  * The size of the node in bytes.
28
28
  */
29
29
  size?: bigint;
30
+ /**
31
+ * The file or folder name with the extension.
32
+ *
33
+ * Calculated from the path.
34
+ */
35
+ readonly name: string;
36
+ /**
37
+ * The file extension.
38
+ *
39
+ * Calculated from the path.
40
+ */
41
+ readonly extension: string;
42
+ /**
43
+ * File title.
44
+ *
45
+ * The name without the extension.
46
+ * Calculated from the path.
47
+ */
48
+ readonly title: string;
49
+ /**
50
+ * Parent directory path.
51
+ */
52
+ readonly parent: string;
30
53
  }
31
54
  /**
32
55
  * Represents a builder for a file system node.
33
56
  */
34
57
  export declare class ZFileSystemNodeBuilder {
35
58
  private _node;
36
- constructor();
37
59
  created(at?: Date | string | undefined): this;
38
60
  updated(at?: Date | string | undefined): this;
39
61
  size(bytes: bigint | number | undefined): this;
@@ -43,4 +65,5 @@ export declare class ZFileSystemNodeBuilder {
43
65
  folder: () => this;
44
66
  stats(s: Stats): this;
45
67
  build(): IZFileSystemNode;
68
+ private decorate;
46
69
  }
package/dist/index.cjs CHANGED
@@ -16,6 +16,19 @@ const node_url = require('node:url');
16
16
  const path = require('path');
17
17
  const promises$1 = require('fs/promises');
18
18
 
19
+ function _define_property$3(obj, key, value) {
20
+ if (key in obj) {
21
+ Object.defineProperty(obj, key, {
22
+ value: value,
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true
26
+ });
27
+ } else {
28
+ obj[key] = value;
29
+ }
30
+ return obj;
31
+ }
19
32
  /**
20
33
  * Represents a type of a file system node.
21
34
  */ var ZFileSystemNodeType = /*#__PURE__*/ function(ZFileSystemNodeType) {
@@ -26,13 +39,6 @@ const promises$1 = require('fs/promises');
26
39
  /**
27
40
  * Represents a builder for a file system node.
28
41
  */ class ZFileSystemNodeBuilder {
29
- _node;
30
- constructor(){
31
- this._node = {
32
- path: "/",
33
- type: "folder"
34
- };
35
- }
36
42
  created(at) {
37
43
  this._node.created = at instanceof Date ? at.toJSON() : at;
38
44
  return this;
@@ -47,14 +53,12 @@ const promises$1 = require('fs/promises');
47
53
  }
48
54
  path(path) {
49
55
  this._node.path = path;
50
- return this;
56
+ return this.decorate();
51
57
  }
52
58
  type(type) {
53
59
  this._node.type = type;
54
- return this;
60
+ return this.decorate();
55
61
  }
56
- file = this.type.bind(this, "file");
57
- folder = this.type.bind(this, "folder");
58
62
  stats(s) {
59
63
  const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);
60
64
  return s.isFile() ? builder.file() : builder.folder();
@@ -63,6 +67,34 @@ const promises$1 = require('fs/promises');
63
67
  const clone = structuredClone(this._node);
64
68
  return lodashEs.omitBy(clone, lodashEs.isUndefined);
65
69
  }
70
+ decorate() {
71
+ const { path, type } = this._node;
72
+ this._node.name = node_path.basename(path);
73
+ this._node.extension = "";
74
+ this._node.title = this._node.name;
75
+ this._node.parent = node_path.dirname(path);
76
+ if (type === "file") {
77
+ const extension = node_path.extname(path);
78
+ this._node.extension = extension;
79
+ this._node.title = node_path.basename(path, extension);
80
+ }
81
+ if (!path || path === "/" || this._node.parent === ".") {
82
+ this._node.parent = "";
83
+ }
84
+ return this;
85
+ }
86
+ constructor(){
87
+ _define_property$3(this, "_node", {
88
+ path: "/",
89
+ type: "folder",
90
+ extension: "",
91
+ name: "",
92
+ parent: "",
93
+ title: ""
94
+ });
95
+ _define_property$3(this, "file", this.type.bind(this, "file"));
96
+ _define_property$3(this, "folder", this.type.bind(this, "folder"));
97
+ }
66
98
  }
67
99
 
68
100
  /**
@@ -114,22 +146,22 @@ const promises$1 = require('fs/promises');
114
146
  }
115
147
  }
116
148
 
149
+ function _define_property$2(obj, key, value) {
150
+ if (key in obj) {
151
+ Object.defineProperty(obj, key, {
152
+ value: value,
153
+ enumerable: true,
154
+ configurable: true,
155
+ writable: true
156
+ });
157
+ } else {
158
+ obj[key] = value;
159
+ }
160
+ return obj;
161
+ }
117
162
  /**
118
163
  * An implementation of the IZFileWatch.
119
164
  */ class ZFileWatch {
120
- path;
121
- _add = new rxjs.Subject();
122
- _update = new rxjs.Subject();
123
- _remove = new rxjs.Subject();
124
- _watcher;
125
- /**
126
- * Initializes a new instance of this object.
127
- *
128
- * @param path -
129
- * The path to watch.
130
- */ constructor(path){
131
- this.path = path;
132
- }
133
165
  async start() {
134
166
  await this.stop();
135
167
  this._watcher = chokidar.watch(this.path, {
@@ -162,8 +194,37 @@ const promises$1 = require('fs/promises');
162
194
  remove() {
163
195
  return this._remove.asObservable();
164
196
  }
197
+ /**
198
+ * Initializes a new instance of this object.
199
+ *
200
+ * @param path -
201
+ * The path to watch.
202
+ */ constructor(path){
203
+ _define_property$2(this, "path", void 0);
204
+ _define_property$2(this, "_add", void 0);
205
+ _define_property$2(this, "_update", void 0);
206
+ _define_property$2(this, "_remove", void 0);
207
+ _define_property$2(this, "_watcher", void 0);
208
+ this.path = path;
209
+ this._add = new rxjs.Subject();
210
+ this._update = new rxjs.Subject();
211
+ this._remove = new rxjs.Subject();
212
+ }
165
213
  }
166
214
 
215
+ function _define_property$1(obj, key, value) {
216
+ if (key in obj) {
217
+ Object.defineProperty(obj, key, {
218
+ value: value,
219
+ enumerable: true,
220
+ configurable: true,
221
+ writable: true
222
+ });
223
+ } else {
224
+ obj[key] = value;
225
+ }
226
+ return obj;
227
+ }
167
228
  /**
168
229
  * Represents an implementation of a ZFileRepository that watches
169
230
  * a given path scope.
@@ -171,16 +232,6 @@ const promises$1 = require('fs/promises');
171
232
  * This repository is only concerned about files. Folders
172
233
  * will not be retrieved from this repository.
173
234
  */ class ZFileRepository {
174
- _service = new ZFileSystemService();
175
- _watcher;
176
- _nodes = Promise.resolve(new helpfulQuery.ZDataSourceStatic([]));
177
- _globs = [
178
- "**"
179
- ];
180
- _path = "";
181
- _add;
182
- _remove;
183
- _update;
184
235
  /**
185
236
  * Gets the path that this repository is watching.
186
237
  */ get path() {
@@ -300,6 +351,18 @@ const promises$1 = require('fs/promises');
300
351
  const source = await this._nodes;
301
352
  return source.retrieve(request);
302
353
  }
354
+ constructor(){
355
+ _define_property$1(this, "_service", new ZFileSystemService());
356
+ _define_property$1(this, "_watcher", void 0);
357
+ _define_property$1(this, "_nodes", Promise.resolve(new helpfulQuery.ZDataSourceStatic([])));
358
+ _define_property$1(this, "_globs", [
359
+ "**"
360
+ ]);
361
+ _define_property$1(this, "_path", "");
362
+ _define_property$1(this, "_add", void 0);
363
+ _define_property$1(this, "_remove", void 0);
364
+ _define_property$1(this, "_update", void 0);
365
+ }
303
366
  }
304
367
 
305
368
  function resolvePathLike(path) {
@@ -336,25 +399,26 @@ function resolvePathLike(path) {
336
399
  * operation still succeeds
337
400
  */ class ZStreamFolder {
338
401
  async write(path) {
339
- try {
340
- await promises$1.mkdir(path, {
341
- recursive: true
342
- });
343
- } catch {
344
- // The folder may exist, but if it is a file then
345
- // we have a conflict and in that case, we will throw an
346
- // error. We are going to let stat fail if it cannot
347
- // access the path (permission error).
348
- const stats = await promises$1.stat(path);
349
- if (stats.isFile()) {
350
- const msg = `Cannot create folder, ${path}, because a file with the same name exists at the target location`;
351
- throw new Error(msg);
352
- }
353
- }
402
+ await promises$1.mkdir(path, {
403
+ recursive: true
404
+ });
354
405
  return 0;
355
406
  }
356
407
  }
357
408
 
409
+ function _define_property(obj, key, value) {
410
+ if (key in obj) {
411
+ Object.defineProperty(obj, key, {
412
+ value: value,
413
+ enumerable: true,
414
+ configurable: true,
415
+ writable: true
416
+ });
417
+ } else {
418
+ obj[key] = value;
419
+ }
420
+ return obj;
421
+ }
358
422
  /**
359
423
  * A stream that can read and write to files.
360
424
  *
@@ -365,18 +429,6 @@ function resolvePathLike(path) {
365
429
  * that's under a certain size threshold will store it in memory for
366
430
  * later retrieval.
367
431
  */ class ZStreamFile {
368
- options;
369
- static FileSizeDefault = 102400;
370
- static MaxFilesDefault = 1000;
371
- _cache = new Map();
372
- /**
373
- * Initializes a new instance of this object.
374
- *
375
- * @param options -
376
- * The options for file read and writes.
377
- */ constructor(options = {}){
378
- this.options = options;
379
- }
380
432
  async read(path, options) {
381
433
  const _path = resolvePathLike(path);
382
434
  const stats = await promises.stat(_path);
@@ -425,7 +477,20 @@ function resolvePathLike(path) {
425
477
  }
426
478
  return item.buffer;
427
479
  }
480
+ /**
481
+ * Initializes a new instance of this object.
482
+ *
483
+ * @param options -
484
+ * The options for file read and writes.
485
+ */ constructor(options = {}){
486
+ _define_property(this, "options", void 0);
487
+ _define_property(this, "_cache", void 0);
488
+ this.options = options;
489
+ this._cache = new Map();
490
+ }
428
491
  }
492
+ _define_property(ZStreamFile, "FileSizeDefault", 102400); // One Hundred KibiBytes
493
+ _define_property(ZStreamFile, "MaxFilesDefault", 1000);
429
494
 
430
495
  exports.ZFileRepository = ZFileRepository;
431
496
  exports.ZFileSystemNodeBuilder = ZFileSystemNodeBuilder;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/file-system/file-system-node.mts","../src/file-system/file-system-service.mts","../src/file-watch/file-watch.mts","../src/file-repository/file-repository.mts","../src/resolve-path-like/resolve-path-like.ts","../src/sleep-watch-delay/sleep-watch-delay.mts","../src/stream/stream-folder.mts","../src/stream/stream-file.mts"],"sourcesContent":["import { isUndefined, omitBy } from \"lodash-es\";\nimport type { Stats } from \"node:fs\";\n\n/**\n * Represents a type of a file system node.\n */\nexport enum ZFileSystemNodeType {\n File = \"file\",\n Folder = \"folder\",\n}\n\nexport interface IZFileSystemNode {\n /**\n * The absolute path of the node.\n */\n path: string;\n\n /**\n * The type of the node (file or folder).\n */\n type: ZFileSystemNodeType;\n\n /**\n * The creation date of the node.\n */\n created?: string;\n\n /**\n * The modification date of the node.\n */\n updated?: string;\n\n /**\n * The size of the node in bytes.\n */\n size?: bigint;\n}\n\n/**\n * Represents a builder for a file system node.\n */\nexport class ZFileSystemNodeBuilder {\n private _node: IZFileSystemNode;\n\n public constructor() {\n this._node = {\n path: \"/\",\n type: ZFileSystemNodeType.Folder,\n };\n }\n\n public created(at?: Date | string | undefined) {\n this._node.created = at instanceof Date ? at.toJSON() : at;\n return this;\n }\n\n public updated(at?: Date | string | undefined) {\n this._node.updated = at instanceof Date ? at.toJSON() : at;\n return this;\n }\n\n public size(bytes: bigint | number | undefined) {\n this._node.size = typeof bytes == \"number\" ? BigInt(bytes) : bytes;\n return this;\n }\n\n public path(path: string) {\n this._node.path = path;\n return this;\n }\n\n public type(type: ZFileSystemNodeType) {\n this._node.type = type;\n return this;\n }\n\n public file = this.type.bind(this, ZFileSystemNodeType.File);\n public folder = this.type.bind(this, ZFileSystemNodeType.Folder);\n\n public stats(s: Stats) {\n const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);\n return s.isFile() ? builder.file() : builder.folder();\n }\n\n public build() {\n const clone = structuredClone(this._node);\n return omitBy(clone, isUndefined) as IZFileSystemNode;\n }\n}\n","import { glob } from \"glob\";\nimport { access } from \"node:fs/promises\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { cwd } from \"node:process\";\nimport type { IZFileSystemNode } from \"./file-system-node.mjs\";\nimport { ZFileSystemNodeBuilder } from \"./file-system-node.mjs\";\n\n/**\n * Represents options for searches.\n */\nexport interface IZFileSystemSearchOptions {\n /**\n * The directory to search in.\n *\n * If this is not set, then the cwd of the application is used.\n */\n cwd?: string;\n\n /**\n * A flag that determines whether or not to load the\n * file system information.\n *\n * This is true by default.\n */\n stat?: boolean;\n}\n\n/**\n * Represents options for directory walking.\n */\nexport interface IZFileSystemWalkOptions {\n /**\n * The starting directory.\n *\n * The default is the current working directory\n *\n * @see process.cwd for more information.\n */\n start?: string;\n\n /**\n * The directory to stop at.\n *\n * The default is the root of the file system.\n */\n stop?: string;\n\n /**\n * The type of mode that the path must support in order\n * to be approved.\n *\n * The default is undefined and left up to the node api.\n */\n mode?: number;\n}\n\n/**\n * Represents a service to enumerate the file system.\n */\nexport interface IZFileSystemService {\n /**\n * Gets information about a node.\n *\n * @param path -\n * The path to get information for.\n *\n * @returns\n * Information about the node.\n */\n info(path: string): Promise<IZFileSystemNode>;\n\n /**\n * Reads all nodes that match a pattern.\n *\n * @param pattern -\n * The pattern string to match against or a list\n * of patterns to match.\n * @param options -\n * The options for the search.\n *\n * @returns\n * A list of path strings that match the given patterns.\n */\n search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]>;\n\n /**\n * Walks up a directory tree to search for existence of a given path.\n *\n * @param search -\n * The path to search for. This is the candidate folder path that\n * may or may not exist somewhere from the start directory all the\n * way up the directory tree.\n * @param options -\n * The given options for the search.\n *\n * @returns\n * The fully qualified path to the first path that matches the search\n * starting at the options start or the current working directory if not\n * specified. Returns null if no such directory exists.\n *\n * @example\n *\n * ```ts\n * import { resolve } from 'path'\n *\n * // Find any folder named .vscode from the current working directory all the way\n * // up the directory tree. Returns null if no vscode directory can be found.\n * const service = new ZFileSystemService();\n * const vscode = service.walk('.vscode');\n *\n * // Walk the directory tree from the current script and find the .config folder.\n * const config = service.walk('.config', { start: __dirname });\n *\n * // Walk the directory tree from the current script and stop when we reach\n * // at most 2 directories up.\n * const start = __dirname;\n * const stop = resolve(__dirname, '../..');\n * const file = service.walk('path/to/file.json', { start, stop });\n * ```\n */\n walk(\n search: string,\n options?: IZFileSystemWalkOptions,\n ): Promise<string | null>;\n}\n\n/**\n * Represents a node implementation of a file system service.\n */\nexport class ZFileSystemService implements IZFileSystemService {\n public async info(path: string): Promise<IZFileSystemNode> {\n const [file] = await this.search(path);\n return file;\n }\n\n public async search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]> {\n const paths = await glob(pattern, {\n stat: true,\n ...options,\n withFileTypes: true,\n });\n\n return paths.map((path) => {\n let info = new ZFileSystemNodeBuilder()\n .path(path.fullpath())\n .created(path.birthtime)\n .updated(path.atime)\n .size(path.size);\n\n // Note that for folders, node will return the size of the underlying OS metadata,\n // hence, why we remove the size on the folder here.\n info = path.isFile() ? info.file() : info.folder().size(undefined);\n\n return info.build();\n });\n }\n\n public async walk(search: string, options?: IZFileSystemWalkOptions) {\n const start = options?.start || cwd();\n const stop = options?.stop || \"/\";\n const mode = options?.mode;\n\n const _test = async (path: string) => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n };\n\n if (isAbsolute(search)) {\n return (await _test(search)) ? search : null;\n }\n\n let dir = start;\n do {\n const path = resolve(dir, search);\n const exists = await _test(path);\n\n if (exists) {\n return path;\n }\n\n dir = dir === stop ? \"\" : dirname(dir);\n } while (dir.length);\n\n return null;\n }\n}\n","import type { FSWatcher } from \"chokidar\";\nimport { watch } from \"chokidar\";\nimport type { Stats } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Observable } from \"rxjs\";\nimport { Subject } from \"rxjs\";\nimport {\n ZFileSystemNodeBuilder,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\n\n/**\n * Represents and object that can watch a folder or file on the file system.\n */\nexport interface IZFileWatch {\n /**\n * Starts the watch operation.\n */\n start(): Promise<void>;\n\n /**\n * Stops the watch operation.\n */\n stop(): Promise<void>;\n\n /**\n * The stream for files being added.\n *\n * This can only occur if the target being watched\n * is a folder.\n *\n * @returns\n * The observable that will publish files that\n * get added.\n */\n add(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files being updated.\n *\n * If this watcher points to a folder, then all files\n * recursively will send when they get updated. If this\n * watcher points to a file, then this will only invoke\n * when the file is updated.\n *\n * @returns\n * The observable that will publish files and folders\n * that are updated.\n */\n update(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files and folders being deleted.\n *\n * If this watcher points to a folder, then all files under the\n * folder will be sent through this observable, including the\n * folder being watched. If this points to a file, then\n * this will only receive when the file is unlinked.\n *\n * @returns\n * The observable that will publish file and folders\n * that are unlinked and removed respectively. Note\n * that files and folders streamed this way will not\n * have their stats set.\n */\n remove(): Observable<IZFileSystemNode>;\n}\n\n/**\n * An implementation of the IZFileWatch.\n */\nexport class ZFileWatch implements IZFileWatch {\n private _add: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _update: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _remove: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _watcher: FSWatcher | undefined;\n\n /**\n * Initializes a new instance of this object.\n *\n * @param path -\n * The path to watch.\n */\n public constructor(public readonly path: string) {}\n\n public async start() {\n await this.stop();\n\n this._watcher = watch(this.path, {\n usePolling: true,\n alwaysStat: true,\n ignoreInitial: true,\n\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 50,\n },\n });\n\n function next(\n observable: Subject<IZFileSystemNode>,\n file: string,\n stats: Stats | undefined,\n ) {\n const node = new ZFileSystemNodeBuilder().path(resolve(this.path, file));\n observable.next(stats ? node.stats(stats).build() : node.build());\n }\n\n this._watcher\n .on(\"add\", next.bind(this, this._add))\n .on(\"addDir\", next.bind(this, this._add))\n .on(\"change\", next.bind(this, this._update))\n .on(\"unlink\", next.bind(this, this._remove))\n .on(\"unlinkDir\", next.bind(this, this._remove));\n\n return new Promise<void>((resolve) =>\n this._watcher?.on(\"ready\", () => resolve()),\n );\n }\n\n public async stop() {\n await this._watcher?.close();\n delete this._watcher;\n return Promise.resolve();\n }\n\n public add() {\n return this._add.asObservable();\n }\n\n public update() {\n return this._update.asObservable();\n }\n\n public remove() {\n return this._remove.asObservable();\n }\n}\n","import { firstDefined, sleep } from \"@zthun/helpful-fn\";\nimport type { IZDataRequest, IZDataSource } from \"@zthun/helpful-query\";\nimport { ZDataSourceStatic } from \"@zthun/helpful-query\";\nimport { find, findIndex, flatten, trimEnd, uniqBy } from \"lodash-es\";\nimport { minimatch } from \"minimatch\";\nimport { resolve, sep } from \"node:path\";\nimport type { Subscription } from \"rxjs\";\nimport {\n ZFileSystemNodeType,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\nimport {\n ZFileSystemService,\n type IZFileSystemService,\n} from \"../file-system/file-system-service.mjs\";\nimport { ZFileWatch, type IZFileWatch } from \"../file-watch/file-watch.mjs\";\n\n/**\n * Represents a repository for the file system.\n */\nexport interface IZFileRepository extends IZDataSource<IZFileSystemNode> {\n /**\n * Retrieves a single file from the repository.\n *\n * @param path -\n * The fully qualified path to the file.\n *\n * @returns\n * The node that represents the file. Returns null if no\n * such file exists.\n */\n get(path: string): Promise<IZFileSystemNode | null>;\n}\n\n/**\n * Represents an implementation of a ZFileRepository that watches\n * a given path scope.\n *\n * This repository is only concerned about files. Folders\n * will not be retrieved from this repository.\n */\nexport class ZFileRepository implements IZFileRepository {\n private _service: IZFileSystemService = new ZFileSystemService();\n private _watcher: IZFileWatch | undefined;\n private _nodes: Promise<ZDataSourceStatic<IZFileSystemNode>> =\n Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n private _globs: string[] = [\"**\"];\n private _path: string = \"\";\n private _add: Subscription | undefined;\n private _remove: Subscription | undefined;\n private _update: Subscription | undefined;\n\n /**\n * Gets the path that this repository is watching.\n */\n public get path() {\n return this._path;\n }\n\n /**\n * Gets the globs matchers that this repository is matching against.\n */\n public get globs() {\n return this._globs.slice();\n }\n\n /**\n * Initializes the repository with the given root and glob filter.\n *\n * This will initially scan the file system and setup watches.\n * If you call this method again, then the repository will be\n * {@link reset} and a new set of files will be added to the\n * repository.\n *\n * @param path -\n * The root path of the repository.\n * @param globs -\n * The optional relative globs of the repository. If this is falsy,\n * then ** is used. You can achieve the same kind of operation\n * using filters, but filtering out unwanted files frees up the internal\n * memory being used.\n */\n public async initialize(path: string, globs: string[] = [\"**\"]) {\n await this.reset();\n\n this._path = path;\n this._globs = globs;\n\n // Note that this all happens in the background and should\n // only be awaited later. So the search should not be\n // required to finish when existing this method. The only\n // requirement is that the repository is reset and the path +\n // glob scope is updated. Everything beyond here should not\n // be awaited - it will be awaited later once the caller\n // tries to retrieve the files using retrieve, get, or\n // count.\n const matches = globs.map((g) =>\n this._service.search(g, {\n cwd: path,\n stat: true,\n }),\n );\n\n this._nodes = Promise.all(matches)\n .then((nodes) => {\n const flat = flatten(nodes);\n const uniq = uniqBy(flat, (n) => n.path);\n return uniq.filter((n) => n.type === ZFileSystemNodeType.File);\n })\n .then((files) => {\n return new ZDataSourceStatic(files);\n });\n\n this._watcher = new ZFileWatch(path);\n\n this._add = this._watcher\n .add()\n .subscribe(async (node: IZFileSystemNode) => {\n if (\n node.type === ZFileSystemNodeType.File &&\n this._globs.some((g) => minimatch(node.path, resolve(this._path, g)))\n ) {\n const nodes = await this._nodes;\n this._nodes = nodes.insert(node);\n }\n });\n\n this._remove = this._watcher\n .remove()\n .subscribe(async (node: IZFileSystemNode) => {\n let nodes = await this._nodes;\n const path = trimEnd(node.path, sep);\n\n // It's possible that the node given was a folder. If that happens,\n // we need to remove all files that start with the given path.\n // If the node does point to a file, then there is no possibility that\n // more than 1 item would be removed.\n\n const next = async () =>\n findIndex(await nodes.items(), (n) => {\n return (\n n.path === path ||\n (n.path.startsWith(path) &&\n n.path.substring(path.length).charAt(0) === sep)\n );\n });\n\n for (let index = await next(); index >= 0; index = await next()) {\n nodes = await nodes.removeAt(index);\n }\n\n this._nodes = Promise.resolve(nodes);\n });\n\n this._update = this._watcher\n .update()\n .subscribe(async (node: IZFileSystemNode) => {\n const nodes = await this._nodes;\n const index = findIndex(\n await nodes.items(),\n (n) => n.path === node.path,\n );\n\n // It's possible node was filtered out by the globs, or\n // it is a directory. If so, then we won't have it in our\n // list.\n if (index >= 0) {\n const next = await nodes.removeAt(index);\n this._nodes = next.insert(node, index);\n }\n });\n\n // Kick off the initial seed operation with an even loop\n // invocation.\n await sleep(100);\n\n await this._watcher?.start();\n }\n\n /**\n * Resets the repository as if it was initially created.\n */\n public async reset(): Promise<void> {\n await this._watcher?.stop();\n\n this._add?.unsubscribe();\n this._remove?.unsubscribe();\n this._update?.unsubscribe();\n\n delete this._add;\n delete this._remove;\n delete this._update;\n delete this._watcher;\n\n this._path = \"\";\n this._globs = [\"**\"];\n this._nodes = Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n }\n\n public async get(path: string): Promise<IZFileSystemNode | null> {\n const nodes = await this._nodes;\n const items = await nodes.items();\n const node = find(items, (f) => f.path === path);\n\n return firstDefined(null, node);\n }\n\n public async count(request: IZDataRequest): Promise<number> {\n const source = await this._nodes;\n return source.count(request);\n }\n\n public async retrieve(request: IZDataRequest): Promise<IZFileSystemNode[]> {\n const source = await this._nodes;\n return source.retrieve(request);\n }\n}\n","import type { PathLike } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function resolvePathLike(path: PathLike): string {\n if (typeof path === \"string\") {\n return resolve(path);\n }\n\n if (path instanceof URL) {\n return fileURLToPath(path);\n }\n\n return resolve(path.toString());\n}\n","import { sleep } from \"@zthun/helpful-fn\";\n\n/**\n * The actual delay time that you should wait for a watch\n * operation to pick up your file changes.\n */\nexport const ZWatchDelay = 1500;\n\n/**\n * Performs a sleep long enough to allow a watch operation\n * to pick up a change.\n *\n * You should never really need this. Where it is useful\n * is for unit testing with IO operations and you want to\n * wait for your write operations to get picked up by\n * a file watch operation.\n */\nexport function sleepWatchDelay() {\n return sleep(ZWatchDelay);\n}\n","import type { PathLike } from \"fs\";\nimport { mkdir, stat } from \"fs/promises\";\nimport type { IZStreamWrite } from \"./stream-write.mjs\";\n\n/**\n * A stream that writes folders.\n *\n * Writing folders is idempotent. If the folder you\n * are trying to write already exists, then the write\n * operation still succeeds\n */\nexport class ZStreamFolder implements IZStreamWrite {\n public async write(path: PathLike): Promise<number> {\n try {\n await mkdir(path, { recursive: true });\n } catch {\n // The folder may exist, but if it is a file then\n // we have a conflict and in that case, we will throw an\n // error. We are going to let stat fail if it cannot\n // access the path (permission error).\n const stats = await stat(path);\n\n if (stats.isFile()) {\n const msg = `Cannot create folder, ${path}, because a file with the same name exists at the target location`;\n throw new Error(msg);\n }\n }\n\n return 0;\n }\n}\n","import type { PathLike, Stats } from \"node:fs\";\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"path\";\nimport { resolvePathLike } from \"../resolve-path-like/resolve-path-like.js\";\nimport { ZStreamFolder } from \"./stream-folder.mjs\";\nimport type { IZStreamRead, IZStreamReadOptions } from \"./stream-read.mjs\";\nimport type { IZStreamWrite, IZStreamWriteOptions } from \"./stream-write.mjs\";\n\n/**\n * Options for the stream file object.\n */\nexport interface IZStreamFileOptions {\n /**\n * Cache options.\n *\n * A warning that file content caching will take up significant memory\n * if the file size is too big or the max files is too big. Make sure\n * you know what you're doing when you change the default values of this.\n */\n cache?: {\n /**\n * Maximum number of bytes a file can be before it will not be cached.\n * The default is 100 Kib (102400 bytes)\n *\n * @default 102400\n */\n fileSize?: bigint;\n /**\n * The maximum number of files that are to be cached. The cache order\n * is first in, first out. Set this to 0 to not cache anything. The\n * default is 1000.\n *\n * @default 1000\n */\n maxFiles?: number;\n };\n}\n\n/**\n * A stream that can read and write to files.\n *\n * This is mostly a wrapper to readFile and writeFile from node, but\n * with some optimizations.\n *\n * First, this class supports file content caching so reading in a file\n * that's under a certain size threshold will store it in memory for\n * later retrieval.\n */\nexport class ZStreamFile implements IZStreamWrite, IZStreamRead {\n private static readonly FileSizeDefault = 102400; // One Hundred KibiBytes\n private static readonly MaxFilesDefault = 1000;\n\n private _cache = new Map<string, { stats: Stats; buffer: Promise<Buffer> }>();\n\n /**\n * Initializes a new instance of this object.\n *\n * @param options -\n * The options for file read and writes.\n */\n public constructor(public readonly options: IZStreamFileOptions = {}) {}\n\n public async read(\n path: PathLike,\n options?: IZStreamReadOptions,\n ): Promise<Buffer> {\n const _path = resolvePathLike(path);\n\n const stats = await stat(_path);\n const cached = this._cache.get(_path);\n\n const buffer =\n cached && cached.stats.mtimeMs >= stats.mtimeMs\n ? cached.buffer\n : readFile(_path, options);\n\n return this._addToCache(_path, { stats, buffer });\n }\n\n public async write(\n path: PathLike,\n { buffer = Buffer.from(\"\") }: IZStreamWriteOptions = {},\n ): Promise<number> {\n const _path = resolvePathLike(path);\n const directory = dirname(_path);\n\n await new ZStreamFolder().write(directory);\n await writeFile(_path, buffer, { flush: true });\n\n // If this file specifically was cached earlier,\n // we can just remove it now so we make room for\n // another file. Consumers can just read the\n // file again to recache it.\n this._cache.delete(_path);\n\n return buffer.length;\n }\n\n private _addToCache(\n path: string,\n item: { stats: Stats; buffer: Promise<Buffer> },\n ) {\n const { cache = {} } = this.options;\n const {\n fileSize = ZStreamFile.FileSizeDefault,\n maxFiles = ZStreamFile.MaxFilesDefault,\n } = cache;\n\n if (item.stats.size > fileSize) {\n // In this case, the file size is too big to cache in memory,\n // so we're bowing out here.\n return item.buffer;\n }\n\n // We will remove this path from the cache first since\n // we want it to be the most recent file (at the end)\n // of the key list. The removal does nothing if the\n // file was not cached.\n this._cache.delete(path);\n this._cache.set(path, item);\n\n if (this._cache.size > maxFiles) {\n // Retrieving the keys from a javascript map is order\n // by the time in which the keys are created. So\n // we are going to remove the first key which is the\n // oldest.\n const itr = this._cache.keys();\n this._cache.delete(itr.next().value);\n }\n\n return item.buffer;\n }\n}\n"],"names":["ZFileSystemNodeType","ZFileSystemNodeBuilder","_node","path","type","created","at","Date","toJSON","updated","size","bytes","BigInt","file","bind","folder","stats","s","builder","birthtime","mtime","isFile","build","clone","structuredClone","omitBy","isUndefined","ZFileSystemService","info","search","pattern","options","paths","glob","stat","withFileTypes","map","fullpath","atime","undefined","walk","start","cwd","stop","mode","_test","access","isAbsolute","dir","resolve","exists","dirname","length","ZFileWatch","_add","Subject","_update","_remove","_watcher","watch","usePolling","alwaysStat","ignoreInitial","awaitWriteFinish","stabilityThreshold","pollInterval","next","observable","node","on","Promise","close","add","asObservable","update","remove","ZFileRepository","_service","_nodes","ZDataSourceStatic","_globs","_path","globs","slice","initialize","reset","matches","g","all","then","nodes","flat","flatten","uniq","uniqBy","n","filter","File","files","subscribe","some","minimatch","insert","trimEnd","sep","findIndex","items","startsWith","substring","charAt","index","removeAt","sleep","unsubscribe","get","find","f","firstDefined","count","request","source","retrieve","resolvePathLike","URL","fileURLToPath","toString","ZWatchDelay","sleepWatchDelay","ZStreamFolder","write","mkdir","recursive","msg","Error","ZStreamFile","FileSizeDefault","MaxFilesDefault","_cache","Map","read","cached","buffer","mtimeMs","readFile","_addToCache","Buffer","from","directory","writeFile","flush","delete","item","cache","fileSize","maxFiles","set","itr","keys","value"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/file-system/file-system-node.mts","../src/file-system/file-system-service.mts","../src/file-watch/file-watch.mts","../src/file-repository/file-repository.mts","../src/resolve-path-like/resolve-path-like.ts","../src/sleep-watch-delay/sleep-watch-delay.mts","../src/stream/stream-folder.mts","../src/stream/stream-file.mts"],"sourcesContent":["import { type ZMutable } from \"@zthun/helpful-fn\";\nimport { isUndefined, omitBy } from \"lodash-es\";\nimport type { Stats } from \"node:fs\";\nimport { basename, dirname, extname } from \"node:path\";\n\n/**\n * Represents a type of a file system node.\n */\nexport enum ZFileSystemNodeType {\n File = \"file\",\n Folder = \"folder\",\n}\n\nexport interface IZFileSystemNode {\n /**\n * The absolute path of the node.\n */\n path: string;\n\n /**\n * The type of the node (file or folder).\n */\n type: ZFileSystemNodeType;\n\n /**\n * The creation date of the node.\n */\n created?: string;\n\n /**\n * The modification date of the node.\n */\n updated?: string;\n\n /**\n * The size of the node in bytes.\n */\n size?: bigint;\n\n /**\n * The file or folder name with the extension.\n *\n * Calculated from the path.\n */\n readonly name: string;\n\n /**\n * The file extension.\n *\n * Calculated from the path.\n */\n readonly extension: string;\n\n /**\n * File title.\n *\n * The name without the extension.\n * Calculated from the path.\n */\n readonly title: string;\n\n /**\n * Parent directory path.\n */\n readonly parent: string;\n}\n\n/**\n * Represents a builder for a file system node.\n */\nexport class ZFileSystemNodeBuilder {\n private _node: ZMutable<IZFileSystemNode> = {\n path: \"/\",\n type: ZFileSystemNodeType.Folder,\n extension: \"\",\n name: \"\",\n parent: \"\",\n title: \"\",\n };\n\n public created(at?: Date | string | undefined) {\n this._node.created = at instanceof Date ? at.toJSON() : at;\n\n return this;\n }\n\n public updated(at?: Date | string | undefined) {\n this._node.updated = at instanceof Date ? at.toJSON() : at;\n\n return this;\n }\n\n public size(bytes: bigint | number | undefined) {\n this._node.size = typeof bytes == \"number\" ? BigInt(bytes) : bytes;\n\n return this;\n }\n\n public path(path: string) {\n this._node.path = path;\n\n return this.decorate();\n }\n\n public type(type: ZFileSystemNodeType) {\n this._node.type = type;\n\n return this.decorate();\n }\n\n public file = this.type.bind(this, ZFileSystemNodeType.File);\n public folder = this.type.bind(this, ZFileSystemNodeType.Folder);\n\n public stats(s: Stats) {\n const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);\n\n return s.isFile() ? builder.file() : builder.folder();\n }\n\n public build() {\n const clone = structuredClone(this._node);\n\n return omitBy(clone, isUndefined) as IZFileSystemNode;\n }\n\n private decorate() {\n const { path, type } = this._node;\n\n this._node.name = basename(path);\n this._node.extension = \"\";\n this._node.title = this._node.name;\n this._node.parent = dirname(path);\n\n if (type === ZFileSystemNodeType.File) {\n const extension = extname(path);\n this._node.extension = extension;\n this._node.title = basename(path, extension);\n }\n\n if (!path || path === \"/\" || this._node.parent === \".\") {\n this._node.parent = \"\";\n }\n\n return this;\n }\n}\n","import { glob } from \"glob\";\nimport { access } from \"node:fs/promises\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { cwd } from \"node:process\";\nimport type { IZFileSystemNode } from \"./file-system-node.mjs\";\nimport { ZFileSystemNodeBuilder } from \"./file-system-node.mjs\";\n\n/**\n * Represents options for searches.\n */\nexport interface IZFileSystemSearchOptions {\n /**\n * The directory to search in.\n *\n * If this is not set, then the cwd of the application is used.\n */\n cwd?: string;\n\n /**\n * A flag that determines whether or not to load the\n * file system information.\n *\n * This is true by default.\n */\n stat?: boolean;\n}\n\n/**\n * Represents options for directory walking.\n */\nexport interface IZFileSystemWalkOptions {\n /**\n * The starting directory.\n *\n * The default is the current working directory\n *\n * @see process.cwd for more information.\n */\n start?: string;\n\n /**\n * The directory to stop at.\n *\n * The default is the root of the file system.\n */\n stop?: string;\n\n /**\n * The type of mode that the path must support in order\n * to be approved.\n *\n * The default is undefined and left up to the node api.\n */\n mode?: number;\n}\n\n/**\n * Represents a service to enumerate the file system.\n */\nexport interface IZFileSystemService {\n /**\n * Gets information about a node.\n *\n * @param path -\n * The path to get information for.\n *\n * @returns\n * Information about the node.\n */\n info(path: string): Promise<IZFileSystemNode>;\n\n /**\n * Reads all nodes that match a pattern.\n *\n * @param pattern -\n * The pattern string to match against or a list\n * of patterns to match.\n * @param options -\n * The options for the search.\n *\n * @returns\n * A list of path strings that match the given patterns.\n */\n search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]>;\n\n /**\n * Walks up a directory tree to search for existence of a given path.\n *\n * @param search -\n * The path to search for. This is the candidate folder path that\n * may or may not exist somewhere from the start directory all the\n * way up the directory tree.\n * @param options -\n * The given options for the search.\n *\n * @returns\n * The fully qualified path to the first path that matches the search\n * starting at the options start or the current working directory if not\n * specified. Returns null if no such directory exists.\n *\n * @example\n *\n * ```ts\n * import { resolve } from 'path'\n *\n * // Find any folder named .vscode from the current working directory all the way\n * // up the directory tree. Returns null if no vscode directory can be found.\n * const service = new ZFileSystemService();\n * const vscode = service.walk('.vscode');\n *\n * // Walk the directory tree from the current script and find the .config folder.\n * const config = service.walk('.config', { start: __dirname });\n *\n * // Walk the directory tree from the current script and stop when we reach\n * // at most 2 directories up.\n * const start = __dirname;\n * const stop = resolve(__dirname, '../..');\n * const file = service.walk('path/to/file.json', { start, stop });\n * ```\n */\n walk(\n search: string,\n options?: IZFileSystemWalkOptions,\n ): Promise<string | null>;\n}\n\n/**\n * Represents a node implementation of a file system service.\n */\nexport class ZFileSystemService implements IZFileSystemService {\n public async info(path: string): Promise<IZFileSystemNode> {\n const [file] = await this.search(path);\n return file;\n }\n\n public async search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]> {\n const paths = await glob(pattern, {\n stat: true,\n ...options,\n withFileTypes: true,\n });\n\n return paths.map((path) => {\n let info = new ZFileSystemNodeBuilder()\n .path(path.fullpath())\n .created(path.birthtime)\n .updated(path.atime)\n .size(path.size);\n\n // Note that for folders, node will return the size of the underlying OS metadata,\n // hence, why we remove the size on the folder here.\n info = path.isFile() ? info.file() : info.folder().size(undefined);\n\n return info.build();\n });\n }\n\n public async walk(search: string, options?: IZFileSystemWalkOptions) {\n const start = options?.start || cwd();\n const stop = options?.stop || \"/\";\n const mode = options?.mode;\n\n const _test = async (path: string) => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n };\n\n if (isAbsolute(search)) {\n return (await _test(search)) ? search : null;\n }\n\n let dir = start;\n do {\n const path = resolve(dir, search);\n const exists = await _test(path);\n\n if (exists) {\n return path;\n }\n\n dir = dir === stop ? \"\" : dirname(dir);\n } while (dir.length);\n\n return null;\n }\n}\n","import type { FSWatcher } from \"chokidar\";\nimport { watch } from \"chokidar\";\nimport type { Stats } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Observable } from \"rxjs\";\nimport { Subject } from \"rxjs\";\nimport {\n ZFileSystemNodeBuilder,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\n\n/**\n * Represents and object that can watch a folder or file on the file system.\n */\nexport interface IZFileWatch {\n /**\n * Starts the watch operation.\n */\n start(): Promise<void>;\n\n /**\n * Stops the watch operation.\n */\n stop(): Promise<void>;\n\n /**\n * The stream for files being added.\n *\n * This can only occur if the target being watched\n * is a folder.\n *\n * @returns\n * The observable that will publish files that\n * get added.\n */\n add(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files being updated.\n *\n * If this watcher points to a folder, then all files\n * recursively will send when they get updated. If this\n * watcher points to a file, then this will only invoke\n * when the file is updated.\n *\n * @returns\n * The observable that will publish files and folders\n * that are updated.\n */\n update(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files and folders being deleted.\n *\n * If this watcher points to a folder, then all files under the\n * folder will be sent through this observable, including the\n * folder being watched. If this points to a file, then\n * this will only receive when the file is unlinked.\n *\n * @returns\n * The observable that will publish file and folders\n * that are unlinked and removed respectively. Note\n * that files and folders streamed this way will not\n * have their stats set.\n */\n remove(): Observable<IZFileSystemNode>;\n}\n\n/**\n * An implementation of the IZFileWatch.\n */\nexport class ZFileWatch implements IZFileWatch {\n private _add: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _update: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _remove: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _watcher: FSWatcher | undefined;\n\n /**\n * Initializes a new instance of this object.\n *\n * @param path -\n * The path to watch.\n */\n public constructor(public readonly path: string) {}\n\n public async start() {\n await this.stop();\n\n this._watcher = watch(this.path, {\n usePolling: true,\n alwaysStat: true,\n ignoreInitial: true,\n\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 50,\n },\n });\n\n function next(\n observable: Subject<IZFileSystemNode>,\n file: string,\n stats: Stats | undefined,\n ) {\n const node = new ZFileSystemNodeBuilder().path(resolve(this.path, file));\n observable.next(stats ? node.stats(stats).build() : node.build());\n }\n\n this._watcher\n .on(\"add\", next.bind(this, this._add))\n .on(\"addDir\", next.bind(this, this._add))\n .on(\"change\", next.bind(this, this._update))\n .on(\"unlink\", next.bind(this, this._remove))\n .on(\"unlinkDir\", next.bind(this, this._remove));\n\n return new Promise<void>((resolve) =>\n this._watcher?.on(\"ready\", () => resolve()),\n );\n }\n\n public async stop() {\n await this._watcher?.close();\n delete this._watcher;\n return Promise.resolve();\n }\n\n public add() {\n return this._add.asObservable();\n }\n\n public update() {\n return this._update.asObservable();\n }\n\n public remove() {\n return this._remove.asObservable();\n }\n}\n","import { firstDefined, sleep } from \"@zthun/helpful-fn\";\nimport type { IZDataRequest, IZDataSource } from \"@zthun/helpful-query\";\nimport { ZDataSourceStatic } from \"@zthun/helpful-query\";\nimport { find, findIndex, flatten, trimEnd, uniqBy } from \"lodash-es\";\nimport { minimatch } from \"minimatch\";\nimport { resolve, sep } from \"node:path\";\nimport type { Subscription } from \"rxjs\";\nimport {\n ZFileSystemNodeType,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\nimport {\n ZFileSystemService,\n type IZFileSystemService,\n} from \"../file-system/file-system-service.mjs\";\nimport { ZFileWatch, type IZFileWatch } from \"../file-watch/file-watch.mjs\";\n\n/**\n * Represents a repository for the file system.\n */\nexport interface IZFileRepository extends IZDataSource<IZFileSystemNode> {\n /**\n * Retrieves a single file from the repository.\n *\n * @param path -\n * The fully qualified path to the file.\n *\n * @returns\n * The node that represents the file. Returns null if no\n * such file exists.\n */\n get(path: string): Promise<IZFileSystemNode | null>;\n}\n\n/**\n * Represents an implementation of a ZFileRepository that watches\n * a given path scope.\n *\n * This repository is only concerned about files. Folders\n * will not be retrieved from this repository.\n */\nexport class ZFileRepository implements IZFileRepository {\n private _service: IZFileSystemService = new ZFileSystemService();\n private _watcher: IZFileWatch | undefined;\n private _nodes: Promise<ZDataSourceStatic<IZFileSystemNode>> =\n Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n private _globs: string[] = [\"**\"];\n private _path: string = \"\";\n private _add: Subscription | undefined;\n private _remove: Subscription | undefined;\n private _update: Subscription | undefined;\n\n /**\n * Gets the path that this repository is watching.\n */\n public get path() {\n return this._path;\n }\n\n /**\n * Gets the globs matchers that this repository is matching against.\n */\n public get globs() {\n return this._globs.slice();\n }\n\n /**\n * Initializes the repository with the given root and glob filter.\n *\n * This will initially scan the file system and setup watches.\n * If you call this method again, then the repository will be\n * {@link reset} and a new set of files will be added to the\n * repository.\n *\n * @param path -\n * The root path of the repository.\n * @param globs -\n * The optional relative globs of the repository. If this is falsy,\n * then ** is used. You can achieve the same kind of operation\n * using filters, but filtering out unwanted files frees up the internal\n * memory being used.\n */\n public async initialize(path: string, globs: string[] = [\"**\"]) {\n await this.reset();\n\n this._path = path;\n this._globs = globs;\n\n // Note that this all happens in the background and should\n // only be awaited later. So the search should not be\n // required to finish when existing this method. The only\n // requirement is that the repository is reset and the path +\n // glob scope is updated. Everything beyond here should not\n // be awaited - it will be awaited later once the caller\n // tries to retrieve the files using retrieve, get, or\n // count.\n const matches = globs.map((g) =>\n this._service.search(g, {\n cwd: path,\n stat: true,\n }),\n );\n\n this._nodes = Promise.all(matches)\n .then((nodes) => {\n const flat = flatten(nodes);\n const uniq = uniqBy(flat, (n) => n.path);\n return uniq.filter((n) => n.type === ZFileSystemNodeType.File);\n })\n .then((files) => {\n return new ZDataSourceStatic(files);\n });\n\n this._watcher = new ZFileWatch(path);\n\n this._add = this._watcher\n .add()\n .subscribe(async (node: IZFileSystemNode) => {\n if (\n node.type === ZFileSystemNodeType.File &&\n this._globs.some((g) => minimatch(node.path, resolve(this._path, g)))\n ) {\n const nodes = await this._nodes;\n this._nodes = nodes.insert(node);\n }\n });\n\n this._remove = this._watcher\n .remove()\n .subscribe(async (node: IZFileSystemNode) => {\n let nodes = await this._nodes;\n const path = trimEnd(node.path, sep);\n\n // It's possible that the node given was a folder. If that happens,\n // we need to remove all files that start with the given path.\n // If the node does point to a file, then there is no possibility that\n // more than 1 item would be removed.\n\n const next = async () =>\n findIndex(await nodes.items(), (n) => {\n return (\n n.path === path ||\n (n.path.startsWith(path) &&\n n.path.substring(path.length).charAt(0) === sep)\n );\n });\n\n for (let index = await next(); index >= 0; index = await next()) {\n nodes = await nodes.removeAt(index);\n }\n\n this._nodes = Promise.resolve(nodes);\n });\n\n this._update = this._watcher\n .update()\n .subscribe(async (node: IZFileSystemNode) => {\n const nodes = await this._nodes;\n const index = findIndex(\n await nodes.items(),\n (n) => n.path === node.path,\n );\n\n // It's possible node was filtered out by the globs, or\n // it is a directory. If so, then we won't have it in our\n // list.\n if (index >= 0) {\n const next = await nodes.removeAt(index);\n this._nodes = next.insert(node, index);\n }\n });\n\n // Kick off the initial seed operation with an even loop\n // invocation.\n await sleep(100);\n\n await this._watcher?.start();\n }\n\n /**\n * Resets the repository as if it was initially created.\n */\n public async reset(): Promise<void> {\n await this._watcher?.stop();\n\n this._add?.unsubscribe();\n this._remove?.unsubscribe();\n this._update?.unsubscribe();\n\n delete this._add;\n delete this._remove;\n delete this._update;\n delete this._watcher;\n\n this._path = \"\";\n this._globs = [\"**\"];\n this._nodes = Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n }\n\n public async get(path: string): Promise<IZFileSystemNode | null> {\n const nodes = await this._nodes;\n const items = await nodes.items();\n const node = find(items, (f) => f.path === path);\n\n return firstDefined(null, node);\n }\n\n public async count(request: IZDataRequest): Promise<number> {\n const source = await this._nodes;\n return source.count(request);\n }\n\n public async retrieve(request: IZDataRequest): Promise<IZFileSystemNode[]> {\n const source = await this._nodes;\n return source.retrieve(request);\n }\n}\n","import type { PathLike } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function resolvePathLike(path: PathLike): string {\n if (typeof path === \"string\") {\n return resolve(path);\n }\n\n if (path instanceof URL) {\n return fileURLToPath(path);\n }\n\n return resolve(path.toString());\n}\n","import { sleep } from \"@zthun/helpful-fn\";\n\n/**\n * The actual delay time that you should wait for a watch\n * operation to pick up your file changes.\n */\nexport const ZWatchDelay = 1500;\n\n/**\n * Performs a sleep long enough to allow a watch operation\n * to pick up a change.\n *\n * You should never really need this. Where it is useful\n * is for unit testing with IO operations and you want to\n * wait for your write operations to get picked up by\n * a file watch operation.\n */\nexport function sleepWatchDelay() {\n return sleep(ZWatchDelay);\n}\n","import type { PathLike } from \"fs\";\nimport { mkdir } from \"fs/promises\";\nimport type { IZStreamWrite } from \"./stream-write.mjs\";\n\n/**\n * A stream that writes folders.\n *\n * Writing folders is idempotent. If the folder you\n * are trying to write already exists, then the write\n * operation still succeeds\n */\nexport class ZStreamFolder implements IZStreamWrite {\n public async write(path: PathLike): Promise<number> {\n await mkdir(path, { recursive: true });\n\n return 0;\n }\n}\n","import type { PathLike, Stats } from \"node:fs\";\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"path\";\nimport { resolvePathLike } from \"../resolve-path-like/resolve-path-like.js\";\nimport { ZStreamFolder } from \"./stream-folder.mjs\";\nimport type { IZStreamRead, IZStreamReadOptions } from \"./stream-read.mjs\";\nimport type { IZStreamWrite, IZStreamWriteOptions } from \"./stream-write.mjs\";\n\n/**\n * Options for the stream file object.\n */\nexport interface IZStreamFileOptions {\n /**\n * Cache options.\n *\n * A warning that file content caching will take up significant memory\n * if the file size is too big or the max files is too big. Make sure\n * you know what you're doing when you change the default values of this.\n */\n cache?: {\n /**\n * Maximum number of bytes a file can be before it will not be cached.\n * The default is 100 Kib (102400 bytes)\n *\n * @default 102400\n */\n fileSize?: bigint;\n /**\n * The maximum number of files that are to be cached. The cache order\n * is first in, first out. Set this to 0 to not cache anything. The\n * default is 1000.\n *\n * @default 1000\n */\n maxFiles?: number;\n };\n}\n\n/**\n * A stream that can read and write to files.\n *\n * This is mostly a wrapper to readFile and writeFile from node, but\n * with some optimizations.\n *\n * First, this class supports file content caching so reading in a file\n * that's under a certain size threshold will store it in memory for\n * later retrieval.\n */\nexport class ZStreamFile implements IZStreamWrite, IZStreamRead {\n private static readonly FileSizeDefault = 102400; // One Hundred KibiBytes\n private static readonly MaxFilesDefault = 1000;\n\n private _cache = new Map<string, { stats: Stats; buffer: Promise<Buffer> }>();\n\n /**\n * Initializes a new instance of this object.\n *\n * @param options -\n * The options for file read and writes.\n */\n public constructor(public readonly options: IZStreamFileOptions = {}) {}\n\n public async read(\n path: PathLike,\n options?: IZStreamReadOptions,\n ): Promise<Buffer> {\n const _path = resolvePathLike(path);\n\n const stats = await stat(_path);\n const cached = this._cache.get(_path);\n\n const buffer =\n cached && cached.stats.mtimeMs >= stats.mtimeMs\n ? cached.buffer\n : readFile(_path, options);\n\n return this._addToCache(_path, { stats, buffer });\n }\n\n public async write(\n path: PathLike,\n { buffer = Buffer.from(\"\") }: IZStreamWriteOptions = {},\n ): Promise<number> {\n const _path = resolvePathLike(path);\n const directory = dirname(_path);\n\n await new ZStreamFolder().write(directory);\n await writeFile(_path, buffer, { flush: true });\n\n // If this file specifically was cached earlier,\n // we can just remove it now so we make room for\n // another file. Consumers can just read the\n // file again to recache it.\n this._cache.delete(_path);\n\n return buffer.length;\n }\n\n private _addToCache(\n path: string,\n item: { stats: Stats; buffer: Promise<Buffer> },\n ) {\n const { cache = {} } = this.options;\n const {\n fileSize = ZStreamFile.FileSizeDefault,\n maxFiles = ZStreamFile.MaxFilesDefault,\n } = cache;\n\n if (item.stats.size > fileSize) {\n // In this case, the file size is too big to cache in memory,\n // so we're bowing out here.\n return item.buffer;\n }\n\n // We will remove this path from the cache first since\n // we want it to be the most recent file (at the end)\n // of the key list. The removal does nothing if the\n // file was not cached.\n this._cache.delete(path);\n this._cache.set(path, item);\n\n if (this._cache.size > maxFiles) {\n // Retrieving the keys from a javascript map is order\n // by the time in which the keys are created. So\n // we are going to remove the first key which is the\n // oldest.\n const itr = this._cache.keys();\n this._cache.delete(itr.next().value);\n }\n\n return item.buffer;\n }\n}\n"],"names":["ZFileSystemNodeType","ZFileSystemNodeBuilder","created","at","_node","Date","toJSON","updated","size","bytes","BigInt","path","decorate","type","stats","s","builder","birthtime","mtime","isFile","file","folder","build","clone","structuredClone","omitBy","isUndefined","name","basename","extension","title","parent","dirname","extname","_define_property","bind","ZFileSystemService","info","search","pattern","options","paths","glob","stat","withFileTypes","map","fullpath","atime","undefined","walk","start","cwd","stop","mode","_test","access","isAbsolute","dir","resolve","exists","length","ZFileWatch","_watcher","watch","usePolling","alwaysStat","ignoreInitial","awaitWriteFinish","stabilityThreshold","pollInterval","next","observable","node","on","_add","_update","_remove","Promise","close","add","asObservable","update","remove","Subject","ZFileRepository","_path","globs","_globs","slice","initialize","reset","matches","g","_service","_nodes","all","then","nodes","flat","flatten","uniq","uniqBy","n","filter","File","files","ZDataSourceStatic","subscribe","some","minimatch","insert","trimEnd","sep","findIndex","items","startsWith","substring","charAt","index","removeAt","sleep","unsubscribe","get","find","f","firstDefined","count","request","source","retrieve","resolvePathLike","URL","fileURLToPath","toString","ZWatchDelay","sleepWatchDelay","ZStreamFolder","write","mkdir","recursive","ZStreamFile","read","cached","_cache","buffer","mtimeMs","readFile","_addToCache","Buffer","from","directory","writeFile","flush","delete","item","cache","fileSize","FileSizeDefault","maxFiles","MaxFilesDefault","set","itr","keys","value","Map"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -6,4 +6,5 @@ export * from './resolve-path-like/resolve-path-like.js';
6
6
  export * from './sleep-watch-delay/sleep-watch-delay.mjs';
7
7
  export * from './stream/stream-file.mjs';
8
8
  export * from './stream/stream-folder.mjs';
9
+ export * from './stream/stream-read.mjs';
9
10
  export * from './stream/stream-write.mjs';
package/dist/index.js CHANGED
@@ -2,16 +2,29 @@ import { sleep, firstDefined } from '@zthun/helpful-fn';
2
2
  import { ZDataSourceStatic } from '@zthun/helpful-query';
3
3
  import { omitBy, isUndefined, flatten, uniqBy, trimEnd, findIndex, find } from 'lodash-es';
4
4
  import { minimatch } from 'minimatch';
5
- import { isAbsolute, resolve, dirname, sep } from 'node:path';
5
+ import { basename, dirname, extname, isAbsolute, resolve, sep } from 'node:path';
6
6
  import { glob } from 'glob';
7
- import { access, stat as stat$1, readFile, writeFile } from 'node:fs/promises';
7
+ import { access, stat, readFile, writeFile } from 'node:fs/promises';
8
8
  import { cwd } from 'node:process';
9
9
  import { watch } from 'chokidar';
10
10
  import { Subject } from 'rxjs';
11
11
  import { fileURLToPath } from 'node:url';
12
12
  import { dirname as dirname$1 } from 'path';
13
- import { mkdir, stat } from 'fs/promises';
13
+ import { mkdir } from 'fs/promises';
14
14
 
15
+ function _define_property$3(obj, key, value) {
16
+ if (key in obj) {
17
+ Object.defineProperty(obj, key, {
18
+ value: value,
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true
22
+ });
23
+ } else {
24
+ obj[key] = value;
25
+ }
26
+ return obj;
27
+ }
15
28
  /**
16
29
  * Represents a type of a file system node.
17
30
  */ var ZFileSystemNodeType = /*#__PURE__*/ function(ZFileSystemNodeType) {
@@ -22,13 +35,6 @@ import { mkdir, stat } from 'fs/promises';
22
35
  /**
23
36
  * Represents a builder for a file system node.
24
37
  */ class ZFileSystemNodeBuilder {
25
- _node;
26
- constructor(){
27
- this._node = {
28
- path: "/",
29
- type: "folder"
30
- };
31
- }
32
38
  created(at) {
33
39
  this._node.created = at instanceof Date ? at.toJSON() : at;
34
40
  return this;
@@ -43,14 +49,12 @@ import { mkdir, stat } from 'fs/promises';
43
49
  }
44
50
  path(path) {
45
51
  this._node.path = path;
46
- return this;
52
+ return this.decorate();
47
53
  }
48
54
  type(type) {
49
55
  this._node.type = type;
50
- return this;
56
+ return this.decorate();
51
57
  }
52
- file = this.type.bind(this, "file");
53
- folder = this.type.bind(this, "folder");
54
58
  stats(s) {
55
59
  const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);
56
60
  return s.isFile() ? builder.file() : builder.folder();
@@ -59,6 +63,34 @@ import { mkdir, stat } from 'fs/promises';
59
63
  const clone = structuredClone(this._node);
60
64
  return omitBy(clone, isUndefined);
61
65
  }
66
+ decorate() {
67
+ const { path, type } = this._node;
68
+ this._node.name = basename(path);
69
+ this._node.extension = "";
70
+ this._node.title = this._node.name;
71
+ this._node.parent = dirname(path);
72
+ if (type === "file") {
73
+ const extension = extname(path);
74
+ this._node.extension = extension;
75
+ this._node.title = basename(path, extension);
76
+ }
77
+ if (!path || path === "/" || this._node.parent === ".") {
78
+ this._node.parent = "";
79
+ }
80
+ return this;
81
+ }
82
+ constructor(){
83
+ _define_property$3(this, "_node", {
84
+ path: "/",
85
+ type: "folder",
86
+ extension: "",
87
+ name: "",
88
+ parent: "",
89
+ title: ""
90
+ });
91
+ _define_property$3(this, "file", this.type.bind(this, "file"));
92
+ _define_property$3(this, "folder", this.type.bind(this, "folder"));
93
+ }
62
94
  }
63
95
 
64
96
  /**
@@ -110,22 +142,22 @@ import { mkdir, stat } from 'fs/promises';
110
142
  }
111
143
  }
112
144
 
145
+ function _define_property$2(obj, key, value) {
146
+ if (key in obj) {
147
+ Object.defineProperty(obj, key, {
148
+ value: value,
149
+ enumerable: true,
150
+ configurable: true,
151
+ writable: true
152
+ });
153
+ } else {
154
+ obj[key] = value;
155
+ }
156
+ return obj;
157
+ }
113
158
  /**
114
159
  * An implementation of the IZFileWatch.
115
160
  */ class ZFileWatch {
116
- path;
117
- _add = new Subject();
118
- _update = new Subject();
119
- _remove = new Subject();
120
- _watcher;
121
- /**
122
- * Initializes a new instance of this object.
123
- *
124
- * @param path -
125
- * The path to watch.
126
- */ constructor(path){
127
- this.path = path;
128
- }
129
161
  async start() {
130
162
  await this.stop();
131
163
  this._watcher = watch(this.path, {
@@ -158,8 +190,37 @@ import { mkdir, stat } from 'fs/promises';
158
190
  remove() {
159
191
  return this._remove.asObservable();
160
192
  }
193
+ /**
194
+ * Initializes a new instance of this object.
195
+ *
196
+ * @param path -
197
+ * The path to watch.
198
+ */ constructor(path){
199
+ _define_property$2(this, "path", void 0);
200
+ _define_property$2(this, "_add", void 0);
201
+ _define_property$2(this, "_update", void 0);
202
+ _define_property$2(this, "_remove", void 0);
203
+ _define_property$2(this, "_watcher", void 0);
204
+ this.path = path;
205
+ this._add = new Subject();
206
+ this._update = new Subject();
207
+ this._remove = new Subject();
208
+ }
161
209
  }
162
210
 
211
+ function _define_property$1(obj, key, value) {
212
+ if (key in obj) {
213
+ Object.defineProperty(obj, key, {
214
+ value: value,
215
+ enumerable: true,
216
+ configurable: true,
217
+ writable: true
218
+ });
219
+ } else {
220
+ obj[key] = value;
221
+ }
222
+ return obj;
223
+ }
163
224
  /**
164
225
  * Represents an implementation of a ZFileRepository that watches
165
226
  * a given path scope.
@@ -167,16 +228,6 @@ import { mkdir, stat } from 'fs/promises';
167
228
  * This repository is only concerned about files. Folders
168
229
  * will not be retrieved from this repository.
169
230
  */ class ZFileRepository {
170
- _service = new ZFileSystemService();
171
- _watcher;
172
- _nodes = Promise.resolve(new ZDataSourceStatic([]));
173
- _globs = [
174
- "**"
175
- ];
176
- _path = "";
177
- _add;
178
- _remove;
179
- _update;
180
231
  /**
181
232
  * Gets the path that this repository is watching.
182
233
  */ get path() {
@@ -296,6 +347,18 @@ import { mkdir, stat } from 'fs/promises';
296
347
  const source = await this._nodes;
297
348
  return source.retrieve(request);
298
349
  }
350
+ constructor(){
351
+ _define_property$1(this, "_service", new ZFileSystemService());
352
+ _define_property$1(this, "_watcher", void 0);
353
+ _define_property$1(this, "_nodes", Promise.resolve(new ZDataSourceStatic([])));
354
+ _define_property$1(this, "_globs", [
355
+ "**"
356
+ ]);
357
+ _define_property$1(this, "_path", "");
358
+ _define_property$1(this, "_add", void 0);
359
+ _define_property$1(this, "_remove", void 0);
360
+ _define_property$1(this, "_update", void 0);
361
+ }
299
362
  }
300
363
 
301
364
  function resolvePathLike(path) {
@@ -332,25 +395,26 @@ function resolvePathLike(path) {
332
395
  * operation still succeeds
333
396
  */ class ZStreamFolder {
334
397
  async write(path) {
335
- try {
336
- await mkdir(path, {
337
- recursive: true
338
- });
339
- } catch {
340
- // The folder may exist, but if it is a file then
341
- // we have a conflict and in that case, we will throw an
342
- // error. We are going to let stat fail if it cannot
343
- // access the path (permission error).
344
- const stats = await stat(path);
345
- if (stats.isFile()) {
346
- const msg = `Cannot create folder, ${path}, because a file with the same name exists at the target location`;
347
- throw new Error(msg);
348
- }
349
- }
398
+ await mkdir(path, {
399
+ recursive: true
400
+ });
350
401
  return 0;
351
402
  }
352
403
  }
353
404
 
405
+ function _define_property(obj, key, value) {
406
+ if (key in obj) {
407
+ Object.defineProperty(obj, key, {
408
+ value: value,
409
+ enumerable: true,
410
+ configurable: true,
411
+ writable: true
412
+ });
413
+ } else {
414
+ obj[key] = value;
415
+ }
416
+ return obj;
417
+ }
354
418
  /**
355
419
  * A stream that can read and write to files.
356
420
  *
@@ -361,21 +425,9 @@ function resolvePathLike(path) {
361
425
  * that's under a certain size threshold will store it in memory for
362
426
  * later retrieval.
363
427
  */ class ZStreamFile {
364
- options;
365
- static FileSizeDefault = 102400;
366
- static MaxFilesDefault = 1000;
367
- _cache = new Map();
368
- /**
369
- * Initializes a new instance of this object.
370
- *
371
- * @param options -
372
- * The options for file read and writes.
373
- */ constructor(options = {}){
374
- this.options = options;
375
- }
376
428
  async read(path, options) {
377
429
  const _path = resolvePathLike(path);
378
- const stats = await stat$1(_path);
430
+ const stats = await stat(_path);
379
431
  const cached = this._cache.get(_path);
380
432
  const buffer = cached && cached.stats.mtimeMs >= stats.mtimeMs ? cached.buffer : readFile(_path, options);
381
433
  return this._addToCache(_path, {
@@ -421,7 +473,20 @@ function resolvePathLike(path) {
421
473
  }
422
474
  return item.buffer;
423
475
  }
476
+ /**
477
+ * Initializes a new instance of this object.
478
+ *
479
+ * @param options -
480
+ * The options for file read and writes.
481
+ */ constructor(options = {}){
482
+ _define_property(this, "options", void 0);
483
+ _define_property(this, "_cache", void 0);
484
+ this.options = options;
485
+ this._cache = new Map();
486
+ }
424
487
  }
488
+ _define_property(ZStreamFile, "FileSizeDefault", 102400); // One Hundred KibiBytes
489
+ _define_property(ZStreamFile, "MaxFilesDefault", 1000);
425
490
 
426
491
  export { ZFileRepository, ZFileSystemNodeBuilder, ZFileSystemNodeType, ZFileSystemService, ZFileWatch, ZStreamFile, ZStreamFolder, ZWatchDelay, resolvePathLike, sleepWatchDelay };
427
492
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/file-system/file-system-node.mts","../src/file-system/file-system-service.mts","../src/file-watch/file-watch.mts","../src/file-repository/file-repository.mts","../src/resolve-path-like/resolve-path-like.ts","../src/sleep-watch-delay/sleep-watch-delay.mts","../src/stream/stream-folder.mts","../src/stream/stream-file.mts"],"sourcesContent":["import { isUndefined, omitBy } from \"lodash-es\";\nimport type { Stats } from \"node:fs\";\n\n/**\n * Represents a type of a file system node.\n */\nexport enum ZFileSystemNodeType {\n File = \"file\",\n Folder = \"folder\",\n}\n\nexport interface IZFileSystemNode {\n /**\n * The absolute path of the node.\n */\n path: string;\n\n /**\n * The type of the node (file or folder).\n */\n type: ZFileSystemNodeType;\n\n /**\n * The creation date of the node.\n */\n created?: string;\n\n /**\n * The modification date of the node.\n */\n updated?: string;\n\n /**\n * The size of the node in bytes.\n */\n size?: bigint;\n}\n\n/**\n * Represents a builder for a file system node.\n */\nexport class ZFileSystemNodeBuilder {\n private _node: IZFileSystemNode;\n\n public constructor() {\n this._node = {\n path: \"/\",\n type: ZFileSystemNodeType.Folder,\n };\n }\n\n public created(at?: Date | string | undefined) {\n this._node.created = at instanceof Date ? at.toJSON() : at;\n return this;\n }\n\n public updated(at?: Date | string | undefined) {\n this._node.updated = at instanceof Date ? at.toJSON() : at;\n return this;\n }\n\n public size(bytes: bigint | number | undefined) {\n this._node.size = typeof bytes == \"number\" ? BigInt(bytes) : bytes;\n return this;\n }\n\n public path(path: string) {\n this._node.path = path;\n return this;\n }\n\n public type(type: ZFileSystemNodeType) {\n this._node.type = type;\n return this;\n }\n\n public file = this.type.bind(this, ZFileSystemNodeType.File);\n public folder = this.type.bind(this, ZFileSystemNodeType.Folder);\n\n public stats(s: Stats) {\n const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);\n return s.isFile() ? builder.file() : builder.folder();\n }\n\n public build() {\n const clone = structuredClone(this._node);\n return omitBy(clone, isUndefined) as IZFileSystemNode;\n }\n}\n","import { glob } from \"glob\";\nimport { access } from \"node:fs/promises\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { cwd } from \"node:process\";\nimport type { IZFileSystemNode } from \"./file-system-node.mjs\";\nimport { ZFileSystemNodeBuilder } from \"./file-system-node.mjs\";\n\n/**\n * Represents options for searches.\n */\nexport interface IZFileSystemSearchOptions {\n /**\n * The directory to search in.\n *\n * If this is not set, then the cwd of the application is used.\n */\n cwd?: string;\n\n /**\n * A flag that determines whether or not to load the\n * file system information.\n *\n * This is true by default.\n */\n stat?: boolean;\n}\n\n/**\n * Represents options for directory walking.\n */\nexport interface IZFileSystemWalkOptions {\n /**\n * The starting directory.\n *\n * The default is the current working directory\n *\n * @see process.cwd for more information.\n */\n start?: string;\n\n /**\n * The directory to stop at.\n *\n * The default is the root of the file system.\n */\n stop?: string;\n\n /**\n * The type of mode that the path must support in order\n * to be approved.\n *\n * The default is undefined and left up to the node api.\n */\n mode?: number;\n}\n\n/**\n * Represents a service to enumerate the file system.\n */\nexport interface IZFileSystemService {\n /**\n * Gets information about a node.\n *\n * @param path -\n * The path to get information for.\n *\n * @returns\n * Information about the node.\n */\n info(path: string): Promise<IZFileSystemNode>;\n\n /**\n * Reads all nodes that match a pattern.\n *\n * @param pattern -\n * The pattern string to match against or a list\n * of patterns to match.\n * @param options -\n * The options for the search.\n *\n * @returns\n * A list of path strings that match the given patterns.\n */\n search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]>;\n\n /**\n * Walks up a directory tree to search for existence of a given path.\n *\n * @param search -\n * The path to search for. This is the candidate folder path that\n * may or may not exist somewhere from the start directory all the\n * way up the directory tree.\n * @param options -\n * The given options for the search.\n *\n * @returns\n * The fully qualified path to the first path that matches the search\n * starting at the options start or the current working directory if not\n * specified. Returns null if no such directory exists.\n *\n * @example\n *\n * ```ts\n * import { resolve } from 'path'\n *\n * // Find any folder named .vscode from the current working directory all the way\n * // up the directory tree. Returns null if no vscode directory can be found.\n * const service = new ZFileSystemService();\n * const vscode = service.walk('.vscode');\n *\n * // Walk the directory tree from the current script and find the .config folder.\n * const config = service.walk('.config', { start: __dirname });\n *\n * // Walk the directory tree from the current script and stop when we reach\n * // at most 2 directories up.\n * const start = __dirname;\n * const stop = resolve(__dirname, '../..');\n * const file = service.walk('path/to/file.json', { start, stop });\n * ```\n */\n walk(\n search: string,\n options?: IZFileSystemWalkOptions,\n ): Promise<string | null>;\n}\n\n/**\n * Represents a node implementation of a file system service.\n */\nexport class ZFileSystemService implements IZFileSystemService {\n public async info(path: string): Promise<IZFileSystemNode> {\n const [file] = await this.search(path);\n return file;\n }\n\n public async search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]> {\n const paths = await glob(pattern, {\n stat: true,\n ...options,\n withFileTypes: true,\n });\n\n return paths.map((path) => {\n let info = new ZFileSystemNodeBuilder()\n .path(path.fullpath())\n .created(path.birthtime)\n .updated(path.atime)\n .size(path.size);\n\n // Note that for folders, node will return the size of the underlying OS metadata,\n // hence, why we remove the size on the folder here.\n info = path.isFile() ? info.file() : info.folder().size(undefined);\n\n return info.build();\n });\n }\n\n public async walk(search: string, options?: IZFileSystemWalkOptions) {\n const start = options?.start || cwd();\n const stop = options?.stop || \"/\";\n const mode = options?.mode;\n\n const _test = async (path: string) => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n };\n\n if (isAbsolute(search)) {\n return (await _test(search)) ? search : null;\n }\n\n let dir = start;\n do {\n const path = resolve(dir, search);\n const exists = await _test(path);\n\n if (exists) {\n return path;\n }\n\n dir = dir === stop ? \"\" : dirname(dir);\n } while (dir.length);\n\n return null;\n }\n}\n","import type { FSWatcher } from \"chokidar\";\nimport { watch } from \"chokidar\";\nimport type { Stats } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Observable } from \"rxjs\";\nimport { Subject } from \"rxjs\";\nimport {\n ZFileSystemNodeBuilder,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\n\n/**\n * Represents and object that can watch a folder or file on the file system.\n */\nexport interface IZFileWatch {\n /**\n * Starts the watch operation.\n */\n start(): Promise<void>;\n\n /**\n * Stops the watch operation.\n */\n stop(): Promise<void>;\n\n /**\n * The stream for files being added.\n *\n * This can only occur if the target being watched\n * is a folder.\n *\n * @returns\n * The observable that will publish files that\n * get added.\n */\n add(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files being updated.\n *\n * If this watcher points to a folder, then all files\n * recursively will send when they get updated. If this\n * watcher points to a file, then this will only invoke\n * when the file is updated.\n *\n * @returns\n * The observable that will publish files and folders\n * that are updated.\n */\n update(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files and folders being deleted.\n *\n * If this watcher points to a folder, then all files under the\n * folder will be sent through this observable, including the\n * folder being watched. If this points to a file, then\n * this will only receive when the file is unlinked.\n *\n * @returns\n * The observable that will publish file and folders\n * that are unlinked and removed respectively. Note\n * that files and folders streamed this way will not\n * have their stats set.\n */\n remove(): Observable<IZFileSystemNode>;\n}\n\n/**\n * An implementation of the IZFileWatch.\n */\nexport class ZFileWatch implements IZFileWatch {\n private _add: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _update: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _remove: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _watcher: FSWatcher | undefined;\n\n /**\n * Initializes a new instance of this object.\n *\n * @param path -\n * The path to watch.\n */\n public constructor(public readonly path: string) {}\n\n public async start() {\n await this.stop();\n\n this._watcher = watch(this.path, {\n usePolling: true,\n alwaysStat: true,\n ignoreInitial: true,\n\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 50,\n },\n });\n\n function next(\n observable: Subject<IZFileSystemNode>,\n file: string,\n stats: Stats | undefined,\n ) {\n const node = new ZFileSystemNodeBuilder().path(resolve(this.path, file));\n observable.next(stats ? node.stats(stats).build() : node.build());\n }\n\n this._watcher\n .on(\"add\", next.bind(this, this._add))\n .on(\"addDir\", next.bind(this, this._add))\n .on(\"change\", next.bind(this, this._update))\n .on(\"unlink\", next.bind(this, this._remove))\n .on(\"unlinkDir\", next.bind(this, this._remove));\n\n return new Promise<void>((resolve) =>\n this._watcher?.on(\"ready\", () => resolve()),\n );\n }\n\n public async stop() {\n await this._watcher?.close();\n delete this._watcher;\n return Promise.resolve();\n }\n\n public add() {\n return this._add.asObservable();\n }\n\n public update() {\n return this._update.asObservable();\n }\n\n public remove() {\n return this._remove.asObservable();\n }\n}\n","import { firstDefined, sleep } from \"@zthun/helpful-fn\";\nimport type { IZDataRequest, IZDataSource } from \"@zthun/helpful-query\";\nimport { ZDataSourceStatic } from \"@zthun/helpful-query\";\nimport { find, findIndex, flatten, trimEnd, uniqBy } from \"lodash-es\";\nimport { minimatch } from \"minimatch\";\nimport { resolve, sep } from \"node:path\";\nimport type { Subscription } from \"rxjs\";\nimport {\n ZFileSystemNodeType,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\nimport {\n ZFileSystemService,\n type IZFileSystemService,\n} from \"../file-system/file-system-service.mjs\";\nimport { ZFileWatch, type IZFileWatch } from \"../file-watch/file-watch.mjs\";\n\n/**\n * Represents a repository for the file system.\n */\nexport interface IZFileRepository extends IZDataSource<IZFileSystemNode> {\n /**\n * Retrieves a single file from the repository.\n *\n * @param path -\n * The fully qualified path to the file.\n *\n * @returns\n * The node that represents the file. Returns null if no\n * such file exists.\n */\n get(path: string): Promise<IZFileSystemNode | null>;\n}\n\n/**\n * Represents an implementation of a ZFileRepository that watches\n * a given path scope.\n *\n * This repository is only concerned about files. Folders\n * will not be retrieved from this repository.\n */\nexport class ZFileRepository implements IZFileRepository {\n private _service: IZFileSystemService = new ZFileSystemService();\n private _watcher: IZFileWatch | undefined;\n private _nodes: Promise<ZDataSourceStatic<IZFileSystemNode>> =\n Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n private _globs: string[] = [\"**\"];\n private _path: string = \"\";\n private _add: Subscription | undefined;\n private _remove: Subscription | undefined;\n private _update: Subscription | undefined;\n\n /**\n * Gets the path that this repository is watching.\n */\n public get path() {\n return this._path;\n }\n\n /**\n * Gets the globs matchers that this repository is matching against.\n */\n public get globs() {\n return this._globs.slice();\n }\n\n /**\n * Initializes the repository with the given root and glob filter.\n *\n * This will initially scan the file system and setup watches.\n * If you call this method again, then the repository will be\n * {@link reset} and a new set of files will be added to the\n * repository.\n *\n * @param path -\n * The root path of the repository.\n * @param globs -\n * The optional relative globs of the repository. If this is falsy,\n * then ** is used. You can achieve the same kind of operation\n * using filters, but filtering out unwanted files frees up the internal\n * memory being used.\n */\n public async initialize(path: string, globs: string[] = [\"**\"]) {\n await this.reset();\n\n this._path = path;\n this._globs = globs;\n\n // Note that this all happens in the background and should\n // only be awaited later. So the search should not be\n // required to finish when existing this method. The only\n // requirement is that the repository is reset and the path +\n // glob scope is updated. Everything beyond here should not\n // be awaited - it will be awaited later once the caller\n // tries to retrieve the files using retrieve, get, or\n // count.\n const matches = globs.map((g) =>\n this._service.search(g, {\n cwd: path,\n stat: true,\n }),\n );\n\n this._nodes = Promise.all(matches)\n .then((nodes) => {\n const flat = flatten(nodes);\n const uniq = uniqBy(flat, (n) => n.path);\n return uniq.filter((n) => n.type === ZFileSystemNodeType.File);\n })\n .then((files) => {\n return new ZDataSourceStatic(files);\n });\n\n this._watcher = new ZFileWatch(path);\n\n this._add = this._watcher\n .add()\n .subscribe(async (node: IZFileSystemNode) => {\n if (\n node.type === ZFileSystemNodeType.File &&\n this._globs.some((g) => minimatch(node.path, resolve(this._path, g)))\n ) {\n const nodes = await this._nodes;\n this._nodes = nodes.insert(node);\n }\n });\n\n this._remove = this._watcher\n .remove()\n .subscribe(async (node: IZFileSystemNode) => {\n let nodes = await this._nodes;\n const path = trimEnd(node.path, sep);\n\n // It's possible that the node given was a folder. If that happens,\n // we need to remove all files that start with the given path.\n // If the node does point to a file, then there is no possibility that\n // more than 1 item would be removed.\n\n const next = async () =>\n findIndex(await nodes.items(), (n) => {\n return (\n n.path === path ||\n (n.path.startsWith(path) &&\n n.path.substring(path.length).charAt(0) === sep)\n );\n });\n\n for (let index = await next(); index >= 0; index = await next()) {\n nodes = await nodes.removeAt(index);\n }\n\n this._nodes = Promise.resolve(nodes);\n });\n\n this._update = this._watcher\n .update()\n .subscribe(async (node: IZFileSystemNode) => {\n const nodes = await this._nodes;\n const index = findIndex(\n await nodes.items(),\n (n) => n.path === node.path,\n );\n\n // It's possible node was filtered out by the globs, or\n // it is a directory. If so, then we won't have it in our\n // list.\n if (index >= 0) {\n const next = await nodes.removeAt(index);\n this._nodes = next.insert(node, index);\n }\n });\n\n // Kick off the initial seed operation with an even loop\n // invocation.\n await sleep(100);\n\n await this._watcher?.start();\n }\n\n /**\n * Resets the repository as if it was initially created.\n */\n public async reset(): Promise<void> {\n await this._watcher?.stop();\n\n this._add?.unsubscribe();\n this._remove?.unsubscribe();\n this._update?.unsubscribe();\n\n delete this._add;\n delete this._remove;\n delete this._update;\n delete this._watcher;\n\n this._path = \"\";\n this._globs = [\"**\"];\n this._nodes = Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n }\n\n public async get(path: string): Promise<IZFileSystemNode | null> {\n const nodes = await this._nodes;\n const items = await nodes.items();\n const node = find(items, (f) => f.path === path);\n\n return firstDefined(null, node);\n }\n\n public async count(request: IZDataRequest): Promise<number> {\n const source = await this._nodes;\n return source.count(request);\n }\n\n public async retrieve(request: IZDataRequest): Promise<IZFileSystemNode[]> {\n const source = await this._nodes;\n return source.retrieve(request);\n }\n}\n","import type { PathLike } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function resolvePathLike(path: PathLike): string {\n if (typeof path === \"string\") {\n return resolve(path);\n }\n\n if (path instanceof URL) {\n return fileURLToPath(path);\n }\n\n return resolve(path.toString());\n}\n","import { sleep } from \"@zthun/helpful-fn\";\n\n/**\n * The actual delay time that you should wait for a watch\n * operation to pick up your file changes.\n */\nexport const ZWatchDelay = 1500;\n\n/**\n * Performs a sleep long enough to allow a watch operation\n * to pick up a change.\n *\n * You should never really need this. Where it is useful\n * is for unit testing with IO operations and you want to\n * wait for your write operations to get picked up by\n * a file watch operation.\n */\nexport function sleepWatchDelay() {\n return sleep(ZWatchDelay);\n}\n","import type { PathLike } from \"fs\";\nimport { mkdir, stat } from \"fs/promises\";\nimport type { IZStreamWrite } from \"./stream-write.mjs\";\n\n/**\n * A stream that writes folders.\n *\n * Writing folders is idempotent. If the folder you\n * are trying to write already exists, then the write\n * operation still succeeds\n */\nexport class ZStreamFolder implements IZStreamWrite {\n public async write(path: PathLike): Promise<number> {\n try {\n await mkdir(path, { recursive: true });\n } catch {\n // The folder may exist, but if it is a file then\n // we have a conflict and in that case, we will throw an\n // error. We are going to let stat fail if it cannot\n // access the path (permission error).\n const stats = await stat(path);\n\n if (stats.isFile()) {\n const msg = `Cannot create folder, ${path}, because a file with the same name exists at the target location`;\n throw new Error(msg);\n }\n }\n\n return 0;\n }\n}\n","import type { PathLike, Stats } from \"node:fs\";\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"path\";\nimport { resolvePathLike } from \"../resolve-path-like/resolve-path-like.js\";\nimport { ZStreamFolder } from \"./stream-folder.mjs\";\nimport type { IZStreamRead, IZStreamReadOptions } from \"./stream-read.mjs\";\nimport type { IZStreamWrite, IZStreamWriteOptions } from \"./stream-write.mjs\";\n\n/**\n * Options for the stream file object.\n */\nexport interface IZStreamFileOptions {\n /**\n * Cache options.\n *\n * A warning that file content caching will take up significant memory\n * if the file size is too big or the max files is too big. Make sure\n * you know what you're doing when you change the default values of this.\n */\n cache?: {\n /**\n * Maximum number of bytes a file can be before it will not be cached.\n * The default is 100 Kib (102400 bytes)\n *\n * @default 102400\n */\n fileSize?: bigint;\n /**\n * The maximum number of files that are to be cached. The cache order\n * is first in, first out. Set this to 0 to not cache anything. The\n * default is 1000.\n *\n * @default 1000\n */\n maxFiles?: number;\n };\n}\n\n/**\n * A stream that can read and write to files.\n *\n * This is mostly a wrapper to readFile and writeFile from node, but\n * with some optimizations.\n *\n * First, this class supports file content caching so reading in a file\n * that's under a certain size threshold will store it in memory for\n * later retrieval.\n */\nexport class ZStreamFile implements IZStreamWrite, IZStreamRead {\n private static readonly FileSizeDefault = 102400; // One Hundred KibiBytes\n private static readonly MaxFilesDefault = 1000;\n\n private _cache = new Map<string, { stats: Stats; buffer: Promise<Buffer> }>();\n\n /**\n * Initializes a new instance of this object.\n *\n * @param options -\n * The options for file read and writes.\n */\n public constructor(public readonly options: IZStreamFileOptions = {}) {}\n\n public async read(\n path: PathLike,\n options?: IZStreamReadOptions,\n ): Promise<Buffer> {\n const _path = resolvePathLike(path);\n\n const stats = await stat(_path);\n const cached = this._cache.get(_path);\n\n const buffer =\n cached && cached.stats.mtimeMs >= stats.mtimeMs\n ? cached.buffer\n : readFile(_path, options);\n\n return this._addToCache(_path, { stats, buffer });\n }\n\n public async write(\n path: PathLike,\n { buffer = Buffer.from(\"\") }: IZStreamWriteOptions = {},\n ): Promise<number> {\n const _path = resolvePathLike(path);\n const directory = dirname(_path);\n\n await new ZStreamFolder().write(directory);\n await writeFile(_path, buffer, { flush: true });\n\n // If this file specifically was cached earlier,\n // we can just remove it now so we make room for\n // another file. Consumers can just read the\n // file again to recache it.\n this._cache.delete(_path);\n\n return buffer.length;\n }\n\n private _addToCache(\n path: string,\n item: { stats: Stats; buffer: Promise<Buffer> },\n ) {\n const { cache = {} } = this.options;\n const {\n fileSize = ZStreamFile.FileSizeDefault,\n maxFiles = ZStreamFile.MaxFilesDefault,\n } = cache;\n\n if (item.stats.size > fileSize) {\n // In this case, the file size is too big to cache in memory,\n // so we're bowing out here.\n return item.buffer;\n }\n\n // We will remove this path from the cache first since\n // we want it to be the most recent file (at the end)\n // of the key list. The removal does nothing if the\n // file was not cached.\n this._cache.delete(path);\n this._cache.set(path, item);\n\n if (this._cache.size > maxFiles) {\n // Retrieving the keys from a javascript map is order\n // by the time in which the keys are created. So\n // we are going to remove the first key which is the\n // oldest.\n const itr = this._cache.keys();\n this._cache.delete(itr.next().value);\n }\n\n return item.buffer;\n }\n}\n"],"names":["ZFileSystemNodeType","ZFileSystemNodeBuilder","_node","path","type","created","at","Date","toJSON","updated","size","bytes","BigInt","file","bind","folder","stats","s","builder","birthtime","mtime","isFile","build","clone","structuredClone","omitBy","isUndefined","ZFileSystemService","info","search","pattern","options","paths","glob","stat","withFileTypes","map","fullpath","atime","undefined","walk","start","cwd","stop","mode","_test","access","isAbsolute","dir","resolve","exists","dirname","length","ZFileWatch","_add","Subject","_update","_remove","_watcher","watch","usePolling","alwaysStat","ignoreInitial","awaitWriteFinish","stabilityThreshold","pollInterval","next","observable","node","on","Promise","close","add","asObservable","update","remove","ZFileRepository","_service","_nodes","ZDataSourceStatic","_globs","_path","globs","slice","initialize","reset","matches","g","all","then","nodes","flat","flatten","uniq","uniqBy","n","filter","File","files","subscribe","some","minimatch","insert","trimEnd","sep","findIndex","items","startsWith","substring","charAt","index","removeAt","sleep","unsubscribe","get","find","f","firstDefined","count","request","source","retrieve","resolvePathLike","URL","fileURLToPath","toString","ZWatchDelay","sleepWatchDelay","ZStreamFolder","write","mkdir","recursive","msg","Error","ZStreamFile","FileSizeDefault","MaxFilesDefault","_cache","Map","read","cached","buffer","mtimeMs","readFile","_addToCache","Buffer","from","directory","writeFile","flush","delete","item","cache","fileSize","maxFiles","set","itr","keys","value"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/file-system/file-system-node.mts","../src/file-system/file-system-service.mts","../src/file-watch/file-watch.mts","../src/file-repository/file-repository.mts","../src/resolve-path-like/resolve-path-like.ts","../src/sleep-watch-delay/sleep-watch-delay.mts","../src/stream/stream-folder.mts","../src/stream/stream-file.mts"],"sourcesContent":["import { type ZMutable } from \"@zthun/helpful-fn\";\nimport { isUndefined, omitBy } from \"lodash-es\";\nimport type { Stats } from \"node:fs\";\nimport { basename, dirname, extname } from \"node:path\";\n\n/**\n * Represents a type of a file system node.\n */\nexport enum ZFileSystemNodeType {\n File = \"file\",\n Folder = \"folder\",\n}\n\nexport interface IZFileSystemNode {\n /**\n * The absolute path of the node.\n */\n path: string;\n\n /**\n * The type of the node (file or folder).\n */\n type: ZFileSystemNodeType;\n\n /**\n * The creation date of the node.\n */\n created?: string;\n\n /**\n * The modification date of the node.\n */\n updated?: string;\n\n /**\n * The size of the node in bytes.\n */\n size?: bigint;\n\n /**\n * The file or folder name with the extension.\n *\n * Calculated from the path.\n */\n readonly name: string;\n\n /**\n * The file extension.\n *\n * Calculated from the path.\n */\n readonly extension: string;\n\n /**\n * File title.\n *\n * The name without the extension.\n * Calculated from the path.\n */\n readonly title: string;\n\n /**\n * Parent directory path.\n */\n readonly parent: string;\n}\n\n/**\n * Represents a builder for a file system node.\n */\nexport class ZFileSystemNodeBuilder {\n private _node: ZMutable<IZFileSystemNode> = {\n path: \"/\",\n type: ZFileSystemNodeType.Folder,\n extension: \"\",\n name: \"\",\n parent: \"\",\n title: \"\",\n };\n\n public created(at?: Date | string | undefined) {\n this._node.created = at instanceof Date ? at.toJSON() : at;\n\n return this;\n }\n\n public updated(at?: Date | string | undefined) {\n this._node.updated = at instanceof Date ? at.toJSON() : at;\n\n return this;\n }\n\n public size(bytes: bigint | number | undefined) {\n this._node.size = typeof bytes == \"number\" ? BigInt(bytes) : bytes;\n\n return this;\n }\n\n public path(path: string) {\n this._node.path = path;\n\n return this.decorate();\n }\n\n public type(type: ZFileSystemNodeType) {\n this._node.type = type;\n\n return this.decorate();\n }\n\n public file = this.type.bind(this, ZFileSystemNodeType.File);\n public folder = this.type.bind(this, ZFileSystemNodeType.Folder);\n\n public stats(s: Stats) {\n const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);\n\n return s.isFile() ? builder.file() : builder.folder();\n }\n\n public build() {\n const clone = structuredClone(this._node);\n\n return omitBy(clone, isUndefined) as IZFileSystemNode;\n }\n\n private decorate() {\n const { path, type } = this._node;\n\n this._node.name = basename(path);\n this._node.extension = \"\";\n this._node.title = this._node.name;\n this._node.parent = dirname(path);\n\n if (type === ZFileSystemNodeType.File) {\n const extension = extname(path);\n this._node.extension = extension;\n this._node.title = basename(path, extension);\n }\n\n if (!path || path === \"/\" || this._node.parent === \".\") {\n this._node.parent = \"\";\n }\n\n return this;\n }\n}\n","import { glob } from \"glob\";\nimport { access } from \"node:fs/promises\";\nimport { dirname, isAbsolute, resolve } from \"node:path\";\nimport { cwd } from \"node:process\";\nimport type { IZFileSystemNode } from \"./file-system-node.mjs\";\nimport { ZFileSystemNodeBuilder } from \"./file-system-node.mjs\";\n\n/**\n * Represents options for searches.\n */\nexport interface IZFileSystemSearchOptions {\n /**\n * The directory to search in.\n *\n * If this is not set, then the cwd of the application is used.\n */\n cwd?: string;\n\n /**\n * A flag that determines whether or not to load the\n * file system information.\n *\n * This is true by default.\n */\n stat?: boolean;\n}\n\n/**\n * Represents options for directory walking.\n */\nexport interface IZFileSystemWalkOptions {\n /**\n * The starting directory.\n *\n * The default is the current working directory\n *\n * @see process.cwd for more information.\n */\n start?: string;\n\n /**\n * The directory to stop at.\n *\n * The default is the root of the file system.\n */\n stop?: string;\n\n /**\n * The type of mode that the path must support in order\n * to be approved.\n *\n * The default is undefined and left up to the node api.\n */\n mode?: number;\n}\n\n/**\n * Represents a service to enumerate the file system.\n */\nexport interface IZFileSystemService {\n /**\n * Gets information about a node.\n *\n * @param path -\n * The path to get information for.\n *\n * @returns\n * Information about the node.\n */\n info(path: string): Promise<IZFileSystemNode>;\n\n /**\n * Reads all nodes that match a pattern.\n *\n * @param pattern -\n * The pattern string to match against or a list\n * of patterns to match.\n * @param options -\n * The options for the search.\n *\n * @returns\n * A list of path strings that match the given patterns.\n */\n search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]>;\n\n /**\n * Walks up a directory tree to search for existence of a given path.\n *\n * @param search -\n * The path to search for. This is the candidate folder path that\n * may or may not exist somewhere from the start directory all the\n * way up the directory tree.\n * @param options -\n * The given options for the search.\n *\n * @returns\n * The fully qualified path to the first path that matches the search\n * starting at the options start or the current working directory if not\n * specified. Returns null if no such directory exists.\n *\n * @example\n *\n * ```ts\n * import { resolve } from 'path'\n *\n * // Find any folder named .vscode from the current working directory all the way\n * // up the directory tree. Returns null if no vscode directory can be found.\n * const service = new ZFileSystemService();\n * const vscode = service.walk('.vscode');\n *\n * // Walk the directory tree from the current script and find the .config folder.\n * const config = service.walk('.config', { start: __dirname });\n *\n * // Walk the directory tree from the current script and stop when we reach\n * // at most 2 directories up.\n * const start = __dirname;\n * const stop = resolve(__dirname, '../..');\n * const file = service.walk('path/to/file.json', { start, stop });\n * ```\n */\n walk(\n search: string,\n options?: IZFileSystemWalkOptions,\n ): Promise<string | null>;\n}\n\n/**\n * Represents a node implementation of a file system service.\n */\nexport class ZFileSystemService implements IZFileSystemService {\n public async info(path: string): Promise<IZFileSystemNode> {\n const [file] = await this.search(path);\n return file;\n }\n\n public async search(\n pattern: string | string[],\n options?: IZFileSystemSearchOptions,\n ): Promise<IZFileSystemNode[]> {\n const paths = await glob(pattern, {\n stat: true,\n ...options,\n withFileTypes: true,\n });\n\n return paths.map((path) => {\n let info = new ZFileSystemNodeBuilder()\n .path(path.fullpath())\n .created(path.birthtime)\n .updated(path.atime)\n .size(path.size);\n\n // Note that for folders, node will return the size of the underlying OS metadata,\n // hence, why we remove the size on the folder here.\n info = path.isFile() ? info.file() : info.folder().size(undefined);\n\n return info.build();\n });\n }\n\n public async walk(search: string, options?: IZFileSystemWalkOptions) {\n const start = options?.start || cwd();\n const stop = options?.stop || \"/\";\n const mode = options?.mode;\n\n const _test = async (path: string) => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n };\n\n if (isAbsolute(search)) {\n return (await _test(search)) ? search : null;\n }\n\n let dir = start;\n do {\n const path = resolve(dir, search);\n const exists = await _test(path);\n\n if (exists) {\n return path;\n }\n\n dir = dir === stop ? \"\" : dirname(dir);\n } while (dir.length);\n\n return null;\n }\n}\n","import type { FSWatcher } from \"chokidar\";\nimport { watch } from \"chokidar\";\nimport type { Stats } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { Observable } from \"rxjs\";\nimport { Subject } from \"rxjs\";\nimport {\n ZFileSystemNodeBuilder,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\n\n/**\n * Represents and object that can watch a folder or file on the file system.\n */\nexport interface IZFileWatch {\n /**\n * Starts the watch operation.\n */\n start(): Promise<void>;\n\n /**\n * Stops the watch operation.\n */\n stop(): Promise<void>;\n\n /**\n * The stream for files being added.\n *\n * This can only occur if the target being watched\n * is a folder.\n *\n * @returns\n * The observable that will publish files that\n * get added.\n */\n add(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files being updated.\n *\n * If this watcher points to a folder, then all files\n * recursively will send when they get updated. If this\n * watcher points to a file, then this will only invoke\n * when the file is updated.\n *\n * @returns\n * The observable that will publish files and folders\n * that are updated.\n */\n update(): Observable<IZFileSystemNode>;\n\n /**\n * The stream for files and folders being deleted.\n *\n * If this watcher points to a folder, then all files under the\n * folder will be sent through this observable, including the\n * folder being watched. If this points to a file, then\n * this will only receive when the file is unlinked.\n *\n * @returns\n * The observable that will publish file and folders\n * that are unlinked and removed respectively. Note\n * that files and folders streamed this way will not\n * have their stats set.\n */\n remove(): Observable<IZFileSystemNode>;\n}\n\n/**\n * An implementation of the IZFileWatch.\n */\nexport class ZFileWatch implements IZFileWatch {\n private _add: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _update: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _remove: Subject<IZFileSystemNode> = new Subject<IZFileSystemNode>();\n private _watcher: FSWatcher | undefined;\n\n /**\n * Initializes a new instance of this object.\n *\n * @param path -\n * The path to watch.\n */\n public constructor(public readonly path: string) {}\n\n public async start() {\n await this.stop();\n\n this._watcher = watch(this.path, {\n usePolling: true,\n alwaysStat: true,\n ignoreInitial: true,\n\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 50,\n },\n });\n\n function next(\n observable: Subject<IZFileSystemNode>,\n file: string,\n stats: Stats | undefined,\n ) {\n const node = new ZFileSystemNodeBuilder().path(resolve(this.path, file));\n observable.next(stats ? node.stats(stats).build() : node.build());\n }\n\n this._watcher\n .on(\"add\", next.bind(this, this._add))\n .on(\"addDir\", next.bind(this, this._add))\n .on(\"change\", next.bind(this, this._update))\n .on(\"unlink\", next.bind(this, this._remove))\n .on(\"unlinkDir\", next.bind(this, this._remove));\n\n return new Promise<void>((resolve) =>\n this._watcher?.on(\"ready\", () => resolve()),\n );\n }\n\n public async stop() {\n await this._watcher?.close();\n delete this._watcher;\n return Promise.resolve();\n }\n\n public add() {\n return this._add.asObservable();\n }\n\n public update() {\n return this._update.asObservable();\n }\n\n public remove() {\n return this._remove.asObservable();\n }\n}\n","import { firstDefined, sleep } from \"@zthun/helpful-fn\";\nimport type { IZDataRequest, IZDataSource } from \"@zthun/helpful-query\";\nimport { ZDataSourceStatic } from \"@zthun/helpful-query\";\nimport { find, findIndex, flatten, trimEnd, uniqBy } from \"lodash-es\";\nimport { minimatch } from \"minimatch\";\nimport { resolve, sep } from \"node:path\";\nimport type { Subscription } from \"rxjs\";\nimport {\n ZFileSystemNodeType,\n type IZFileSystemNode,\n} from \"../file-system/file-system-node.mjs\";\nimport {\n ZFileSystemService,\n type IZFileSystemService,\n} from \"../file-system/file-system-service.mjs\";\nimport { ZFileWatch, type IZFileWatch } from \"../file-watch/file-watch.mjs\";\n\n/**\n * Represents a repository for the file system.\n */\nexport interface IZFileRepository extends IZDataSource<IZFileSystemNode> {\n /**\n * Retrieves a single file from the repository.\n *\n * @param path -\n * The fully qualified path to the file.\n *\n * @returns\n * The node that represents the file. Returns null if no\n * such file exists.\n */\n get(path: string): Promise<IZFileSystemNode | null>;\n}\n\n/**\n * Represents an implementation of a ZFileRepository that watches\n * a given path scope.\n *\n * This repository is only concerned about files. Folders\n * will not be retrieved from this repository.\n */\nexport class ZFileRepository implements IZFileRepository {\n private _service: IZFileSystemService = new ZFileSystemService();\n private _watcher: IZFileWatch | undefined;\n private _nodes: Promise<ZDataSourceStatic<IZFileSystemNode>> =\n Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n private _globs: string[] = [\"**\"];\n private _path: string = \"\";\n private _add: Subscription | undefined;\n private _remove: Subscription | undefined;\n private _update: Subscription | undefined;\n\n /**\n * Gets the path that this repository is watching.\n */\n public get path() {\n return this._path;\n }\n\n /**\n * Gets the globs matchers that this repository is matching against.\n */\n public get globs() {\n return this._globs.slice();\n }\n\n /**\n * Initializes the repository with the given root and glob filter.\n *\n * This will initially scan the file system and setup watches.\n * If you call this method again, then the repository will be\n * {@link reset} and a new set of files will be added to the\n * repository.\n *\n * @param path -\n * The root path of the repository.\n * @param globs -\n * The optional relative globs of the repository. If this is falsy,\n * then ** is used. You can achieve the same kind of operation\n * using filters, but filtering out unwanted files frees up the internal\n * memory being used.\n */\n public async initialize(path: string, globs: string[] = [\"**\"]) {\n await this.reset();\n\n this._path = path;\n this._globs = globs;\n\n // Note that this all happens in the background and should\n // only be awaited later. So the search should not be\n // required to finish when existing this method. The only\n // requirement is that the repository is reset and the path +\n // glob scope is updated. Everything beyond here should not\n // be awaited - it will be awaited later once the caller\n // tries to retrieve the files using retrieve, get, or\n // count.\n const matches = globs.map((g) =>\n this._service.search(g, {\n cwd: path,\n stat: true,\n }),\n );\n\n this._nodes = Promise.all(matches)\n .then((nodes) => {\n const flat = flatten(nodes);\n const uniq = uniqBy(flat, (n) => n.path);\n return uniq.filter((n) => n.type === ZFileSystemNodeType.File);\n })\n .then((files) => {\n return new ZDataSourceStatic(files);\n });\n\n this._watcher = new ZFileWatch(path);\n\n this._add = this._watcher\n .add()\n .subscribe(async (node: IZFileSystemNode) => {\n if (\n node.type === ZFileSystemNodeType.File &&\n this._globs.some((g) => minimatch(node.path, resolve(this._path, g)))\n ) {\n const nodes = await this._nodes;\n this._nodes = nodes.insert(node);\n }\n });\n\n this._remove = this._watcher\n .remove()\n .subscribe(async (node: IZFileSystemNode) => {\n let nodes = await this._nodes;\n const path = trimEnd(node.path, sep);\n\n // It's possible that the node given was a folder. If that happens,\n // we need to remove all files that start with the given path.\n // If the node does point to a file, then there is no possibility that\n // more than 1 item would be removed.\n\n const next = async () =>\n findIndex(await nodes.items(), (n) => {\n return (\n n.path === path ||\n (n.path.startsWith(path) &&\n n.path.substring(path.length).charAt(0) === sep)\n );\n });\n\n for (let index = await next(); index >= 0; index = await next()) {\n nodes = await nodes.removeAt(index);\n }\n\n this._nodes = Promise.resolve(nodes);\n });\n\n this._update = this._watcher\n .update()\n .subscribe(async (node: IZFileSystemNode) => {\n const nodes = await this._nodes;\n const index = findIndex(\n await nodes.items(),\n (n) => n.path === node.path,\n );\n\n // It's possible node was filtered out by the globs, or\n // it is a directory. If so, then we won't have it in our\n // list.\n if (index >= 0) {\n const next = await nodes.removeAt(index);\n this._nodes = next.insert(node, index);\n }\n });\n\n // Kick off the initial seed operation with an even loop\n // invocation.\n await sleep(100);\n\n await this._watcher?.start();\n }\n\n /**\n * Resets the repository as if it was initially created.\n */\n public async reset(): Promise<void> {\n await this._watcher?.stop();\n\n this._add?.unsubscribe();\n this._remove?.unsubscribe();\n this._update?.unsubscribe();\n\n delete this._add;\n delete this._remove;\n delete this._update;\n delete this._watcher;\n\n this._path = \"\";\n this._globs = [\"**\"];\n this._nodes = Promise.resolve(new ZDataSourceStatic<IZFileSystemNode>([]));\n }\n\n public async get(path: string): Promise<IZFileSystemNode | null> {\n const nodes = await this._nodes;\n const items = await nodes.items();\n const node = find(items, (f) => f.path === path);\n\n return firstDefined(null, node);\n }\n\n public async count(request: IZDataRequest): Promise<number> {\n const source = await this._nodes;\n return source.count(request);\n }\n\n public async retrieve(request: IZDataRequest): Promise<IZFileSystemNode[]> {\n const source = await this._nodes;\n return source.retrieve(request);\n }\n}\n","import type { PathLike } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function resolvePathLike(path: PathLike): string {\n if (typeof path === \"string\") {\n return resolve(path);\n }\n\n if (path instanceof URL) {\n return fileURLToPath(path);\n }\n\n return resolve(path.toString());\n}\n","import { sleep } from \"@zthun/helpful-fn\";\n\n/**\n * The actual delay time that you should wait for a watch\n * operation to pick up your file changes.\n */\nexport const ZWatchDelay = 1500;\n\n/**\n * Performs a sleep long enough to allow a watch operation\n * to pick up a change.\n *\n * You should never really need this. Where it is useful\n * is for unit testing with IO operations and you want to\n * wait for your write operations to get picked up by\n * a file watch operation.\n */\nexport function sleepWatchDelay() {\n return sleep(ZWatchDelay);\n}\n","import type { PathLike } from \"fs\";\nimport { mkdir } from \"fs/promises\";\nimport type { IZStreamWrite } from \"./stream-write.mjs\";\n\n/**\n * A stream that writes folders.\n *\n * Writing folders is idempotent. If the folder you\n * are trying to write already exists, then the write\n * operation still succeeds\n */\nexport class ZStreamFolder implements IZStreamWrite {\n public async write(path: PathLike): Promise<number> {\n await mkdir(path, { recursive: true });\n\n return 0;\n }\n}\n","import type { PathLike, Stats } from \"node:fs\";\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"path\";\nimport { resolvePathLike } from \"../resolve-path-like/resolve-path-like.js\";\nimport { ZStreamFolder } from \"./stream-folder.mjs\";\nimport type { IZStreamRead, IZStreamReadOptions } from \"./stream-read.mjs\";\nimport type { IZStreamWrite, IZStreamWriteOptions } from \"./stream-write.mjs\";\n\n/**\n * Options for the stream file object.\n */\nexport interface IZStreamFileOptions {\n /**\n * Cache options.\n *\n * A warning that file content caching will take up significant memory\n * if the file size is too big or the max files is too big. Make sure\n * you know what you're doing when you change the default values of this.\n */\n cache?: {\n /**\n * Maximum number of bytes a file can be before it will not be cached.\n * The default is 100 Kib (102400 bytes)\n *\n * @default 102400\n */\n fileSize?: bigint;\n /**\n * The maximum number of files that are to be cached. The cache order\n * is first in, first out. Set this to 0 to not cache anything. The\n * default is 1000.\n *\n * @default 1000\n */\n maxFiles?: number;\n };\n}\n\n/**\n * A stream that can read and write to files.\n *\n * This is mostly a wrapper to readFile and writeFile from node, but\n * with some optimizations.\n *\n * First, this class supports file content caching so reading in a file\n * that's under a certain size threshold will store it in memory for\n * later retrieval.\n */\nexport class ZStreamFile implements IZStreamWrite, IZStreamRead {\n private static readonly FileSizeDefault = 102400; // One Hundred KibiBytes\n private static readonly MaxFilesDefault = 1000;\n\n private _cache = new Map<string, { stats: Stats; buffer: Promise<Buffer> }>();\n\n /**\n * Initializes a new instance of this object.\n *\n * @param options -\n * The options for file read and writes.\n */\n public constructor(public readonly options: IZStreamFileOptions = {}) {}\n\n public async read(\n path: PathLike,\n options?: IZStreamReadOptions,\n ): Promise<Buffer> {\n const _path = resolvePathLike(path);\n\n const stats = await stat(_path);\n const cached = this._cache.get(_path);\n\n const buffer =\n cached && cached.stats.mtimeMs >= stats.mtimeMs\n ? cached.buffer\n : readFile(_path, options);\n\n return this._addToCache(_path, { stats, buffer });\n }\n\n public async write(\n path: PathLike,\n { buffer = Buffer.from(\"\") }: IZStreamWriteOptions = {},\n ): Promise<number> {\n const _path = resolvePathLike(path);\n const directory = dirname(_path);\n\n await new ZStreamFolder().write(directory);\n await writeFile(_path, buffer, { flush: true });\n\n // If this file specifically was cached earlier,\n // we can just remove it now so we make room for\n // another file. Consumers can just read the\n // file again to recache it.\n this._cache.delete(_path);\n\n return buffer.length;\n }\n\n private _addToCache(\n path: string,\n item: { stats: Stats; buffer: Promise<Buffer> },\n ) {\n const { cache = {} } = this.options;\n const {\n fileSize = ZStreamFile.FileSizeDefault,\n maxFiles = ZStreamFile.MaxFilesDefault,\n } = cache;\n\n if (item.stats.size > fileSize) {\n // In this case, the file size is too big to cache in memory,\n // so we're bowing out here.\n return item.buffer;\n }\n\n // We will remove this path from the cache first since\n // we want it to be the most recent file (at the end)\n // of the key list. The removal does nothing if the\n // file was not cached.\n this._cache.delete(path);\n this._cache.set(path, item);\n\n if (this._cache.size > maxFiles) {\n // Retrieving the keys from a javascript map is order\n // by the time in which the keys are created. So\n // we are going to remove the first key which is the\n // oldest.\n const itr = this._cache.keys();\n this._cache.delete(itr.next().value);\n }\n\n return item.buffer;\n }\n}\n"],"names":["ZFileSystemNodeType","ZFileSystemNodeBuilder","created","at","_node","Date","toJSON","updated","size","bytes","BigInt","path","decorate","type","stats","s","builder","birthtime","mtime","isFile","file","folder","build","clone","structuredClone","omitBy","isUndefined","name","basename","extension","title","parent","dirname","extname","_define_property","bind","ZFileSystemService","info","search","pattern","options","paths","glob","stat","withFileTypes","map","fullpath","atime","undefined","walk","start","cwd","stop","mode","_test","access","isAbsolute","dir","resolve","exists","length","ZFileWatch","_watcher","watch","usePolling","alwaysStat","ignoreInitial","awaitWriteFinish","stabilityThreshold","pollInterval","next","observable","node","on","_add","_update","_remove","Promise","close","add","asObservable","update","remove","Subject","ZFileRepository","_path","globs","_globs","slice","initialize","reset","matches","g","_service","_nodes","all","then","nodes","flat","flatten","uniq","uniqBy","n","filter","File","files","ZDataSourceStatic","subscribe","some","minimatch","insert","trimEnd","sep","findIndex","items","startsWith","substring","charAt","index","removeAt","sleep","unsubscribe","get","find","f","firstDefined","count","request","source","retrieve","resolvePathLike","URL","fileURLToPath","toString","ZWatchDelay","sleepWatchDelay","ZStreamFolder","write","mkdir","recursive","ZStreamFile","read","cached","_cache","buffer","mtimeMs","readFile","_addToCache","Buffer","from","directory","writeFile","flush","delete","item","cache","fileSize","FileSizeDefault","maxFiles","MaxFilesDefault","set","itr","keys","value","Map"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA;;IAGO,IAAKA,mBAAAA,iBAAAA,SAAAA,mBAAAA,EAAAA;;;AAAAA,IAAAA,OAAAA,mBAAAA;AAGX,CAAA,CAAA,EAAA;AAwDD;;AAEC,IACM,MAAMC,sBAAAA,CAAAA;AAUJC,IAAAA,OAAAA,CAAQC,EAA8B,EAAE;QAC7C,IAAI,CAACC,KAAK,CAACF,OAAO,GAAGC,EAAAA,YAAcE,IAAAA,GAAOF,EAAAA,CAAGG,MAAM,EAAA,GAAKH,EAAAA;AAExD,QAAA,OAAO,IAAI;AACb,IAAA;AAEOI,IAAAA,OAAAA,CAAQJ,EAA8B,EAAE;QAC7C,IAAI,CAACC,KAAK,CAACG,OAAO,GAAGJ,EAAAA,YAAcE,IAAAA,GAAOF,EAAAA,CAAGG,MAAM,EAAA,GAAKH,EAAAA;AAExD,QAAA,OAAO,IAAI;AACb,IAAA;AAEOK,IAAAA,IAAAA,CAAKC,KAAkC,EAAE;QAC9C,IAAI,CAACL,KAAK,CAACI,IAAI,GAAG,OAAOC,KAAAA,IAAS,QAAA,GAAWC,MAAAA,CAAOD,KAAAA,CAAAA,GAASA,KAAAA;AAE7D,QAAA,OAAO,IAAI;AACb,IAAA;AAEOE,IAAAA,IAAAA,CAAKA,IAAY,EAAE;AACxB,QAAA,IAAI,CAACP,KAAK,CAACO,IAAI,GAAGA,IAAAA;QAElB,OAAO,IAAI,CAACC,QAAQ,EAAA;AACtB,IAAA;AAEOC,IAAAA,IAAAA,CAAKA,IAAyB,EAAE;AACrC,QAAA,IAAI,CAACT,KAAK,CAACS,IAAI,GAAGA,IAAAA;QAElB,OAAO,IAAI,CAACD,QAAQ,EAAA;AACtB,IAAA;AAKOE,IAAAA,KAAAA,CAAMC,CAAQ,EAAE;AACrB,QAAA,MAAMC,UAAU,IAAI,CAACR,IAAI,CAACO,EAAEP,IAAI,CAAA,CAAEN,OAAO,CAACa,EAAEE,SAAS,CAAA,CAAEV,OAAO,CAACQ,EAAEG,KAAK,CAAA;AAEtE,QAAA,OAAOH,EAAEI,MAAM,EAAA,GAAKH,QAAQI,IAAI,EAAA,GAAKJ,QAAQK,MAAM,EAAA;AACrD,IAAA;IAEOC,KAAAA,GAAQ;AACb,QAAA,MAAMC,KAAAA,GAAQC,eAAAA,CAAgB,IAAI,CAACpB,KAAK,CAAA;AAExC,QAAA,OAAOqB,OAAOF,KAAAA,EAAOG,WAAAA,CAAAA;AACvB,IAAA;IAEQd,QAAAA,GAAW;QACjB,MAAM,EAAED,IAAI,EAAEE,IAAI,EAAE,GAAG,IAAI,CAACT,KAAK;AAEjC,QAAA,IAAI,CAACA,KAAK,CAACuB,IAAI,GAAGC,QAAAA,CAASjB,IAAAA,CAAAA;AAC3B,QAAA,IAAI,CAACP,KAAK,CAACyB,SAAS,GAAG,EAAA;QACvB,IAAI,CAACzB,KAAK,CAAC0B,KAAK,GAAG,IAAI,CAAC1B,KAAK,CAACuB,IAAI;AAClC,QAAA,IAAI,CAACvB,KAAK,CAAC2B,MAAM,GAAGC,OAAAA,CAAQrB,IAAAA,CAAAA;AAE5B,QAAA,IAAIE,IAAAA,KAAAA,MAAAA,EAAmC;AACrC,YAAA,MAAMgB,YAAYI,OAAAA,CAAQtB,IAAAA,CAAAA;AAC1B,YAAA,IAAI,CAACP,KAAK,CAACyB,SAAS,GAAGA,SAAAA;AACvB,YAAA,IAAI,CAACzB,KAAK,CAAC0B,KAAK,GAAGF,SAASjB,IAAAA,EAAMkB,SAAAA,CAAAA;AACpC,QAAA;QAEA,IAAI,CAAClB,IAAAA,IAAQA,IAAAA,KAAS,GAAA,IAAO,IAAI,CAACP,KAAK,CAAC2B,MAAM,KAAK,GAAA,EAAK;AACtD,YAAA,IAAI,CAAC3B,KAAK,CAAC2B,MAAM,GAAG,EAAA;AACtB,QAAA;AAEA,QAAA,OAAO,IAAI;AACb,IAAA;;AAzEA,QAAAG,kBAAA,CAAA,IAAA,EAAQ9B,OAAAA,EAAoC;YAC1CO,IAAAA,EAAM,GAAA;YACNE,IAAI,EAAA,QAAA;YACJgB,SAAAA,EAAW,EAAA;YACXF,IAAAA,EAAM,EAAA;YACNI,MAAAA,EAAQ,EAAA;YACRD,KAAAA,EAAO;AACT,SAAA,CAAA;AAgCA,QAAAI,kBAAA,CAAA,IAAA,EAAOd,QAAO,IAAI,CAACP,IAAI,CAACsB,IAAI,CAAC,IAAI,EAAA,MAAA,CAAA,CAAA;AACjC,QAAAD,kBAAA,CAAA,IAAA,EAAOb,UAAS,IAAI,CAACR,IAAI,CAACsB,IAAI,CAAC,IAAI,EAAA,QAAA,CAAA,CAAA;;AAkCrC;;AChBA;;AAEC,IACM,MAAMC,kBAAAA,CAAAA;IACX,MAAaC,IAAAA,CAAK1B,IAAY,EAA6B;AACzD,QAAA,MAAM,CAACS,IAAAA,CAAK,GAAG,MAAM,IAAI,CAACkB,MAAM,CAAC3B,IAAAA,CAAAA;QACjC,OAAOS,IAAAA;AACT,IAAA;AAEA,IAAA,MAAakB,MAAAA,CACXC,OAA0B,EAC1BC,OAAmC,EACN;QAC7B,MAAMC,KAAAA,GAAQ,MAAMC,IAAAA,CAAKH,OAAAA,EAAS;YAChCI,IAAAA,EAAM,IAAA;AACN,YAAA,GAAGH,OAAO;YACVI,aAAAA,EAAe;AACjB,SAAA,CAAA;QAEA,OAAOH,KAAAA,CAAMI,GAAG,CAAC,CAAClC,IAAAA,GAAAA;YAChB,IAAI0B,IAAAA,GAAO,IAAIpC,sBAAAA,EAAAA,CACZU,IAAI,CAACA,IAAAA,CAAKmC,QAAQ,IAClB5C,OAAO,CAACS,KAAKM,SAAS,CAAA,CACtBV,OAAO,CAACI,IAAAA,CAAKoC,KAAK,CAAA,CAClBvC,IAAI,CAACG,IAAAA,CAAKH,IAAI,CAAA;;;YAIjB6B,IAAAA,GAAO1B,IAAAA,CAAKQ,MAAM,EAAA,GAAKkB,IAAAA,CAAKjB,IAAI,KAAKiB,IAAAA,CAAKhB,MAAM,EAAA,CAAGb,IAAI,CAACwC,SAAAA,CAAAA;AAExD,YAAA,OAAOX,KAAKf,KAAK,EAAA;AACnB,QAAA,CAAA,CAAA;AACF,IAAA;AAEA,IAAA,MAAa2B,IAAAA,CAAKX,MAAc,EAAEE,OAAiC,EAAE;QACnE,MAAMU,KAAAA,GAAQV,SAASU,KAAAA,IAASC,GAAAA,EAAAA;QAChC,MAAMC,IAAAA,GAAOZ,SAASY,IAAAA,IAAQ,GAAA;AAC9B,QAAA,MAAMC,OAAOb,OAAAA,EAASa,IAAAA;AAEtB,QAAA,MAAMC,QAAQ,OAAO3C,IAAAA,GAAAA;YACnB,IAAI;AACF,gBAAA,MAAM4C,OAAO5C,IAAAA,EAAM0C,IAAAA,CAAAA;gBACnB,OAAO,IAAA;AACT,YAAA,CAAA,CAAE,OAAM;gBACN,OAAO,KAAA;AACT,YAAA;AACF,QAAA,CAAA;AAEA,QAAA,IAAIG,WAAWlB,MAAAA,CAAAA,EAAS;AACtB,YAAA,OAAO,MAAOgB,KAAAA,CAAMhB,MAAAA,CAAAA,GAAWA,MAAAA,GAAS,IAAA;AAC1C,QAAA;AAEA,QAAA,IAAImB,GAAAA,GAAMP,KAAAA;QACV,GAAG;YACD,MAAMvC,IAAAA,GAAO+C,QAAQD,GAAAA,EAAKnB,MAAAA,CAAAA;YAC1B,MAAMqB,MAAAA,GAAS,MAAML,KAAAA,CAAM3C,IAAAA,CAAAA;AAE3B,YAAA,IAAIgD,MAAAA,EAAQ;gBACV,OAAOhD,IAAAA;AACT,YAAA;YAEA8C,GAAAA,GAAMA,GAAAA,KAAQL,IAAAA,GAAO,EAAA,GAAKpB,OAAAA,CAAQyB,GAAAA,CAAAA;QACpC,CAAA,OAASA,GAAAA,CAAIG,MAAM;QAEnB,OAAO,IAAA;AACT,IAAA;AACF;;;;;;;;;;;;;;;AC/HA;;AAEC,IACM,MAAMC,UAAAA,CAAAA;AAcX,IAAA,MAAaX,KAAAA,GAAQ;QACnB,MAAM,IAAI,CAACE,IAAI,EAAA;AAEf,QAAA,IAAI,CAACU,QAAQ,GAAGC,MAAM,IAAI,CAACpD,IAAI,EAAE;YAC/BqD,UAAAA,EAAY,IAAA;YACZC,UAAAA,EAAY,IAAA;YACZC,aAAAA,EAAe,IAAA;YAEfC,gBAAAA,EAAkB;gBAChBC,kBAAAA,EAAoB,GAAA;gBACpBC,YAAAA,EAAc;AAChB;AACF,SAAA,CAAA;AAEA,QAAA,SAASC,IAAAA,CACPC,UAAqC,EACrCnD,IAAY,EACZN,KAAwB,EAAA;YAExB,MAAM0D,IAAAA,GAAO,IAAIvE,sBAAAA,EAAAA,CAAyBU,IAAI,CAAC+C,OAAAA,CAAQ,IAAI,CAAC/C,IAAI,EAAES,IAAAA,CAAAA,CAAAA;YAClEmD,UAAAA,CAAWD,IAAI,CAACxD,KAAAA,GAAQ0D,IAAAA,CAAK1D,KAAK,CAACA,KAAAA,CAAAA,CAAOQ,KAAK,EAAA,GAAKkD,IAAAA,CAAKlD,KAAK,EAAA,CAAA;AAChE,QAAA;AAEA,QAAA,IAAI,CAACwC,QAAQ,CACVW,EAAE,CAAC,KAAA,EAAOH,IAAAA,CAAKnC,IAAI,CAAC,IAAI,EAAE,IAAI,CAACuC,IAAI,CAAA,CAAA,CACnCD,EAAE,CAAC,QAAA,EAAUH,IAAAA,CAAKnC,IAAI,CAAC,IAAI,EAAE,IAAI,CAACuC,IAAI,CAAA,CAAA,CACtCD,EAAE,CAAC,QAAA,EAAUH,IAAAA,CAAKnC,IAAI,CAAC,IAAI,EAAE,IAAI,CAACwC,OAAO,CAAA,CAAA,CACzCF,EAAE,CAAC,QAAA,EAAUH,IAAAA,CAAKnC,IAAI,CAAC,IAAI,EAAE,IAAI,CAACyC,OAAO,CAAA,CAAA,CACzCH,EAAE,CAAC,WAAA,EAAaH,IAAAA,CAAKnC,IAAI,CAAC,IAAI,EAAE,IAAI,CAACyC,OAAO,CAAA,CAAA;QAE/C,OAAO,IAAIC,OAAAA,CAAc,CAACnB,OAAAA,GACxB,IAAI,CAACI,QAAQ,EAAEW,EAAAA,CAAG,OAAA,EAAS,IAAMf,OAAAA,EAAAA,CAAAA,CAAAA;AAErC,IAAA;AAEA,IAAA,MAAaN,IAAAA,GAAO;QAClB,MAAM,IAAI,CAACU,QAAQ,EAAEgB,KAAAA,EAAAA;QACrB,OAAO,IAAI,CAAChB,QAAQ;AACpB,QAAA,OAAOe,QAAQnB,OAAO,EAAA;AACxB,IAAA;IAEOqB,GAAAA,GAAM;AACX,QAAA,OAAO,IAAI,CAACL,IAAI,CAACM,YAAY,EAAA;AAC/B,IAAA;IAEOC,MAAAA,GAAS;AACd,QAAA,OAAO,IAAI,CAACN,OAAO,CAACK,YAAY,EAAA;AAClC,IAAA;IAEOE,MAAAA,GAAS;AACd,QAAA,OAAO,IAAI,CAACN,OAAO,CAACI,YAAY,EAAA;AAClC,IAAA;AA3DA;;;;;MAMA,WAAA,CAAmB,IAA4B,CAAE;;AAXjD,QAAA9C,kBAAA,CAAA,IAAA,EAAQwC,QAAR,MAAA,CAAA;AACA,QAAAxC,kBAAA,CAAA,IAAA,EAAQyC,WAAR,MAAA,CAAA;AACA,QAAAzC,kBAAA,CAAA,IAAA,EAAQ0C,WAAR,MAAA,CAAA;AACA,QAAA1C,kBAAA,CAAA,IAAA,EAAQ4B,YAAR,MAAA,CAAA;aAQmCnD,IAAAA,GAAAA,IAAAA;AAX3B+D,QAAAA,IAAAA,CAAAA,IAAAA,GAAkC,IAAIS,OAAAA,EAAAA;AACtCR,QAAAA,IAAAA,CAAAA,OAAAA,GAAqC,IAAIQ,OAAAA,EAAAA;AACzCP,QAAAA,IAAAA,CAAAA,OAAAA,GAAqC,IAAIO,OAAAA,EAAAA;AASC,IAAA;AAsDpD;;;;;;;;;;;;;;;ACvGA;;;;;;AAMC,IACM,MAAMC,eAAAA,CAAAA;AAWX;;AAEC,MACD,IAAWzE,IAAAA,GAAO;QAChB,OAAO,IAAI,CAAC0E,KAAK;AACnB,IAAA;AAEA;;AAEC,MACD,IAAWC,KAAAA,GAAQ;AACjB,QAAA,OAAO,IAAI,CAACC,MAAM,CAACC,KAAK,EAAA;AAC1B,IAAA;AAEA;;;;;;;;;;;;;;;AAeC,MACD,MAAaC,UAAAA,CAAW9E,IAAY,EAAE2E,KAAAA,GAAkB;AAAC,QAAA;KAAK,EAAE;QAC9D,MAAM,IAAI,CAACI,KAAK,EAAA;QAEhB,IAAI,CAACL,KAAK,GAAG1E,IAAAA;QACb,IAAI,CAAC4E,MAAM,GAAGD,KAAAA;;;;;;;;;AAUd,QAAA,MAAMK,OAAAA,GAAUL,KAAAA,CAAMzC,GAAG,CAAC,CAAC+C,CAAAA,GACzB,IAAI,CAACC,QAAQ,CAACvD,MAAM,CAACsD,CAAAA,EAAG;gBACtBzC,GAAAA,EAAKxC,IAAAA;gBACLgC,IAAAA,EAAM;AACR,aAAA,CAAA,CAAA;QAGF,IAAI,CAACmD,MAAM,GAAGjB,OAAAA,CAAQkB,GAAG,CAACJ,OAAAA,CAAAA,CACvBK,IAAI,CAAC,CAACC,KAAAA,GAAAA;AACL,YAAA,MAAMC,OAAOC,OAAAA,CAAQF,KAAAA,CAAAA;AACrB,YAAA,MAAMG,OAAOC,MAAAA,CAAOH,IAAAA,EAAM,CAACI,CAAAA,GAAMA,EAAE3F,IAAI,CAAA;YACvC,OAAOyF,IAAAA,CAAKG,MAAM,CAAC,CAACD,IAAMA,CAAAA,CAAEzF,IAAI,KAAKb,mBAAAA,CAAoBwG,IAAI,CAAA;QAC/D,CAAA,CAAA,CACCR,IAAI,CAAC,CAACS,KAAAA,GAAAA;AACL,YAAA,OAAO,IAAIC,iBAAAA,CAAkBD,KAAAA,CAAAA;AAC/B,QAAA,CAAA,CAAA;AAEF,QAAA,IAAI,CAAC3C,QAAQ,GAAG,IAAID,UAAAA,CAAWlD,IAAAA,CAAAA;QAE/B,IAAI,CAAC+D,IAAI,GAAG,IAAI,CAACZ,QAAQ,CACtBiB,GAAG,EAAA,CACH4B,SAAS,CAAC,OAAOnC,IAAAA,GAAAA;YAChB,IACEA,IAAAA,CAAK3D,IAAI,KAAKb,mBAAAA,CAAoBwG,IAAI,IACtC,IAAI,CAACjB,MAAM,CAACqB,IAAI,CAAC,CAAChB,CAAAA,GAAMiB,SAAAA,CAAUrC,IAAAA,CAAK7D,IAAI,EAAE+C,QAAQ,IAAI,CAAC2B,KAAK,EAAEO,CAAAA,CAAAA,CAAAA,CAAAA,EACjE;AACA,gBAAA,MAAMK,KAAAA,GAAQ,MAAM,IAAI,CAACH,MAAM;AAC/B,gBAAA,IAAI,CAACA,MAAM,GAAGG,KAAAA,CAAMa,MAAM,CAACtC,IAAAA,CAAAA;AAC7B,YAAA;AACF,QAAA,CAAA,CAAA;QAEF,IAAI,CAACI,OAAO,GAAG,IAAI,CAACd,QAAQ,CACzBoB,MAAM,EAAA,CACNyB,SAAS,CAAC,OAAOnC,IAAAA,GAAAA;AAChB,YAAA,IAAIyB,KAAAA,GAAQ,MAAM,IAAI,CAACH,MAAM;AAC7B,YAAA,MAAMnF,IAAAA,GAAOoG,OAAAA,CAAQvC,IAAAA,CAAK7D,IAAI,EAAEqG,GAAAA,CAAAA;;;;;AAOhC,YAAA,MAAM1C,OAAO,UACX2C,SAAAA,CAAU,MAAMhB,KAAAA,CAAMiB,KAAK,IAAI,CAACZ,CAAAA,GAAAA;oBAC9B,OACEA,CAAAA,CAAE3F,IAAI,KAAKA,IAAAA,IACV2F,EAAE3F,IAAI,CAACwG,UAAU,CAACxG,IAAAA,CAAAA,IACjB2F,EAAE3F,IAAI,CAACyG,SAAS,CAACzG,IAAAA,CAAKiD,MAAM,CAAA,CAAEyD,MAAM,CAAC,CAAA,CAAA,KAAOL,GAAAA;AAElD,gBAAA,CAAA,CAAA;YAEF,IAAK,IAAIM,QAAQ,MAAMhD,IAAAA,EAAAA,EAAQgD,SAAS,CAAA,EAAGA,KAAAA,GAAQ,MAAMhD,IAAAA,EAAAA,CAAQ;gBAC/D2B,KAAAA,GAAQ,MAAMA,KAAAA,CAAMsB,QAAQ,CAACD,KAAAA,CAAAA;AAC/B,YAAA;AAEA,YAAA,IAAI,CAACxB,MAAM,GAAGjB,OAAAA,CAAQnB,OAAO,CAACuC,KAAAA,CAAAA;AAChC,QAAA,CAAA,CAAA;QAEF,IAAI,CAACtB,OAAO,GAAG,IAAI,CAACb,QAAQ,CACzBmB,MAAM,EAAA,CACN0B,SAAS,CAAC,OAAOnC,IAAAA,GAAAA;AAChB,YAAA,MAAMyB,KAAAA,GAAQ,MAAM,IAAI,CAACH,MAAM;AAC/B,YAAA,MAAMwB,KAAAA,GAAQL,SAAAA,CACZ,MAAMhB,KAAAA,CAAMiB,KAAK,EAAA,EACjB,CAACZ,CAAAA,GAAMA,CAAAA,CAAE3F,IAAI,KAAK6D,IAAAA,CAAK7D,IAAI,CAAA;;;;AAM7B,YAAA,IAAI2G,SAAS,CAAA,EAAG;AACd,gBAAA,MAAMhD,IAAAA,GAAO,MAAM2B,KAAAA,CAAMsB,QAAQ,CAACD,KAAAA,CAAAA;AAClC,gBAAA,IAAI,CAACxB,MAAM,GAAGxB,IAAAA,CAAKwC,MAAM,CAACtC,IAAAA,EAAM8C,KAAAA,CAAAA;AAClC,YAAA;AACF,QAAA,CAAA,CAAA;;;AAIF,QAAA,MAAME,KAAAA,CAAM,GAAA,CAAA;QAEZ,MAAM,IAAI,CAAC1D,QAAQ,EAAEZ,KAAAA,EAAAA;AACvB,IAAA;AAEA;;AAEC,MACD,MAAawC,KAAAA,GAAuB;QAClC,MAAM,IAAI,CAAC5B,QAAQ,EAAEV,IAAAA,EAAAA;QAErB,IAAI,CAACsB,IAAI,EAAE+C,WAAAA,EAAAA;QACX,IAAI,CAAC7C,OAAO,EAAE6C,WAAAA,EAAAA;QACd,IAAI,CAAC9C,OAAO,EAAE8C,WAAAA,EAAAA;QAEd,OAAO,IAAI,CAAC/C,IAAI;QAChB,OAAO,IAAI,CAACE,OAAO;QACnB,OAAO,IAAI,CAACD,OAAO;QACnB,OAAO,IAAI,CAACb,QAAQ;QAEpB,IAAI,CAACuB,KAAK,GAAG,EAAA;QACb,IAAI,CAACE,MAAM,GAAG;AAAC,YAAA;AAAK,SAAA;QACpB,IAAI,CAACO,MAAM,GAAGjB,OAAAA,CAAQnB,OAAO,CAAC,IAAIgD,kBAAoC,EAAE,CAAA,CAAA;AAC1E,IAAA;IAEA,MAAagB,GAAAA,CAAI/G,IAAY,EAAoC;AAC/D,QAAA,MAAMsF,KAAAA,GAAQ,MAAM,IAAI,CAACH,MAAM;QAC/B,MAAMoB,KAAAA,GAAQ,MAAMjB,KAAAA,CAAMiB,KAAK,EAAA;AAC/B,QAAA,MAAM1C,OAAOmD,IAAAA,CAAKT,KAAAA,EAAO,CAACU,CAAAA,GAAMA,CAAAA,CAAEjH,IAAI,KAAKA,IAAAA,CAAAA;AAE3C,QAAA,OAAOkH,aAAa,IAAA,EAAMrD,IAAAA,CAAAA;AAC5B,IAAA;IAEA,MAAasD,KAAAA,CAAMC,OAAsB,EAAmB;AAC1D,QAAA,MAAMC,MAAAA,GAAS,MAAM,IAAI,CAAClC,MAAM;QAChC,OAAOkC,MAAAA,CAAOF,KAAK,CAACC,OAAAA,CAAAA;AACtB,IAAA;IAEA,MAAaE,QAAAA,CAASF,OAAsB,EAA+B;AACzE,QAAA,MAAMC,MAAAA,GAAS,MAAM,IAAI,CAAClC,MAAM;QAChC,OAAOkC,MAAAA,CAAOC,QAAQ,CAACF,OAAAA,CAAAA;AACzB,IAAA;;AA7KA,QAAA7F,kBAAA,CAAA,IAAA,EAAQ2D,YAAgC,IAAIzD,kBAAAA,EAAAA,CAAAA;AAC5C,QAAAF,kBAAA,CAAA,IAAA,EAAQ4B,YAAR,MAAA,CAAA;AACA,QAAA5B,kBAAA,CAAA,IAAA,EAAQ4D,UACNjB,OAAAA,CAAQnB,OAAO,CAAC,IAAIgD,kBAAoC,EAAE,CAAA,CAAA,CAAA;AAC5D,QAAAxE,kBAAA,CAAA,IAAA,EAAQqD,QAAAA,EAAmB;AAAC,YAAA;AAAK,SAAA,CAAA;AACjC,QAAArD,kBAAA,CAAA,IAAA,EAAQmD,OAAAA,EAAgB,EAAA,CAAA;AACxB,QAAAnD,kBAAA,CAAA,IAAA,EAAQwC,QAAR,MAAA,CAAA;AACA,QAAAxC,kBAAA,CAAA,IAAA,EAAQ0C,WAAR,MAAA,CAAA;AACA,QAAA1C,kBAAA,CAAA,IAAA,EAAQyC,WAAR,MAAA,CAAA;;AAsKF;;ACpNO,SAASuD,gBAAgBvH,IAAc,EAAA;IAC5C,IAAI,OAAOA,SAAS,QAAA,EAAU;AAC5B,QAAA,OAAO+C,OAAAA,CAAQ/C,IAAAA,CAAAA;AACjB,IAAA;AAEA,IAAA,IAAIA,gBAAgBwH,GAAAA,EAAK;AACvB,QAAA,OAAOC,aAAAA,CAAczH,IAAAA,CAAAA;AACvB,IAAA;IAEA,OAAO+C,OAAAA,CAAQ/C,KAAK0H,QAAQ,EAAA,CAAA;AAC9B;;ACZA;;;IAIO,MAAMC,WAAAA,GAAc;AAE3B;;;;;;;;AAQC,IACM,SAASC,eAAAA,GAAAA;AACd,IAAA,OAAOf,KAAAA,CAAMc,WAAAA,CAAAA;AACf;;ACfA;;;;;;AAMC,IACM,MAAME,aAAAA,CAAAA;IACX,MAAaC,KAAAA,CAAM9H,IAAc,EAAmB;AAClD,QAAA,MAAM+H,MAAM/H,IAAAA,EAAM;YAAEgI,SAAAA,EAAW;AAAK,SAAA,CAAA;QAEpC,OAAO,CAAA;AACT,IAAA;AACF;;;;;;;;;;;;;;;ACqBA;;;;;;;;;AASC,IACM,MAAMC,WAAAA,CAAAA;AAcX,IAAA,MAAaC,IAAAA,CACXlI,IAAc,EACd6B,OAA6B,EACZ;AACjB,QAAA,MAAM6C,QAAQ6C,eAAAA,CAAgBvH,IAAAA,CAAAA;QAE9B,MAAMG,KAAAA,GAAQ,MAAM6B,IAAAA,CAAK0C,KAAAA,CAAAA;AACzB,QAAA,MAAMyD,SAAS,IAAI,CAACC,MAAM,CAACrB,GAAG,CAACrC,KAAAA,CAAAA;AAE/B,QAAA,MAAM2D,MAAAA,GACJF,MAAAA,IAAUA,MAAAA,CAAOhI,KAAK,CAACmI,OAAO,IAAInI,KAAAA,CAAMmI,OAAO,GAC3CH,MAAAA,CAAOE,MAAM,GACbE,SAAS7D,KAAAA,EAAO7C,OAAAA,CAAAA;AAEtB,QAAA,OAAO,IAAI,CAAC2G,WAAW,CAAC9D,KAAAA,EAAO;AAAEvE,YAAAA,KAAAA;AAAOkI,YAAAA;AAAO,SAAA,CAAA;AACjD,IAAA;AAEA,IAAA,MAAaP,KAAAA,CACX9H,IAAc,EACd,EAAEqI,MAAAA,GAASI,MAAAA,CAAOC,IAAI,CAAC,EAAA,CAAG,EAAwB,GAAG,EAAE,EACtC;AACjB,QAAA,MAAMhE,QAAQ6C,eAAAA,CAAgBvH,IAAAA,CAAAA;AAC9B,QAAA,MAAM2I,YAAYtH,SAAAA,CAAQqD,KAAAA,CAAAA;QAE1B,MAAM,IAAImD,aAAAA,EAAAA,CAAgBC,KAAK,CAACa,SAAAA,CAAAA;QAChC,MAAMC,SAAAA,CAAUlE,OAAO2D,MAAAA,EAAQ;YAAEQ,KAAAA,EAAO;AAAK,SAAA,CAAA;;;;;AAM7C,QAAA,IAAI,CAACT,MAAM,CAACU,MAAM,CAACpE,KAAAA,CAAAA;AAEnB,QAAA,OAAO2D,OAAOpF,MAAM;AACtB,IAAA;IAEQuF,WAAAA,CACNxI,IAAY,EACZ+I,IAA+C,EAC/C;QACA,MAAM,EAAEC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAACnH,OAAO;QACnC,MAAM,EACJoH,WAAWhB,WAAAA,CAAYiB,eAAe,EACtCC,QAAAA,GAAWlB,WAAAA,CAAYmB,eAAe,EACvC,GAAGJ,KAAAA;AAEJ,QAAA,IAAID,IAAAA,CAAK5I,KAAK,CAACN,IAAI,GAAGoJ,QAAAA,EAAU;;;AAG9B,YAAA,OAAOF,KAAKV,MAAM;AACpB,QAAA;;;;;AAMA,QAAA,IAAI,CAACD,MAAM,CAACU,MAAM,CAAC9I,IAAAA,CAAAA;AACnB,QAAA,IAAI,CAACoI,MAAM,CAACiB,GAAG,CAACrJ,IAAAA,EAAM+I,IAAAA,CAAAA;AAEtB,QAAA,IAAI,IAAI,CAACX,MAAM,CAACvI,IAAI,GAAGsJ,QAAAA,EAAU;;;;;AAK/B,YAAA,MAAMG,GAAAA,GAAM,IAAI,CAAClB,MAAM,CAACmB,IAAI,EAAA;YAC5B,IAAI,CAACnB,MAAM,CAACU,MAAM,CAACQ,GAAAA,CAAI3F,IAAI,GAAG6F,KAAK,CAAA;AACrC,QAAA;AAEA,QAAA,OAAOT,KAAKV,MAAM;AACpB,IAAA;AA7EA;;;;;AAKC,MACD,WAAA,CAAmCxG,OAAAA,GAA+B,EAAE,CAAE;;AARtE,QAAA,gBAAA,CAAA,IAAA,EAAQuG,UAAR,MAAA,CAAA;aAQmCvG,OAAAA,GAAAA,OAAAA;AAR3BuG,QAAAA,IAAAA,CAAAA,MAAAA,GAAS,IAAIqB,GAAAA,EAAAA;AAQkD,IAAA;AAwEzE;AAnFE,gBAAA,CADWxB,WAAAA,EACaiB,iBAAAA,EAAkB,MAAA,CAAA,CAAA;AAC1C,gBAAA,CAFWjB,aAEamB,iBAAAA,EAAkB,IAAA,CAAA;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zthun/crumbtrail-fs",
3
- "version": "2.3.3",
3
+ "version": "2.4.0",
4
4
  "description": "A better file system module for node",
5
5
  "author": "Anthony Bonta",
6
6
  "license": "MIT",
@@ -28,8 +28,8 @@
28
28
  "access": "public"
29
29
  },
30
30
  "dependencies": {
31
- "@zthun/helpful-fn": "^9.6.0",
32
- "@zthun/helpful-query": "^9.7.1",
31
+ "@zthun/helpful-fn": "^9.9.0",
32
+ "@zthun/helpful-query": "^9.9.0",
33
33
  "chokidar": "^4.0.3",
34
34
  "glob": "^11.0.3",
35
35
  "lodash-es": "^4.17.21",
@@ -37,15 +37,15 @@
37
37
  "rxjs": "^7.8.2"
38
38
  },
39
39
  "devDependencies": {
40
- "@zthun/janitor-build-config": "^19.4.0",
40
+ "@zthun/janitor-build-config": "^19.4.1",
41
41
  "typescript": "^5.9.3",
42
- "vite": "^7.1.11",
43
- "vitest": "^3.2.4",
42
+ "vite": "^7.1.12",
43
+ "vitest": "^4.0.3",
44
44
  "vitest-mock-extended": "^3.1.0"
45
45
  },
46
46
  "files": [
47
47
  "dist"
48
48
  ],
49
49
  "sideEffects": false,
50
- "gitHead": "086635545b4ba91b19a9cf687fd341a939eaefa9"
50
+ "gitHead": "267114b2304618449923fb2e0a5af4b503302548"
51
51
  }