@effect-vfs/core 0.1.0 → 0.3.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 (58) hide show
  1. package/README.md +97 -8
  2. package/dist/BytePath.d.ts +34 -0
  3. package/dist/BytePath.d.ts.map +1 -0
  4. package/dist/BytePath.js +16 -0
  5. package/dist/Snapshot.d.ts +5 -5
  6. package/dist/Snapshot.d.ts.map +1 -1
  7. package/dist/Snapshot.js +5 -6
  8. package/dist/SnapshotDelta.d.ts +193 -0
  9. package/dist/SnapshotDelta.d.ts.map +1 -0
  10. package/dist/SnapshotDelta.js +139 -0
  11. package/dist/VirtualFileSystem.d.ts +193 -342
  12. package/dist/VirtualFileSystem.d.ts.map +1 -1
  13. package/dist/VirtualFileSystem.js +104 -1774
  14. package/dist/internal/bytePath.d.ts +10 -0
  15. package/dist/internal/bytePath.d.ts.map +1 -0
  16. package/dist/internal/bytePath.js +46 -0
  17. package/dist/internal/canonicalBase64.d.ts +7 -0
  18. package/dist/internal/canonicalBase64.d.ts.map +1 -0
  19. package/dist/internal/canonicalBase64.js +11 -0
  20. package/dist/internal/image.d.ts +28 -31
  21. package/dist/internal/image.d.ts.map +1 -1
  22. package/dist/internal/image.js +14 -23
  23. package/dist/internal/snapshotDelta.d.ts +87 -0
  24. package/dist/internal/snapshotDelta.d.ts.map +1 -0
  25. package/dist/internal/snapshotDelta.js +576 -0
  26. package/dist/internal/snapshotDeltaModel.d.ts +10 -0
  27. package/dist/internal/snapshotDeltaModel.d.ts.map +1 -0
  28. package/dist/internal/snapshotDeltaModel.js +13 -0
  29. package/dist/internal/virtualFileSystem/errors.d.ts +26 -0
  30. package/dist/internal/virtualFileSystem/errors.d.ts.map +1 -0
  31. package/dist/internal/virtualFileSystem/errors.js +32 -0
  32. package/dist/internal/virtualFileSystem/fixture.d.ts +63 -0
  33. package/dist/internal/virtualFileSystem/fixture.d.ts.map +1 -0
  34. package/dist/internal/virtualFileSystem/fixture.js +144 -0
  35. package/dist/internal/{content.d.ts → virtualFileSystem/overlayContent.d.ts} +4 -14
  36. package/dist/internal/virtualFileSystem/overlayContent.d.ts.map +1 -0
  37. package/dist/internal/{content.js → virtualFileSystem/overlayContent.js} +3 -7
  38. package/dist/internal/{overlayChanges.d.ts → virtualFileSystem/overlayDiff.d.ts} +1 -1
  39. package/dist/internal/virtualFileSystem/overlayDiff.d.ts.map +1 -0
  40. package/dist/internal/{overlayChanges.js → virtualFileSystem/overlayDiff.js} +4 -15
  41. package/dist/internal/virtualFileSystem/path.d.ts +43 -0
  42. package/dist/internal/virtualFileSystem/path.d.ts.map +1 -0
  43. package/dist/internal/virtualFileSystem/path.js +124 -0
  44. package/dist/internal/virtualFileSystem/testHooks.d.ts +20 -0
  45. package/dist/internal/virtualFileSystem/testHooks.d.ts.map +1 -0
  46. package/dist/internal/virtualFileSystem/testHooks.js +23 -0
  47. package/dist/internal/virtualFileSystem/watchHub.d.ts +16 -0
  48. package/dist/internal/virtualFileSystem/watchHub.d.ts.map +1 -0
  49. package/dist/internal/virtualFileSystem/watchHub.js +33 -0
  50. package/dist/internal/virtualFileSystem.d.ts +290 -0
  51. package/dist/internal/virtualFileSystem.d.ts.map +1 -0
  52. package/dist/internal/virtualFileSystem.js +1677 -0
  53. package/package.json +5 -4
  54. package/dist/internal/content.d.ts.map +0 -1
  55. package/dist/internal/overlayChanges.d.ts.map +0 -1
  56. package/dist/internal/overlayTesting.d.ts +0 -12
  57. package/dist/internal/overlayTesting.d.ts.map +0 -1
  58. package/dist/internal/overlayTesting.js +0 -12
