@effect-vfs/core 0.5.0 → 0.7.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.
Files changed (130) hide show
  1. package/README.md +29 -21
  2. package/dist/BytePath.d.ts +115 -4
  3. package/dist/BytePath.d.ts.map +1 -1
  4. package/dist/BytePath.js +155 -0
  5. package/dist/Caller.d.ts +391 -0
  6. package/dist/Caller.d.ts.map +1 -0
  7. package/dist/Caller.js +199 -0
  8. package/dist/FileHandle.d.ts +50 -0
  9. package/dist/FileHandle.d.ts.map +1 -0
  10. package/dist/FileHandle.js +28 -0
  11. package/dist/Fixture.d.ts +155 -0
  12. package/dist/Fixture.d.ts.map +1 -0
  13. package/dist/Fixture.js +65 -0
  14. package/dist/LiveVolume.d.ts +13 -20
  15. package/dist/LiveVolume.d.ts.map +1 -1
  16. package/dist/LiveVolume.js +19 -14
  17. package/dist/Metadata.d.ts +186 -0
  18. package/dist/Metadata.d.ts.map +1 -0
  19. package/dist/Metadata.js +125 -0
  20. package/dist/Snapshot.d.ts +32 -53
  21. package/dist/Snapshot.d.ts.map +1 -1
  22. package/dist/Snapshot.js +27 -49
  23. package/dist/SnapshotDelta.d.ts +24 -39
  24. package/dist/SnapshotDelta.d.ts.map +1 -1
  25. package/dist/SnapshotDelta.js +14 -35
  26. package/dist/Target.d.ts +225 -0
  27. package/dist/Target.d.ts.map +1 -0
  28. package/dist/Target.js +92 -0
  29. package/dist/Testing.d.ts +132 -0
  30. package/dist/Testing.d.ts.map +1 -0
  31. package/dist/Testing.js +100 -0
  32. package/dist/VfsError.d.ts +200 -0
  33. package/dist/VfsError.d.ts.map +1 -0
  34. package/dist/VfsError.js +165 -0
  35. package/dist/VirtualFileSystem.d.ts +676 -353
  36. package/dist/VirtualFileSystem.d.ts.map +1 -1
  37. package/dist/VirtualFileSystem.js +487 -121
  38. package/dist/Volume.d.ts +211 -0
  39. package/dist/Volume.d.ts.map +1 -0
  40. package/dist/Volume.js +172 -0
  41. package/dist/Watch.d.ts +68 -0
  42. package/dist/Watch.d.ts.map +1 -0
  43. package/dist/Watch.js +46 -0
  44. package/dist/index.d.ts +56 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +56 -1
  47. package/dist/internal/budget.d.ts +90 -0
  48. package/dist/internal/budget.d.ts.map +1 -0
  49. package/dist/internal/budget.js +70 -0
  50. package/dist/internal/bytePath.d.ts +2 -0
  51. package/dist/internal/bytePath.d.ts.map +1 -1
  52. package/dist/internal/bytePath.js +3 -2
  53. package/dist/internal/bytes.d.ts +3 -0
  54. package/dist/internal/bytes.d.ts.map +1 -1
  55. package/dist/internal/bytes.js +4 -2
  56. package/dist/internal/canonicalBase64.d.ts +1 -4
  57. package/dist/internal/canonicalBase64.d.ts.map +1 -1
  58. package/dist/internal/canonicalBase64.js +9 -13
  59. package/dist/internal/errors.d.ts +47 -5
  60. package/dist/internal/errors.d.ts.map +1 -1
  61. package/dist/internal/errors.js +80 -36
  62. package/dist/internal/fixture.d.ts +2 -2
  63. package/dist/internal/fixture.d.ts.map +1 -1
  64. package/dist/internal/fixture.js +57 -74
  65. package/dist/internal/hex128.d.ts +12 -0
  66. package/dist/internal/hex128.d.ts.map +1 -0
  67. package/dist/internal/hex128.js +7 -0
  68. package/dist/internal/hmac.d.ts +5 -0
  69. package/dist/internal/hmac.d.ts.map +1 -0
  70. package/dist/internal/hmac.js +150 -0
  71. package/dist/internal/image.d.ts +14 -117
  72. package/dist/internal/image.d.ts.map +1 -1
  73. package/dist/internal/image.js +137 -167
  74. package/dist/internal/inodeTable.d.ts +20 -0
  75. package/dist/internal/inodeTable.d.ts.map +1 -0
  76. package/dist/internal/inodeTable.js +48 -0
  77. package/dist/internal/lines.d.ts +36 -0
  78. package/dist/internal/lines.d.ts.map +1 -0
  79. package/dist/internal/lines.js +115 -0
  80. package/dist/internal/liveImage.d.ts +19 -278
  81. package/dist/internal/liveImage.d.ts.map +1 -1
  82. package/dist/internal/liveImage.js +75 -166
  83. package/dist/internal/merkle.d.ts +45 -0
  84. package/dist/internal/merkle.d.ts.map +1 -0
  85. package/dist/internal/merkle.js +179 -0
  86. package/dist/internal/metadata.d.ts +2 -13
  87. package/dist/internal/metadata.d.ts.map +1 -1
  88. package/dist/internal/metadata.js +5 -15
  89. package/dist/internal/overlayDiff.d.ts +2 -2
  90. package/dist/internal/overlayDiff.d.ts.map +1 -1
  91. package/dist/internal/overlayDiff.js +4 -15
  92. package/dist/internal/path.d.ts +17 -5
  93. package/dist/internal/path.d.ts.map +1 -1
  94. package/dist/internal/path.js +38 -24
  95. package/dist/internal/snapshotDelta.d.ts +61 -60
  96. package/dist/internal/snapshotDelta.d.ts.map +1 -1
  97. package/dist/internal/snapshotDelta.js +605 -503
  98. package/dist/internal/snapshotDeltaModel.d.ts.map +1 -1
  99. package/dist/internal/snapshotDeltaModel.js +0 -1
  100. package/dist/internal/testSeams.d.ts +17 -0
  101. package/dist/internal/testSeams.d.ts.map +1 -0
  102. package/dist/internal/testSeams.js +20 -0
  103. package/dist/internal/tree.d.ts +225 -0
  104. package/dist/internal/tree.d.ts.map +1 -0
  105. package/dist/internal/tree.js +385 -0
  106. package/dist/internal/turnstile.d.ts +8 -0
  107. package/dist/internal/turnstile.d.ts.map +1 -0
  108. package/dist/internal/turnstile.js +43 -0
  109. package/dist/internal/virtualFileSystem.d.ts +44 -488
  110. package/dist/internal/virtualFileSystem.d.ts.map +1 -1
  111. package/dist/internal/virtualFileSystem.js +2111 -2466
  112. package/dist/internal/volumeState.d.ts +111 -0
  113. package/dist/internal/volumeState.d.ts.map +1 -0
  114. package/dist/internal/volumeState.js +202 -0
  115. package/dist/internal/watchHub.d.ts +15 -6
  116. package/dist/internal/watchHub.d.ts.map +1 -1
  117. package/dist/internal/watchHub.js +56 -42
  118. package/package.json +54 -10
  119. package/dist/VirtualFileSystemError.d.ts +0 -54
  120. package/dist/VirtualFileSystemError.d.ts.map +0 -1
  121. package/dist/VirtualFileSystemError.js +0 -49
  122. package/dist/internal/overlayContent.d.ts +0 -15
  123. package/dist/internal/overlayContent.d.ts.map +0 -1
  124. package/dist/internal/overlayContent.js +0 -29
  125. package/dist/internal/stagedState.d.ts +0 -22
  126. package/dist/internal/stagedState.d.ts.map +0 -1
  127. package/dist/internal/stagedState.js +0 -62
  128. package/dist/internal/testHooks.d.ts +0 -20
  129. package/dist/internal/testHooks.d.ts.map +0 -1
  130. package/dist/internal/testHooks.js +0 -23
