@zthun/crumbtrail-fs 2.4.6 → 2.4.10

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,491 +1,378 @@
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
- }
183
- add() {
184
- return this._add.asObservable();
185
- }
186
- update() {
187
- return this._update.asObservable();
188
- }
189
- remove() {
190
- return this._remove.asObservable();
191
- }
192
- /**
193
- * Initializes a new instance of this object.
194
- *
195
- * @param path -
196
- * The path to watch.
197
- */ constructor(path){
198
- _define_property$2(this, "path", void 0);
199
- _define_property$2(this, "_add", void 0);
200
- _define_property$2(this, "_update", void 0);
201
- _define_property$2(this, "_remove", void 0);
202
- _define_property$2(this, "_watcher", void 0);
203
- this.path = path;
204
- this._add = new Subject();
205
- this._update = new Subject();
206
- this._remove = new Subject();
207
- }
208
- }
209
-
210
- function _define_property$1(obj, key, value) {
211
- if (key in obj) {
212
- Object.defineProperty(obj, key, {
213
- value: value,
214
- enumerable: true,
215
- configurable: true,
216
- writable: true
217
- });
218
- } else {
219
- obj[key] = value;
220
- }
221
- return obj;
222
- }
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
223
171
  /**
224
- * Represents an implementation of a ZFileRepository that watches
225
- * a given path scope.
226
- *
227
- * This repository is only concerned about files. Folders
228
- * will not be retrieved from this repository.
229
- */ class ZFileRepository {
230
- /**
231
- * Gets the path that this repository is watching.
232
- */ get path() {
233
- return this._path;
234
- }
235
- /**
236
- * Gets the globs matchers that this repository is matching against.
237
- */ get globs() {
238
- return this._globs.slice();
239
- }
240
- /**
241
- * Initializes the repository with the given root and glob filter.
242
- *
243
- * This will initially scan the file system and setup watches.
244
- * If you call this method again, then the repository will be
245
- * {@link reset} and a new set of files will be added to the
246
- * repository.
247
- *
248
- * @param path -
249
- * The root path of the repository.
250
- * @param globs -
251
- * The optional relative globs of the repository. If this is falsy,
252
- * then ** is used. You can achieve the same kind of operation
253
- * using filters, but filtering out unwanted files frees up the internal
254
- * memory being used.
255
- */ async initialize(path, globs = [
256
- "**"
257
- ]) {
258
- await this.reset();
259
- this._path = path;
260
- this._globs = globs;
261
- // Note that this all happens in the background and should
262
- // only be awaited later. So the search should not be
263
- // required to finish when existing this method. The only
264
- // requirement is that the repository is reset and the path +
265
- // glob scope is updated. Everything beyond here should not
266
- // be awaited - it will be awaited later once the caller
267
- // tries to retrieve the files using retrieve, get, or
268
- // count.
269
- const matches = globs.map((g)=>this._service.search(g, {
270
- cwd: path,
271
- stat: true
272
- }));
273
- this._nodes = Promise.all(matches).then((nodes)=>{
274
- const flat = flatten(nodes);
275
- const uniq = uniqBy(flat, (n)=>n.path);
276
- return uniq.filter((n)=>n.type === ZFileSystemNodeType.File);
277
- }).then((files)=>{
278
- return new ZDataSourceStatic(files);
279
- });
280
- this._watcher = new ZFileWatch(path);
281
- this._add = this._watcher.add().subscribe(async (node)=>{
282
- if (node.type === ZFileSystemNodeType.File && this._globs.some((g)=>minimatch(node.path, resolve(this._path, g)))) {
283
- const nodes = await this._nodes;
284
- this._nodes = nodes.insert(node);
285
- }
286
- });
287
- this._remove = this._watcher.remove().subscribe(async (node)=>{
288
- let nodes = await this._nodes;
289
- const path = trimEnd(node.path, sep);
290
- // It's possible that the node given was a folder. If that happens,
291
- // we need to remove all files that start with the given path.
292
- // If the node does point to a file, then there is no possibility that
293
- // more than 1 item would be removed.
294
- const next = async ()=>findIndex(await nodes.items(), (n)=>{
295
- return n.path === path || n.path.startsWith(path) && n.path.substring(path.length).charAt(0) === sep;
296
- });
297
- for(let index = await next(); index >= 0; index = await next()){
298
- nodes = await nodes.removeAt(index);
299
- }
300
- this._nodes = Promise.resolve(nodes);
301
- });
302
- this._update = this._watcher.update().subscribe(async (node)=>{
303
- const nodes = await this._nodes;
304
- const index = findIndex(await nodes.items(), (n)=>n.path === node.path);
305
- // It's possible node was filtered out by the globs, or
306
- // it is a directory. If so, then we won't have it in our
307
- // list.
308
- if (index >= 0) {
309
- const next = await nodes.removeAt(index);
310
- this._nodes = next.insert(node, index);
311
- }
312
- });
313
- // Kick off the initial seed operation with an even loop
314
- // invocation.
315
- await sleep(100);
316
- await this._watcher?.start();
317
- }
318
- /**
319
- * Resets the repository as if it was initially created.
320
- */ async reset() {
321
- await this._watcher?.stop();
322
- this._add?.unsubscribe();
323
- this._remove?.unsubscribe();
324
- this._update?.unsubscribe();
325
- delete this._add;
326
- delete this._remove;
327
- delete this._update;
328
- delete this._watcher;
329
- this._path = "";
330
- this._globs = [
331
- "**"
332
- ];
333
- this._nodes = Promise.resolve(new ZDataSourceStatic([]));
334
- }
335
- async get(path) {
336
- const nodes = await this._nodes;
337
- const items = await nodes.items();
338
- const node = find(items, (f)=>f.path === path);
339
- return firstDefined(null, node);
340
- }
341
- async count(request) {
342
- const source = await this._nodes;
343
- return source.count(request);
344
- }
345
- async retrieve(request) {
346
- const source = await this._nodes;
347
- return source.retrieve(request);
348
- }
349
- constructor(){
350
- _define_property$1(this, "_service", new ZFileSystemService());
351
- _define_property$1(this, "_watcher", void 0);
352
- _define_property$1(this, "_nodes", Promise.resolve(new ZDataSourceStatic([])));
353
- _define_property$1(this, "_globs", [
354
- "**"
355
- ]);
356
- _define_property$1(this, "_path", "");
357
- _define_property$1(this, "_add", void 0);
358
- _define_property$1(this, "_remove", void 0);
359
- _define_property$1(this, "_update", void 0);
360
- }
361
- }
362
-
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)))) {
228
+ const nodes = await this._nodes;
229
+ this._nodes = nodes.insert(node);
230
+ }
231
+ })();
232
+ });
233
+ this._remove = this._watcher.remove().subscribe((node) => {
234
+ (async () => {
235
+ let nodes = await this._nodes;
236
+ const path = trimEnd(node.path, sep);
237
+ const next = async () => findIndex(await nodes.items(), (n) => {
238
+ return n.path === path || n.path.startsWith(path) && n.path.substring(path.length).charAt(0) === sep;
239
+ });
240
+ for (let index = await next(); index >= 0; index = await next()) nodes = await nodes.removeAt(index);
241
+ this._nodes = Promise.resolve(nodes);
242
+ })();
243
+ });
244
+ this._update = this._watcher.update().subscribe((node) => {
245
+ (async () => {
246
+ const nodes = await this._nodes;
247
+ const index = findIndex(await nodes.items(), (n) => n.path === node.path);
248
+ if (index >= 0) {
249
+ const next = await nodes.removeAt(index);
250
+ this._nodes = next.insert(node, index);
251
+ }
252
+ })();
253
+ });
254
+ await sleep(100);
255
+ await this._watcher?.start();
256
+ }
257
+ /**
258
+ * Resets the repository as if it was initially created.
259
+ */ async reset() {
260
+ await this._watcher?.stop();
261
+ this._add?.unsubscribe();
262
+ this._remove?.unsubscribe();
263
+ this._update?.unsubscribe();
264
+ delete this._add;
265
+ delete this._remove;
266
+ delete this._update;
267
+ delete this._watcher;
268
+ this._path = "";
269
+ this._globs = ["**"];
270
+ this._nodes = Promise.resolve(new ZDataSourceStatic([]));
271
+ }
272
+ async get(path) {
273
+ return firstDefined(null, find(await (await this._nodes).items(), (f) => f.path === path));
274
+ }
275
+ async count(request) {
276
+ return (await this._nodes).count(request);
277
+ }
278
+ async retrieve(request) {
279
+ return (await this._nodes).retrieve(request);
280
+ }
281
+ };
282
+ //#endregion
283
+ //#region src/resolve-path-like/resolve-path-like.ts
363
284
  function resolvePathLike(path) {
364
- if (typeof path === "string") {
365
- return resolve(path);
366
- }
367
- if (path instanceof URL) {
368
- return fileURLToPath(path);
369
- }
370
- return resolve(path.toString());
285
+ if (typeof path === "string") return resolve(path);
286
+ if (path instanceof URL) return fileURLToPath(path);
287
+ return resolve(path.toString());
371
288
  }