package/README.md CHANGED
@@ -16,10 +16,10 @@ for the exact permission, path, timestamp, quota, and atomicity rules.
16
16
  ## Install
17
17
 
18
18
  ```sh
19
- npm install @effect-vfs/core effect@4.0.0-rc.112
19
+ npm install @effect-vfs/core effect@4.0.0-rc.114
20
20
  ```
21
21
 
22
- Version `0.1.0` targets the exact peer version `effect@4.0.0-rc.112`.
22
+ Version `0.1.0` targets the exact peer version `effect@4.0.0-rc.114`.
23
23
 
24
24
  ## The mental model
25
25
 
@@ -40,15 +40,15 @@ lifetime are explicit values that can be composed in one Effect program.
40
40
 
41
41
  ```ts
42
42
  import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
43
- import { Effect } from "effect"
43
+ import { ByteSize, Effect } from "effect"
44
44
 
45
45
  const utf8 = new TextEncoder()
46
46
 
47
47
  const program = Effect.scoped(Effect.gen(function*() {
48
48
  const volume = yield* Vfs.make({
49
49
  maxEntries: 100,
50
- maxBytes: 1_000_000,
51
- maxFileBytes: 100_000
50
+ maxBytes: ByteSize.megabytes(1),
51
+ maxFileBytes: ByteSize.kilobytes(100)
52
52
  })
53
53
 
54
54
  const admin = yield* volume.caller()
@@ -129,12 +129,13 @@ resettable sandboxes.
129
129
  ```ts
130
130
  import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
131
131
  import { Effect } from "effect"
132
+ import * as ByteSize from "effect/ByteSize"
132
133
 
133
134
  const decodeLimits = {
134
- maxEncodedBytes: 1_000_000,
135
+ maxEncodedBytes: ByteSize.megabytes(1),
135
136
  maxRecords: 1_000,
136
137
  maxEntries: 1_000,
137
- maxDecodedBytes: 1_000_000
138
+ maxDecodedBytes: ByteSize.megabytes(1)
138
139
  }
139
140
 
