@zenfs/core 1.0.9 → 1.0.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.
@@ -79,8 +79,8 @@ export declare class UnmutexedOverlayFS extends FileSystem {
79
79
  * - Ensures p is on writable before proceeding. Throws an error if it doesn't exist.
80
80
  * - Calls f to perform operation on writable.
81
81
  */
82
- private operateOnWritable;
83
- private operateOnWritableAsync;
82
+ private copyForWriteSync;
83
+ private copyForWrite;
84
84
  /**
85
85
  * Copy from readable to writable storage.
86
86
  * PRECONDITION: File does not exist on writable storage.
@@ -1,3 +1,48 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ }
13
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
14
+ env.stack.push({ value: value, dispose: dispose, async: async });
15
+ }
16
+ else if (async) {
17
+ env.stack.push({ async: true });
18
+ }
19
+ return value;
20
+ };
21
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
22
+ return function (env) {
23
+ function fail(e) {
24
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
25
+ env.hasError = true;
26
+ }
27
+ function next() {
28
+ while (env.stack.length) {
29
+ var rec = env.stack.pop();
30
+ try {
31
+ var result = rec.dispose && rec.dispose.call(rec.value);
32
+ if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
33
+ }
34
+ catch (e) {
35
+ fail(e);
36
+ }
37
+ }
38
+ if (env.hasError) throw env.error;
39
+ }
40
+ return next();
41
+ };
42
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
43
+ var e = new Error(message);
44
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
45
+ });
1
46
  import { dirname } from '../emulation/path.js';
2
47
  import { Errno, ErrnoError } from '../error.js';
3
48
  import { PreloadFile, parseFlag } from '../file.js';
@@ -47,14 +92,14 @@ export class UnmutexedOverlayFS extends FileSystem {
47
92
  };
48
93
  }
49
94
  async sync(path, data, stats) {
50
- await this.createParentDirectories(path);
95
+ await this.copyForWrite(path);
51
96
  if (!(await this.writable.exists(path))) {
52
97
  await this.writable.createFile(path, 'w', 0o644);
53
98
  }
54
99
  await this.writable.sync(path, data, stats);
55
100
  }
56
101
  syncSync(path, data, stats) {
57
- this.createParentDirectoriesSync(path);
102
+ this.copyForWriteSync(path);
58
103
  this.writable.syncSync(path, data, stats);
59
104
  }
60
105
  /**
@@ -92,6 +137,7 @@ export class UnmutexedOverlayFS extends FileSystem {
92
137
  this.checkInitialized();
93
138
  this.checkPath(oldPath);
94
139
  this.checkPath(newPath);
140
+ await this.copyForWrite(oldPath);
95
141
  try {
96
142
  await this.writable.rename(oldPath, newPath);
97
143
  }
@@ -105,6 +151,7 @@ export class UnmutexedOverlayFS extends FileSystem {
105
151
  this.checkInitialized();
106
152
  this.checkPath(oldPath);
107
153
  this.checkPath(newPath);
154
+ this.copyForWriteSync(oldPath);
108
155
  try {
109
156
  this.writable.renameSync(oldPath, newPath);
110
157
  }
@@ -124,7 +171,7 @@ export class UnmutexedOverlayFS extends FileSystem {
124
171
  throw ErrnoError.With('ENOENT', path, 'stat');
125
172
  }
126
173
  const oldStat = new Stats(await this.readable.stat(path));
127
- // Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type
174
+ // Make the oldStat's mode writable.
128
175
  oldStat.mode |= 0o222;
129
176
  return oldStat;
130
177
  }
@@ -139,7 +186,7 @@ export class UnmutexedOverlayFS extends FileSystem {
139
186
  throw ErrnoError.With('ENOENT', path, 'stat');
140
187
  }
141
188
  const oldStat = new Stats(this.readable.statSync(path));
142
- // Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type.
189
+ // Make the oldStat's mode writable.
143
190
  oldStat.mode |= 0o222;
144
191
  return oldStat;
145
192
  }
@@ -150,7 +197,7 @@ export class UnmutexedOverlayFS extends FileSystem {
150
197
  }
151
198
  // Create an OverlayFile.
152
199
  const file = await this.readable.openFile(path, parseFlag('r'));
153
- const stats = new Stats(await file.stat());
200
+ const stats = await file.stat();
154
201
  const { buffer } = await file.read(new Uint8Array(stats.size));
155
202
  return new PreloadFile(this, path, flag, stats, buffer);
156
203
  }
@@ -160,7 +207,7 @@ export class UnmutexedOverlayFS extends FileSystem {
160
207
  }
161
208
  // Create an OverlayFile.
162
209
  const file = this.readable.openFileSync(path, parseFlag('r'));
163
- const stats = new Stats(file.statSync());
210
+ const stats = file.statSync();
164
211
  const data = new Uint8Array(stats.size);
165
212
  file.readSync(data);
166
213
  return new PreloadFile(this, path, flag, stats, data);
@@ -177,10 +224,12 @@ export class UnmutexedOverlayFS extends FileSystem {
177
224
  }
178
225
  async link(srcpath, dstpath) {
179
226
  this.checkInitialized();
227
+ await this.copyForWrite(srcpath);
180
228
  await this.writable.link(srcpath, dstpath);
181
229
  }
182
230
  linkSync(srcpath, dstpath) {
183
231
  this.checkInitialized();
232
+ this.copyForWriteSync(srcpath);
184
233
  this.writable.linkSync(srcpath, dstpath);
185
234
  }
186
235
  async unlink(path) {
@@ -219,15 +268,14 @@ export class UnmutexedOverlayFS extends FileSystem {
219
268
  if (await this.writable.exists(path)) {
220
269
  await this.writable.rmdir(path);
221
270
  }
222
- if (await this.exists(path)) {
223
- // Check if directory is empty.
224
- if ((await this.readdir(path)).length > 0) {
225
- throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
226
- }
227
- else {
228
- await this.deletePath(path);
229
- }
271
+ if (!(await this.exists(path))) {
272
+ return;
230
273
  }
274
+ // Check if directory is empty.
275
+ if ((await this.readdir(path)).length) {
276
+ throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
277
+ }
278
+ await this.deletePath(path);
231
279
  }
232
280
  rmdirSync(path) {
233
281
  this.checkInitialized();
@@ -237,15 +285,14 @@ export class UnmutexedOverlayFS extends FileSystem {
237
285
  if (this.writable.existsSync(path)) {
238
286
  this.writable.rmdirSync(path);
239
287
  }
240
- if (this.existsSync(path)) {
241
- // Check if directory is empty.
242
- if (this.readdirSync(path).length > 0) {
243
- throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
244
- }
245
- else {
246
- void this.deletePath(path);
247
- }
288
+ if (!this.existsSync(path)) {
289
+ return;
248
290
  }
291
+ // Check if directory is empty.
292
+ if (this.readdirSync(path).length) {
293
+ throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
294
+ }
295
+ void this.deletePath(path);
249
296
  }
250
297
  async mkdir(path, mode) {
251
298
  this.checkInitialized();
@@ -403,19 +450,23 @@ export class UnmutexedOverlayFS extends FileSystem {
403
450
  * - Ensures p is on writable before proceeding. Throws an error if it doesn't exist.
404
451
  * - Calls f to perform operation on writable.
405
452
  */
406
- operateOnWritable(path) {
453
+ copyForWriteSync(path) {
407
454
  if (!this.existsSync(path)) {
408
- throw ErrnoError.With('ENOENT', path, 'operateOnWriteable');
455
+ throw ErrnoError.With('ENOENT', path, 'copyForWrite');
456
+ }
457
+ if (!this.writable.existsSync(dirname(path))) {
458
+ this.createParentDirectoriesSync(path);
409
459
  }
410
460
  if (!this.writable.existsSync(path)) {
411
- // File is on readable storage. Copy to writable storage before
412
- // changing its mode.
413
461
  this.copyToWritableSync(path);
414
462
  }
415
463
  }
416
- async operateOnWritableAsync(path) {
464
+ async copyForWrite(path) {
417
465
  if (!(await this.exists(path))) {
418
- throw ErrnoError.With('ENOENT', path, 'operateOnWritable');
466
+ throw ErrnoError.With('ENOENT', path, 'copyForWrite');
467
+ }
468
+ if (!(await this.writable.exists(dirname(path)))) {
469
+ await this.createParentDirectories(path);
419
470
  }
420
471
  if (!(await this.writable.exists(path))) {
421
472
  return this.copyToWritable(path);
@@ -426,32 +477,50 @@ export class UnmutexedOverlayFS extends FileSystem {
426
477
  * PRECONDITION: File does not exist on writable storage.
427
478
  */
428
479
  copyToWritableSync(path) {
429
- const stats = this.statSync(path);
430
- if (stats.isDirectory()) {
431
- this.writable.mkdirSync(path, stats.mode);
432
- return;
480
+ const env_1 = { stack: [], error: void 0, hasError: false };
481
+ try {
482
+ const stats = this.statSync(path);
483
+ if (stats.isDirectory()) {
484
+ this.writable.mkdirSync(path, stats.mode);
485
+ return;
486
+ }
487
+ const data = new Uint8Array(stats.size);
488
+ const readable = __addDisposableResource(env_1, this.readable.openFileSync(path, 'r'), false);
489
+ readable.readSync(data);
490
+ const writable = __addDisposableResource(env_1, this.writable.createFileSync(path, 'w', stats.mode | 0o222), false);
491
+ writable.writeSync(data);
492
+ }
493
+ catch (e_1) {
494
+ env_1.error = e_1;
495
+ env_1.hasError = true;
496
+ }
497
+ finally {
498
+ __disposeResources(env_1);
433
499
  }
434
- const data = new Uint8Array(stats.size);
435
- const readable = this.readable.openFileSync(path, parseFlag('r'));
436
- readable.readSync(data);
437
- readable.closeSync();
438
- const writable = this.writable.openFileSync(path, parseFlag('w'));
439
- writable.writeSync(data);
440
- writable.closeSync();
441
500
  }
442
501
  async copyToWritable(path) {
443
- const stats = await this.stat(path);
444
- if (stats.isDirectory()) {
445
- await this.writable.mkdir(path, stats.mode);
446
- return;
502
+ const env_2 = { stack: [], error: void 0, hasError: false };
503
+ try {
504
+ const stats = await this.stat(path);
505
+ if (stats.isDirectory()) {
506
+ await this.writable.mkdir(path, stats.mode);
507
+ return;
508
+ }
509
+ const data = new Uint8Array(stats.size);
510
+ const readable = __addDisposableResource(env_2, await this.readable.openFile(path, 'r'), true);
511
+ await readable.read(data);
512
+ const writable = __addDisposableResource(env_2, await this.writable.createFile(path, 'w', stats.mode | 0o222), true);
513
+ await writable.write(data);
514
+ }
515
+ catch (e_2) {
516
+ env_2.error = e_2;
517
+ env_2.hasError = true;
518
+ }
519
+ finally {
520
+ const result_1 = __disposeResources(env_2);
521
+ if (result_1)
522
+ await result_1;
447
523
  }
448
- const data = new Uint8Array(stats.size);
449
- const readable = await this.readable.openFile(path, parseFlag('r'));
450
- await readable.read(data);
451
- await readable.close();
452
- const writable = await this.writable.openFile(path, parseFlag('w'));
453
- await writable.write(data);
454
- await writable.close();
455
524
  }
456
525
  }
457
526
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "A filesystem, anywhere",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -75,7 +75,7 @@ export class UnmutexedOverlayFS extends FileSystem {
75
75
  }
76
76
 
77
77
  public async sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void> {
78
- await this.createParentDirectories(path);
78
+ await this.copyForWrite(path);
79
79
  if (!(await this.writable.exists(path))) {
80
80
  await this.writable.createFile(path, 'w', 0o644);
81
81
  }
@@ -83,7 +83,7 @@ export class UnmutexedOverlayFS extends FileSystem {
83
83
  }
84
84
 
85
85
  public syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void {
86
- this.createParentDirectoriesSync(path);
86
+ this.copyForWriteSync(path);
87
87
  this.writable.syncSync(path, data, stats);
88
88
  }
89
89
 
@@ -126,6 +126,8 @@ export class UnmutexedOverlayFS extends FileSystem {
126
126
  this.checkPath(oldPath);
127
127
  this.checkPath(newPath);
128
128
 
129
+ await this.copyForWrite(oldPath);
130
+
129
131
  try {
130
132
  await this.writable.rename(oldPath, newPath);
131
133
  } catch (e) {
@@ -140,6 +142,8 @@ export class UnmutexedOverlayFS extends FileSystem {
140
142
  this.checkPath(oldPath);
141
143
  this.checkPath(newPath);
142
144
 
145
+ this.copyForWriteSync(oldPath);
146
+
143
147
  try {
144
148
  this.writable.renameSync(oldPath, newPath);
145
149
  } catch (e) {
@@ -158,7 +162,7 @@ export class UnmutexedOverlayFS extends FileSystem {
158
162
  throw ErrnoError.With('ENOENT', path, 'stat');
159
163
  }
160
164
  const oldStat = new Stats(await this.readable.stat(path));
161
- // Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type
165
+ // Make the oldStat's mode writable.
162
166
  oldStat.mode |= 0o222;
163
167
  return oldStat;
164
168
  }
@@ -173,7 +177,7 @@ export class UnmutexedOverlayFS extends FileSystem {
173
177
  throw ErrnoError.With('ENOENT', path, 'stat');
174
178
  }
175
179
  const oldStat = new Stats(this.readable.statSync(path));
176
- // Make the oldStat's mode writable. Preserve the topmost part of the mode, which specifies the type.
180
+ // Make the oldStat's mode writable.
177
181
  oldStat.mode |= 0o222;
178
182
  return oldStat;
179
183
  }
@@ -185,7 +189,7 @@ export class UnmutexedOverlayFS extends FileSystem {
185
189
  }
186
190
  // Create an OverlayFile.
187
191
  const file = await this.readable.openFile(path, parseFlag('r'));
188
- const stats = new Stats(await file.stat());
192
+ const stats = await file.stat();
189
193
  const { buffer } = await file.read(new Uint8Array(stats.size));
190
194
  return new PreloadFile(this, path, flag, stats, buffer);
191
195
  }
@@ -196,7 +200,7 @@ export class UnmutexedOverlayFS extends FileSystem {
196
200
  }
197
201
  // Create an OverlayFile.
198
202
  const file = this.readable.openFileSync(path, parseFlag('r'));
199
- const stats = new Stats(file.statSync());
203
+ const stats = file.statSync();
200
204
  const data = new Uint8Array(stats.size);
201
205
  file.readSync(data);
202
206
  return new PreloadFile(this, path, flag, stats, data);
@@ -216,11 +220,13 @@ export class UnmutexedOverlayFS extends FileSystem {
216
220
 
217
221
  public async link(srcpath: string, dstpath: string): Promise<void> {
218
222
  this.checkInitialized();
223
+ await this.copyForWrite(srcpath);
219
224
  await this.writable.link(srcpath, dstpath);
220
225
  }
221
226
 
222
227
  public linkSync(srcpath: string, dstpath: string): void {
223
228
  this.checkInitialized();
229
+ this.copyForWriteSync(srcpath);
224
230
  this.writable.linkSync(srcpath, dstpath);
225
231
  }
226
232
 
@@ -266,14 +272,14 @@ export class UnmutexedOverlayFS extends FileSystem {
266
272
  if (await this.writable.exists(path)) {
267
273
  await this.writable.rmdir(path);
268
274
  }
269
- if (await this.exists(path)) {
270
- // Check if directory is empty.
271
- if ((await this.readdir(path)).length > 0) {
272
- throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
273
- } else {
274
- await this.deletePath(path);
275
- }
275
+ if (!(await this.exists(path))) {
276
+ return;
277
+ }
278
+ // Check if directory is empty.
279
+ if ((await this.readdir(path)).length) {
280
+ throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
276
281
  }
282
+ await this.deletePath(path);
277
283
  }
278
284
 
279
285
  public rmdirSync(path: string): void {
@@ -284,14 +290,14 @@ export class UnmutexedOverlayFS extends FileSystem {
284
290
  if (this.writable.existsSync(path)) {
285
291
  this.writable.rmdirSync(path);
286
292
  }
287
- if (this.existsSync(path)) {
288
- // Check if directory is empty.
289
- if (this.readdirSync(path).length > 0) {
290
- throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
291
- } else {
292
- void this.deletePath(path);
293
- }
293
+ if (!this.existsSync(path)) {
294
+ return;
294
295
  }
296
+ // Check if directory is empty.
297
+ if (this.readdirSync(path).length) {
298
+ throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
299
+ }
300
+ void this.deletePath(path);
295
301
  }
296
302
 
297
303
  public async mkdir(path: string, mode: number): Promise<void> {
@@ -463,20 +469,25 @@ export class UnmutexedOverlayFS extends FileSystem {
463
469
  * - Ensures p is on writable before proceeding. Throws an error if it doesn't exist.
464
470
  * - Calls f to perform operation on writable.
465
471
  */
466
- private operateOnWritable(path: string): void {
472
+ private copyForWriteSync(path: string): void {
467
473
  if (!this.existsSync(path)) {
468
- throw ErrnoError.With('ENOENT', path, 'operateOnWriteable');
474
+ throw ErrnoError.With('ENOENT', path, 'copyForWrite');
475
+ }
476
+ if (!this.writable.existsSync(dirname(path))) {
477
+ this.createParentDirectoriesSync(path);
469
478
  }
470
479
  if (!this.writable.existsSync(path)) {
471
- // File is on readable storage. Copy to writable storage before
472
- // changing its mode.
473
480
  this.copyToWritableSync(path);
474
481
  }
475
482
  }
476
483
 
477
- private async operateOnWritableAsync(path: string): Promise<void> {
484
+ private async copyForWrite(path: string): Promise<void> {
478
485
  if (!(await this.exists(path))) {
479
- throw ErrnoError.With('ENOENT', path, 'operateOnWritable');
486
+ throw ErrnoError.With('ENOENT', path, 'copyForWrite');
487
+ }
488
+
489
+ if (!(await this.writable.exists(dirname(path)))) {
490
+ await this.createParentDirectories(path);
480
491
  }
481
492
 
482
493
  if (!(await this.writable.exists(path))) {
@@ -496,12 +507,10 @@ export class UnmutexedOverlayFS extends FileSystem {
496
507
  }
497
508
 
498
509
  const data = new Uint8Array(stats.size);
499
- const readable = this.readable.openFileSync(path, parseFlag('r'));
510
+ using readable = this.readable.openFileSync(path, 'r');
500
511
  readable.readSync(data);
501
- readable.closeSync();
502
- const writable = this.writable.openFileSync(path, parseFlag('w'));
512
+ using writable = this.writable.createFileSync(path, 'w', stats.mode | 0o222);
503
513
  writable.writeSync(data);
504
- writable.closeSync();
505
514
  }
506
515
 
507
516
  private async copyToWritable(path: string): Promise<void> {
@@ -512,12 +521,10 @@ export class UnmutexedOverlayFS extends FileSystem {
512
521
  }
513
522
 
514
523
  const data = new Uint8Array(stats.size);
515
- const readable = await this.readable.openFile(path, parseFlag('r'));
524
+ await using readable = await this.readable.openFile(path, 'r');
516
525
  await readable.read(data);
517
- await readable.close();
518
- const writable = await this.writable.openFile(path, parseFlag('w'));
526
+ await using writable = await this.writable.createFile(path, 'w', stats.mode | 0o222);
519
527
  await writable.write(data);
520
- await writable.close();
521
528
  }
522
529
  }
523
530