@zthun/crumbtrail-fs 2.4.5 → 2.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,492 +1,372 @@
1
- import { sleep, firstDefined } from '@zthun/helpful-fn';
2
- import { ZDataSourceStatic } from '@zthun/helpful-query';
3
- import { omitBy, isUndefined, flatten, uniqBy, trimEnd, findIndex, find } from 'lodash-es';
4
- import { minimatch } from 'minimatch';
5
- import { basename, dirname, extname, isAbsolute, resolve, sep } from 'node:path';
6
- import { glob } from 'glob';
7
- import { access, stat, readFile, writeFile } from 'node:fs/promises';
8
- import { cwd } from 'node:process';
9
- import { watch } from 'chokidar';
10
- import { Subject } from 'rxjs';
11
- import { fileURLToPath } from 'node:url';
12
- import { dirname as dirname$1 } from 'path';
13
- import { mkdir } from 'fs/promises';
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
- }
1
+ import { basename, dirname, extname, isAbsolute, resolve, sep } from "node:path";
2
+ import { firstDefined, sleep } from "@zthun/helpful-fn";
3
+ import { ZDataSourceStatic } from "@zthun/helpful-query";
4
+ import { find, findIndex, flatten, isUndefined, omitBy, trimEnd, uniqBy } from "lodash-es";
5
+ import { minimatch } from "minimatch";
6
+ import { access, readFile, stat, writeFile } from "node:fs/promises";
7
+ import { cwd } from "node:process";
8
+ import { glob } from "glob";
9
+ import { watch } from "chokidar";
10
+ import { Subject } from "rxjs";
11
+ import { fileURLToPath } from "node:url";
12
+ import { dirname as dirname$1 } from "path";
13
+ import { mkdir } from "fs/promises";
14
+ //#region src/file-system/file-system-node.mts
28
15
  /**
29
- * Represents a type of a file system node.
30
- */ var ZFileSystemNodeType = /*#__PURE__*/ function(ZFileSystemNodeType) {
31
- ZFileSystemNodeType["File"] = "file";
32
- ZFileSystemNodeType["Folder"] = "folder";
33
- return ZFileSystemNodeType;
16
+ * Represents a type of a file system node.
17
+ */ var ZFileSystemNodeType = /* @__PURE__ */ function(ZFileSystemNodeType) {
18
+ ZFileSystemNodeType["File"] = "file";
19
+ ZFileSystemNodeType["Folder"] = "folder";
20
+ return ZFileSystemNodeType;
34
21
  }({});
35
22
  /**
36
- * Represents a builder for a file system node.
37
- */ class ZFileSystemNodeBuilder {
38
- created(at) {
39
- this._node.created = at instanceof Date ? at.toJSON() : at;
40
- return this;
41
- }
42
- updated(at) {
43
- this._node.updated = at instanceof Date ? at.toJSON() : at;
44
- return this;
45
- }
46
- size(bytes) {
47
- this._node.size = typeof bytes == "number" ? BigInt(bytes) : bytes;
48
- return this;
49
- }
50
- path(path) {
51
- this._node.path = path;
52
- return this.decorate();
53
- }
54
- type(type) {
55
- this._node.type = type;
56
- return this.decorate();
57
- }
58
- stats(s) {
59
- const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);
60
- return s.isFile() ? builder.file() : builder.folder();
61
- }
62
- build() {
63
- const clone = structuredClone(this._node);
64
- return omitBy(clone, isUndefined);
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
- }
94
- }
95
-
23
+ * Represents a builder for a file system node.
24
+ */ var ZFileSystemNodeBuilder = class {
25
+ _node = {
26
+ path: "/",
27
+ type: "folder",
28
+ extension: "",
29
+ name: "",
30
+ parent: "",
31
+ title: ""
32
+ };
33
+ created(at) {
34
+ this._node.created = at instanceof Date ? at.toJSON() : at;
35
+ return this;
36
+ }
37
+ updated(at) {
38
+ this._node.updated = at instanceof Date ? at.toJSON() : at;
39
+ return this;
40
+ }
41
+ size(bytes) {
42
+ this._node.size = typeof bytes == "number" ? BigInt(bytes) : bytes;
43
+ return this;
44
+ }
45
+ path(path) {
46
+ this._node.path = path;
47
+ return this.decorate();
48
+ }
49
+ type(type) {
50
+ this._node.type = type;
51
+ return this.decorate();
52
+ }
53
+ file = this.type.bind(this, "file");
54
+ folder = this.type.bind(this, "folder");
55
+ stats(s) {
56
+ const builder = this.size(s.size).created(s.birthtime).updated(s.mtime);
57
+ return s.isFile() ? builder.file() : builder.folder();
58
+ }
59
+ build() {
60
+ return omitBy(structuredClone(this._node), isUndefined);
61
+ }
62
+ decorate() {
63
+ const { path, type } = this._node;
64
+ this._node.name = basename(path);
65
+ this._node.extension = "";
66
+ this._node.title = this._node.name;
67
+ this._node.parent = dirname(path);
68
+ if (type === "file") {
69
+ const extension = extname(path);
70
+ this._node.extension = extension;
71
+ this._node.title = basename(path, extension);
72
+ }
73
+ if (!path || path === "/" || this._node.parent === ".") this._node.parent = "";
74
+ return this;
75
+ }
76
+ };
77
+ //#endregion
78
+ //#region src/file-system/file-system-service.mts
96
79
  /**
97
- * Represents a node implementation of a file system service.
98
- */ class ZFileSystemService {
99
- async info(path) {
100
- const [file] = await this.search(path);
101
- return file;
102
- }
103
- async search(pattern, options) {
104
- const paths = await glob(pattern, {
105
- stat: true,
106
- ...options,
107
- withFileTypes: true
108
- });
109
- return paths.map((path)=>{
110
- let info = new ZFileSystemNodeBuilder().path(path.fullpath()).created(path.birthtime).updated(path.atime).size(path.size);
111
- // Note that for folders, node will return the size of the underlying OS metadata,
112
- // hence, why we remove the size on the folder here.
113
- info = path.isFile() ? info.file() : info.folder().size(undefined);
114
- return info.build();
115
- });
116
- }
117
- async walk(search, options) {
118
- const start = options?.start || cwd();
119
- const stop = options?.stop || "/";
120
- const mode = options?.mode;
121
- const _test = async (path)=>{
122
- try {
123
- await access(path, mode);
124
- return true;
125
- } catch {
126
- return false;
127
- }
128
- };
129
- if (isAbsolute(search)) {
130
- return await _test(search) ? search : null;
131
- }
132
- let dir = start;
133
- do {
134
- const path = resolve(dir, search);
135
- const exists = await _test(path);
136
- if (exists) {
137
- return path;
138
- }
139
- dir = dir === stop ? "" : dirname(dir);
140
- }while (dir.length)
141
- return null;
142
- }
143
- }
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
- }
80
+ * Represents a node implementation of a file system service.
81
+ */ var ZFileSystemService = class {
82
+ async info(path) {
83
+ const [file] = await this.search(path);
84
+ return file;
85
+ }
86
+ async search(pattern, options) {
87
+ return (await glob(pattern, {
88
+ stat: true,
89
+ ...options,
90
+ withFileTypes: true
91
+ })).map((path) => {
92
+ let info = new ZFileSystemNodeBuilder().path(path.fullpath()).created(path.birthtime).updated(path.atime).size(path.size);
93
+ info = path.isFile() ? info.file() : info.folder().size(void 0);
94
+ return info.build();
95
+ });
96
+ }
97
+ async walk(search, options) {
98
+ const start = options?.start || cwd();
99
+ const stop = options?.stop || "/";
100
+ const mode = options?.mode;
101
+ const _test = async (path) => {
102
+ try {
103
+ await access(path, mode);
104
+ return true;
105
+ } catch {
106
+ return false;
107
+ }
108
+ };
109
+ if (isAbsolute(search)) return await _test(search) ? search : null;
110
+ let dir = start;
111
+ do {
112
+ const path = resolve(dir, search);
113
+ if (await _test(path)) return path;
114
+ dir = dir === stop ? "" : dirname(dir);
115
+ } while (dir.length);
116
+ return null;
117
+ }
118
+ };
119
+ //#endregion
120
+ //#region src/file-watch/file-watch.mts
158
121
  /**
159
- * An implementation of the IZFileWatch.
160
- */ class ZFileWatch {
161
- async start() {
162
- await this.stop();
163
- this._watcher = watch(this.path, {
164
- usePolling: true,
165
- alwaysStat: true,
166
- ignoreInitial: true,
167
- awaitWriteFinish: {
168
- stabilityThreshold: 500,
169
- pollInterval: 50
170
- }
171
- });
172
- function next(observable, file, stats) {
173
- const node = new ZFileSystemNodeBuilder().path(resolve(this.path, file));
174
- observable.next(stats ? node.stats(stats).build() : node.build());
175
- }
176
- this._watcher.on("add", next.bind(this, this._add)).on("addDir", next.bind(this, this._add)).on("change", next.bind(this, this._update)).on("unlink", next.bind(this, this._remove)).on("unlinkDir", next.bind(this, this._remove));
177
- return new Promise((resolve)=>this._watcher?.on("ready", ()=>resolve()));
178
- }
179
- async stop() {
180
- await this._watcher?.close();
181
- delete this._watcher;
182
- return Promise.resolve();
183
- }
184
- add() {
185
- return this._add.asObservable();
186
- }
187
- update() {
188
- return this._update.asObservable();
189
- }
190
- remove() {
191
- return this._remove.asObservable();
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
- }
209
- }
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
- }
122
+ * An implementation of the IZFileWatch.
123
+ */ var ZFileWatch = class {
124
+ path;
125
+ _add = new Subject();
126
+ _update = new Subject();
127
+ _remove = new Subject();
128
+ _watcher;
129
+ /**
130
+ * Initializes a new instance of this object.
131
+ *
132
+ * @param path -
133
+ * The path to watch.
134
+ */ constructor(path) {
135
+ this.path = path;
136
+ }
137
+ async start() {
138
+ await this.stop();
139
+ this._watcher = watch(this.path, {
140
+ usePolling: true,
141
+ alwaysStat: true,
142
+ ignoreInitial: true,
143
+ awaitWriteFinish: {
144
+ stabilityThreshold: 500,
145
+ pollInterval: 50
146
+ }
147
+ });
148
+ function next(observable, file, stats) {
149
+ const node = new ZFileSystemNodeBuilder().path(resolve(this.path, file));
150
+ observable.next(stats ? node.stats(stats).build() : node.build());
151
+ }
152
+ this._watcher.on("add", next.bind(this, this._add)).on("addDir", next.bind(this, this._add)).on("change", next.bind(this, this._update)).on("unlink", next.bind(this, this._remove)).on("unlinkDir", next.bind(this, this._remove));
153
+ return new Promise((resolve) => this._watcher?.on("ready", () => resolve()));
154
+ }
155
+ async stop() {
156
+ await this._watcher?.close();
157
+ delete this._watcher;
158
+ }
159
+ add() {
160
+ return this._add.asObservable();
161
+ }
162
+ update() {
163
+ return this._update.asObservable();
164
+ }
165
+ remove() {
166
+ return this._remove.asObservable();
167
+ }
168
+ };
169
+ //#endregion
170
+ //#region src/file-repository/file-repository.mts
224
171
  /**
225
- * Represents an implementation of a ZFileRepository that watches
226
- * a given path scope.
227
- *
228
- * This repository is only concerned about files. Folders
229
- * will not be retrieved from this repository.
230
- */ class ZFileRepository {
231
- /**
232
- * Gets the path that this repository is watching.
233
- */ get path() {
234
- return this._path;
235
- }
236
- /**
237
- * Gets the globs matchers that this repository is matching against.
238
- */ get globs() {
239
- return this._globs.slice();
240
- }
241
- /**
242
- * Initializes the repository with the given root and glob filter.
243
- *
244
- * This will initially scan the file system and setup watches.
245
- * If you call this method again, then the repository will be
246
- * {@link reset} and a new set of files will be added to the
247
- * repository.
248
- *
249
- * @param path -
250
- * The root path of the repository.
251
- * @param globs -
252
- * The optional relative globs of the repository. If this is falsy,
253
- * then ** is used. You can achieve the same kind of operation
254
- * using filters, but filtering out unwanted files frees up the internal
255
- * memory being used.
256
- */ async initialize(path, globs = [
257
- "**"
258
- ]) {
259
- await this.reset();
260
- this._path = path;
261
- this._globs = globs;
262
- // Note that this all happens in the background and should
263
- // only be awaited later. So the search should not be
264
- // required to finish when existing this method. The only
265
- // requirement is that the repository is reset and the path +
266
- // glob scope is updated. Everything beyond here should not
267
- // be awaited - it will be awaited later once the caller
268
- // tries to retrieve the files using retrieve, get, or
269
- // count.
270
- const matches = globs.map((g)=>this._service.search(g, {
271
- cwd: path,
272
- stat: true
273
- }));
274
- this._nodes = Promise.all(matches).then((nodes)=>{
275
- const flat = flatten(nodes);
276
- const uniq = uniqBy(flat, (n)=>n.path);
277
- return uniq.filter((n)=>n.type === ZFileSystemNodeType.File);
278
- }).then((files)=>{
279
- return new ZDataSourceStatic(files);
280
- });
281
- this._watcher = new ZFileWatch(path);
282
- this._add = this._watcher.add().subscribe(async (node)=>{
283
- if (node.type === ZFileSystemNodeType.File && this._globs.some((g)=>minimatch(node.path, resolve(this._path, g)))) {
284
- const nodes = await this._nodes;
285
- this._nodes = nodes.insert(node);
286
- }
287
- });
288
- this._remove = this._watcher.remove().subscribe(async (node)=>{
289
- let nodes = await this._nodes;
290
- const path = trimEnd(node.path, sep);
291
- // It's possible that the node given was a folder. If that happens,
292
- // we need to remove all files that start with the given path.
293
- // If the node does point to a file, then there is no possibility that
294
- // more than 1 item would be removed.
295
- const next = async ()=>findIndex(await nodes.items(), (n)=>{
296
- return n.path === path || n.path.startsWith(path) && n.path.substring(path.length).charAt(0) === sep;
297
- });
298
- for(let index = await next(); index >= 0; index = await next()){
299
- nodes = await nodes.removeAt(index);
300
- }
301
- this._nodes = Promise.resolve(nodes);
302
- });
303
- this._update = this._watcher.update().subscribe(async (node)=>{
304
- const nodes = await this._nodes;
305
- const index = findIndex(await nodes.items(), (n)=>n.path === node.path);
306
- // It's possible node was filtered out by the globs, or
307
- // it is a directory. If so, then we won't have it in our
308
- // list.
309
- if (index >= 0) {
310
- const next = await nodes.removeAt(index);
311
- this._nodes = next.insert(node, index);
312
- }
313
- });
314
- // Kick off the initial seed operation with an even loop
315
- // invocation.
316
- await sleep(100);
317
- await this._watcher?.start();
318
- }
319
- /**
320
- * Resets the repository as if it was initially created.
321
- */ async reset() {
322
- await this._watcher?.stop();
323
- this._add?.unsubscribe();
324
- this._remove?.unsubscribe();
325
- this._update?.unsubscribe();
326
- delete this._add;
327
- delete this._remove;
328
- delete this._update;
329
- delete this._watcher;
330
- this._path = "";
331
- this._globs = [
332
- "**"
333
- ];
334
- this._nodes = Promise.resolve(new ZDataSourceStatic([]));
335
- }
336
- async get(path) {
337
- const nodes = await this._nodes;
338
- const items = await nodes.items();
339
- const node = find(items, (f)=>f.path === path);
340
- return firstDefined(null, node);
341
- }
342
- async count(request) {
343
- const source = await this._nodes;
344
- return source.count(request);
345
- }
346
- async retrieve(request) {
347
- const source = await this._nodes;
348
- return source.retrieve(request);
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
- }
362
- }
363
-
172
+ * Represents an implementation of a ZFileRepository that watches
173
+ * a given path scope.
174
+ *
175
+ * This repository is only concerned about files. Folders
176
+ * will not be retrieved from this repository.
177
+ */ var ZFileRepository = class {
178
+ _service = new ZFileSystemService();
179
+ _watcher;
180
+ _nodes = Promise.resolve(new ZDataSourceStatic([]));
181
+ _globs = ["**"];
182
+ _path = "";
183
+ _add;
184
+ _remove;
185
+ _update;
186
+ /**
187
+ * Gets the path that this repository is watching.
188
+ */ get path() {
189
+ return this._path;
190
+ }
191
+ /**
192
+ * Gets the globs matchers that this repository is matching against.
193
+ */ get globs() {
194
+ return this._globs.slice();
195
+ }
196
+ /**
197
+ * Initializes the repository with the given root and glob filter.
198
+ *
199
+ * This will initially scan the file system and setup watches.
200
+ * If you call this method again, then the repository will be
201
+ * {@link reset} and a new set of files will be added to the
202
+ * repository.
203
+ *
204
+ * @param path -
205
+ * The root path of the repository.
206
+ * @param globs -
207
+ * The optional relative globs of the repository. If this is falsy,
208
+ * then ** is used. You can achieve the same kind of operation
209
+ * using filters, but filtering out unwanted files frees up the internal
210
+ * memory being used.
211
+ */ async initialize(path, globs = ["**"]) {
212
+ await this.reset();
213
+ this._path = path;
214
+ this._globs = globs;
215
+ const matches = globs.map((g) => this._service.search(g, {
216
+ cwd: path,
217
+ stat: true
218
+ }));
219
+ this._nodes = Promise.all(matches).then((nodes) => {
220
+ return uniqBy(flatten(nodes), (n) => n.path).filter((n) => n.type === ZFileSystemNodeType.File);
221
+ }).then((files) => {
222
+ return new ZDataSourceStatic(files);
223
+ });
224
+ this._watcher = new ZFileWatch(path);
225
+ this._add = this._watcher.add().subscribe((node) => {
226
+ (async () => {
227
+ if (node.type === ZFileSystemNodeType.File && this._globs.some((g) => minimatch(node.path, resolve(this._path, g)))) this._nodes = (await this._nodes).insert(node);
228
+ })();
229
+ });
230
+ this._remove = this._watcher.remove().subscribe((node) => {
231
+ (async () => {
232
+ let nodes = await this._nodes;
233
+ const path = trimEnd(node.path, sep);
234
+ const next = async () => findIndex(await nodes.items(), (n) => {
235
+ return n.path === path || n.path.startsWith(path) && n.path.substring(path.length).charAt(0) === sep;
236
+ });
237
+ for (let index = await next(); index >= 0; index = await next()) nodes = await nodes.removeAt(index);
238
+ this._nodes = Promise.resolve(nodes);
239
+ })();
240
+ });
241
+ this._update = this._watcher.update().subscribe((node) => {
242
+ (async () => {
243
+ const nodes = await this._nodes;
244
+ const index = findIndex(await nodes.items(), (n) => n.path === node.path);
245
+ if (index >= 0) this._nodes = (await nodes.removeAt(index)).insert(node, index);
246
+ })();
247
+ });
248
+ await sleep(100);
249
+ await this._watcher?.start();
250
+ }
251
+ /**
252
+ * Resets the repository as if it was initially created.
253
+ */ async reset() {
254
+ await this._watcher?.stop();
255
+ this._add?.unsubscribe();
256
+ this._remove?.unsubscribe();
257
+ this._update?.unsubscribe();
258
+ delete this._add;
259
+ delete this._remove;
260
+ delete this._update;
261
+ delete this._watcher;
262
+ this._path = "";
263
+ this._globs = ["**"];
264
+ this._nodes = Promise.resolve(new ZDataSourceStatic([]));
265
+ }
266
+ async get(path) {
267
+ return firstDefined(null, find(await (await this._nodes).items(), (f) => f.path === path));
268
+ }
269
+ async count(request) {
270
+ return (await this._nodes).count(request);
271
+ }
272
+ async retrieve(request) {
273
+ return (await this._nodes).retrieve(request);
274
+ }
275
+ };
276
+ //#endregion
277
+ //#region src/resolve-path-like/resolve-path-like.ts
364
278
  function resolvePathLike(path) {
365
- if (typeof path === "string") {
366
- return resolve(path);
367
- }
368
- if (path instanceof URL) {
369
- return fileURLToPath(path);
370
- }
371
- return resolve(path.toString());
279
+ if (typeof path === "string") return resolve(path);
280
+ if (path instanceof URL) return fileURLToPath(path);
281
+ return resolve(path.toString());
372
282
  }
