@zenfs/core 1.10.2 → 1.10.4
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/backends/cow.d.ts +18 -30
- package/dist/backends/cow.js +14 -19
- package/dist/internal/file.js +3 -5
- package/dist/vfs/promises.js +10 -6
- package/dist/vfs/sync.js +7 -1
- package/package.json +1 -1
package/dist/backends/cow.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { CreationOptions, UsageInfo } from '../internal/filesystem.js';
|
|
|
3
3
|
import type { InodeLike } from '../internal/inode.js';
|
|
4
4
|
import type { Stats } from '../stats.js';
|
|
5
5
|
import { FileSystem } from '../internal/filesystem.js';
|
|
6
|
+
import { EventEmitter } from 'eventemitter3';
|
|
6
7
|
/**
|
|
7
8
|
* Configuration options for CoW.
|
|
8
9
|
* @category Backends and Configuration
|
|
@@ -12,22 +13,13 @@ export interface CopyOnWriteOptions {
|
|
|
12
13
|
readable: FileSystem;
|
|
13
14
|
/** The file system to write modified files to. */
|
|
14
15
|
writable: FileSystem;
|
|
15
|
-
/**
|
|
16
|
-
journal?:
|
|
16
|
+
/** @see {@link Journal} */
|
|
17
|
+
journal?: Journal;
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
19
20
|
* @hidden @deprecated use `CopyOnWriteOptions`
|
|
20
21
|
*/
|
|
21
22
|
export type OverlayOptions = CopyOnWriteOptions;
|
|
22
|
-
/**
|
|
23
|
-
* Configuration options for the journal used by CoW.
|
|
24
|
-
* @category Backends and Configuration
|
|
25
|
-
* @internal
|
|
26
|
-
*/
|
|
27
|
-
export interface JournalOptions {
|
|
28
|
-
/** The contents of the journal */
|
|
29
|
-
contents?: string | JournalEntry[];
|
|
30
|
-
}
|
|
31
23
|
declare const journalOperations: readonly ["delete"];
|
|
32
24
|
/**
|
|
33
25
|
* @internal
|
|
@@ -44,15 +36,16 @@ export interface JournalEntry {
|
|
|
44
36
|
* Tracks various operations for the CoW backend
|
|
45
37
|
* @internal
|
|
46
38
|
*/
|
|
47
|
-
export declare class Journal {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
export declare class Journal extends EventEmitter<{
|
|
40
|
+
update: [op: JournalOperation, path: string];
|
|
41
|
+
delete: [path: string];
|
|
42
|
+
}> {
|
|
43
|
+
protected entries: JournalEntry[];
|
|
51
44
|
toString(): string;
|
|
52
45
|
/**
|
|
53
46
|
* Parse a journal from a string
|
|
54
47
|
*/
|
|
55
|
-
fromString(value: string):
|
|
48
|
+
fromString(value: string): this;
|
|
56
49
|
add(op: JournalOperation, path: string): void;
|
|
57
50
|
has(op: JournalOperation, path: string): boolean;
|
|
58
51
|
isDeleted(path: string): boolean;
|
|
@@ -62,25 +55,20 @@ export declare class Journal {
|
|
|
62
55
|
* @internal
|
|
63
56
|
*/
|
|
64
57
|
export declare class CopyOnWriteFS extends FileSystem {
|
|
65
|
-
/**
|
|
66
|
-
* The file system that initially populates this file system.
|
|
67
|
-
*/
|
|
58
|
+
/** The file system that initially populates this file system. */
|
|
68
59
|
readonly readable: FileSystem;
|
|
69
|
-
/**
|
|
70
|
-
* The file system to write modified files to.
|
|
71
|
-
*/
|
|
60
|
+
/** The file system to write modified files to. */
|
|
72
61
|
readonly writable: FileSystem;
|
|
73
|
-
|
|
62
|
+
/** The journal to use for persisting deletions */
|
|
74
63
|
readonly journal: Journal;
|
|
64
|
+
ready(): Promise<void>;
|
|
75
65
|
constructor(
|
|
76
|
-
/**
|
|
77
|
-
* The file system that initially populates this file system.
|
|
78
|
-
*/
|
|
66
|
+
/** The file system that initially populates this file system. */
|
|
79
67
|
readable: FileSystem,
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
68
|
+
/** The file system to write modified files to. */
|
|
69
|
+
writable: FileSystem,
|
|
70
|
+
/** The journal to use for persisting deletions */
|
|
71
|
+
journal?: Journal);
|
|
84
72
|
isDeleted(path: string): boolean;
|
|
85
73
|
/**
|
|
86
74
|
* @todo Consider trying to track information on the writable as well
|
package/dist/backends/cow.js
CHANGED
|
@@ -56,6 +56,7 @@ import { LazyFile } from '../internal/file.js';
|
|
|
56
56
|
import { FileSystem } from '../internal/filesystem.js';
|
|
57
57
|
import { debug, err, warn } from '../internal/log.js';
|
|
58
58
|
import { dirname, join } from '../vfs/path.js';
|
|
59
|
+
import { EventEmitter } from 'eventemitter3';
|
|
59
60
|
const journalOperations = ['delete'];
|
|
60
61
|
/** Because TS doesn't work right w/o it */
|
|
61
62
|
function isJournalOp(op) {
|
|
@@ -67,9 +68,9 @@ const journalMagicString = '#journal@v0\n';
|
|
|
67
68
|
* Tracks various operations for the CoW backend
|
|
68
69
|
* @internal
|
|
69
70
|
*/
|
|
70
|
-
export class Journal {
|
|
71
|
-
constructor(
|
|
72
|
-
|
|
71
|
+
export class Journal extends EventEmitter {
|
|
72
|
+
constructor() {
|
|
73
|
+
super(...arguments);
|
|
73
74
|
this.entries = [];
|
|
74
75
|
}
|
|
75
76
|
toString() {
|
|
@@ -91,9 +92,12 @@ export class Journal {
|
|
|
91
92
|
}
|
|
92
93
|
this.entries.push({ op, path });
|
|
93
94
|
}
|
|
95
|
+
return this;
|
|
94
96
|
}
|
|
95
97
|
add(op, path) {
|
|
96
98
|
this.entries.push({ op, path });
|
|
99
|
+
this.emit('update', op, path);
|
|
100
|
+
this.emit(op, path);
|
|
97
101
|
}
|
|
98
102
|
has(op, path) {
|
|
99
103
|
const test = JSON.stringify({ op, path });
|
|
@@ -125,18 +129,16 @@ export class CopyOnWriteFS extends FileSystem {
|
|
|
125
129
|
await this.writable.ready();
|
|
126
130
|
}
|
|
127
131
|
constructor(
|
|
128
|
-
/**
|
|
129
|
-
* The file system that initially populates this file system.
|
|
130
|
-
*/
|
|
132
|
+
/** The file system that initially populates this file system. */
|
|
131
133
|
readable,
|
|
132
|
-
/**
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
/** The file system to write modified files to. */
|
|
135
|
+
writable,
|
|
136
|
+
/** The journal to use for persisting deletions */
|
|
137
|
+
journal = new Journal()) {
|
|
136
138
|
super(0x62756c6c, readable.name);
|
|
137
139
|
this.readable = readable;
|
|
138
140
|
this.writable = writable;
|
|
139
|
-
this.journal =
|
|
141
|
+
this.journal = journal;
|
|
140
142
|
if (writable.attributes.has('no_write')) {
|
|
141
143
|
throw err(new ErrnoError(Errno.EINVAL, 'Writable file system can not be written to'));
|
|
142
144
|
}
|
|
@@ -477,14 +479,7 @@ const _CopyOnWrite = {
|
|
|
477
479
|
journal: { type: 'object', required: false },
|
|
478
480
|
},
|
|
479
481
|
create(options) {
|
|
480
|
-
|
|
481
|
-
if (typeof options.journal == 'string') {
|
|
482
|
-
fs.journal.fromString(options.journal);
|
|
483
|
-
}
|
|
484
|
-
if (Array.isArray(options.journal)) {
|
|
485
|
-
fs.journal.entries.push(...options.journal);
|
|
486
|
-
}
|
|
487
|
-
return fs;
|
|
482
|
+
return new CopyOnWriteFS(options.readable, options.writable, options.journal);
|
|
488
483
|
},
|
|
489
484
|
};
|
|
490
485
|
/**
|
package/dist/internal/file.js
CHANGED
|
@@ -3,7 +3,7 @@ import { _chown, Stats } from '../stats.js';
|
|
|
3
3
|
import { config } from '../vfs/config.js';
|
|
4
4
|
import * as c from '../vfs/constants.js';
|
|
5
5
|
import { Errno, ErrnoError } from './error.js';
|
|
6
|
-
import { log_deprecated } from './log.js';
|
|
6
|
+
import { err, log_deprecated } from './log.js';
|
|
7
7
|
import '../polyfills.js';
|
|
8
8
|
const maxByteLength = 0xffff; // 64 KiB
|
|
9
9
|
const validFlags = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+'];
|
|
@@ -191,11 +191,10 @@ export class PreloadFile extends File {
|
|
|
191
191
|
This invariant is *not* maintained once the file starts getting modified.
|
|
192
192
|
It only actually matters if file is readable, as writeable modes may truncate/append to file.
|
|
193
193
|
*/
|
|
194
|
-
if (this.stats.size == _buffer.byteLength)
|
|
194
|
+
if (this.stats.size == _buffer.byteLength)
|
|
195
195
|
return;
|
|
196
|
-
}
|
|
197
196
|
if (!isWriteable(this.flag)) {
|
|
198
|
-
throw new ErrnoError(Errno.EIO, `Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`, path);
|
|
197
|
+
throw err(new ErrnoError(Errno.EIO, `Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`, path));
|
|
199
198
|
}
|
|
200
199
|
this.stats.size = _buffer.byteLength;
|
|
201
200
|
this.dirty = true;
|
|
@@ -515,7 +514,6 @@ export class LazyFile extends File {
|
|
|
515
514
|
* Whether the file is open or closed
|
|
516
515
|
*/
|
|
517
516
|
this.closed = false;
|
|
518
|
-
this.dirty = true;
|
|
519
517
|
}
|
|
520
518
|
async sync() {
|
|
521
519
|
if (this.closed)
|
package/dist/vfs/promises.js
CHANGED
|
@@ -64,6 +64,7 @@ import { dirname, join, parse, resolve } from './path.js';
|
|
|
64
64
|
import { _statfs, fd2file, fdMap, file2fd, fixError, resolveMount } from './shared.js';
|
|
65
65
|
import { ReadStream, WriteStream } from './streams.js';
|
|
66
66
|
import { FSWatcher, emitChange } from './watchers.js';
|
|
67
|
+
import { _throw } from 'utilium';
|
|
67
68
|
export * as constants from './constants.js';
|
|
68
69
|
export class FileHandle {
|
|
69
70
|
constructor(fdOrFile, context) {
|
|
@@ -677,11 +678,8 @@ mkdir;
|
|
|
677
678
|
export async function readdir(path, options) {
|
|
678
679
|
options = typeof options === 'object' ? options : { encoding: options };
|
|
679
680
|
path = await realpath.call(this, path);
|
|
680
|
-
const handleError = (e) => {
|
|
681
|
-
throw fixError(e, { [resolved]: path });
|
|
682
|
-
};
|
|
683
681
|
const { fs, path: resolved } = resolveMount(path, this);
|
|
684
|
-
const stats = await fs.stat(resolved).catch(
|
|
682
|
+
const stats = await fs.stat(resolved).catch((e) => _throw(fixError(e, { [resolved]: path })));
|
|
685
683
|
if (!stats) {
|
|
686
684
|
throw ErrnoError.With('ENOENT', path, 'readdir');
|
|
687
685
|
}
|
|
@@ -691,12 +689,18 @@ export async function readdir(path, options) {
|
|
|
691
689
|
if (!stats.isDirectory()) {
|
|
692
690
|
throw ErrnoError.With('ENOTDIR', path, 'readdir');
|
|
693
691
|
}
|
|
694
|
-
const entries = await fs.readdir(resolved).catch(
|
|
692
|
+
const entries = await fs.readdir(resolved).catch((e) => _throw(fixError(e, { [resolved]: path })));
|
|
695
693
|
const values = [];
|
|
696
694
|
const addEntry = async (entry) => {
|
|
697
695
|
let entryStats;
|
|
698
696
|
if ((options === null || options === void 0 ? void 0 : options.recursive) || (options === null || options === void 0 ? void 0 : options.withFileTypes)) {
|
|
699
|
-
entryStats = await fs.stat(join(resolved, entry)).catch(
|
|
697
|
+
entryStats = await fs.stat(join(resolved, entry)).catch((e) => {
|
|
698
|
+
if (e.code == 'ENOENT')
|
|
699
|
+
return;
|
|
700
|
+
throw fixError(e, { [resolved]: path });
|
|
701
|
+
});
|
|
702
|
+
if (!entryStats)
|
|
703
|
+
return;
|
|
700
704
|
}
|
|
701
705
|
if (options === null || options === void 0 ? void 0 : options.withFileTypes) {
|
|
702
706
|
values.push(new Dirent(entry, entryStats));
|
package/dist/vfs/sync.js
CHANGED
|
@@ -499,7 +499,13 @@ export function readdirSync(path, options) {
|
|
|
499
499
|
// Iterate over entries and handle recursive case if needed
|
|
500
500
|
const values = [];
|
|
501
501
|
for (const entry of entries) {
|
|
502
|
-
|
|
502
|
+
let entryStat;
|
|
503
|
+
try {
|
|
504
|
+
entryStat = fs.statSync(join(resolved, entry));
|
|
505
|
+
}
|
|
506
|
+
catch {
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
503
509
|
if (options === null || options === void 0 ? void 0 : options.withFileTypes) {
|
|
504
510
|
values.push(new Dirent(entry, entryStat));
|
|
505
511
|
}
|