@@ -1,49 +0,0 @@
1
- /**
2
- * Tagged errors shared by the public filesystem API and its implementation.
3
- *
4
- * @since 0.1.0
5
- */
6
- import * as Data from "effect/Data";
7
- /**
8
- * An expected filesystem operation failure.
9
- *
10
- * The `code` distinguishes portable failures while `operation` names the action.
11
- * Byte paths are intentionally omitted from the formatted message.
12
- *
13
- * @example
14
- * ```ts
15
- * import { VirtualFileSystemError } from "@effect-vfs/core"
16
- *
17
- * const error = new VirtualFileSystemError.FsError({ code: "NotFound", operation: "readFile" })
18
- * console.log(error.code, error.message)
19
- * // NotFound readFile failed with NotFound
20
- * ```
21
- *
22
- * @category errors
23
- * @since 0.1.0
24
- */
25
- export class FsError extends Data.TaggedError("FsError") {
26
- get message() {
27
- return `${this.operation} failed with ${this.code}`;
28
- }
29
- }
30
- /**
31
- * An invalid volume or caller option, identified by its field name.
32
- *
33
- * @example
34
- * ```ts
35
- * import { VirtualFileSystemError } from "@effect-vfs/core"
36
- *
37
- * const error = new VirtualFileSystemError.ConfigurationError({ field: "maxEntries" })
38
- * console.log(error.field, error.message)
39
- * // maxEntries Invalid option: maxEntries
40
- * ```
41
- *
42
- * @category errors
43
- * @since 0.1.0
44
- */
45
- export class ConfigurationError extends Data.TaggedError("ConfigurationError") {
46
- get message() {
47
- return `Invalid option: ${this.field}`;
48
- }
49
- }
@@ -1,15 +0,0 @@
1
- import type { Snapshot } from "../Snapshot.js";
2
- import * as Image from "./image.js";
3
- /** @internal */
4
- export interface Content {
5
- readonly bytes: Uint8Array;
6
- }
7
- /** @internal */
8
- export declare const hasOverlayContents: (snapshot: Snapshot) => boolean;
9
- /** @internal */
10
- export declare const make: (bytes: Uint8Array) => Content;
11
- /** @internal */
12
- export declare const empty: () => Content;
13
- /** @internal */
14
- export declare const forOverlay: (snapshot: Snapshot, image: Image.Document) => ReadonlyMap<string, Content>;
15
- //# sourceMappingURL=overlayContent.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlayContent.d.ts","sourceRoot":"","sources":["../../src/internal/overlayContent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE9C,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;AAG3D,gBAAgB;AAChB,eAAO,MAAM,UAAU,aAAc,QAAQ,SAAS,KAAK,CAAC,QAAQ,KAAG,WAAW,CAAC,MAAM,EAAE,OAAO,CAiBjG,CAAA"}
@@ -1,29 +0,0 @@
1
- // Immutable regular-file payloads shared by overlay workspaces.
2
- import * as Result from "effect/Result";
3
- import * as Schema from "effect/Schema";
4
- import { CanonicalBase64 } from "./canonicalBase64.js";
5
- import * as Image from "./image.js";
6
- const overlayContents = new WeakMap();
7
- /** @internal */
8
- export const hasOverlayContents = (snapshot) => overlayContents.has(snapshot);
9
- /** @internal */
10
- export const make = (bytes) => ({ bytes });
11
- /** @internal */
12
- export const empty = () => make(new Uint8Array(0));
13
- // The weak cache shares immutable payloads without extending the snapshot's lifetime.
14
- /** @internal */
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 (Image.Record.guards.file(record)) {
22
- const bytes = Schema.decodeResult(CanonicalBase64.Bytes)(record.data);
23
- if (Result.isSuccess(bytes))
24
- decoded.set(record.id, make(bytes.success));
25
- }
26
- }
27
- overlayContents.set(snapshot, decoded);
28
- return decoded;
29
- };
@@ -1,22 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import { FsError } from "./errors.js";
3
- /** @internal */
4
- export type CommitOutcome = "committed" | "rejected" | "unknown";
5
- /** @internal */
6
- export interface CommitProvider<State> {
7
- /** Provides a gate-coordinated shutdown effect once staging is ready. */
8
- readonly onReady?: (shutdown: Effect.Effect<void>) => void;
9
- /** Checks and encodes a candidate before the commit boundary. Failure leaves the volume available. */
10
- readonly prepare?: (candidate: State) => Effect.Effect<void, FsError>;
11
- /** Classifies a candidate as committed, definitely rejected, or uncertain. */
12
- readonly commit: (candidate: State) => Effect.Effect<CommitOutcome>;
13
- }
14
- /** @internal */
15
- export declare const makeStagedState: <State, Event = never>(initial: State, copy: (current: State) => Effect.Effect<State>, rawProvider: CommitProvider<State>, publish?: (candidate: State, events: ReadonlyArray<Event>) => void) => {
16
- read: <A, E, R>(operation: string, inspect: (state: Readonly<State>) => Effect.Effect<A, E, R>) => Effect.Effect<A, E | FsError, R>;
17
- mutate: <A, E, R>(operation: string, change: (candidate: State, emit: (event: Event) => void) => Effect.Effect<A, E, R>, onStorageFailure?: () => void) => Effect.Effect<A, E | FsError, R>;
18
- coordinate: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
19
- checkAvailable: (operation: string) => Effect.Effect<void, FsError, never>;
20
- shutdown: Effect.Effect<void, never, never>;
21
- };
22
- //# sourceMappingURL=stagedState.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stagedState.d.ts","sourceRoot":"","sources":["../../src/internal/stagedState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAErC,gBAAgB;AAChB,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAA;AAEhE,gBAAgB;AAChB,MAAM,WAAW,cAAc,CAAC,KAAK;IACnC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;IAC1D,sGAAsG;IACtG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACrE,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;CACpE;AAED,gBAAgB;AAChB,eAAO,MAAM,eAAe,GAAI,KAAK,EAAE,KAAK,mBACjC,KAAK,QAER,CAAC,OAAO,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,eACjC,cAAc,CAAC,KAAK,CAAC,YACxB,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,IAAI;WAyBpD,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,MAAM,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aAOrF,CAAC,EAAE,CAAC,EAAE,CAAC,aACV,MAAM,UACT,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,qBAC/D,MAAM,IAAI;iBAhBX,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gCAPxB,MAAM;;CA0E1C,CAAA"}
@@ -1,62 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import * as Exit from "effect/Exit";
3
- import * as Semaphore from "effect/Semaphore";
4
- import { FsError } from "./errors.js";
5
- /** @internal */
6
- export const makeStagedState = (initial,
7
- // The copy must detach every mutable value that change can reach.
8
- copy, rawProvider, publish) => {
9
- const gate = Semaphore.makeUnsafe(1);
10
- const provider = {
11
- ...rawProvider,
12
- commit: (candidate) => Effect.suspend(() => rawProvider.commit(candidate))
13
- };
14
- let current = initial;
15
- let available = true;
16
- const checkAvailable = (operation) => Effect.suspend(() => available
17
- ? Effect.void
18
- : Effect.fail(new FsError({ code: "VolumeUnavailable", operation })));
19
- const coordinate = (effect) => gate.withPermit(effect);
20
- const shutdown = coordinate(Effect.sync(() => {
21
- available = false;
22
- }));
23
- const read = (operation, inspect) => coordinate(Effect.gen(function* () {
24
- yield* checkAvailable(operation);
25
- return yield* inspect(current);
26
- }));
27
- const mutate = (operation, change, onStorageFailure) => coordinate(Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
28
- yield* checkAvailable(operation);
29
- const candidate = yield* restore(copy(current));
30
- const events = [];
31
- const value = yield* restore(change(candidate, (event) => events.push(event)));
32
- if (provider.prepare !== undefined)
33
- yield* restore(provider.prepare(candidate));
34
- const committed = yield* Effect.exit(Effect.suspend(() => provider.commit(candidate)));
35
- if (Exit.isFailure(committed)) {
36
- available = false;
37
- onStorageFailure?.();
38
- return yield* new FsError({ code: "OutcomeUnknown", operation });
39
- }
40
- const outcome = committed.value;
41
- if (outcome === "rejected") {
42
- if (onStorageFailure !== undefined) {
43
- available = false;
44
- onStorageFailure();
45
- }
46
- return yield* new FsError({ code: "StorageRejected", operation });
47
- }
48
- if (outcome === "unknown") {
49
- available = false;
50
- onStorageFailure?.();
51
- return yield* new FsError({ code: "OutcomeUnknown", operation });
52
- }
53
- current = candidate;
54
- const published = yield* Effect.exit(Effect.sync(() => publish?.(candidate, events)));
55
- if (Exit.isFailure(published)) {
56
- available = false;
57
- return yield* new FsError({ code: "OutcomeUnknown", operation });
58
- }
59
- return value;
60
- })));
61
- return { read, mutate, coordinate, checkAvailable, shutdown };
62
- };
@@ -1,20 +0,0 @@
1
- import type * as Effect from "effect/Effect";
2
- import type { Snapshot } from "../Snapshot.js";
3
- import type { Volume } from "../VirtualFileSystem.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
- /** @internal */
13
- export interface RegistrationHook {
14
- readonly afterSubscribe: Effect.Effect<void>;
15
- }
16
- /** @internal */
17
- export declare const getRegistrationHook: (volume: Volume) => RegistrationHook | undefined;
18
- /** @internal */
19
- export declare const setRegistrationHook: (volume: Volume, hook: RegistrationHook) => () => void;
20
- //# sourceMappingURL=testHooks.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"testHooks.d.ts","sourceRoot":"","sources":["../../src/internal/testHooks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,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,IAMpF,CAAA;AAED,gBAAgB;AAChB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CAC7C;AAID,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,WAAY,MAAM,KAAG,gBAAgB,GAAG,SAA0C,CAAA;AAElH,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,WAAY,MAAM,QAAQ,gBAAgB,KAAG,MAAM,IAMlF,CAAA"}
@@ -1,23 +0,0 @@
1
- // Package-internal synchronization hooks for deterministic volume tests.
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
- };
13
- const registrationHooks = new WeakMap();
14
- /** @internal */
15
- export const getRegistrationHook = (volume) => registrationHooks.get(volume);
16
- /** @internal */
17
- export const setRegistrationHook = (volume, hook) => {
18
- registrationHooks.set(volume, hook);
19
- return () => {
20
- if (registrationHooks.get(volume) === hook)
21
- registrationHooks.delete(volume);
22
- };
23
- };