373
-
283
+ //#endregion
284
+ //#region src/sleep-watch-delay/sleep-watch-delay.mts
374
285
  /**
375
- * The actual delay time that you should wait for a watch
376
- * operation to pick up your file changes.
377
- */ const ZWatchDelay = 1500;
286
+ * The actual delay time that you should wait for a watch
287
+ * operation to pick up your file changes.
288
+ */ var ZWatchDelay = 1500;
378
289
  /**
379
- * Performs a sleep long enough to allow a watch operation
380
- * to pick up a change.
381
- *
382
- * You should never really need this. Where it is useful
383
- * is for unit testing with IO operations and you want to
384
- * wait for your write operations to get picked up by
385
- * a file watch operation.
386
- */ function sleepWatchDelay() {
387
- return sleep(ZWatchDelay);
290
+ * Performs a sleep long enough to allow a watch operation
291
+ * to pick up a change.
292
+ *
293
+ * You should never really need this. Where it is useful
294
+ * is for unit testing with IO operations and you want to
295
+ * wait for your write operations to get picked up by
296
+ * a file watch operation.
297
+ */ function sleepWatchDelay() {
298
+ return sleep(ZWatchDelay);
388
299
  }
389
-
300
+ //#endregion
301
+ //#region src/stream/stream-folder.mts
390
302
  /**
391
- * A stream that writes folders.
392
- *
393
- * Writing folders is idempotent. If the folder you
394
- * are trying to write already exists, then the write
395
- * operation still succeeds
396
- */ class ZStreamFolder {
397
- async write(path) {
398
- await mkdir(path, {
399
- recursive: true
400
- });
401
- return 0;
402
- }
403
- }
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
- }
303
+ * A stream that writes folders.
304
+ *
305
+ * Writing folders is idempotent. If the folder you
306
+ * are trying to write already exists, then the write
307
+ * operation still succeeds
308
+ */ var ZStreamFolder = class {
309
+ async write(path) {
310
+ await mkdir(path, { recursive: true });
311
+ return 0;
312
+ }
313
+ };
314
+ //#endregion
315
+ //#region src/stream/stream-file.mts
418
316
  /**
419
- * A stream that can read and write to files.
420
- *
421
- * This is mostly a wrapper to readFile and writeFile from node, but
422
- * with some optimizations.
423
- *
424
- * First, this class supports file content caching so reading in a file
425
- * that's under a certain size threshold will store it in memory for
426
- * later retrieval.
427
- */ class ZStreamFile {
428
- async read(path, options) {
429
- const _path = resolvePathLike(path);
430
- const stats = await stat(_path);
431
- const cached = this._cache.get(_path);
432
- const buffer = cached && cached.stats.mtimeMs >= stats.mtimeMs ? cached.buffer : readFile(_path, options);
433
- return this._addToCache(_path, {
434
- stats,
435
- buffer
436
- });
437
- }
438
- async write(path, { buffer = Buffer.from("") } = {}) {
439
- const _path = resolvePathLike(path);
440
- const directory = dirname$1(_path);
441
- await new ZStreamFolder().write(directory);
442
- await writeFile(_path, buffer, {
443
- flush: true
444
- });
445
- // If this file specifically was cached earlier,
446
- // we can just remove it now so we make room for
447
- // another file. Consumers can just read the
448
- // file again to recache it.
449
- this._cache.delete(_path);
450
- return buffer.length;
451
- }
452
- _addToCache(path, item) {
453
- const { cache = {} } = this.options;
454
- const { fileSize = ZStreamFile.FileSizeDefault, maxFiles = ZStreamFile.MaxFilesDefault } = cache;
455
- if (item.stats.size > fileSize) {
456
- // In this case, the file size is too big to cache in memory,
457
- // so we're bowing out here.
458
- return item.buffer;
459
- }
460
- // We will remove this path from the cache first since
461
- // we want it to be the most recent file (at the end)
462
- // of the key list. The removal does nothing if the
463
- // file was not cached.
464
- this._cache.delete(path);
465
- this._cache.set(path, item);
466
- if (this._cache.size > maxFiles) {
467
- // Retrieving the keys from a javascript map is order
468
- // by the time in which the keys are created. So
469
- // we are going to remove the first key which is the
470
- // oldest.
471
- const itr = this._cache.keys();
472
- this._cache.delete(itr.next().value);
473
- }
474
- return item.buffer;
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
- }
487
- }
488
- _define_property(ZStreamFile, "FileSizeDefault", 102400); // One Hundred KibiBytes
489
- _define_property(ZStreamFile, "MaxFilesDefault", 1000);
490
-
317
+ * A stream that can read and write to files.
318
+ *
319
+ * This is mostly a wrapper to readFile and writeFile from node, but
320
+ * with some optimizations.
321
+ *
322
+ * First, this class supports file content caching so reading in a file
323
+ * that's under a certain size threshold will store it in memory for
324
+ * later retrieval.
325
+ */ var ZStreamFile = class ZStreamFile {
326
+ options;
327
+ static FileSizeDefault = 102400;
328
+ static MaxFilesDefault = 1e3;
329
+ _cache = /* @__PURE__ */ new Map();
330
+ /**
331
+ * Initializes a new instance of this object.
332
+ *
333
+ * @param options -
334
+ * The options for file read and writes.
335
+ */ constructor(options = {}) {
336
+ this.options = options;
337
+ }
338
+ async read(path, options) {
339
+ const _path = resolvePathLike(path);
340
+ const stats = await stat(_path);
341
+ const cached = this._cache.get(_path);
342
+ const buffer = cached && cached.stats.mtimeMs >= stats.mtimeMs ? cached.buffer : readFile(_path, options);
343
+ return this._addToCache(_path, {
344
+ stats,
345
+ buffer
346
+ });
347
+ }
348
+ async write(path, { buffer = Buffer.from("") } = {}) {
349
+ const _path = resolvePathLike(path);
350
+ const directory = dirname$1(_path);
351
+ await new ZStreamFolder().write(directory);
352
+ await writeFile(_path, buffer, { flush: true });
353
+ this._cache.delete(_path);
354
+ return buffer.length;
355
+ }
356
+ _addToCache(path, item) {
357
+ const { cache = {} } = this.options;
358
+ const { fileSize = ZStreamFile.FileSizeDefault, maxFiles = ZStreamFile.MaxFilesDefault } = cache;
359
+ if (item.stats.size > fileSize) return item.buffer;
360
+ this._cache.delete(path);
361
+ this._cache.set(path, item);
362
+ if (this._cache.size > maxFiles) {
363
+ const itr = this._cache.keys();
364
+ this._cache.delete(itr.next().value);
365
+ }
366
+ return item.buffer;
367
+ }
368
+ };
369
+ //#endregion
491
370
  export { ZFileRepository, ZFileSystemNodeBuilder, ZFileSystemNodeType, ZFileSystemService, ZFileWatch, ZStreamFile, ZStreamFolder, ZWatchDelay, resolvePathLike, sleepWatchDelay };
492
- //# sourceMappingURL=index.js.map
371
+
372
+ //# sourceMappingURL=index.js.map