372
-
289
+ //#endregion
290
+ //#region src/sleep-watch-delay/sleep-watch-delay.mts
373
291
  /**
374
- * The actual delay time that you should wait for a watch
375
- * operation to pick up your file changes.
376
- */ const ZWatchDelay = 1500;
292
+ * The actual delay time that you should wait for a watch
293
+ * operation to pick up your file changes.
294
+ */ var ZWatchDelay = 1500;
377
295
  /**
378
- * Performs a sleep long enough to allow a watch operation
379
- * to pick up a change.
380
- *
381
- * You should never really need this. Where it is useful
382
- * is for unit testing with IO operations and you want to
383
- * wait for your write operations to get picked up by
384
- * a file watch operation.
385
- */ function sleepWatchDelay() {
386
- return sleep(ZWatchDelay);
296
+ * Performs a sleep long enough to allow a watch operation
297
+ * to pick up a change.
298
+ *
299
+ * You should never really need this. Where it is useful
300
+ * is for unit testing with IO operations and you want to
301
+ * wait for your write operations to get picked up by
302
+ * a file watch operation.
303
+ */ function sleepWatchDelay() {
304
+ return sleep(ZWatchDelay);
387
305
  }
388
-
306
+ //#endregion
307
+ //#region src/stream/stream-folder.mts
389
308
  /**
390
- * A stream that writes folders.
391
- *
392
- * Writing folders is idempotent. If the folder you
393
- * are trying to write already exists, then the write
394
- * operation still succeeds
395
- */ class ZStreamFolder {
396
- async write(path) {
397
- await mkdir(path, {
398
- recursive: true
399
- });
400
- return 0;
401
- }
402
- }
403
-
404
- function _define_property(obj, key, value) {
405
- if (key in obj) {
406
- Object.defineProperty(obj, key, {
407
- value: value,
408
- enumerable: true,
409
- configurable: true,
410
- writable: true
411
- });
412
- } else {
413
- obj[key] = value;
414
- }
415
- return obj;
416
- }
309
+ * A stream that writes folders.
310
+ *
311
+ * Writing folders is idempotent. If the folder you
312
+ * are trying to write already exists, then the write
313
+ * operation still succeeds
314
+ */ var ZStreamFolder = class {
315
+ async write(path) {
316
+ await mkdir(path, { recursive: true });
317
+ return 0;
318
+ }
319
+ };
320
+ //#endregion
321
+ //#region src/stream/stream-file.mts
417
322
  /**
418
- * A stream that can read and write to files.
419
- *
420
- * This is mostly a wrapper to readFile and writeFile from node, but
421
- * with some optimizations.
422
- *
423
- * First, this class supports file content caching so reading in a file
424
- * that's under a certain size threshold will store it in memory for
425
- * later retrieval.
426
- */ class ZStreamFile {
427
- async read(path, options) {
428
- const _path = resolvePathLike(path);
429
- const stats = await stat(_path);
430
- const cached = this._cache.get(_path);
431
- const buffer = cached && cached.stats.mtimeMs >= stats.mtimeMs ? cached.buffer : readFile(_path, options);
432
- return this._addToCache(_path, {
433
- stats,
434
- buffer
435
- });
436
- }
437
- async write(path, { buffer = Buffer.from("") } = {}) {
438
- const _path = resolvePathLike(path);
439
- const directory = dirname$1(_path);
440
- await new ZStreamFolder().write(directory);
441
- await writeFile(_path, buffer, {
442
- flush: true
443
- });
444
- // If this file specifically was cached earlier,
445
- // we can just remove it now so we make room for
446
- // another file. Consumers can just read the
447
- // file again to recache it.
448
- this._cache.delete(_path);
449
- return buffer.length;
450
- }
451
- _addToCache(path, item) {
452
- const { cache = {} } = this.options;
453
- const { fileSize = ZStreamFile.FileSizeDefault, maxFiles = ZStreamFile.MaxFilesDefault } = cache;
454
- if (item.stats.size > fileSize) {
455
- // In this case, the file size is too big to cache in memory,
456
- // so we're bowing out here.
457
- return item.buffer;
458
- }
459
- // We will remove this path from the cache first since
460
- // we want it to be the most recent file (at the end)
461
- // of the key list. The removal does nothing if the
462
- // file was not cached.
463
- this._cache.delete(path);
464
- this._cache.set(path, item);
465
- if (this._cache.size > maxFiles) {
466
- // Retrieving the keys from a javascript map is order
467
- // by the time in which the keys are created. So
468
- // we are going to remove the first key which is the
469
- // oldest.
470
- const itr = this._cache.keys();
471
- this._cache.delete(itr.next().value);
472
- }
473
- return item.buffer;
474
- }
475
- /**
476
- * Initializes a new instance of this object.
477
- *
478
- * @param options -
479
- * The options for file read and writes.
480
- */ constructor(options = {}){
481
- _define_property(this, "options", void 0);
482
- _define_property(this, "_cache", void 0);
483
- this.options = options;
484
- this._cache = new Map();
485
- }
486
- }
487
- _define_property(ZStreamFile, "FileSizeDefault", 102400); // One Hundred KibiBytes
488
- _define_property(ZStreamFile, "MaxFilesDefault", 1000);
489
-
323
+ * A stream that can read and write to files.
324
+ *
325
+ * This is mostly a wrapper to readFile and writeFile from node, but
326
+ * with some optimizations.
327
+ *
328
+ * First, this class supports file content caching so reading in a file
329
+ * that's under a certain size threshold will store it in memory for
330
+ * later retrieval.
331
+ */ var ZStreamFile = class ZStreamFile {
332
+ options;
333
+ static FileSizeDefault = 102400;
334
+ static MaxFilesDefault = 1e3;
335
+ _cache = /* @__PURE__ */ new Map();
336
+ /**
337
+ * Initializes a new instance of this object.
338
+ *
339
+ * @param options -
340
+ * The options for file read and writes.
341
+ */ constructor(options = {}) {
342
+ this.options = options;
343
+ }
344
+ async read(path, options) {
345
+ const _path = resolvePathLike(path);
346
+ const stats = await stat(_path);
347
+ const cached = this._cache.get(_path);
348
+ const buffer = cached && cached.stats.mtimeMs >= stats.mtimeMs ? cached.buffer : readFile(_path, options);
349
+ return this._addToCache(_path, {
350
+ stats,
351
+ buffer
352
+ });
353
+ }
354
+ async write(path, { buffer = Buffer.from("") } = {}) {
355
+ const _path = resolvePathLike(path);
356
+ const directory = dirname$1(_path);
357
+ await new ZStreamFolder().write(directory);
358
+ await writeFile(_path, buffer, { flush: true });
359
+ this._cache.delete(_path);
360
+ return buffer.length;
361
+ }
362
+ _addToCache(path, item) {
363
+ const { cache = {} } = this.options;
364
+ const { fileSize = ZStreamFile.FileSizeDefault, maxFiles = ZStreamFile.MaxFilesDefault } = cache;
365
+ if (item.stats.size > fileSize) return item.buffer;
366
+ this._cache.delete(path);
367
+ this._cache.set(path, item);
368
+ if (this._cache.size > maxFiles) {
369
+ const itr = this._cache.keys();
370
+ this._cache.delete(itr.next().value);
371
+ }
372
+ return item.buffer;
373
+ }
374
+ };
375
+ //#endregion
490
376
  export { ZFileRepository, ZFileSystemNodeBuilder, ZFileSystemNodeType, ZFileSystemService, ZFileWatch, ZStreamFile, ZStreamFolder, ZWatchDelay, resolvePathLike, sleepWatchDelay };
491
- //# sourceMappingURL=index.js.map
377
+
378
+ //# sourceMappingURL=index.js.map