@effect-vfs/core 0.0.1 → 0.1.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.
- package/README.md +49 -2
- package/dist/VirtualFileSystem.d.ts +137 -0
- package/dist/VirtualFileSystem.d.ts.map +1 -1
- package/dist/VirtualFileSystem.js +262 -63
- package/dist/internal/content.d.ts +25 -0
- package/dist/internal/content.d.ts.map +1 -0
- package/dist/internal/content.js +26 -0
- package/dist/internal/overlayChanges.d.ts +50 -0
- package/dist/internal/overlayChanges.d.ts.map +1 -0
- package/dist/internal/overlayChanges.js +157 -0
- package/dist/internal/overlayTesting.d.ts +12 -0
- package/dist/internal/overlayTesting.d.ts.map +1 -0
- package/dist/internal/overlayTesting.js +12 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Effect's standard `FileSystem` service, use [`@effect-vfs/memory`](https://www.n
|
|
|
10
10
|
which adapts this package to that interface.
|
|
11
11
|
|
|
12
12
|
The package implements a documented subset of POSIX behavior. It does not claim full POSIX conformance. See the
|
|
13
|
-
[implemented profile](https://github.com/lloydrichards/effect-virtual-fs/blob/main/.
|
|
13
|
+
[implemented profile](https://github.com/lloydrichards/effect-virtual-fs/blob/main/.okf/profiles/implemented-filesystem.md)
|
|
14
14
|
for the exact permission, path, timestamp, quota, and atomicity rules.
|
|
15
15
|
|
|
16
16
|
## Install
|
|
@@ -174,6 +174,53 @@ Snapshot decoding requires explicit work limits because encoded bytes may come f
|
|
|
174
174
|
contains the reachable namespace and metadata. It excludes callers, open handles, cursor positions, watch
|
|
175
175
|
subscriptions, and unlinked content. Each restored volume is independent.
|
|
176
176
|
|
|
177
|
+
## Branch from one immutable snapshot
|
|
178
|
+
|
|
179
|
+
Use `makeOverlay` when several writable workspaces start from the same snapshot. Untouched regular-file contents are
|
|
180
|
+
shared internally. A content change copies that whole file for the editing workspace; namespace and metadata state are
|
|
181
|
+
always private. Logical quotas still count the complete visible volume, including shared base files and unlinked-open
|
|
182
|
+
contents.
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
186
|
+
import { Effect } from "effect"
|
|
187
|
+
|
|
188
|
+
const branch = Effect.gen(function*() {
|
|
189
|
+
const template = yield* Vfs.fromFixture({
|
|
190
|
+
entries: [
|
|
191
|
+
{ kind: "directory", path: "/project" },
|
|
192
|
+
{ kind: "file", path: "/project/settings.json", bytes: new Uint8Array() }
|
|
193
|
+
]
|
|
194
|
+
})
|
|
195
|
+
const base = yield* template.snapshot
|
|
196
|
+
const workspace = yield* Vfs.makeOverlay(base, { maxBytes: 1_000_000 })
|
|
197
|
+
const fs = yield* workspace.caller()
|
|
198
|
+
|
|
199
|
+
yield* fs.rename("/project/settings.json", "/project/preferences.json")
|
|
200
|
+
return yield* workspace.capture()
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`makeOverlay(base, options)` returns a reusable Effect. Each execution creates a fresh workspace from `base`; it does
|
|
205
|
+
not memoize or reset an earlier workspace. Invalid volume options fail with `ConfigurationError`, while failure to
|
|
206
|
+
inspect the base snapshot fails with `ImageError`.
|
|
207
|
+
|
|
208
|
+
`changes()` reports final differences from the base. It hides timestamp-only differences unless called with
|
|
209
|
+
`{ includeTimestamps: true }`. Renames are paired only from retained object identity; equal contents are never treated
|
|
210
|
+
as rename evidence. Paths in summaries are `BytePath` values, so inspect them with `pathToBytes` when names may not be
|
|
211
|
+
UTF-8. Although `OverlayChange` and its options have schemas, a summary is an in-process value containing opaque
|
|
212
|
+
`BytePath` objects. The schema is not a portable summary encoding.
|
|
213
|
+
|
|
214
|
+
`capture()` returns a complete version 1 snapshot and matching summary from one committed state. Later writes change
|
|
215
|
+
neither result. The snapshot works with `encodeSnapshot`, `fromSnapshot`, and `@effect-vfs/persistence` checkpoints.
|
|
216
|
+
Restoring it recovers the complete filesystem state, not the earlier overlay base relationship or summary. To reset,
|
|
217
|
+
create a fresh overlay from the base and replace your application reference; existing callers, handles, and watches
|
|
218
|
+
remain attached to the old workspace until their own lifetimes end.
|
|
219
|
+
|
|
220
|
+
The Effects returned by `changes(options)` and `capture(options)` are also reusable. Each execution observes the
|
|
221
|
+
workspace again. Invalid summary options fail with `ConfigurationError`; failure to construct the complete observed
|
|
222
|
+
snapshot fails with `ImageError`. Reusing a previously completed `capture()` result does not observe later writes.
|
|
223
|
+
|
|
177
224
|
## Use scoped handles for incremental I/O
|
|
178
225
|
|
|
179
226
|
Whole-file operations are convenient, but handles give each open file an independent `bigint` cursor and support
|
|
@@ -280,4 +327,4 @@ candidate.
|
|
|
280
327
|
- `sync` checks handle liveness. An in-memory volume provides no host or crash durability.
|
|
281
328
|
|
|
282
329
|
For the complete contract, read the
|
|
283
|
-
[implemented profile](https://github.com/lloydrichards/effect-virtual-fs/blob/main/.
|
|
330
|
+
[implemented profile](https://github.com/lloydrichards/effect-virtual-fs/blob/main/.okf/profiles/implemented-filesystem.md).
|
|
@@ -19,6 +19,13 @@ declare const DirectoryHandleId: unique symbol;
|
|
|
19
19
|
export interface BytePath {
|
|
20
20
|
readonly [BytePathId]: true;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Schema for an opaque byte-preserving filesystem path.
|
|
24
|
+
*
|
|
25
|
+
* @category schemas
|
|
26
|
+
* @since 0.1.0
|
|
27
|
+
*/
|
|
28
|
+
export declare const BytePath: Schema.declare<BytePath, BytePath>;
|
|
22
29
|
/**
|
|
23
30
|
* A UTF-8 string path or an opaque byte-preserving path.
|
|
24
31
|
*
|
|
@@ -450,6 +457,102 @@ export interface Change {
|
|
|
450
457
|
/** Absolute path of the changed entry. */
|
|
451
458
|
readonly path: BytePath;
|
|
452
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* Schema for the filesystem entry kinds reported by overlay summaries.
|
|
462
|
+
*
|
|
463
|
+
* @category schemas
|
|
464
|
+
* @since 0.1.0
|
|
465
|
+
*/
|
|
466
|
+
export declare const OverlayNodeKind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
467
|
+
/**
|
|
468
|
+
* A filesystem entry kind reported by an overlay summary.
|
|
469
|
+
*
|
|
470
|
+
* @category models
|
|
471
|
+
* @since 0.1.0
|
|
472
|
+
*/
|
|
473
|
+
export type OverlayNodeKind = typeof OverlayNodeKind.Type;
|
|
474
|
+
/**
|
|
475
|
+
* Schema for observable fields that can differ from an overlay's immutable base.
|
|
476
|
+
*
|
|
477
|
+
* @category schemas
|
|
478
|
+
* @since 0.1.0
|
|
479
|
+
*/
|
|
480
|
+
export declare const OverlayDifference: Schema.Literals<readonly ["content", "mode", "uid", "gid", "atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]>;
|
|
481
|
+
/**
|
|
482
|
+
* A content, ownership, permission, or timestamp field that differs from the overlay base.
|
|
483
|
+
*
|
|
484
|
+
* @category models
|
|
485
|
+
* @since 0.1.0
|
|
486
|
+
*/
|
|
487
|
+
export type OverlayDifference = typeof OverlayDifference.Type;
|
|
488
|
+
/**
|
|
489
|
+
* Schema for a final-state overlay difference.
|
|
490
|
+
*
|
|
491
|
+
* **Details**
|
|
492
|
+
*
|
|
493
|
+
* Paths retain arbitrary non-NUL bytes. Renames are reported only when retained
|
|
494
|
+
* base identity makes the removed and added names unambiguous.
|
|
495
|
+
*
|
|
496
|
+
* @category schemas
|
|
497
|
+
* @since 0.1.0
|
|
498
|
+
*/
|
|
499
|
+
export declare const OverlayChange: Schema.Union<readonly [Schema.TaggedStruct<"Added", {
|
|
500
|
+
readonly path: Schema.declare<BytePath, BytePath>;
|
|
501
|
+
readonly kind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
502
|
+
}>, Schema.TaggedStruct<"Removed", {
|
|
503
|
+
readonly path: Schema.declare<BytePath, BytePath>;
|
|
504
|
+
readonly kind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
505
|
+
}>, Schema.TaggedStruct<"Replaced", {
|
|
506
|
+
readonly path: Schema.declare<BytePath, BytePath>;
|
|
507
|
+
readonly beforeKind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
508
|
+
readonly afterKind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
509
|
+
readonly differences: Schema.$Array<Schema.Literals<readonly ["content", "mode", "uid", "gid", "atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]>>;
|
|
510
|
+
}>, Schema.TaggedStruct<"Renamed", {
|
|
511
|
+
readonly from: Schema.declare<BytePath, BytePath>;
|
|
512
|
+
readonly to: Schema.declare<BytePath, BytePath>;
|
|
513
|
+
readonly kind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
514
|
+
readonly differences: Schema.$Array<Schema.Literals<readonly ["content", "mode", "uid", "gid", "atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]>>;
|
|
515
|
+
}>, Schema.TaggedStruct<"Updated", {
|
|
516
|
+
readonly path: Schema.declare<BytePath, BytePath>;
|
|
517
|
+
readonly kind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
|
|
518
|
+
readonly differences: Schema.$Array<Schema.Literals<readonly ["content", "mode", "uid", "gid", "atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]>>;
|
|
519
|
+
}>]>;
|
|
520
|
+
/**
|
|
521
|
+
* A path-oriented final-state difference from an overlay's immutable base.
|
|
522
|
+
*
|
|
523
|
+
* @category models
|
|
524
|
+
* @since 0.1.0
|
|
525
|
+
*/
|
|
526
|
+
export type OverlayChange = typeof OverlayChange.Type;
|
|
527
|
+
/**
|
|
528
|
+
* Schema for overlay summary filtering.
|
|
529
|
+
*
|
|
530
|
+
* @category schemas
|
|
531
|
+
* @since 0.1.0
|
|
532
|
+
*/
|
|
533
|
+
export declare const OverlayChangesOptions: Schema.Struct<{
|
|
534
|
+
/** Include access, modification, change, and birth-time differences. Defaults to `false`. */
|
|
535
|
+
readonly includeTimestamps: Schema.optionalKey<Schema.Boolean>;
|
|
536
|
+
}>;
|
|
537
|
+
/**
|
|
538
|
+
* Filtering options for an overlay final-difference summary.
|
|
539
|
+
*
|
|
540
|
+
* @category models
|
|
541
|
+
* @since 0.1.0
|
|
542
|
+
*/
|
|
543
|
+
export type OverlayChangesOptions = typeof OverlayChangesOptions.Type;
|
|
544
|
+
/**
|
|
545
|
+
* A complete snapshot and final-difference summary captured from one committed state.
|
|
546
|
+
*
|
|
547
|
+
* @category models
|
|
548
|
+
* @since 0.1.0
|
|
549
|
+
*/
|
|
550
|
+
export interface OverlayCapture {
|
|
551
|
+
/** Complete version 1 snapshot owned by this capture. */
|
|
552
|
+
readonly snapshot: Snapshot;
|
|
553
|
+
/** Owned summary that describes the same state as `snapshot`. */
|
|
554
|
+
readonly changes: ReadonlyArray<OverlayChange>;
|
|
555
|
+
}
|
|
453
556
|
/**
|
|
454
557
|
* An isolated virtual filesystem namespace that creates callers, snapshots, and watch streams.
|
|
455
558
|
*
|
|
@@ -465,6 +568,18 @@ export interface Volume {
|
|
|
465
568
|
/** Creates a caller rooted at `/` with independent credentials, umask, and current directory. */
|
|
466
569
|
readonly caller: (options?: RootCallerOptions) => Effect.Effect<Caller, ConfigurationError>;
|
|
467
570
|
}
|
|
571
|
+
/**
|
|
572
|
+
* An ordinary volume with final-state inspection relative to one immutable snapshot base.
|
|
573
|
+
*
|
|
574
|
+
* @category models
|
|
575
|
+
* @since 0.1.0
|
|
576
|
+
*/
|
|
577
|
+
export interface OverlayVolume extends Volume {
|
|
578
|
+
/** Computes final differences from the immutable base when this reusable effect executes. */
|
|
579
|
+
readonly changes: (options?: OverlayChangesOptions) => Effect.Effect<ReadonlyArray<OverlayChange>, ConfigurationError | ImageError>;
|
|
580
|
+
/** Captures one committed state when this reusable effect executes. */
|
|
581
|
+
readonly capture: (options?: OverlayChangesOptions) => Effect.Effect<OverlayCapture, ConfigurationError | ImageError>;
|
|
582
|
+
}
|
|
468
583
|
declare const CurrentFileSystem_base: Context.ServiceClass<CurrentFileSystem, "@effect-vfs/core/CurrentFileSystem", Caller>;
|
|
469
584
|
/**
|
|
470
585
|
* Optional Effect service for providing an existing filesystem caller.
|
|
@@ -535,6 +650,28 @@ export declare const fromSnapshot: (snapshot: Snapshot, options?: {
|
|
|
535
650
|
readonly maxFileBytes?: number;
|
|
536
651
|
readonly maxPathBytes?: number;
|
|
537
652
|
} | undefined) => Effect.Effect<Volume, ConfigurationError | ImageError, never>;
|
|
653
|
+
/**
|
|
654
|
+
* Creates an isolated writable volume relative to one immutable snapshot base.
|
|
655
|
+
*
|
|
656
|
+
* **Details**
|
|
657
|
+
*
|
|
658
|
+
* Workspaces made from the same snapshot share unchanged regular-file payloads.
|
|
659
|
+
* The first content mutation copies the whole file into workspace-private
|
|
660
|
+
* storage. Metadata, namespace state, coordination, handles, and watches are
|
|
661
|
+
* always private to the new workspace.
|
|
662
|
+
*
|
|
663
|
+
* Invalid base snapshots fail with `ImageError`; invalid volume limits fail
|
|
664
|
+
* with `ConfigurationError`. Each execution creates a fresh workspace.
|
|
665
|
+
*
|
|
666
|
+
* @category constructors
|
|
667
|
+
* @since 0.1.0
|
|
668
|
+
*/
|
|
669
|
+
export declare const makeOverlay: (base: Snapshot, options?: {
|
|
670
|
+
readonly maxEntries?: number;
|
|
671
|
+
readonly maxBytes?: number;
|
|
672
|
+
readonly maxFileBytes?: number;
|
|
673
|
+
readonly maxPathBytes?: number;
|
|
674
|
+
} | undefined) => Effect.Effect<OverlayVolume, ConfigurationError | ImageError, never>;
|
|
538
675
|
/**
|
|
539
676
|
* Schema for a complete fixture namespace with optional metadata and forward hard links.
|
|
540
677
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualFileSystem.d.ts","sourceRoot":"","sources":["../src/VirtualFileSystem.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AACvE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAEvF,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAIvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,QAAA,MAAM,UAAU,eAAsC,CAAA;AACtD,QAAA,MAAM,QAAQ,eAAoC,CAAA;AAClD,QAAA,MAAM,QAAQ,eAAoC,CAAA;AAClD,QAAA,MAAM,YAAY,eAAwC,CAAA;AAC1D,QAAA,MAAM,iBAAiB,eAA6C,CAAA;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,CAAA;CAC5B;AACD;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,MAAM,0SAkBjB,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;;;;AACvC;;;;;GAKG;AACH,qBAAa,OAAQ,SAAQ,aAA4B;IACvD,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAC1B,CAAC;CAAG;;;;AACL;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAC;CAAG;AAQL;;;;;GAKG;AACH,eAAO,MAAM,QAAQ;IACnB,uEAAuE;;IAEvE,wCAAwC;;IAExC,uEAAuE;;IAEvE,oEAAoE;;EAEpE,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAC3C;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;IAC5B,+DAA+D;;QAvB/D,uEAAuE;;QAEvE,wCAAwC;;QAExC,uEAAuE;;QAEvE,oEAAoE;;;IAmBpE,qEAAqE;;EAErE,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAA;AAC7D;;;;;GAKG;AACH,eAAO,MAAM,aAAa;IACxB,+EAA+E;;IAE/E,sDAAsD;;IAEtD,yDAAyD;;IAEzD,mEAAmE;;EAEnE,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AAOrD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;EAYnB,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,2GAA2G;IAC3G,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAA;CACtC;AACD;;;;;GAKG;AACH,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,0DAA0D;IAC1D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CACtC;AACD;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;EAAwF,CAAA;AAChH;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AACjD;;;;;GAKG;AACH,eAAO,MAAM,UAAU;;;;;;;IAIrB,CAAA;AACF;;;;;GAKG;AACH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;EAAkE,CAAA;AACpF;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AACrC;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAA;IAClC,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC/C,sFAAsF;IACtF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;CAC7C;AACD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,uEAA+D,CAAA;AACpF;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAC3C;;;;;GAKG;AACH,eAAO,MAAM,YAAY;IACvB,mDAAmD;;IAEnD,8CAA8C;;IAE9C,yEAAyE;;IAEzE,wEAAwE;;IAExE,mEAAmE;;IAEnE,0DAA0D;;EAE1D,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,YAAY,CAAC,IAAI,GAAG,eAAe,CAAA;AACpE,QAAA,MAAM,iBAAiB;IApBrB,mDAAmD;;IAEnD,8CAA8C;;IAE9C,yEAAyE;;IAEzE,wEAAwE;;IAExE,mEAAmE;;IAEnE,0DAA0D;;IAY1D,oEAAoE;;IAEpE,sDAAsD;;EAEtD,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,iBAAiB,CAAC,IAAI,GAAG,eAAe,CAAA;AAC9E;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,CAAA;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC3E,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC5F,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACrE,qGAAqG;IACrG,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtF,sGAAsG;IACtG,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjF,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACnE,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC/C,0FAA0F;IAC1F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC3C,sFAAsF;IACtF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;CAC7C;AACD;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;IACzB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC/F,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,CACf,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,SAAS,EACtB,OAAO,CAAC,EAAE;QACR,iDAAiD;QACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,eAAe,CAAA;QAC3C,sDAAsD;QACtD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,eAAe,CAAA;KACjD,KACE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IACrG,sFAAsF;IACtF,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACnH,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC5G,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC/G,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC1G,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAChH,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC3G,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC1G,oEAAoE;IACpE,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,EAAE,KAAK,EAAE,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAChH,gFAAgF;IAChF,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC3G,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAChG,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,CACb,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,SAAS,EACtB,OAAO,CAAC,EAAE;QACR,iDAAiD;QACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,eAAe,CAAA;QAC3C,sDAAsD;QACtD,QAAQ,CAAC,qBAAqB,CAAC,EAAE,eAAe,CAAA;QAChD,2EAA2E;QAC3E,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;KACvC,KACE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACjC,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACjH,iGAAiG;IACjG,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjG,mDAAmD;IACnD,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC1G,gFAAgF;IAChF,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAA;IACrH,kDAAkD;IAClD,QAAQ,CAAC,kBAAkB,EAAE,CAC3B,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,eAAe,KACtB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,CAAA;IACtD,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjG,0EAA0E;IAC1E,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACxG,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACzG,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC7F,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC5F,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,CACd,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,eAAe,GAAG;QAC1B,8EAA8E;QAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KACvB,KACE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACjC,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACnH,iFAAiF;IACjF,QAAQ,CAAC,aAAa,EAAE,CACtB,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,eAAe,KACtB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;CAC1D;AACD;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;IAC7C,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CACxB;AACD;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACxE,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACtD,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;IACzB,iGAAiG;IACjG,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;CAC5F;;AACD;;;;;GAKG;AACH,qBAAa,iBACX,SAAQ,sBAAkF;CAC1F;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAwB,CAAA;AAEjH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,CAC3B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,YAAY,KACjB,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAwB,CAAA;AAgC/D;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,iFAUxB,CAAA;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,4EAItB,CAAA;AA80CF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI;;;;;kEAEf,CAAA;AACF;;;;;GAKG;AACH,eAAO,MAAM,YAAY;;;;;+EAKxB,CAAA;AAiBD;;;;;;;;;GASG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBlB,CAAA;AACF;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AACzC;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+EAoIvB,CAAA"}
|
|
1
|
+
{"version":3,"file":"VirtualFileSystem.d.ts","sourceRoot":"","sources":["../src/VirtualFileSystem.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,12 +21,23 @@ import * as Schema from "effect/Schema";
|
|
|
21
21
|
import * as Scope from "effect/Scope";
|
|
22
22
|
import * as Semaphore from "effect/Semaphore";
|
|
23
23
|
import * as Stream from "effect/Stream";
|
|
24
|
+
import * as Content from "./internal/content.js";
|
|
24
25
|
import * as Image from "./internal/image.js";
|
|
26
|
+
import { compareOverlay } from "./internal/overlayChanges.js";
|
|
27
|
+
import * as OverlayTesting from "./internal/overlayTesting.js";
|
|
25
28
|
const BytePathId = Symbol("@effect-vfs/core/BytePath");
|
|
26
29
|
const VolumeId = Symbol("@effect-vfs/core/Volume");
|
|
27
30
|
const CallerId = Symbol("@effect-vfs/core/Caller");
|
|
28
31
|
const FileHandleId = Symbol("@effect-vfs/core/FileHandle");
|
|
29
32
|
const DirectoryHandleId = Symbol("@effect-vfs/core/DirectoryHandle");
|
|
33
|
+
const bytePaths = new WeakMap();
|
|
34
|
+
/**
|
|
35
|
+
* Schema for an opaque byte-preserving filesystem path.
|
|
36
|
+
*
|
|
37
|
+
* @category schemas
|
|
38
|
+
* @since 0.1.0
|
|
39
|
+
*/
|
|
40
|
+
export const BytePath = Schema.declare((value) => typeof value === "object" && value !== null && bytePaths.has(value));
|
|
30
41
|
/**
|
|
31
42
|
* Schema for portable virtual filesystem error codes.
|
|
32
43
|
*
|
|
@@ -195,6 +206,69 @@ const WriteFileSettings = Schema.Struct({
|
|
|
195
206
|
/** Mode to apply after replacing an existing file. */
|
|
196
207
|
finalMode: Schema.optionalKey(Mode)
|
|
197
208
|
});
|
|
209
|
+
/**
|
|
210
|
+
* Schema for the filesystem entry kinds reported by overlay summaries.
|
|
211
|
+
*
|
|
212
|
+
* @category schemas
|
|
213
|
+
* @since 0.1.0
|
|
214
|
+
*/
|
|
215
|
+
export const OverlayNodeKind = Schema.Literals(["directory", "file", "symlink"]);
|
|
216
|
+
/**
|
|
217
|
+
* Schema for observable fields that can differ from an overlay's immutable base.
|
|
218
|
+
*
|
|
219
|
+
* @category schemas
|
|
220
|
+
* @since 0.1.0
|
|
221
|
+
*/
|
|
222
|
+
export const OverlayDifference = Schema.Literals([
|
|
223
|
+
"content",
|
|
224
|
+
"mode",
|
|
225
|
+
"uid",
|
|
226
|
+
"gid",
|
|
227
|
+
"atimeNs",
|
|
228
|
+
"mtimeNs",
|
|
229
|
+
"ctimeNs",
|
|
230
|
+
"birthtimeNs"
|
|
231
|
+
]);
|
|
232
|
+
const OverlayDifferences = Schema.Array(OverlayDifference);
|
|
233
|
+
const NonEmptyOverlayDifferences = OverlayDifferences.check(Schema.isMinLength(1));
|
|
234
|
+
/**
|
|
235
|
+
* Schema for a final-state overlay difference.
|
|
236
|
+
*
|
|
237
|
+
* **Details**
|
|
238
|
+
*
|
|
239
|
+
* Paths retain arbitrary non-NUL bytes. Renames are reported only when retained
|
|
240
|
+
* base identity makes the removed and added names unambiguous.
|
|
241
|
+
*
|
|
242
|
+
* @category schemas
|
|
243
|
+
* @since 0.1.0
|
|
244
|
+
*/
|
|
245
|
+
export const OverlayChange = Schema.Union([
|
|
246
|
+
Schema.TaggedStruct("Added", { path: BytePath, kind: OverlayNodeKind }),
|
|
247
|
+
Schema.TaggedStruct("Removed", { path: BytePath, kind: OverlayNodeKind }),
|
|
248
|
+
Schema.TaggedStruct("Replaced", {
|
|
249
|
+
path: BytePath,
|
|
250
|
+
beforeKind: OverlayNodeKind,
|
|
251
|
+
afterKind: OverlayNodeKind,
|
|
252
|
+
differences: OverlayDifferences
|
|
253
|
+
}),
|
|
254
|
+
Schema.TaggedStruct("Renamed", {
|
|
255
|
+
from: BytePath,
|
|
256
|
+
to: BytePath,
|
|
257
|
+
kind: OverlayNodeKind,
|
|
258
|
+
differences: OverlayDifferences
|
|
259
|
+
}),
|
|
260
|
+
Schema.TaggedStruct("Updated", { path: BytePath, kind: OverlayNodeKind, differences: NonEmptyOverlayDifferences })
|
|
261
|
+
]);
|
|
262
|
+
/**
|
|
263
|
+
* Schema for overlay summary filtering.
|
|
264
|
+
*
|
|
265
|
+
* @category schemas
|
|
266
|
+
* @since 0.1.0
|
|
267
|
+
*/
|
|
268
|
+
export const OverlayChangesOptions = Schema.Struct({
|
|
269
|
+
/** Include access, modification, change, and birth-time differences. Defaults to `false`. */
|
|
270
|
+
includeTimestamps: Schema.optionalKey(Schema.Boolean)
|
|
271
|
+
});
|
|
198
272
|
/**
|
|
199
273
|
* Optional Effect service for providing an existing filesystem caller.
|
|
200
274
|
*
|
|
@@ -217,7 +291,6 @@ export const encodeSnapshot = Image.encodeSnapshot;
|
|
|
217
291
|
* @since 0.1.0
|
|
218
292
|
*/
|
|
219
293
|
export const decodeSnapshot = Image.decodeSnapshot;
|
|
220
|
-
const bytePaths = new WeakMap();
|
|
221
294
|
const failure = (code, operation, path) => new FsError({ code, operation, ...(path === undefined ? {} : { path }) });
|
|
222
295
|
const ownedPath = (bytes) => {
|
|
223
296
|
const path = Object.freeze({ [BytePathId]: true });
|
|
@@ -370,7 +443,8 @@ const storedMetadata = (metadata) => ({
|
|
|
370
443
|
birthtimeNs: String(metadata.birthtimeNs)
|
|
371
444
|
});
|
|
372
445
|
/** Each execution constructs a fresh volume and captures its Clock. */
|
|
373
|
-
const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (
|
|
446
|
+
const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (source, options) {
|
|
447
|
+
const image = source._tag === "Empty" ? undefined : source.image;
|
|
374
448
|
const decoded = decodeConfiguration(VolumeOptions, options === undefined ? {} : options);
|
|
375
449
|
if (Result.isFailure(decoded))
|
|
376
450
|
return yield* decoded.failure;
|
|
@@ -388,6 +462,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
388
462
|
const gate = Semaphore.makeUnsafe(1);
|
|
389
463
|
const root = {
|
|
390
464
|
kind: "directory",
|
|
465
|
+
lineage: image?.root,
|
|
391
466
|
parent: undefined,
|
|
392
467
|
entries: new Map(),
|
|
393
468
|
metadata: directoryMetadata(1n, 0, 0, 0o755, initialTime)
|
|
@@ -415,6 +490,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
415
490
|
(settings.maxBytes !== undefined && content > settings.maxBytes)) {
|
|
416
491
|
return yield* new ImageError({ code: "LimitExceeded", field: "volume" });
|
|
417
492
|
}
|
|
493
|
+
const baseContents = source._tag === "Overlay" ? Content.forOverlay(source.base, image) : undefined;
|
|
418
494
|
for (const record of image.records) {
|
|
419
495
|
const metadata = {
|
|
420
496
|
...record.metadata,
|
|
@@ -430,22 +506,28 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
430
506
|
if (record.kind === "directory") {
|
|
431
507
|
const node = record.id === image.root
|
|
432
508
|
? root
|
|
433
|
-
: { kind: "directory", parent: undefined, entries: new Map(), metadata };
|
|
509
|
+
: { kind: "directory", lineage: record.id, parent: undefined, entries: new Map(), metadata };
|
|
434
510
|
node.metadata = metadata;
|
|
435
511
|
incoming.set(record.id, node);
|
|
436
512
|
}
|
|
437
513
|
else if (record.kind === "file") {
|
|
438
|
-
const data = Image.bytes(record.data);
|
|
514
|
+
const data = baseContents?.get(record.id) ?? Content.make(Image.bytes(record.data));
|
|
439
515
|
incoming.set(record.id, {
|
|
440
516
|
kind: "file",
|
|
517
|
+
lineage: record.id,
|
|
441
518
|
data,
|
|
442
519
|
openCount: 0,
|
|
443
|
-
metadata: { ...metadata, size: BigInt(data.length) }
|
|
520
|
+
metadata: { ...metadata, size: BigInt(data.bytes.length) }
|
|
444
521
|
});
|
|
445
522
|
}
|
|
446
523
|
else {
|
|
447
524
|
const target = Image.bytes(record.target);
|
|
448
|
-
incoming.set(record.id, {
|
|
525
|
+
incoming.set(record.id, {
|
|
526
|
+
kind: "symlink",
|
|
527
|
+
lineage: record.id,
|
|
528
|
+
target,
|
|
529
|
+
metadata: { ...metadata, size: BigInt(target.length) }
|
|
530
|
+
});
|
|
449
531
|
}
|
|
450
532
|
}
|
|
451
533
|
for (const record of image.records) {
|
|
@@ -513,6 +595,75 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
513
595
|
}
|
|
514
596
|
}
|
|
515
597
|
};
|
|
598
|
+
const captureSnapshot = Effect.fnUntraced(function* () {
|
|
599
|
+
const ids = new Map([[root, "0"]]);
|
|
600
|
+
const pending = [root];
|
|
601
|
+
const records = [];
|
|
602
|
+
for (let index = 0; index < pending.length; index++) {
|
|
603
|
+
const node = pending[index];
|
|
604
|
+
if (node === undefined)
|
|
605
|
+
continue;
|
|
606
|
+
const id = ids.get(node);
|
|
607
|
+
if (id === undefined)
|
|
608
|
+
return yield* new ImageError({ code: "InvalidStructure" });
|
|
609
|
+
const metadata = storedMetadata(node.metadata);
|
|
610
|
+
if (node.kind === "directory") {
|
|
611
|
+
const children = [];
|
|
612
|
+
for (const [name, child] of node.entries) {
|
|
613
|
+
let target = ids.get(child);
|
|
614
|
+
if (target === undefined) {
|
|
615
|
+
target = String(ids.size);
|
|
616
|
+
ids.set(child, target);
|
|
617
|
+
pending.push(child);
|
|
618
|
+
}
|
|
619
|
+
children.push({ name: Image.base64(nameBytes(name)), target });
|
|
620
|
+
}
|
|
621
|
+
records.push({ id, kind: "directory", metadata, entries: children });
|
|
622
|
+
}
|
|
623
|
+
else if (node.kind === "file") {
|
|
624
|
+
records.push({ id, kind: "file", metadata, data: Image.base64(node.data.bytes) });
|
|
625
|
+
}
|
|
626
|
+
else
|
|
627
|
+
records.push({ id, kind: "symlink", metadata, target: Image.base64(node.target) });
|
|
628
|
+
}
|
|
629
|
+
return yield* Image.capture({ format: "effect-vfs", version: 1, root: "0", records });
|
|
630
|
+
});
|
|
631
|
+
const observeChanges = () => {
|
|
632
|
+
const observation = [];
|
|
633
|
+
const paths = [[root, new Uint8Array([47])]];
|
|
634
|
+
for (let index = 0; index < paths.length; index++) {
|
|
635
|
+
const current = paths[index];
|
|
636
|
+
if (current === undefined)
|
|
637
|
+
continue;
|
|
638
|
+
const [node, path] = current;
|
|
639
|
+
observation.push({
|
|
640
|
+
path: new Uint8Array(path),
|
|
641
|
+
lineage: node.lineage,
|
|
642
|
+
kind: node.kind,
|
|
643
|
+
content: node.kind === "file" ? node.data.bytes : node.kind === "symlink" ? node.target : undefined,
|
|
644
|
+
metadata: storedMetadata(node.metadata)
|
|
645
|
+
});
|
|
646
|
+
if (node.kind !== "directory")
|
|
647
|
+
continue;
|
|
648
|
+
for (const [name, child] of node.entries) {
|
|
649
|
+
const bytes = nameBytes(name);
|
|
650
|
+
const childPath = new Uint8Array(path.length + (path.length === 1 ? 0 : 1) + bytes.length);
|
|
651
|
+
childPath.set(path);
|
|
652
|
+
let offset = path.length;
|
|
653
|
+
if (path.length !== 1)
|
|
654
|
+
childPath[offset++] = 47;
|
|
655
|
+
childPath.set(bytes, offset);
|
|
656
|
+
paths.push([child, childPath]);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return observation;
|
|
660
|
+
};
|
|
661
|
+
const captureState = Effect.fnUntraced(function* (hook) {
|
|
662
|
+
const snapshot = yield* captureSnapshot();
|
|
663
|
+
if (hook !== undefined)
|
|
664
|
+
yield* hook.betweenSnapshotAndSummary;
|
|
665
|
+
return { snapshot, observation: observeChanges() };
|
|
666
|
+
});
|
|
516
667
|
// Permit waits stay interruptible. State transitions and resource registration do not.
|
|
517
668
|
const coordinated = (effect) => gate.withPermit(Effect.uninterruptible(effect));
|
|
518
669
|
const release = (reference) => coordinated(Effect.sync(() => {
|
|
@@ -534,8 +685,8 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
534
685
|
};
|
|
535
686
|
const reclaim = (file) => {
|
|
536
687
|
if (file.metadata.nlink === 0 && file.openCount === 0) {
|
|
537
|
-
usedBytes -= file.data.length;
|
|
538
|
-
file.data =
|
|
688
|
+
usedBytes -= file.data.bytes.length;
|
|
689
|
+
file.data = Content.empty();
|
|
539
690
|
}
|
|
540
691
|
};
|
|
541
692
|
const detach = (node, now) => {
|
|
@@ -565,14 +716,14 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
565
716
|
if (length > BigInt(maxFileBytes))
|
|
566
717
|
return yield* failure("FileTooLarge", operation);
|
|
567
718
|
const size = Number(length);
|
|
568
|
-
if (size - file.data.length > (settings.maxBytes ?? Number.MAX_SAFE_INTEGER) - usedBytes) {
|
|
719
|
+
if (size - file.data.bytes.length > (settings.maxBytes ?? Number.MAX_SAFE_INTEGER) - usedBytes) {
|
|
569
720
|
return yield* failure("NoSpace", operation);
|
|
570
721
|
}
|
|
571
722
|
const data = new Uint8Array(size);
|
|
572
|
-
data.set(file.data.subarray(0, size));
|
|
723
|
+
data.set(file.data.bytes.subarray(0, size));
|
|
573
724
|
const now = yield* timestamp(operation);
|
|
574
|
-
usedBytes += size - file.data.length;
|
|
575
|
-
file.data = data;
|
|
725
|
+
usedBytes += size - file.data.bytes.length;
|
|
726
|
+
file.data = Content.make(data);
|
|
576
727
|
file.metadata = {
|
|
577
728
|
...file.metadata,
|
|
578
729
|
size: length,
|
|
@@ -596,7 +747,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
596
747
|
return yield* failure("InvalidArgument", "read");
|
|
597
748
|
}
|
|
598
749
|
const start = Number(offset > file.metadata.size ? file.metadata.size : offset);
|
|
599
|
-
const data = file.data.slice(start, start + Math.min(maximum, file.data.length - start));
|
|
750
|
+
const data = file.data.bytes.slice(start, start + Math.min(maximum, file.data.bytes.length - start));
|
|
600
751
|
if (maximum > 0) {
|
|
601
752
|
file.metadata = { ...file.metadata, atimeNs: (yield* timestamp("read")) };
|
|
602
753
|
}
|
|
@@ -622,18 +773,19 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
622
773
|
return yield* failure("FileTooLarge", "write");
|
|
623
774
|
const start = Number(offset);
|
|
624
775
|
const free = (settings.maxBytes ?? Number.MAX_SAFE_INTEGER) - usedBytes;
|
|
625
|
-
const end = Math.min(maxFileBytes, file.data.length + free);
|
|
776
|
+
const end = Math.min(maxFileBytes, file.data.bytes.length + free);
|
|
626
777
|
const count = Math.min(bytes.length, Math.max(0, end - start));
|
|
627
778
|
if (count === 0)
|
|
628
779
|
return yield* failure("NoSpace", "write");
|
|
629
|
-
const size = Math.max(file.data.length, start + count);
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
780
|
+
const size = Math.max(file.data.bytes.length, start + count);
|
|
781
|
+
// Always detach before mutation. A same-sized write is the critical
|
|
782
|
+
// case: the current payload may belong to the base or a prior capture.
|
|
783
|
+
const data = new Uint8Array(size);
|
|
784
|
+
data.set(file.data.bytes);
|
|
633
785
|
const now = yield* timestamp("write");
|
|
634
786
|
data.set(bytes.subarray(0, count), start);
|
|
635
|
-
usedBytes += size - file.data.length;
|
|
636
|
-
file.data = data;
|
|
787
|
+
usedBytes += size - file.data.bytes.length;
|
|
788
|
+
file.data = Content.make(data);
|
|
637
789
|
file.metadata = {
|
|
638
790
|
...file.metadata,
|
|
639
791
|
size: BigInt(size),
|
|
@@ -958,7 +1110,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
958
1110
|
if (node.kind !== "file")
|
|
959
1111
|
return yield* failure("IsDirectory", "readFile", input);
|
|
960
1112
|
yield* authorize(node, identity, 4, "readFile", input);
|
|
961
|
-
const data = new Uint8Array(node.data);
|
|
1113
|
+
const data = new Uint8Array(node.data.bytes);
|
|
962
1114
|
node.metadata = { ...node.metadata, atimeNs: (yield* timestamp("readFile")) };
|
|
963
1115
|
return data;
|
|
964
1116
|
}));
|
|
@@ -1009,7 +1161,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1009
1161
|
else
|
|
1010
1162
|
yield* authorize(file, identity, chosen.access === "readWrite" ? 6 : 2, "writeFile", input);
|
|
1011
1163
|
const finalMode = chosen.finalMode === undefined ? undefined : yield* permittedMode(file?.metadata ?? { kind: "file", uid: identity.uid, gid: parent.metadata.gid }, chosen.finalMode, "writeFile", input);
|
|
1012
|
-
const previous = file?.data.length ?? 0;
|
|
1164
|
+
const previous = file?.data.bytes.length ?? 0;
|
|
1013
1165
|
const initial = chosen.truncate ? 0 : previous;
|
|
1014
1166
|
const position = chosen.append ? initial : 0;
|
|
1015
1167
|
const size = Math.max(initial, position + captured.length);
|
|
@@ -1026,14 +1178,15 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1026
1178
|
if (position !== 0 || size !== captured.length) {
|
|
1027
1179
|
data = new Uint8Array(size);
|
|
1028
1180
|
if (file !== undefined && !chosen.truncate)
|
|
1029
|
-
data.set(file.data);
|
|
1181
|
+
data.set(file.data.bytes);
|
|
1030
1182
|
data.set(captured, position);
|
|
1031
1183
|
}
|
|
1032
1184
|
const now = yield* timestamp("writeFile");
|
|
1033
1185
|
const node = file ??
|
|
1034
1186
|
{
|
|
1035
1187
|
kind: "file",
|
|
1036
|
-
|
|
1188
|
+
lineage: undefined,
|
|
1189
|
+
data: Content.make(data),
|
|
1037
1190
|
openCount: 0,
|
|
1038
1191
|
metadata: {
|
|
1039
1192
|
...directoryMetadata(nextInode++, identity.uid, parent.metadata.gid, (chosen.mode ?? 0o666) & 0o777 & ~umask, now),
|
|
@@ -1041,7 +1194,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1041
1194
|
nlink: 1
|
|
1042
1195
|
}
|
|
1043
1196
|
};
|
|
1044
|
-
node.data = data;
|
|
1197
|
+
node.data = Content.make(data);
|
|
1045
1198
|
node.metadata = {
|
|
1046
1199
|
...node.metadata,
|
|
1047
1200
|
mode: finalMode ?? node.metadata.mode & ~0o6000,
|
|
@@ -1175,6 +1328,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1175
1328
|
const now = yield* timestamp("symlink");
|
|
1176
1329
|
const node = {
|
|
1177
1330
|
kind: "symlink",
|
|
1331
|
+
lineage: undefined,
|
|
1178
1332
|
target: new Uint8Array(bytes),
|
|
1179
1333
|
metadata: {
|
|
1180
1334
|
...directoryMetadata(nextInode, identity.uid, parent.metadata.gid, 0o777, now),
|
|
@@ -1269,7 +1423,8 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1269
1423
|
const now = yield* timestamp("open");
|
|
1270
1424
|
file = {
|
|
1271
1425
|
kind: "file",
|
|
1272
|
-
|
|
1426
|
+
lineage: undefined,
|
|
1427
|
+
data: Content.empty(),
|
|
1273
1428
|
openCount: 0,
|
|
1274
1429
|
metadata: {
|
|
1275
1430
|
...directoryMetadata(nextInode, identity.uid, parent.metadata.gid, (chosen.mode ?? 0o666) & 0o777 & ~umask, now),
|
|
@@ -1464,6 +1619,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1464
1619
|
const now = yield* timestamp("mkdir");
|
|
1465
1620
|
const child = {
|
|
1466
1621
|
kind: "directory",
|
|
1622
|
+
lineage: undefined,
|
|
1467
1623
|
parent,
|
|
1468
1624
|
entries: new Map(),
|
|
1469
1625
|
metadata: directoryMetadata(nextInode, identity.uid, parent.metadata.gid, (mode & 0o777 & ~umask) | (mode & 0o1000), now)
|
|
@@ -1506,6 +1662,28 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1506
1662
|
})
|
|
1507
1663
|
});
|
|
1508
1664
|
};
|
|
1665
|
+
const baseObservation = source._tag === "Overlay" ? observeChanges() : undefined;
|
|
1666
|
+
const publicChange = (change) => {
|
|
1667
|
+
switch (change._tag) {
|
|
1668
|
+
case "Added":
|
|
1669
|
+
case "Removed":
|
|
1670
|
+
case "Updated":
|
|
1671
|
+
case "Replaced":
|
|
1672
|
+
return Object.freeze({ ...change, path: ownedPath(new Uint8Array(change.path)) });
|
|
1673
|
+
case "Renamed":
|
|
1674
|
+
return Object.freeze({
|
|
1675
|
+
...change,
|
|
1676
|
+
from: ownedPath(new Uint8Array(change.from)),
|
|
1677
|
+
to: ownedPath(new Uint8Array(change.to))
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
throw new Error("Unknown internal overlay change");
|
|
1681
|
+
};
|
|
1682
|
+
const publicChanges = (changes) => Object.freeze(changes.map(publicChange));
|
|
1683
|
+
const changeOptions = (options) => {
|
|
1684
|
+
const decoded = decodeConfiguration(OverlayChangesOptions, options === undefined ? {} : options);
|
|
1685
|
+
return Result.isFailure(decoded) ? Effect.fail(decoded.failure) : Effect.succeed(decoded.success);
|
|
1686
|
+
};
|
|
1509
1687
|
const volume = Object.freeze({
|
|
1510
1688
|
[VolumeId]: true,
|
|
1511
1689
|
watch: Effect.gen(function* () {
|
|
@@ -1516,39 +1694,7 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1516
1694
|
}));
|
|
1517
1695
|
return Stream.fromEffectRepeat(PubSub.take(subscription));
|
|
1518
1696
|
}).pipe(Effect.withSpan("Volume.watch")),
|
|
1519
|
-
snapshot: coordinated(Effect.
|
|
1520
|
-
const ids = new Map([[root, "0"]]);
|
|
1521
|
-
const pending = [root];
|
|
1522
|
-
const records = [];
|
|
1523
|
-
for (let index = 0; index < pending.length; index++) {
|
|
1524
|
-
const node = pending[index];
|
|
1525
|
-
if (node === undefined)
|
|
1526
|
-
continue;
|
|
1527
|
-
const id = ids.get(node);
|
|
1528
|
-
if (id === undefined)
|
|
1529
|
-
return yield* new ImageError({ code: "InvalidStructure" });
|
|
1530
|
-
const metadata = storedMetadata(node.metadata);
|
|
1531
|
-
if (node.kind === "directory") {
|
|
1532
|
-
const children = [];
|
|
1533
|
-
for (const [name, child] of node.entries) {
|
|
1534
|
-
let target = ids.get(child);
|
|
1535
|
-
if (target === undefined) {
|
|
1536
|
-
target = String(ids.size);
|
|
1537
|
-
ids.set(child, target);
|
|
1538
|
-
pending.push(child);
|
|
1539
|
-
}
|
|
1540
|
-
children.push({ name: Image.base64(nameBytes(name)), target });
|
|
1541
|
-
}
|
|
1542
|
-
records.push({ id, kind: "directory", metadata, entries: children });
|
|
1543
|
-
}
|
|
1544
|
-
else if (node.kind === "file") {
|
|
1545
|
-
records.push({ id, kind: "file", metadata, data: Image.base64(node.data) });
|
|
1546
|
-
}
|
|
1547
|
-
else
|
|
1548
|
-
records.push({ id, kind: "symlink", metadata, target: Image.base64(node.target) });
|
|
1549
|
-
}
|
|
1550
|
-
return yield* Image.capture({ format: "effect-vfs", version: 1, root: "0", records });
|
|
1551
|
-
})).pipe(Effect.withSpan("Volume.snapshot")),
|
|
1697
|
+
snapshot: coordinated(captureSnapshot()).pipe(Effect.withSpan("Volume.snapshot")),
|
|
1552
1698
|
caller: Effect.fn("Volume.caller")(function* (options) {
|
|
1553
1699
|
const decoded = decodeConfiguration(RootCallerOptions, options === undefined ? {} : options);
|
|
1554
1700
|
if (Result.isFailure(decoded))
|
|
@@ -1558,7 +1704,27 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1558
1704
|
return createCaller({ volume: volumeIdentity, directory: root, closed: false }, identity, decoded.success.umask ?? 0o022);
|
|
1559
1705
|
})
|
|
1560
1706
|
});
|
|
1561
|
-
|
|
1707
|
+
if (source._tag !== "Overlay" || baseObservation === undefined) {
|
|
1708
|
+
return { _tag: "Volume", volume };
|
|
1709
|
+
}
|
|
1710
|
+
const hook = OverlayTesting.getObservationHook(source.base);
|
|
1711
|
+
const overlay = Object.freeze({
|
|
1712
|
+
...volume,
|
|
1713
|
+
changes: Effect.fn("OverlayVolume.changes")(function* (options) {
|
|
1714
|
+
const selected = yield* changeOptions(options);
|
|
1715
|
+
const current = yield* coordinated(Effect.sync(observeChanges));
|
|
1716
|
+
return publicChanges(compareOverlay(baseObservation, current, selected.includeTimestamps ?? false));
|
|
1717
|
+
}),
|
|
1718
|
+
capture: Effect.fn("OverlayVolume.capture")(function* (options) {
|
|
1719
|
+
const selected = yield* changeOptions(options);
|
|
1720
|
+
const current = yield* coordinated(captureState(hook));
|
|
1721
|
+
return Object.freeze({
|
|
1722
|
+
snapshot: current.snapshot,
|
|
1723
|
+
changes: publicChanges(compareOverlay(baseObservation, current.observation, selected.includeTimestamps ?? false))
|
|
1724
|
+
});
|
|
1725
|
+
})
|
|
1726
|
+
});
|
|
1727
|
+
return { _tag: "Overlay", volume: overlay };
|
|
1562
1728
|
});
|
|
1563
1729
|
/**
|
|
1564
1730
|
* Creates a fresh empty volume and captures the current Effect `Clock`.
|
|
@@ -1572,7 +1738,10 @@ const makeVolume = Effect.fn("VirtualFileSystem.makeVolume")(function* (options,
|
|
|
1572
1738
|
* @since 0.1.0
|
|
1573
1739
|
*/
|
|
1574
1740
|
export const make = Effect.fn("VirtualFileSystem.make")(function* (options) {
|
|
1575
|
-
|
|
1741
|
+
const result = yield* makeVolume({ _tag: "Empty" }, options).pipe(Effect.catchTag("ImageError", Effect.die));
|
|
1742
|
+
if (result._tag === "Overlay")
|
|
1743
|
+
return yield* Effect.die(new Error("empty volume constructed as overlay"));
|
|
1744
|
+
return result.volume;
|
|
1576
1745
|
});
|
|
1577
1746
|
/**
|
|
1578
1747
|
* Restores a fresh volume from an opaque snapshot under the supplied destination limits.
|
|
@@ -1582,7 +1751,33 @@ export const make = Effect.fn("VirtualFileSystem.make")(function* (options) {
|
|
|
1582
1751
|
*/
|
|
1583
1752
|
export const fromSnapshot = Effect.fn("VirtualFileSystem.fromSnapshot")(function* (snapshot, options) {
|
|
1584
1753
|
const image = yield* Image.inspect(snapshot);
|
|
1585
|
-
|
|
1754
|
+
const result = yield* makeVolume({ _tag: "Snapshot", image }, options);
|
|
1755
|
+
if (result._tag === "Overlay")
|
|
1756
|
+
return yield* new ImageError({ code: "InvalidStructure" });
|
|
1757
|
+
return result.volume;
|
|
1758
|
+
});
|
|
1759
|
+
/**
|
|
1760
|
+
* Creates an isolated writable volume relative to one immutable snapshot base.
|
|
1761
|
+
*
|
|
1762
|
+
* **Details**
|
|
1763
|
+
*
|
|
1764
|
+
* Workspaces made from the same snapshot share unchanged regular-file payloads.
|
|
1765
|
+
* The first content mutation copies the whole file into workspace-private
|
|
1766
|
+
* storage. Metadata, namespace state, coordination, handles, and watches are
|
|
1767
|
+
* always private to the new workspace.
|
|
1768
|
+
*
|
|
1769
|
+
* Invalid base snapshots fail with `ImageError`; invalid volume limits fail
|
|
1770
|
+
* with `ConfigurationError`. Each execution creates a fresh workspace.
|
|
1771
|
+
*
|
|
1772
|
+
* @category constructors
|
|
1773
|
+
* @since 0.1.0
|
|
1774
|
+
*/
|
|
1775
|
+
export const makeOverlay = Effect.fn("VirtualFileSystem.makeOverlay")(function* (base, options) {
|
|
1776
|
+
const image = yield* Image.inspect(base);
|
|
1777
|
+
const result = yield* makeVolume({ _tag: "Overlay", base, image }, options);
|
|
1778
|
+
if (result._tag === "Volume")
|
|
1779
|
+
return yield* new ImageError({ code: "InvalidStructure" });
|
|
1780
|
+
return result.volume;
|
|
1586
1781
|
});
|
|
1587
1782
|
const FixtureMetadata = Schema.Struct({
|
|
1588
1783
|
uid: Schema.optionalKey(Natural),
|
|
@@ -1764,5 +1959,9 @@ export const fromFixture = Effect.fn("VirtualFileSystem.fromFixture")(function*
|
|
|
1764
1959
|
}
|
|
1765
1960
|
const records = [...new Set(declarations.values())].map((record) => record.kind === "directory" ? { ...record, entries: children.get(record.id) ?? [] } : record);
|
|
1766
1961
|
const snapshot = yield* Image.capture({ format: "effect-vfs", version: 1, root: "root", records });
|
|
1767
|
-
|
|
1962
|
+
const image = yield* Image.inspect(snapshot);
|
|
1963
|
+
const result = yield* makeVolume({ _tag: "Snapshot", image }, config.success);
|
|
1964
|
+
if (result._tag === "Overlay")
|
|
1965
|
+
return yield* new ImageError({ code: "InvalidStructure" });
|
|
1966
|
+
return result.volume;
|
|
1768
1967
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Immutable regular-file payloads shared by overlay workspaces.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
import type { Snapshot } from "../Snapshot.js";
|
|
7
|
+
import * as Image from "./image.js";
|
|
8
|
+
/** @internal */
|
|
9
|
+
export interface Content {
|
|
10
|
+
readonly bytes: Uint8Array;
|
|
11
|
+
}
|
|
12
|
+
/** @internal */
|
|
13
|
+
export declare const hasOverlayContents: (snapshot: Snapshot) => boolean;
|
|
14
|
+
/** @internal */
|
|
15
|
+
export declare const make: (bytes: Uint8Array) => Content;
|
|
16
|
+
/** @internal */
|
|
17
|
+
export declare const empty: () => Content;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the immutable file payloads associated with the identity of a base
|
|
20
|
+
* snapshot. The cache is weak so it cannot extend the snapshot's lifetime.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare const forOverlay: (snapshot: Snapshot, image: Image.Document) => ReadonlyMap<string, Content>;
|
|
25
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/internal/content.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC,gBAAgB;AAChB,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAC3B;AAID,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,aAAc,QAAQ,KAAG,OAAwC,CAAA;AAEhG,gBAAgB;AAChB,eAAO,MAAM,IAAI,UAAW,UAAU,KAAG,OAAsB,CAAA;AAE/D,gBAAgB;AAChB,eAAO,MAAM,KAAK,QAAO,OAAkC,CAAA;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,UAAU,aAAc,QAAQ,SAAS,KAAK,CAAC,QAAQ,KAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CASjG,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as Image from "./image.js";
|
|
2
|
+
const overlayContents = new WeakMap();
|
|
3
|
+
/** @internal */
|
|
4
|
+
export const hasOverlayContents = (snapshot) => overlayContents.has(snapshot);
|
|
5
|
+
/** @internal */
|
|
6
|
+
export const make = (bytes) => ({ bytes });
|
|
7
|
+
/** @internal */
|
|
8
|
+
export const empty = () => make(new Uint8Array(0));
|
|
9
|
+
/**
|
|
10
|
+
* Returns the immutable file payloads associated with the identity of a base
|
|
11
|
+
* snapshot. The cache is weak so it cannot extend the snapshot's lifetime.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export const forOverlay = (snapshot, image) => {
|
|
16
|
+
const cached = overlayContents.get(snapshot);
|
|
17
|
+
if (cached !== undefined)
|
|
18
|
+
return cached;
|
|
19
|
+
const decoded = new Map();
|
|
20
|
+
for (const record of image.records) {
|
|
21
|
+
if (record.kind === "file")
|
|
22
|
+
decoded.set(record.id, make(Image.bytes(record.data)));
|
|
23
|
+
}
|
|
24
|
+
overlayContents.set(snapshot, decoded);
|
|
25
|
+
return decoded;
|
|
26
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** @internal */
|
|
2
|
+
export interface ObservationMetadata {
|
|
3
|
+
readonly uid: number;
|
|
4
|
+
readonly gid: number;
|
|
5
|
+
readonly mode: number;
|
|
6
|
+
readonly atimeNs: string;
|
|
7
|
+
readonly mtimeNs: string;
|
|
8
|
+
readonly ctimeNs: string;
|
|
9
|
+
readonly birthtimeNs: string;
|
|
10
|
+
}
|
|
11
|
+
/** @internal */
|
|
12
|
+
export interface ObservationEntry {
|
|
13
|
+
readonly path: Uint8Array;
|
|
14
|
+
readonly lineage: string | undefined;
|
|
15
|
+
readonly kind: "directory" | "file" | "symlink";
|
|
16
|
+
readonly content: Uint8Array | undefined;
|
|
17
|
+
readonly metadata: ObservationMetadata;
|
|
18
|
+
}
|
|
19
|
+
/** @internal */
|
|
20
|
+
export type OverlayDifference = "content" | "mode" | "uid" | "gid" | "atimeNs" | "mtimeNs" | "ctimeNs" | "birthtimeNs";
|
|
21
|
+
/** @internal */
|
|
22
|
+
export type RawOverlayChange = {
|
|
23
|
+
readonly _tag: "Added";
|
|
24
|
+
readonly path: Uint8Array;
|
|
25
|
+
readonly kind: ObservationEntry["kind"];
|
|
26
|
+
} | {
|
|
27
|
+
readonly _tag: "Removed";
|
|
28
|
+
readonly path: Uint8Array;
|
|
29
|
+
readonly kind: ObservationEntry["kind"];
|
|
30
|
+
} | {
|
|
31
|
+
readonly _tag: "Replaced";
|
|
32
|
+
readonly path: Uint8Array;
|
|
33
|
+
readonly beforeKind: ObservationEntry["kind"];
|
|
34
|
+
readonly afterKind: ObservationEntry["kind"];
|
|
35
|
+
readonly differences: ReadonlyArray<OverlayDifference>;
|
|
36
|
+
} | {
|
|
37
|
+
readonly _tag: "Renamed";
|
|
38
|
+
readonly from: Uint8Array;
|
|
39
|
+
readonly to: Uint8Array;
|
|
40
|
+
readonly kind: ObservationEntry["kind"];
|
|
41
|
+
readonly differences: ReadonlyArray<OverlayDifference>;
|
|
42
|
+
} | {
|
|
43
|
+
readonly _tag: "Updated";
|
|
44
|
+
readonly path: Uint8Array;
|
|
45
|
+
readonly kind: ObservationEntry["kind"];
|
|
46
|
+
readonly differences: ReadonlyArray<OverlayDifference>;
|
|
47
|
+
};
|
|
48
|
+
/** @internal */
|
|
49
|
+
export declare const compareOverlay: (base: ReadonlyArray<ObservationEntry>, current: ReadonlyArray<ObservationEntry>, includeTimestamps?: boolean) => ReadonlyArray<RawOverlayChange>;
|
|
50
|
+
//# sourceMappingURL=overlayChanges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlayChanges.d.ts","sourceRoot":"","sources":["../../src/internal/overlayChanges.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAA;CACvC;AAED,gBAAgB;AAChB,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAA;AAEtH,gBAAgB;AAChB,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;CAAE,GAC9F;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;CAAE,GAChG;IACA,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC7C,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IAC5C,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;CACvD,GACC;IACA,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;CACvD,GACC;IACA,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAA;CACvD,CAAA;AAqFH,gBAAgB;AAChB,eAAO,MAAM,cAAc,SACnB,aAAa,CAAC,gBAAgB,CAAC,WAC5B,aAAa,CAAC,gBAAgB,CAAC,kCAEvC,aAAa,CAAC,gBAAgB,CAoEhC,CAAA"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const timestampFields = new Set(["atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]);
|
|
2
|
+
const differenceOrder = [
|
|
3
|
+
"content",
|
|
4
|
+
"mode",
|
|
5
|
+
"uid",
|
|
6
|
+
"gid",
|
|
7
|
+
"atimeNs",
|
|
8
|
+
"mtimeNs",
|
|
9
|
+
"ctimeNs",
|
|
10
|
+
"birthtimeNs"
|
|
11
|
+
];
|
|
12
|
+
const tagOrder = {
|
|
13
|
+
Added: 0,
|
|
14
|
+
Removed: 1,
|
|
15
|
+
Replaced: 2,
|
|
16
|
+
Renamed: 3,
|
|
17
|
+
Updated: 4
|
|
18
|
+
};
|
|
19
|
+
const key = (path) => {
|
|
20
|
+
let result = "";
|
|
21
|
+
for (const byte of path)
|
|
22
|
+
result += byte.toString(16).padStart(2, "0");
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
const comparePaths = (left, right) => {
|
|
26
|
+
const length = Math.min(left.length, right.length);
|
|
27
|
+
for (let index = 0; index < length; index++) {
|
|
28
|
+
const difference = left[index] - right[index];
|
|
29
|
+
if (difference !== 0)
|
|
30
|
+
return difference;
|
|
31
|
+
}
|
|
32
|
+
return left.length - right.length;
|
|
33
|
+
};
|
|
34
|
+
const sameBytes = (left, right) => {
|
|
35
|
+
if (left === right)
|
|
36
|
+
return true;
|
|
37
|
+
if (left === undefined || right === undefined || left.length !== right.length)
|
|
38
|
+
return false;
|
|
39
|
+
for (let index = 0; index < left.length; index++) {
|
|
40
|
+
if (left[index] !== right[index])
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
const differences = (before, after, includeTimestamps) => differenceOrder.filter((field) => {
|
|
46
|
+
if (!includeTimestamps && timestampFields.has(field))
|
|
47
|
+
return false;
|
|
48
|
+
if (field === "content")
|
|
49
|
+
return before.kind !== after.kind || !sameBytes(before.content, after.content);
|
|
50
|
+
return before.metadata[field] !== after.metadata[field];
|
|
51
|
+
});
|
|
52
|
+
const byLineage = (entries) => {
|
|
53
|
+
const result = new Map();
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
if (entry.lineage === undefined)
|
|
56
|
+
continue;
|
|
57
|
+
const group = result.get(entry.lineage);
|
|
58
|
+
if (group === undefined)
|
|
59
|
+
result.set(entry.lineage, new Map([[key(entry.path), entry]]));
|
|
60
|
+
else
|
|
61
|
+
group.set(key(entry.path), entry);
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
const copyChange = (change) => {
|
|
66
|
+
switch (change._tag) {
|
|
67
|
+
case "Added":
|
|
68
|
+
case "Removed":
|
|
69
|
+
return Object.freeze({ ...change, path: change.path.slice() });
|
|
70
|
+
case "Replaced":
|
|
71
|
+
case "Updated":
|
|
72
|
+
return Object.freeze({
|
|
73
|
+
...change,
|
|
74
|
+
path: change.path.slice(),
|
|
75
|
+
differences: Object.freeze([...change.differences])
|
|
76
|
+
});
|
|
77
|
+
case "Renamed":
|
|
78
|
+
return Object.freeze({
|
|
79
|
+
...change,
|
|
80
|
+
from: change.from.slice(),
|
|
81
|
+
to: change.to.slice(),
|
|
82
|
+
differences: Object.freeze([...change.differences])
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/** @internal */
|
|
87
|
+
export const compareOverlay = (base, current, includeTimestamps = false) => {
|
|
88
|
+
const basePaths = new Map(base.map((entry) => [key(entry.path), entry]));
|
|
89
|
+
const currentPaths = new Map(current.map((entry) => [key(entry.path), entry]));
|
|
90
|
+
const baseLineages = byLineage(base);
|
|
91
|
+
const currentLineages = byLineage(current);
|
|
92
|
+
const consumedBase = new Set();
|
|
93
|
+
const consumedCurrent = new Set();
|
|
94
|
+
const changes = [];
|
|
95
|
+
for (const [lineage, beforeEntries] of baseLineages) {
|
|
96
|
+
const afterEntries = currentLineages.get(lineage);
|
|
97
|
+
if (afterEntries === undefined)
|
|
98
|
+
continue;
|
|
99
|
+
const removed = [...beforeEntries].filter(([pathKey]) => !afterEntries.has(pathKey)).map(([, entry]) => entry);
|
|
100
|
+
const added = [...afterEntries].filter(([pathKey]) => !beforeEntries.has(pathKey)).map(([, entry]) => entry);
|
|
101
|
+
if (removed.length !== 1 || added.length !== 1)
|
|
102
|
+
continue;
|
|
103
|
+
const before = removed[0];
|
|
104
|
+
const after = added[0];
|
|
105
|
+
consumedBase.add(key(before.path));
|
|
106
|
+
consumedCurrent.add(key(after.path));
|
|
107
|
+
changes.push({
|
|
108
|
+
_tag: "Renamed",
|
|
109
|
+
from: before.path,
|
|
110
|
+
to: after.path,
|
|
111
|
+
kind: after.kind,
|
|
112
|
+
differences: differences(before, after, includeTimestamps)
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
for (const before of base) {
|
|
116
|
+
const pathKey = key(before.path);
|
|
117
|
+
if (consumedBase.has(pathKey))
|
|
118
|
+
continue;
|
|
119
|
+
const after = currentPaths.get(pathKey);
|
|
120
|
+
if (after === undefined || consumedCurrent.has(pathKey)) {
|
|
121
|
+
changes.push({ _tag: "Removed", path: before.path, kind: before.kind });
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
consumedCurrent.add(pathKey);
|
|
125
|
+
if (before.lineage === undefined || before.lineage !== after.lineage) {
|
|
126
|
+
changes.push({
|
|
127
|
+
_tag: "Replaced",
|
|
128
|
+
path: before.path,
|
|
129
|
+
beforeKind: before.kind,
|
|
130
|
+
afterKind: after.kind,
|
|
131
|
+
differences: differences(before, after, includeTimestamps)
|
|
132
|
+
});
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const changed = differences(before, after, includeTimestamps);
|
|
136
|
+
if (changed.length > 0)
|
|
137
|
+
changes.push({ _tag: "Updated", path: before.path, kind: after.kind, differences: changed });
|
|
138
|
+
}
|
|
139
|
+
for (const after of current) {
|
|
140
|
+
const pathKey = key(after.path);
|
|
141
|
+
if (!consumedCurrent.has(pathKey) && (!basePaths.has(pathKey) || consumedBase.has(pathKey))) {
|
|
142
|
+
changes.push({ _tag: "Added", path: after.path, kind: after.kind });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
changes.sort((left, right) => {
|
|
146
|
+
const leftPath = left._tag === "Renamed" ? left.from : left.path;
|
|
147
|
+
const rightPath = right._tag === "Renamed" ? right.from : right.path;
|
|
148
|
+
const pathOrder = comparePaths(leftPath, rightPath);
|
|
149
|
+
if (pathOrder !== 0)
|
|
150
|
+
return pathOrder;
|
|
151
|
+
const typeOrder = tagOrder[left._tag] - tagOrder[right._tag];
|
|
152
|
+
if (typeOrder !== 0)
|
|
153
|
+
return typeOrder;
|
|
154
|
+
return left._tag === "Renamed" && right._tag === "Renamed" ? comparePaths(left.to, right.to) : 0;
|
|
155
|
+
});
|
|
156
|
+
return Object.freeze(changes.map(copyChange));
|
|
157
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Package-internal synchronization hooks for deterministic overlay tests. @internal */
|
|
2
|
+
import type * as Effect from "effect/Effect";
|
|
3
|
+
import type { Snapshot } from "../Snapshot.js";
|
|
4
|
+
/** @internal */
|
|
5
|
+
export interface ObservationHook {
|
|
6
|
+
readonly betweenSnapshotAndSummary: Effect.Effect<void>;
|
|
7
|
+
}
|
|
8
|
+
/** @internal */
|
|
9
|
+
export declare const getObservationHook: (snapshot: Snapshot) => ObservationHook | undefined;
|
|
10
|
+
/** @internal */
|
|
11
|
+
export declare const setObservationHook: (snapshot: Snapshot, hook: ObservationHook) => () => void;
|
|
12
|
+
//# sourceMappingURL=overlayTesting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlayTesting.d.ts","sourceRoot":"","sources":["../../src/internal/overlayTesting.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE9C,gBAAgB;AAChB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CACxD;AAID,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,aAAc,QAAQ,KAAG,eAAe,GAAG,SAA2C,CAAA;AAErH,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,aAAc,QAAQ,QAAQ,eAAe,KAAG,MAAM,IAKpF,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Package-internal synchronization hooks for deterministic overlay tests. @internal */
|
|
2
|
+
const observationHooks = new WeakMap();
|
|
3
|
+
/** @internal */
|
|
4
|
+
export const getObservationHook = (snapshot) => observationHooks.get(snapshot);
|
|
5
|
+
/** @internal */
|
|
6
|
+
export const setObservationHook = (snapshot, hook) => {
|
|
7
|
+
observationHooks.set(snapshot, hook);
|
|
8
|
+
return () => {
|
|
9
|
+
if (observationHooks.get(snapshot) === hook)
|
|
10
|
+
observationHooks.delete(snapshot);
|
|
11
|
+
};
|
|
12
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-vfs/core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "A runtime-neutral virtual filesystem core for Effect.",
|
|
5
5
|
"homepage": "https://github.com/lloydrichards/effect-virtual-fs#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"build": "tsc --project tsconfig.build.json && tsc --project compatibility/node-next/tsconfig.json",
|
|
18
18
|
"clean": "git clean -xdf .cache .turbo dist node_modules tsconfig.tsbuildinfo",
|
|
19
19
|
"test": "vitest run",
|
|
20
|
-
"type-check": "tsc --noEmit"
|
|
20
|
+
"type-check": "tsc --noEmit && tsc --project contracts/tsconfig.json"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"effect": "4.0.0-rc.112"
|