@effect-vfs/core 0.3.0 → 0.4.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 +36 -149
- package/dist/BytePath.d.ts +34 -2
- package/dist/BytePath.d.ts.map +1 -1
- package/dist/BytePath.js +1 -1
- package/dist/LiveVolume.d.ts +101 -0
- package/dist/LiveVolume.d.ts.map +1 -0
- package/dist/LiveVolume.js +72 -0
- package/dist/Snapshot.d.ts +60 -2
- package/dist/Snapshot.d.ts.map +1 -1
- package/dist/Snapshot.js +59 -1
- package/dist/SnapshotDelta.d.ts +113 -3
- package/dist/SnapshotDelta.d.ts.map +1 -1
- package/dist/SnapshotDelta.js +112 -2
- package/dist/VirtualFileSystem.d.ts +1224 -90
- package/dist/VirtualFileSystem.d.ts.map +1 -1
- package/dist/VirtualFileSystem.js +678 -20
- package/dist/VirtualFileSystemError.d.ts +54 -0
- package/dist/VirtualFileSystemError.d.ts.map +1 -0
- package/dist/VirtualFileSystemError.js +49 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/internal/bytePath.d.ts.map +1 -1
- package/dist/internal/bytePath.js +5 -10
- package/dist/internal/bytes.d.ts +6 -0
- package/dist/internal/bytes.d.ts.map +1 -0
- package/dist/internal/bytes.js +17 -0
- package/dist/internal/canonicalBase64.d.ts +13 -5
- package/dist/internal/canonicalBase64.d.ts.map +1 -1
- package/dist/internal/canonicalBase64.js +28 -6
- package/dist/internal/image.d.ts +76 -90
- package/dist/internal/image.d.ts.map +1 -1
- package/dist/internal/image.js +98 -89
- package/dist/internal/liveImage.d.ts +286 -0
- package/dist/internal/liveImage.d.ts.map +1 -0
- package/dist/internal/liveImage.js +176 -0
- package/dist/internal/metadata.d.ts +28 -0
- package/dist/internal/metadata.d.ts.map +1 -0
- package/dist/internal/metadata.js +29 -0
- package/dist/internal/snapshotDelta.d.ts.map +1 -1
- package/dist/internal/snapshotDelta.js +346 -300
- package/dist/internal/snapshotDeltaModel.d.ts +2 -2
- package/dist/internal/snapshotDeltaModel.d.ts.map +1 -1
- package/dist/internal/snapshotDeltaModel.js +3 -1
- package/dist/internal/virtualFileSystem/errors.d.ts +6 -20
- package/dist/internal/virtualFileSystem/errors.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/errors.js +22 -7
- package/dist/internal/virtualFileSystem/fixture.d.ts +4 -1
- package/dist/internal/virtualFileSystem/fixture.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/fixture.js +80 -74
- package/dist/internal/virtualFileSystem/overlayContent.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/overlayContent.js +9 -2
- package/dist/internal/virtualFileSystem/overlayDiff.d.ts +2 -11
- package/dist/internal/virtualFileSystem/overlayDiff.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/overlayDiff.js +45 -71
- package/dist/internal/virtualFileSystem/path.d.ts +15 -14
- package/dist/internal/virtualFileSystem/path.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/path.js +57 -54
- package/dist/internal/virtualFileSystem/stagedState.d.ts +22 -0
- package/dist/internal/virtualFileSystem/stagedState.d.ts.map +1 -0
- package/dist/internal/virtualFileSystem/stagedState.js +62 -0
- package/dist/internal/virtualFileSystem/testHooks.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/watchHub.d.ts +3 -3
- package/dist/internal/virtualFileSystem/watchHub.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem/watchHub.js +45 -24
- package/dist/internal/virtualFileSystem.d.ts +307 -23
- package/dist/internal/virtualFileSystem.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem.js +1738 -525
- package/package.json +23 -5
package/README.md
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
# @effect-vfs/core
|
|
2
2
|
|
|
3
|
-
`@effect-vfs/core`
|
|
4
|
-
|
|
5
|
-
encoded snapshots without reading from or writing to the host filesystem.
|
|
3
|
+
`@effect-vfs/core` manages in-memory volumes with byte-preserving paths, callers with explicit permissions, quotas,
|
|
4
|
+
watches, fixtures, and portable snapshots. It does not access the host filesystem.
|
|
6
5
|
|
|
7
|
-
Use
|
|
8
|
-
|
|
9
|
-
Effect's standard `FileSystem` service, use [`@effect-vfs/memory`](https://www.npmjs.com/package/@effect-vfs/memory),
|
|
10
|
-
which adapts this package to that interface.
|
|
6
|
+
Use core when you need direct control over a shared volume or byte-oriented paths. For Effect's standard
|
|
7
|
+
`FileSystem` service, use [`@effect-vfs/memory`](../memory/README.md).
|
|
11
8
|
|
|
12
9
|
The package implements a documented subset of POSIX behavior. It does not claim full POSIX conformance. See the
|
|
13
10
|
[implemented profile](https://github.com/lloydrichards/effect-virtual-fs/blob/main/.okf/profiles/implemented-filesystem.md)
|
|
@@ -19,7 +16,8 @@ for the exact permission, path, timestamp, quota, and atomicity rules.
|
|
|
19
16
|
npm install @effect-vfs/core effect@4.0.0-rc.114
|
|
20
17
|
```
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
The package currently requires the exact peer version `effect@4.0.0-rc.114`. The examples also need a `Crypto`
|
|
20
|
+
service; on Node or Bun, install `@effect/platform-node-shared@4.0.0-rc.114` and provide `NodeCrypto.layer`.
|
|
23
21
|
|
|
24
22
|
## The mental model
|
|
25
23
|
|
|
@@ -40,6 +38,7 @@ lifetime are explicit values that can be composed in one Effect program.
|
|
|
40
38
|
|
|
41
39
|
```ts
|
|
42
40
|
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
41
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
43
42
|
import { ByteSize, Effect } from "effect"
|
|
44
43
|
|
|
45
44
|
const utf8 = new TextEncoder()
|
|
@@ -76,7 +75,7 @@ const program = Effect.scoped(Effect.gen(function*() {
|
|
|
76
75
|
}
|
|
77
76
|
}))
|
|
78
77
|
|
|
79
|
-
const result = await Effect.runPromise(program)
|
|
78
|
+
const result = await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer)))
|
|
80
79
|
console.log(result) // { config: { feature: "preview" }, mode: "640" }
|
|
81
80
|
```
|
|
82
81
|
|
|
@@ -94,6 +93,7 @@ contain names which are not valid UTF-8.
|
|
|
94
93
|
|
|
95
94
|
```ts
|
|
96
95
|
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
96
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
97
97
|
import { Effect } from "effect"
|
|
98
98
|
|
|
99
99
|
const program = Effect.gen(function*() {
|
|
@@ -112,7 +112,7 @@ const program = Effect.gen(function*() {
|
|
|
112
112
|
return { names: names.map((name) => Array.from(name)), roundTrip: Array.from(roundTrip) }
|
|
113
113
|
})
|
|
114
114
|
|
|
115
|
-
console.log(await Effect.runPromise(program))
|
|
115
|
+
console.log(await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer))))
|
|
116
116
|
// { names: [[255]], roundTrip: [47, 255] }
|
|
117
117
|
```
|
|
118
118
|
|
|
@@ -128,6 +128,7 @@ resettable sandboxes.
|
|
|
128
128
|
|
|
129
129
|
```ts
|
|
130
130
|
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
131
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
131
132
|
import { Effect } from "effect"
|
|
132
133
|
import * as ByteSize from "effect/ByteSize"
|
|
133
134
|
|
|
@@ -165,7 +166,7 @@ const program = Effect.gen(function*() {
|
|
|
165
166
|
return new TextDecoder().decode(yield* b.readFile("/project/settings.json"))
|
|
166
167
|
})
|
|
167
168
|
|
|
168
|
-
console.log(await Effect.runPromise(program)) // {"theme":"dark"}
|
|
169
|
+
console.log(await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer)))) // {"theme":"dark"}
|
|
169
170
|
```
|
|
170
171
|
|
|
171
172
|
Fixture paths must be absolute and unique, and parent directories must be listed explicitly. Fixtures can also contain
|
|
@@ -175,140 +176,15 @@ Snapshot decoding requires explicit work limits because encoded bytes may come f
|
|
|
175
176
|
contains the reachable namespace and metadata. It excludes callers, open handles, cursor positions, watch
|
|
176
177
|
subscriptions, and unlinked content. Each restored volume is independent.
|
|
177
178
|
|
|
178
|
-
##
|
|
179
|
+
## Overlays and snapshot deltas
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
contents.
|
|
181
|
+
An overlay creates a writable workspace from an immutable snapshot. Untouched file bytes remain shared until a
|
|
182
|
+
workspace edits them. See the [overlay guide](../../apps/docs/app/content/guides/overlay-filesystems.mdx) for the
|
|
183
|
+
workflow and conflict rules.
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
import * as ByteSize from "effect/ByteSize"
|
|
189
|
-
|
|
190
|
-
const branch = Effect.gen(function*() {
|
|
191
|
-
const template = yield* Vfs.fromFixture({
|
|
192
|
-
entries: [
|
|
193
|
-
{ kind: "directory", path: "/project" },
|
|
194
|
-
{ kind: "file", path: "/project/settings.json", bytes: new Uint8Array() }
|
|
195
|
-
]
|
|
196
|
-
})
|
|
197
|
-
const base = yield* template.snapshot
|
|
198
|
-
const workspace = yield* Vfs.makeOverlay(base, { maxBytes: ByteSize.megabytes(1) })
|
|
199
|
-
const fs = yield* workspace.caller()
|
|
200
|
-
|
|
201
|
-
yield* fs.rename("/project/settings.json", "/project/preferences.json")
|
|
202
|
-
return yield* workspace.capture()
|
|
203
|
-
})
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
`makeOverlay(base, options)` returns a reusable Effect. Each execution creates a fresh workspace from `base`; it does
|
|
207
|
-
not memoize or reset an earlier workspace. Invalid volume options fail with `ConfigurationError`, while failure to
|
|
208
|
-
inspect the base snapshot fails with `ImageError`.
|
|
209
|
-
|
|
210
|
-
`changes()` reports final differences from the base. It hides timestamp-only differences unless called with
|
|
211
|
-
`{ includeTimestamps: true }`. Renames are paired only from retained object identity; equal contents are never treated
|
|
212
|
-
as rename evidence. Paths in summaries are `BytePath` values, so inspect them with `pathToBytes` when names may not be
|
|
213
|
-
UTF-8. Although `OverlayChange` and its options have schemas, a summary is an in-process value containing opaque
|
|
214
|
-
`BytePath` objects. The schema is not a portable summary encoding.
|
|
215
|
-
|
|
216
|
-
`capture()` returns a complete version 1 snapshot and matching summary from one committed state. Later writes change
|
|
217
|
-
neither result. The snapshot works with `encodeSnapshot`, `fromSnapshot`, and `@effect-vfs/persistence` checkpoints.
|
|
218
|
-
Restoring it recovers the complete filesystem state, not the earlier overlay base relationship or summary. To reset,
|
|
219
|
-
create a fresh overlay from the base and replace your application reference; existing callers, handles, and watches
|
|
220
|
-
remain attached to the old workspace until their own lifetimes end.
|
|
221
|
-
|
|
222
|
-
The Effects returned by `changes(options)` and `capture(options)` are also reusable. Each execution observes the
|
|
223
|
-
workspace again. Invalid summary options fail with `ConfigurationError`; failure to construct the complete observed
|
|
224
|
-
snapshot fails with `ImageError`. Reusing a previously completed `capture()` result does not observe later writes.
|
|
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
|
-
```
|
|
185
|
+
Snapshot deltas encode exact changes between compatible images. They have separate decode and application limits;
|
|
186
|
+
check those limits before accepting an untrusted delta. See the
|
|
187
|
+
[snapshot delta API](../../apps/docs/app/content/api/core/snapshot-delta.mdx) for operations and defaults.
|
|
312
188
|
|
|
313
189
|
## Use scoped handles for incremental I/O
|
|
314
190
|
|
|
@@ -318,6 +194,7 @@ interruption.
|
|
|
318
194
|
|
|
319
195
|
```ts
|
|
320
196
|
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
197
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
321
198
|
import { Effect } from "effect"
|
|
322
199
|
|
|
323
200
|
const program = Effect.scoped(Effect.gen(function*() {
|
|
@@ -335,7 +212,7 @@ const program = Effect.scoped(Effect.gen(function*() {
|
|
|
335
212
|
return [first, second, preview].map((bytes) => new TextDecoder().decode(bytes))
|
|
336
213
|
}))
|
|
337
214
|
|
|
338
|
-
console.log(await Effect.runPromise(program)) // ["one\n", "two\n", "one"]
|
|
215
|
+
console.log(await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer)))) // ["one\n", "two\n", "one"]
|
|
339
216
|
```
|
|
340
217
|
|
|
341
218
|
Handles also expose an explicit `close` effect when early release matters. Calling explicit close twice fails, while
|
|
@@ -349,6 +226,7 @@ expected failures.
|
|
|
349
226
|
|
|
350
227
|
```ts
|
|
351
228
|
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
229
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
352
230
|
import { Effect } from "effect"
|
|
353
231
|
|
|
354
232
|
const program = Effect.gen(function*() {
|
|
@@ -362,7 +240,7 @@ const program = Effect.gen(function*() {
|
|
|
362
240
|
)
|
|
363
241
|
})
|
|
364
242
|
|
|
365
|
-
const bytes = await Effect.runPromise(program)
|
|
243
|
+
const bytes = await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer)))
|
|
366
244
|
console.log(new TextDecoder().decode(bytes)) // {}
|
|
367
245
|
```
|
|
368
246
|
|
|
@@ -374,6 +252,7 @@ current directory.
|
|
|
374
252
|
|
|
375
253
|
```ts
|
|
376
254
|
import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
255
|
+
import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
377
256
|
import { Effect } from "effect"
|
|
378
257
|
|
|
379
258
|
const loadConfig = Effect.gen(function*() {
|
|
@@ -391,7 +270,7 @@ const program = Effect.gen(function*() {
|
|
|
391
270
|
return yield* loadConfig.pipe(Effect.provideService(Vfs.CurrentFileSystem, fs))
|
|
392
271
|
})
|
|
393
272
|
|
|
394
|
-
const bytes = await Effect.runPromise(program)
|
|
273
|
+
const bytes = await Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer)))
|
|
395
274
|
console.log(new TextDecoder().decode(bytes)) // {}
|
|
396
275
|
```
|
|
397
276
|
|
|
@@ -410,9 +289,17 @@ candidate.
|
|
|
410
289
|
- Components are limited to 255 bytes. Symbolic-link traversal is limited to 40 links.
|
|
411
290
|
- Omitted logical quotas are unbounded by configuration, apart from fixed file and component bounds.
|
|
412
291
|
- Absolute paths ignore a supplied directory base. Relative paths can use a live, same-volume directory handle.
|
|
413
|
-
- Operations coordinate through one permit per volume.
|
|
414
|
-
|
|
415
|
-
|
|
292
|
+
- Operations coordinate through one permit per volume. At most 65 operations are admitted at once by
|
|
293
|
+
default, including the active operation; set `maxPendingOperations` to change the waiting budget.
|
|
294
|
+
Excess work fails with retryable `FsError` code `VolumeBusy`
|
|
295
|
+
before mutation or storage commit. Interruption while waiting makes no change; interruption after a commit
|
|
296
|
+
does not roll it back.
|
|
297
|
+
- Each watch subscriber retains at most 256 events by default; set `maxWatchEvents` to change this bound
|
|
298
|
+
(minimum 2). A subscriber that loses events receives `Rescan` with path `/` after its buffered events.
|
|
299
|
+
Rescan the volume, then continue consuming the watch; repeat the scan if another `Rescan` arrives.
|
|
300
|
+
Delivered events retain their order. The memory `FileSystem.watch` stream fails with a platform error
|
|
301
|
+
identified by `MemoryFileSystem.isWatchOverflow`. Open a new watch before rescanning its path so changes
|
|
302
|
+
during the scan remain observable.
|
|
416
303
|
- `sync` checks handle liveness. An in-memory volume provides no host or crash durability.
|
|
417
304
|
|
|
418
305
|
For the complete contract, read the
|
package/dist/BytePath.d.ts
CHANGED
|
@@ -1,23 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque, byte-preserving filesystem paths.
|
|
3
|
+
*
|
|
4
|
+
* A `BytePath` stores the exact bytes of a path component so that names which
|
|
5
|
+
* are not valid UTF-8 survive a round trip through the virtual filesystem.
|
|
6
|
+
*
|
|
7
|
+
* @since 0.1.0
|
|
8
|
+
*/
|
|
1
9
|
import type * as Equal from "effect/Equal";
|
|
2
10
|
import type { Pipeable } from "effect/Pipeable";
|
|
3
11
|
import * as Schema from "effect/Schema";
|
|
4
12
|
/**
|
|
5
13
|
* Type identifier for opaque byte-preserving filesystem paths.
|
|
6
14
|
*
|
|
7
|
-
* @category type
|
|
15
|
+
* @category type IDs
|
|
8
16
|
* @since 0.1.0
|
|
9
17
|
*/
|
|
10
18
|
export declare const BytePathId: "@effect-vfs/core/BytePath";
|
|
11
19
|
/**
|
|
12
20
|
* Type identifier for opaque byte-preserving filesystem paths.
|
|
13
21
|
*
|
|
14
|
-
* @category type
|
|
22
|
+
* @category type IDs
|
|
15
23
|
* @since 0.1.0
|
|
16
24
|
*/
|
|
17
25
|
export type BytePathId = typeof BytePathId;
|
|
18
26
|
/**
|
|
19
27
|
* An opaque path that preserves arbitrary non-NUL bytes without UTF-8 conversion.
|
|
20
28
|
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
32
|
+
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
33
|
+
* import { Effect } from "effect"
|
|
34
|
+
*
|
|
35
|
+
* // A name that is not valid UTF-8 still round-trips exactly.
|
|
36
|
+
* const program = Effect.gen(function*() {
|
|
37
|
+
* const caller = yield* (yield* Vfs.make()).caller()
|
|
38
|
+
* const path = yield* Vfs.pathFromBytes(new Uint8Array([47, 0xff, 0xfe]))
|
|
39
|
+
*
|
|
40
|
+
* yield* caller.writeFile(path, new Uint8Array([1]), {
|
|
41
|
+
* access: "write",
|
|
42
|
+
* create: "exclusive"
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* // `readDirectory` fails `UnrepresentableName` here; the byte variant keeps it.
|
|
46
|
+
* return yield* caller.readDirectoryBytes("/")
|
|
47
|
+
* })
|
|
48
|
+
*
|
|
49
|
+
* Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer))).then(console.log)
|
|
50
|
+
* // [ Uint8Array(2) [ 255, 254 ] ]
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
21
53
|
* @category models
|
|
22
54
|
* @since 0.1.0
|
|
23
55
|
*/
|
package/dist/BytePath.d.ts.map
CHANGED
|
@@ -1 +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
|
|
1
|
+
{"version":3,"file":"BytePath.d.ts","sourceRoot":"","sources":["../src/BytePath.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;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"}
|
package/dist/BytePath.js
CHANGED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image boundary for a storage adapter that commits each live volume mutation.
|
|
3
|
+
*
|
|
4
|
+
* An adapter must preserve the supplied bytes atomically and classify each
|
|
5
|
+
* commit as confirmed, definitely rejected, or uncertain. The opened volume
|
|
6
|
+
* stays at `memory-only` until the adapter's durability is qualified.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.4.0
|
|
9
|
+
*/
|
|
10
|
+
import { Context, Effect } from "effect";
|
|
11
|
+
import * as ByteSize from "effect/ByteSize";
|
|
12
|
+
import type * as Crypto from "effect/Crypto";
|
|
13
|
+
import type * as PlatformError from "effect/PlatformError";
|
|
14
|
+
import type * as Scope from "effect/Scope";
|
|
15
|
+
import type { ConfigurationError, ImageError, Volume, VolumeOptions } from "./VirtualFileSystem.js";
|
|
16
|
+
/**
|
|
17
|
+
* A storage commit's observed outcome.
|
|
18
|
+
*
|
|
19
|
+
* @since 0.4.0
|
|
20
|
+
*/
|
|
21
|
+
export type CommitOutcome = "committed" | "rejected" | "unknown";
|
|
22
|
+
declare const LiveVolumeError_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 & {
|
|
23
|
+
readonly _tag: "LiveVolumeError";
|
|
24
|
+
} & Readonly<A>;
|
|
25
|
+
/**
|
|
26
|
+
* A failed live-store startup or recovery.
|
|
27
|
+
*
|
|
28
|
+
* @category errors
|
|
29
|
+
* @since 0.4.0
|
|
30
|
+
*/
|
|
31
|
+
export declare class LiveVolumeError extends LiveVolumeError_base<{
|
|
32
|
+
readonly code: "InvalidConfiguration" | "Storage" | "Ownership" | "IncompatibleStore" | "CorruptStore";
|
|
33
|
+
readonly cause?: unknown;
|
|
34
|
+
}> {
|
|
35
|
+
}
|
|
36
|
+
declare const LiveImageStore_base: Context.ServiceClass<LiveImageStore, "@effect-vfs/core/LiveImageStore", {
|
|
37
|
+
readonly loadOrCreate: (initial: Uint8Array) => Effect.Effect<Uint8Array, LiveVolumeError>;
|
|
38
|
+
readonly commit: (image: Uint8Array) => Effect.Effect<CommitOutcome>;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* One exclusively owned store. Its Layer holds the storage resource until the
|
|
42
|
+
* volume has shut down. Providers must atomically replace each image and
|
|
43
|
+
* classify ambiguous commits as `unknown`.
|
|
44
|
+
*
|
|
45
|
+
* @since 0.4.0
|
|
46
|
+
*/
|
|
47
|
+
export declare class LiveImageStore extends LiveImageStore_base {
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Configuration shared by every live-image provider.
|
|
51
|
+
*
|
|
52
|
+
* @category models
|
|
53
|
+
* @since 0.4.0
|
|
54
|
+
*/
|
|
55
|
+
export interface Options {
|
|
56
|
+
readonly maxImageBytes: ByteSize.ByteSize;
|
|
57
|
+
readonly volume: VolumeOptions;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Open a live volume using the supplied store Layer. The caller owns a Scope;
|
|
61
|
+
* the volume shuts down before that Layer releases its storage resource.
|
|
62
|
+
*
|
|
63
|
+
* @since 0.4.0
|
|
64
|
+
*/
|
|
65
|
+
export declare const open: (options: Options) => Effect.Effect<Volume, LiveVolumeError, LiveImageStore | Crypto.Crypto | Scope.Scope>;
|
|
66
|
+
/**
|
|
67
|
+
* A live volume and the shutdown action its storage adapter must run before
|
|
68
|
+
* closing the underlying store.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import type { ImageSession } from "@effect-vfs/core/LiveVolume"
|
|
73
|
+
*
|
|
74
|
+
* const shutdown = (session: ImageSession) => session.shutdown
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @category models
|
|
78
|
+
* @since 0.4.0
|
|
79
|
+
*/
|
|
80
|
+
export interface ImageSession {
|
|
81
|
+
readonly volume: Volume;
|
|
82
|
+
readonly shutdown: Effect.Effect<void>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Construct a versioned image for a new, empty volume.
|
|
86
|
+
* Store this image before opening it for mutation.
|
|
87
|
+
*
|
|
88
|
+
* @since 0.4.0
|
|
89
|
+
*/
|
|
90
|
+
export declare const prepareEmptyImage: (options?: VolumeOptions) => Effect.Effect<Uint8Array, ConfigurationError | ImageError | PlatformError.PlatformError, Crypto.Crypto>;
|
|
91
|
+
/**
|
|
92
|
+
* Open a validated image and stage every mutation before calling `commit`.
|
|
93
|
+
* The returned session contains the volume and a coordinated shutdown effect.
|
|
94
|
+
* Run shutdown before releasing the storage connection. An uncertain commit
|
|
95
|
+
* makes the volume unavailable until it is reopened.
|
|
96
|
+
*
|
|
97
|
+
* @since 0.4.0
|
|
98
|
+
*/
|
|
99
|
+
export declare const openImage: (image: Uint8Array, maxImageBytes: ByteSize.ByteSize, commit: (image: Uint8Array) => Effect.Effect<CommitOutcome>) => Effect.Effect<ImageSession, ConfigurationError | ImageError | PlatformError.PlatformError, Crypto.Crypto>;
|
|
100
|
+
export {};
|
|
101
|
+
//# sourceMappingURL=LiveVolume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveVolume.d.ts","sourceRoot":"","sources":["../src/LiveVolume.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,KAAK,aAAa,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAA;AAE1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEnG;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAA;;;;AAEhE;;;;;GAKG;AACH,qBAAa,eAAgB,SAAQ,qBAAoC;IACvE,QAAQ,CAAC,IAAI,EAAE,sBAAsB,GAAG,SAAS,GAAG,WAAW,GAAG,mBAAmB,GAAG,cAAc,CAAA;IACtG,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAC;CAAG;;2BAUoB,CAAC,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,eAAe,CAAC;qBACzE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;;AATtE;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,mBAGG;CAAG;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAQ,CAAA;IACzC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAC/B;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CACpD,MAAM,EACN,eAAe,EACf,cAAc,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAkC5C,CAAA;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CACvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,CAAC,OAAO,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC,MAAM,CACxE,UAAU,EACV,kBAAkB,GAAG,UAAU,GAAG,aAAa,CAAC,aAAa,EAC7D,MAAM,CAAC,MAAM,CACgB,CAAA;AAE/B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,CACtB,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,QAAQ,CAAC,QAAQ,EAChC,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,KACxD,MAAM,CAAC,MAAM,CAChB,YAAY,EACZ,kBAAkB,GAAG,UAAU,GAAG,aAAa,CAAC,aAAa,EAC7D,MAAM,CAAC,MAAM,CACU,CAAA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image boundary for a storage adapter that commits each live volume mutation.
|
|
3
|
+
*
|
|
4
|
+
* An adapter must preserve the supplied bytes atomically and classify each
|
|
5
|
+
* commit as confirmed, definitely rejected, or uncertain. The opened volume
|
|
6
|
+
* stays at `memory-only` until the adapter's durability is qualified.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.4.0
|
|
9
|
+
*/
|
|
10
|
+
import { Context, Data, Effect } from "effect";
|
|
11
|
+
import * as ByteSize from "effect/ByteSize";
|
|
12
|
+
import * as Model from "./internal/virtualFileSystem.js";
|
|
13
|
+
/**
|
|
14
|
+
* A failed live-store startup or recovery.
|
|
15
|
+
*
|
|
16
|
+
* @category errors
|
|
17
|
+
* @since 0.4.0
|
|
18
|
+
*/
|
|
19
|
+
export class LiveVolumeError extends Data.TaggedError("LiveVolumeError") {
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One exclusively owned store. Its Layer holds the storage resource until the
|
|
23
|
+
* volume has shut down. Providers must atomically replace each image and
|
|
24
|
+
* classify ambiguous commits as `unknown`.
|
|
25
|
+
*
|
|
26
|
+
* @since 0.4.0
|
|
27
|
+
*/
|
|
28
|
+
export class LiveImageStore extends Context.Service()("@effect-vfs/core/LiveImageStore") {
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Open a live volume using the supplied store Layer. The caller owns a Scope;
|
|
32
|
+
* the volume shuts down before that Layer releases its storage resource.
|
|
33
|
+
*
|
|
34
|
+
* @since 0.4.0
|
|
35
|
+
*/
|
|
36
|
+
export const open = Effect.fn("LiveVolume.open")(function* (options) {
|
|
37
|
+
const store = yield* LiveImageStore;
|
|
38
|
+
const initial = yield* prepareEmptyImage(options.volume).pipe(Effect.mapError((cause) => new LiveVolumeError({ code: "InvalidConfiguration", cause })));
|
|
39
|
+
if (BigInt(initial.length) > ByteSize.toBigInt(options.maxImageBytes)) {
|
|
40
|
+
return yield* new LiveVolumeError({ code: "InvalidConfiguration" });
|
|
41
|
+
}
|
|
42
|
+
const image = yield* store.loadOrCreate(initial);
|
|
43
|
+
const session = yield* openImage(image, options.maxImageBytes, store.commit).pipe(Effect.mapError((cause) => new LiveVolumeError({ code: "CorruptStore", cause })));
|
|
44
|
+
yield* Effect.addFinalizer(() => session.shutdown);
|
|
45
|
+
const volume = session.volume;
|
|
46
|
+
if (volume.limits.maxEntries !== options.volume.maxEntries || volume.limits.maxBytes === undefined ||
|
|
47
|
+
volume.limits.maxPathBytes === undefined || options.volume.maxBytes === undefined ||
|
|
48
|
+
options.volume.maxFileBytes === undefined || options.volume.maxPathBytes === undefined ||
|
|
49
|
+
ByteSize.toBigInt(volume.limits.maxBytes) !== ByteSize.toBigInt(options.volume.maxBytes) ||
|
|
50
|
+
ByteSize.toBigInt(volume.limits.maxFileBytes) !== ByteSize.toBigInt(options.volume.maxFileBytes) ||
|
|
51
|
+
ByteSize.toBigInt(volume.limits.maxPathBytes) !== ByteSize.toBigInt(options.volume.maxPathBytes) ||
|
|
52
|
+
(options.volume.identity !== undefined && options.volume.identity !== volume.identity)) {
|
|
53
|
+
return yield* new LiveVolumeError({ code: "IncompatibleStore" });
|
|
54
|
+
}
|
|
55
|
+
return volume;
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* Construct a versioned image for a new, empty volume.
|
|
59
|
+
* Store this image before opening it for mutation.
|
|
60
|
+
*
|
|
61
|
+
* @since 0.4.0
|
|
62
|
+
*/
|
|
63
|
+
export const prepareEmptyImage = Model.prepareEmptyLiveImage;
|
|
64
|
+
/**
|
|
65
|
+
* Open a validated image and stage every mutation before calling `commit`.
|
|
66
|
+
* The returned session contains the volume and a coordinated shutdown effect.
|
|
67
|
+
* Run shutdown before releasing the storage connection. An uncertain commit
|
|
68
|
+
* makes the volume unavailable until it is reopened.
|
|
69
|
+
*
|
|
70
|
+
* @since 0.4.0
|
|
71
|
+
*/
|
|
72
|
+
export const openImage = Model.openImageVolume;
|
package/dist/Snapshot.d.ts
CHANGED
|
@@ -2,14 +2,14 @@ import * as Schema from "effect/Schema";
|
|
|
2
2
|
/**
|
|
3
3
|
* Type identifier for opaque filesystem snapshots.
|
|
4
4
|
*
|
|
5
|
-
* @category type
|
|
5
|
+
* @category type IDs
|
|
6
6
|
* @since 0.1.0
|
|
7
7
|
*/
|
|
8
8
|
export declare const SnapshotTypeId: "@effect-vfs/core/Snapshot";
|
|
9
9
|
/**
|
|
10
10
|
* Type identifier for opaque filesystem snapshots.
|
|
11
11
|
*
|
|
12
|
-
* @category type
|
|
12
|
+
* @category type IDs
|
|
13
13
|
* @since 0.1.0
|
|
14
14
|
*/
|
|
15
15
|
export type SnapshotTypeId = typeof SnapshotTypeId;
|
|
@@ -28,6 +28,36 @@ declare const ImageError_base: new <A extends Record<string, any> = {}>(args: im
|
|
|
28
28
|
/**
|
|
29
29
|
* Describes a snapshot encoding, decoding, structure, or resource-limit failure.
|
|
30
30
|
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
34
|
+
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
35
|
+
* import { ByteSize, Effect } from "effect"
|
|
36
|
+
*
|
|
37
|
+
* // Decoding is a trust boundary. `code` says what went wrong and `field` says
|
|
38
|
+
* // which input or limit it was, so a caller can decline just the bad payload.
|
|
39
|
+
* const program = Effect.gen(function*() {
|
|
40
|
+
* const volume = yield* Vfs.make()
|
|
41
|
+
* const bytes = yield* Vfs.encodeSnapshot(yield* volume.snapshot)
|
|
42
|
+
*
|
|
43
|
+
* return yield* Vfs.decodeSnapshot(bytes, {
|
|
44
|
+
* maxEncodedBytes: ByteSize.bytes(16),
|
|
45
|
+
* maxRecords: 10_000,
|
|
46
|
+
* maxEntries: 10_000,
|
|
47
|
+
* maxDecodedBytes: ByteSize.megabytes(16)
|
|
48
|
+
* }).pipe(
|
|
49
|
+
* Effect.as("accepted"),
|
|
50
|
+
* Effect.catchTag("ImageError", (error) =>
|
|
51
|
+
* error.code === "LimitExceeded"
|
|
52
|
+
* ? Effect.succeed(`declined at ${error.field}`)
|
|
53
|
+
* : Effect.fail(error))
|
|
54
|
+
* )
|
|
55
|
+
* })
|
|
56
|
+
*
|
|
57
|
+
* Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer))).then(console.log)
|
|
58
|
+
* // declined at encodedBytes
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
31
61
|
* @category errors
|
|
32
62
|
* @since 0.1.0
|
|
33
63
|
*/
|
|
@@ -41,6 +71,34 @@ export declare class ImageError extends ImageError_base<{
|
|
|
41
71
|
/**
|
|
42
72
|
* Schema for the mandatory resource limits applied while decoding a snapshot.
|
|
43
73
|
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
77
|
+
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
78
|
+
* import { ByteSize, Effect } from "effect"
|
|
79
|
+
*
|
|
80
|
+
* // All four are required: each bounds a different resource. `maxEncodedBytes`
|
|
81
|
+
* // caps the wire payload before parsing; `maxDecodedBytes` caps memory after it.
|
|
82
|
+
* const limits: Vfs.DecodeLimits = {
|
|
83
|
+
* maxEncodedBytes: ByteSize.megabytes(4),
|
|
84
|
+
* maxRecords: 10_000,
|
|
85
|
+
* maxEntries: 10_000,
|
|
86
|
+
* maxDecodedBytes: ByteSize.megabytes(16)
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* const program = Effect.gen(function*() {
|
|
90
|
+
* const volume = yield* Vfs.make()
|
|
91
|
+
* const bytes = yield* Vfs.encodeSnapshot(yield* volume.snapshot)
|
|
92
|
+
*
|
|
93
|
+
* yield* Vfs.decodeSnapshot(bytes, limits)
|
|
94
|
+
*
|
|
95
|
+
* return "accepted"
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer))).then(console.log)
|
|
99
|
+
* // accepted
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
44
102
|
* @category schemas
|
|
45
103
|
* @since 0.1.0
|
|
46
104
|
*/
|
package/dist/Snapshot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;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"}
|