140
141
  const program = Effect.gen(function*() {
@@ -184,6 +185,7 @@ contents.
184
185
  ```ts
185
186
  import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
186
187
  import { Effect } from "effect"
188
+ import * as ByteSize from "effect/ByteSize"
187
189
 
188
190
  const branch = Effect.gen(function*() {
189
191
  const template = yield* Vfs.fromFixture({
@@ -193,7 +195,7 @@ const branch = Effect.gen(function*() {
193
195
  ]
194
196
  })
195
197
  const base = yield* template.snapshot
196
- const workspace = yield* Vfs.makeOverlay(base, { maxBytes: 1_000_000 })
198
+ const workspace = yield* Vfs.makeOverlay(base, { maxBytes: ByteSize.megabytes(1) })
197
199
  const fs = yield* workspace.caller()
198
200
 
199
201
  yield* fs.rename("/project/settings.json", "/project/preferences.json")
@@ -221,6 +223,93 @@ The Effects returned by `changes(options)` and `capture(options)` are also reusa
221
223
  workspace again. Invalid summary options fail with `ConfigurationError`; failure to construct the complete observed
222
224
  snapshot fails with `ImageError`. Reusing a previously completed `capture()` result does not observe later writes.
223
225
 
226
+ ## Store and apply exact snapshot deltas
227
+
228
+ Use `diffSnapshots` when you need a portable description of the exact difference between two immutable snapshots.
229
+ The result is an opaque `SnapshotDelta`: inspect it for a path-oriented summary, encode it with Effect Schema, or apply
230
+ it to a semantically identical base to reconstruct the target snapshot.
231
+
232
+ ```ts
233
+ import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
234
+ import * as NodeCrypto from "@effect/platform-node/NodeCrypto"
235
+ import { Effect, Schema } from "effect"
236
+ import * as ByteSize from "effect/ByteSize"
237
+
238
+ const Delta = Vfs.SnapshotDeltaFromBytes()
239
+
240
+ const program = Effect.gen(function*() {
241
+ const baseVolume = yield* Vfs.fromFixture({
242
+ entries: [{ kind: "file", path: "/old.txt", bytes: new TextEncoder().encode("before") }]
243
+ })
244
+ const targetVolume = yield* Vfs.fromFixture({
245
+ entries: [{ kind: "file", path: "/new.txt", bytes: new TextEncoder().encode("after") }]
246
+ })
247
+ const base = yield* baseVolume.snapshot
248
+ const target = yield* targetVolume.snapshot
249
+
250
+ const delta = yield* Vfs.diffSnapshots(base, target)
251
+ const changes = yield* Vfs.inspectSnapshotDelta(base, delta)
252
+ const bytes = yield* Schema.encodeEffect(Delta)(delta)
253
+ const decoded = yield* Schema.decodeEffect(Delta)(bytes)
254
+ const restored = yield* Vfs.applySnapshotDelta(base, decoded)
255
+
256
+ return { changes, restored }
257
+ })
258
+
259
+ await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer)))
260
+ ```
261
+
262
+ Inspection verifies the delta against its semantic base before reporting what the two snapshots prove. It does not guess renames from equal contents or paths: a move is a
263
+ `Removed` change followed by an `Added` change. `Updated` records identify changed semantic fields, including content,
264
+ metadata, symbolic-link targets, and hard-link topology. Summaries do not contain replay payloads; the opaque delta does.
265
+
266
+ Each delta records the semantic identity of its required base. Inspecting or applying it against a different valid snapshot fails with a
267
+ `SnapshotDeltaError` whose `code` is `BaseMismatch`. Equivalent snapshots are accepted even if their encoded bytes or
268
+ internal record identifiers differ. Applying a delta returns another immutable `Snapshot`; call `fromSnapshot` when
269
+ you need a writable volume.
270
+
271
+ Creation, inspection, encoding, decoding, and application use finite `SnapshotDeltaLimits.default` limits when none are supplied.
272
+ Delta creation, inspection, and application require Effect's platform-neutral `Crypto.Crypto` service for SHA-256 base identity.
273
+ Provide the official Node, Bun, browser, or Deno crypto layer at the application edge; the core never imports a host
274
+ crypto implementation. Memory-sensitive applications can use one policy throughout the workflow:
275
+
276
+ ```ts
277
+ const limits = Vfs.SnapshotDeltaLimits.constrained
278
+ const Delta = Vfs.SnapshotDeltaFromBytes(limits)
279
+
280
+ const constrained = Effect.gen(function*() {
281
+ const delta = yield* Vfs.diffSnapshots(base, target, limits)
282
+ const bytes = yield* Schema.encodeEffect(Delta)(delta)
283
+ const decoded = yield* Schema.decodeEffect(Delta)(bytes)
284
+ return yield* Vfs.applySnapshotDelta(base, decoded, limits)
285
+ })
286
+ ```
287
+
288
+ Both presets are frozen complete policies. The shipped values are:
289
+
290
+ | limit | `constrained` | `default` |
291
+ | ----------------------------------- | ------------: | --------: |
292
+ | encoded bytes | 2 MiB | 16 MiB |
293
+ | canonical identity bytes | 4 MiB | 32 MiB |
294
+ | stored records plus summary changes | 6,500 | 50,000 |
295
+ | decoded delta bytes | 512 KiB | 8 MiB |
296
+ | base records | 6,500 | 50,000 |
297
+ | target records | 6,500 | 50,000 |
298
+ | namespace entries | 6,500 | 100,000 |
299
+ | output records | 6,500 | 50,000 |
300
+ | output payload bytes | 256 KiB | 4 MiB |
301
+ | inherited records | 6,500 | 50,000 |
302
+
303
+ These are conservative finite defaults, not universal workspace-size or memory guarantees. To tune one dimension,
304
+ spread a preset into a complete `SnapshotDeltaLimits` value and replace that field.
305
+
306
+ ```ts
307
+ const limits = {
308
+ ...Vfs.SnapshotDeltaLimits.default,
309
+ maxOutputBytes: ByteSize.mebibytes(8)
310
+ }
311
+ ```
312
+
224
313
  ## Use scoped handles for incremental I/O
225
314
 
226
315
  Whole-file operations are convenient, but handles give each open file an independent `bigint` cursor and support
@@ -0,0 +1,34 @@
1
+ import type * as Equal from "effect/Equal";
2
+ import type { Pipeable } from "effect/Pipeable";
3
+ import * as Schema from "effect/Schema";
4
+ /**
5
+ * Type identifier for opaque byte-preserving filesystem paths.
6
+ *
7
+ * @category type ids
8
+ * @since 0.1.0
9
+ */
10
+ export declare const BytePathId: "@effect-vfs/core/BytePath";
11
+ /**
12
+ * Type identifier for opaque byte-preserving filesystem paths.
13
+ *
14
+ * @category type ids
15
+ * @since 0.1.0
16
+ */
17
+ export type BytePathId = typeof BytePathId;
18
+ /**
19
+ * An opaque path that preserves arbitrary non-NUL bytes without UTF-8 conversion.
20
+ *
21
+ * @category models
22
+ * @since 0.1.0
23
+ */
24
+ export interface BytePath extends Equal.Equal, Pipeable {
25
+ readonly [BytePathId]: BytePathId;
26
+ }
27
+ /**
28
+ * Schema for an opaque byte-preserving filesystem path.
29
+ *
30
+ * @category schemas
31
+ * @since 0.1.0
32
+ */
33
+ export declare const BytePath: Schema.declare<BytePath, BytePath>;
34
+ //# sourceMappingURL=BytePath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BytePath.d.ts","sourceRoot":"","sources":["../src/BytePath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,2BAAiD,CAAA;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAA;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,QAAS,SAAQ,KAAK,CAAC,KAAK,EAAE,QAAQ;IACrD,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;CAClC;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,oCAAgD,CAAA"}
@@ -0,0 +1,16 @@
1
+ import * as Schema from "effect/Schema";
2
+ import * as Internal from "./internal/bytePath.js";
3
+ /**
4
+ * Type identifier for opaque byte-preserving filesystem paths.
5
+ *
6
+ * @category type ids
7
+ * @since 0.1.0
8
+ */
9
+ export const BytePathId = Internal.BytePathId;
10
+ /**
11
+ * Schema for an opaque byte-preserving filesystem path.
12
+ *
13
+ * @category schemas
14
+ * @since 0.1.0
15
+ */
16
+ export const BytePath = Schema.declare(Internal.isBytePath);
@@ -5,7 +5,7 @@ import * as Schema from "effect/Schema";
5
5
  * @category type ids
6
6
  * @since 0.1.0
7
7
  */
8
- export declare const SnapshotTypeId: unique symbol;
8
+ export declare const SnapshotTypeId: "@effect-vfs/core/Snapshot";
9
9
  /**
10
10
  * Type identifier for opaque filesystem snapshots.
11
11
  *
@@ -46,13 +46,13 @@ export declare class ImageError extends ImageError_base<{
46
46
  */
47
47
  export declare const DecodeLimits: Schema.Struct<{
48
48
  /** Maximum accepted encoded input length in bytes. */
49
- readonly maxEncodedBytes: Schema.Finite;
49
+ readonly maxEncodedBytes: Schema.ByteSize;
50
50
  /** Maximum number of stored metadata and content records. */
51
- readonly maxRecords: Schema.Finite;
51
+ readonly maxRecords: Schema.Natural;
52
52
  /** Maximum number of namespace entries. */
53
- readonly maxEntries: Schema.Finite;
53
+ readonly maxEntries: Schema.Natural;
54
54
  /** Maximum combined decoded byte content. */
55
- readonly maxDecodedBytes: Schema.Finite;
55
+ readonly maxDecodedBytes: Schema.ByteSize;
56
56
  }>;
57
57
  /**
58
58
  * Resource limits applied while decoding a snapshot.
@@ -1 +1 @@
1
- {"version":3,"file":"Snapshot.d.ts","sourceRoot":"","sources":["../src/Snapshot.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAQvC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,eAAsC,CAAA;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAA;AAElD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE,cAAc,CAAA;CAC1C;;;;AAED;;;;;GAKG;AACH,qBAAa,UAAW,SAAQ,gBAA+B;IAC7D,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,eAAe,CAAA;IAC9F,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB,CAAC;CAAG;AAEL;;;;;GAKG;AACH,eAAO,MAAM,YAAY;IACvB,sDAAsD;;IAEtD,6DAA6D;;IAE7D,2CAA2C;;IAE3C,6CAA6C;;EAE7C,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA"}
1
+ {"version":3,"file":"Snapshot.d.ts","sourceRoot":"","sources":["../src/Snapshot.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAG,2BAAoC,CAAA;AAElE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAA;AAElD;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE,cAAc,CAAA;CAC1C;;;;AAED;;;;;GAKG;AACH,qBAAa,UAAW,SAAQ,gBAA+B;IAC7D,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,eAAe,CAAA;IAC9F,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CACxB,CAAC;CAAG;AAEL;;;;;GAKG;AACH,eAAO,MAAM,YAAY;IACvB,sDAAsD;;IAEtD,6DAA6D;;IAE7D,2CAA2C;;IAE3C,6CAA6C;;EAE7C,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA"}
package/dist/Snapshot.js CHANGED
@@ -9,14 +9,13 @@
9
9
  */
10
10
  import * as Data from "effect/Data";
11
11
  import * as Schema from "effect/Schema";
12
- const Natural = Schema.Finite.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0), Schema.isLessThanOrEqualTo(Number.MAX_SAFE_INTEGER));
13
12
  /**
14
13
  * Type identifier for opaque filesystem snapshots.
15
14
  *
16
15
  * @category type ids
17
16
  * @since 0.1.0
18
17
  */
19
- export const SnapshotTypeId = Symbol("@effect-vfs/core/Snapshot");
18
+ export const SnapshotTypeId = "@effect-vfs/core/Snapshot";
20
19
  /**
21
20
  * Describes a snapshot encoding, decoding, structure, or resource-limit failure.
22
21
  *
@@ -33,11 +32,11 @@ export class ImageError extends Data.TaggedError("ImageError") {
33
32
  */
34
33
  export const DecodeLimits = Schema.Struct({
35
34
  /** Maximum accepted encoded input length in bytes. */
36
- maxEncodedBytes: Natural,
35
+ maxEncodedBytes: Schema.ByteSize,
37
36
  /** Maximum number of stored metadata and content records. */
38
- maxRecords: Natural,
37
+ maxRecords: Schema.Natural,
39
38
  /** Maximum number of namespace entries. */
40
- maxEntries: Natural,
39
+ maxEntries: Schema.Natural,
41
40
  /** Maximum combined decoded byte content. */
42
- maxDecodedBytes: Natural
41
+ maxDecodedBytes: Schema.ByteSize
43
42
  });
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Opaque portable snapshot deltas and their public inspection models.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ import * as ByteSize from "effect/ByteSize";
7
+ import * as Schema from "effect/Schema";
8
+ import { BytePath } from "./BytePath.js";
9
+ /**
10
+ * Type identifier for opaque snapshot deltas.
11
+ *
12
+ * @category type ids
13
+ * @since 0.1.0
14
+ */
15
+ export declare const SnapshotDeltaTypeId: "@effect-vfs/core/SnapshotDelta";
16
+ /**
17
+ * Type identifier for opaque snapshot deltas.
18
+ *
19
+ * @category type ids
20
+ * @since 0.1.0
21
+ */
22
+ export type SnapshotDeltaTypeId = typeof SnapshotDeltaTypeId;
23
+ /**
24
+ * An immutable, opaque description of the exact difference between two snapshots.
25
+ *
26
+ * @category models
27
+ * @since 0.1.0
28
+ */
29
+ export interface SnapshotDelta {
30
+ readonly [SnapshotDeltaTypeId]: SnapshotDeltaTypeId;
31
+ }
32
+ /**
33
+ * Schema for an already validated opaque snapshot delta.
34
+ *
35
+ * @category schemas
36
+ * @since 0.1.0
37
+ */
38
+ export declare const SnapshotDelta: Schema.declare<SnapshotDelta, SnapshotDelta>;
39
+ /**
40
+ * Schema for filesystem entry kinds reported by snapshot inspection.
41
+ *
42
+ * @category schemas
43
+ * @since 0.1.0
44
+ */
45
+ export declare const SnapshotNodeKind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
46
+ /**
47
+ * A filesystem entry kind reported by snapshot inspection.
48
+ *
49
+ * @category models
50
+ * @since 0.1.0
51
+ */
52
+ export type SnapshotNodeKind = typeof SnapshotNodeKind.Type;
53
+ /**
54
+ * Schema for semantic fields that can differ between snapshots.
55
+ *
56
+ * @category schemas
57
+ * @since 0.1.0
58
+ */
59
+ export declare const SnapshotDifference: Schema.Literals<readonly ["kind", "content", "target", "hardLinks", "mode", "uid", "gid", "atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]>;
60
+ /**
61
+ * A semantic field that differs between two snapshots.
62
+ *
63
+ * @category models
64
+ * @since 0.1.0
65
+ */
66
+ export type SnapshotDifference = typeof SnapshotDifference.Type;
67
+ /**
68
+ * Schema for a path-oriented difference between two snapshots.
69
+ *
70
+ * Independent snapshots do not preserve shared lineage, so moves are reported
71
+ * as a removal and an addition rather than an inferred rename.
72
+ *
73
+ * @category schemas
74
+ * @since 0.1.0
75
+ */
76
+ export declare const SnapshotChange: Schema.Union<readonly [Schema.TaggedStruct<"Added", {
77
+ readonly path: Schema.declare<BytePath, BytePath>;
78
+ readonly kind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
79
+ }>, Schema.TaggedStruct<"Removed", {
80
+ readonly path: Schema.declare<BytePath, BytePath>;
81
+ readonly kind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
82
+ }>, Schema.TaggedStruct<"Updated", {
83
+ readonly path: Schema.declare<BytePath, BytePath>;
84
+ readonly beforeKind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
85
+ readonly afterKind: Schema.Literals<readonly ["directory", "file", "symlink"]>;
86
+ readonly differences: Schema.$Array<Schema.Literals<readonly ["kind", "content", "target", "hardLinks", "mode", "uid", "gid", "atimeNs", "mtimeNs", "ctimeNs", "birthtimeNs"]>>;
87
+ }>]>;
88
+ /**
89
+ * A path-oriented semantic difference between two snapshots.
90
+ *
91
+ * @category models
92
+ * @since 0.1.0
93
+ */
94
+ export type SnapshotChange = typeof SnapshotChange.Type;
95
+ /**
96
+ * Schema for snapshot-delta inspection options.
97
+ *
98
+ * @category schemas
99
+ * @since 0.1.0
100
+ */
101
+ export declare const SnapshotChangesOptions: Schema.Struct<{
102
+ /** Include access, modification, change, and birth-time differences. Defaults to `false`. */
103
+ readonly includeTimestamps: Schema.optionalKey<Schema.Boolean>;
104
+ }>;
105
+ /**
106
+ * Filtering options for snapshot-delta inspection.
107
+ *
108
+ * @category models
109
+ * @since 0.1.0
110
+ */
111
+ export type SnapshotChangesOptions = typeof SnapshotChangesOptions.Type;
112
+ declare const SnapshotDeltaError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
113
+ readonly _tag: "SnapshotDeltaError";
114
+ } & Readonly<A>;
115
+ /**
116
+ * A valid snapshot delta was inspected or applied against a valid but semantically different base.
117
+ *
118
+ * @category errors
119
+ * @since 0.1.0
120
+ */
121
+ export declare class SnapshotDeltaError extends SnapshotDeltaError_base<{
122
+ readonly code: "BaseMismatch";
123
+ }> {
124
+ }
125
+ declare const SnapshotDeltaLimitsSchema: Schema.Struct<{
126
+ readonly maxEncodedBytes: Schema.ByteSize;
127
+ readonly maxIdentityBytes: Schema.ByteSize;
128
+ readonly maxDeltaRecords: Schema.Natural;
129
+ readonly maxDecodedDeltaBytes: Schema.ByteSize;
130
+ readonly maxBaseRecords: Schema.Natural;
131
+ readonly maxTargetRecords: Schema.Natural;
132
+ readonly maxEntries: Schema.Natural;
133
+ readonly maxOutputRecords: Schema.Natural;
134
+ readonly maxOutputBytes: Schema.ByteSize;
135
+ readonly maxInheritedRecords: Schema.Natural;
136
+ }>;
137
+ /**
138
+ * Resource limits shared by delta creation, inspection, encoding, decoding, and application.
139
+ *
140
+ * @category models
141
+ * @since 0.1.0
142
+ */
143
+ export type SnapshotDeltaLimits = typeof SnapshotDeltaLimitsSchema.Type;
144
+ /** Constructs and freezes a complete snapshot-delta resource policy. @internal */
145
+ export declare const makeSnapshotDeltaLimits: (limits: SnapshotDeltaLimits) => SnapshotDeltaLimits;
146
+ /**
147
+ * Schema for a complete snapshot-delta resource policy, with frozen presets.
148
+ *
149
+ * The constrained preset is intended for memory-sensitive environments. The
150
+ * default preset permits larger snapshots and payloads while remaining finite.
151
+ *
152
+ * @category schemas
153
+ * @since 0.1.0
154
+ */
155
+ export declare const SnapshotDeltaLimits: Schema.Struct<{
156
+ readonly maxEncodedBytes: Schema.ByteSize;
157
+ readonly maxIdentityBytes: Schema.ByteSize;
158
+ readonly maxDeltaRecords: Schema.Natural;
159
+ readonly maxDecodedDeltaBytes: Schema.ByteSize;
160
+ readonly maxBaseRecords: Schema.Natural;
161
+ readonly maxTargetRecords: Schema.Natural;
162
+ readonly maxEntries: Schema.Natural;
163
+ readonly maxOutputRecords: Schema.Natural;
164
+ readonly maxOutputBytes: Schema.ByteSize;
165
+ readonly maxInheritedRecords: Schema.Natural;
166
+ }> & {
167
+ constrained: {
168
+ readonly maxEncodedBytes: ByteSize.ByteSize;
169
+ readonly maxIdentityBytes: ByteSize.ByteSize;
170
+ readonly maxDeltaRecords: number;
171
+ readonly maxDecodedDeltaBytes: ByteSize.ByteSize;
172
+ readonly maxBaseRecords: number;
173
+ readonly maxTargetRecords: number;
174
+ readonly maxEntries: number;
175
+ readonly maxOutputRecords: number;
176
+ readonly maxOutputBytes: ByteSize.ByteSize;
177
+ readonly maxInheritedRecords: number;
178
+ };
179
+ default: {
180
+ readonly maxEncodedBytes: ByteSize.ByteSize;
181
+ readonly maxIdentityBytes: ByteSize.ByteSize;
182
+ readonly maxDeltaRecords: number;
183
+ readonly maxDecodedDeltaBytes: ByteSize.ByteSize;
184
+ readonly maxBaseRecords: number;
185
+ readonly maxTargetRecords: number;
186
+ readonly maxEntries: number;
187
+ readonly maxOutputRecords: number;
188
+ readonly maxOutputBytes: ByteSize.ByteSize;
189
+ readonly maxInheritedRecords: number;
190
+ };
191
+ };
192
+ export {};
193
+ //# sourceMappingURL=SnapshotDelta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SnapshotDelta.d.ts","sourceRoot":"","sources":["../src/SnapshotDelta.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAE3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAGxC;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,gCAA+D,CAAA;AAEjG;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAA;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;CACpD;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,8CAA0D,CAAA;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,4DAAoD,CAAA;AAEjF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,IAAI,CAAA;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,4IAY7B,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC,IAAI,CAAA;AAI/D;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;IASzB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;IACjC,6FAA6F;;EAE7F,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,sBAAsB,CAAC,IAAI,CAAA;;;;AAEvE;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAC9B,CAAC;CAAG;AAEL,QAAA,MAAM,yBAAyB;;;;;;;;;;;EAW7B,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,yBAAyB,CAAC,IAAI,CAAA;AAEvE,kFAAkF;AAClF,eAAO,MAAM,uBAAuB,WAAY,mBAAmB,KAAG,mBACxC,CAAA;AA2B9B;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG9B,CAAA"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Opaque portable snapshot deltas and their public inspection models.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ import * as ByteSize from "effect/ByteSize";
7
+ import * as Data from "effect/Data";
8
+ import * as Schema from "effect/Schema";
9
+ import { BytePath } from "./BytePath.js";
10
+ import * as Internal from "./internal/snapshotDeltaModel.js";
11
+ /**
12
+ * Type identifier for opaque snapshot deltas.
13
+ *
14
+ * @category type ids
15
+ * @since 0.1.0
16
+ */
17
+ export const SnapshotDeltaTypeId = Internal.SnapshotDeltaTypeId;
18
+ /**
19
+ * Schema for an already validated opaque snapshot delta.
20
+ *
21
+ * @category schemas
22
+ * @since 0.1.0
23
+ */
24
+ export const SnapshotDelta = Schema.declare(Internal.isSnapshotDelta);
25
+ /**
26
+ * Schema for filesystem entry kinds reported by snapshot inspection.
27
+ *
28
+ * @category schemas
29
+ * @since 0.1.0
30
+ */
31
+ export const SnapshotNodeKind = Schema.Literals(["directory", "file", "symlink"]);
32
+ /**
33
+ * Schema for semantic fields that can differ between snapshots.
34
+ *
35
+ * @category schemas
36
+ * @since 0.1.0
37
+ */
38
+ export const SnapshotDifference = Schema.Literals([
39
+ "kind",
40
+ "content",
41
+ "target",
42
+ "hardLinks",
43
+ "mode",
44
+ "uid",
45
+ "gid",
46
+ "atimeNs",
47
+ "mtimeNs",
48
+ "ctimeNs",
49
+ "birthtimeNs"
50
+ ]);
51
+ const SnapshotDifferences = Schema.Array(SnapshotDifference).check(Schema.isMinLength(1));
52
+ /**
53
+ * Schema for a path-oriented difference between two snapshots.
54
+ *
55
+ * Independent snapshots do not preserve shared lineage, so moves are reported
56
+ * as a removal and an addition rather than an inferred rename.
57
+ *
58
+ * @category schemas
59
+ * @since 0.1.0
60
+ */
61
+ export const SnapshotChange = Schema.Union([
62
+ Schema.TaggedStruct("Added", { path: BytePath, kind: SnapshotNodeKind }),
63
+ Schema.TaggedStruct("Removed", { path: BytePath, kind: SnapshotNodeKind }),
64
+ Schema.TaggedStruct("Updated", {
65
+ path: BytePath,
66
+ beforeKind: SnapshotNodeKind,
67
+ afterKind: SnapshotNodeKind,
68
+ differences: SnapshotDifferences
69
+ })
70
+ ]);
71
+ /**
72
+ * Schema for snapshot-delta inspection options.
73
+ *
74
+ * @category schemas
75
+ * @since 0.1.0
76
+ */
77
+ export const SnapshotChangesOptions = Schema.Struct({
78
+ /** Include access, modification, change, and birth-time differences. Defaults to `false`. */
79
+ includeTimestamps: Schema.optionalKey(Schema.Boolean)
80
+ });
81
+ /**
82
+ * A valid snapshot delta was inspected or applied against a valid but semantically different base.
83
+ *
84
+ * @category errors
85
+ * @since 0.1.0
86
+ */
87
+ export class SnapshotDeltaError extends Data.TaggedError("SnapshotDeltaError") {
88
+ }
89
+ const SnapshotDeltaLimitsSchema = Schema.Struct({
90
+ maxEncodedBytes: Schema.ByteSize,
91
+ maxIdentityBytes: Schema.ByteSize,
92
+ maxDeltaRecords: Schema.Natural,
93
+ maxDecodedDeltaBytes: Schema.ByteSize,
94
+ maxBaseRecords: Schema.Natural,
95
+ maxTargetRecords: Schema.Natural,
96
+ maxEntries: Schema.Natural,
97
+ maxOutputRecords: Schema.Natural,
98
+ maxOutputBytes: Schema.ByteSize,
99
+ maxInheritedRecords: Schema.Natural
100
+ });
101
+ /** Constructs and freezes a complete snapshot-delta resource policy. @internal */
102
+ export const makeSnapshotDeltaLimits = (limits) => Object.freeze({ ...limits });
103
+ const constrained = makeSnapshotDeltaLimits({
104
+ maxEncodedBytes: ByteSize.mebibytes(2),
105
+ maxIdentityBytes: ByteSize.mebibytes(4),
106
+ maxDeltaRecords: 6_500,
107
+ maxDecodedDeltaBytes: ByteSize.kibibytes(512),
108
+ maxBaseRecords: 6_500,
109
+ maxTargetRecords: 6_500,
110
+ maxEntries: 6_500,
111
+ maxOutputRecords: 6_500,
112
+ maxOutputBytes: ByteSize.kibibytes(256),
113
+ maxInheritedRecords: 6_500
114
+ });
115
+ const defaultLimits = makeSnapshotDeltaLimits({
116
+ maxEncodedBytes: ByteSize.mebibytes(16),
117
+ maxIdentityBytes: ByteSize.mebibytes(32),
118
+ maxDeltaRecords: 50_000,
119
+ maxDecodedDeltaBytes: ByteSize.mebibytes(8),
120
+ maxBaseRecords: 50_000,
121
+ maxTargetRecords: 50_000,
122
+ maxEntries: 100_000,
123
+ maxOutputRecords: 50_000,
124
+ maxOutputBytes: ByteSize.mebibytes(4),
125
+ maxInheritedRecords: 50_000
126
+ });
127
+ /**
128
+ * Schema for a complete snapshot-delta resource policy, with frozen presets.
129
+ *
130
+ * The constrained preset is intended for memory-sensitive environments. The
131
+ * default preset permits larger snapshots and payloads while remaining finite.
132
+ *
133
+ * @category schemas
134
+ * @since 0.1.0
135
+ */
136
+ export const SnapshotDeltaLimits = Object.assign(SnapshotDeltaLimitsSchema, {
137
+ constrained,
138
+ default: defaultLimits
139
+ });