@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.
- package/README.md +29 -21
- package/dist/BytePath.d.ts +115 -4
- package/dist/BytePath.d.ts.map +1 -1
- package/dist/BytePath.js +155 -0
- package/dist/Caller.d.ts +391 -0
- package/dist/Caller.d.ts.map +1 -0
- package/dist/Caller.js +199 -0
- package/dist/FileHandle.d.ts +50 -0
- package/dist/FileHandle.d.ts.map +1 -0
- package/dist/FileHandle.js +28 -0
- package/dist/Fixture.d.ts +155 -0
- package/dist/Fixture.d.ts.map +1 -0
- package/dist/Fixture.js +65 -0
- package/dist/LiveVolume.d.ts +13 -20
- package/dist/LiveVolume.d.ts.map +1 -1
- package/dist/LiveVolume.js +19 -14
- package/dist/Metadata.d.ts +186 -0
- package/dist/Metadata.d.ts.map +1 -0
- package/dist/Metadata.js +125 -0
- package/dist/Snapshot.d.ts +32 -53
- package/dist/Snapshot.d.ts.map +1 -1
- package/dist/Snapshot.js +27 -49
- package/dist/SnapshotDelta.d.ts +24 -39
- package/dist/SnapshotDelta.d.ts.map +1 -1
- package/dist/SnapshotDelta.js +14 -35
- package/dist/Target.d.ts +225 -0
- package/dist/Target.d.ts.map +1 -0
- package/dist/Target.js +92 -0
- package/dist/Testing.d.ts +132 -0
- package/dist/Testing.d.ts.map +1 -0
- package/dist/Testing.js +100 -0
- package/dist/VfsError.d.ts +200 -0
- package/dist/VfsError.d.ts.map +1 -0
- package/dist/VfsError.js +165 -0
- package/dist/VirtualFileSystem.d.ts +676 -353
- package/dist/VirtualFileSystem.d.ts.map +1 -1
- package/dist/VirtualFileSystem.js +487 -121
- package/dist/Volume.d.ts +211 -0
- package/dist/Volume.d.ts.map +1 -0
- package/dist/Volume.js +172 -0
- package/dist/Watch.d.ts +68 -0
- package/dist/Watch.d.ts.map +1 -0
- package/dist/Watch.js +46 -0
- package/dist/index.d.ts +56 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -1
- package/dist/internal/budget.d.ts +90 -0
- package/dist/internal/budget.d.ts.map +1 -0
- package/dist/internal/budget.js +70 -0
- package/dist/internal/bytePath.d.ts +2 -0
- package/dist/internal/bytePath.d.ts.map +1 -1
- package/dist/internal/bytePath.js +3 -2
- package/dist/internal/bytes.d.ts +3 -0
- package/dist/internal/bytes.d.ts.map +1 -1
- package/dist/internal/bytes.js +4 -2
- package/dist/internal/canonicalBase64.d.ts +1 -4
- package/dist/internal/canonicalBase64.d.ts.map +1 -1
- package/dist/internal/canonicalBase64.js +9 -13
- package/dist/internal/errors.d.ts +47 -5
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +80 -36
- package/dist/internal/fixture.d.ts +2 -2
- package/dist/internal/fixture.d.ts.map +1 -1
- package/dist/internal/fixture.js +57 -74
- package/dist/internal/hex128.d.ts +12 -0
- package/dist/internal/hex128.d.ts.map +1 -0
- package/dist/internal/hex128.js +7 -0
- package/dist/internal/hmac.d.ts +5 -0
- package/dist/internal/hmac.d.ts.map +1 -0
- package/dist/internal/hmac.js +150 -0
- package/dist/internal/image.d.ts +14 -117
- package/dist/internal/image.d.ts.map +1 -1
- package/dist/internal/image.js +137 -167
- package/dist/internal/inodeTable.d.ts +20 -0
- package/dist/internal/inodeTable.d.ts.map +1 -0
- package/dist/internal/inodeTable.js +48 -0
- package/dist/internal/lines.d.ts +36 -0
- package/dist/internal/lines.d.ts.map +1 -0
- package/dist/internal/lines.js +115 -0
- package/dist/internal/liveImage.d.ts +19 -278
- package/dist/internal/liveImage.d.ts.map +1 -1
- package/dist/internal/liveImage.js +75 -166
- package/dist/internal/merkle.d.ts +45 -0
- package/dist/internal/merkle.d.ts.map +1 -0
- package/dist/internal/merkle.js +179 -0
- package/dist/internal/metadata.d.ts +2 -13
- package/dist/internal/metadata.d.ts.map +1 -1
- package/dist/internal/metadata.js +5 -15
- package/dist/internal/overlayDiff.d.ts +2 -2
- package/dist/internal/overlayDiff.d.ts.map +1 -1
- package/dist/internal/overlayDiff.js +4 -15
- package/dist/internal/path.d.ts +17 -5
- package/dist/internal/path.d.ts.map +1 -1
- package/dist/internal/path.js +38 -24
- package/dist/internal/snapshotDelta.d.ts +61 -60
- package/dist/internal/snapshotDelta.d.ts.map +1 -1
- package/dist/internal/snapshotDelta.js +605 -503
- package/dist/internal/snapshotDeltaModel.d.ts.map +1 -1
- package/dist/internal/snapshotDeltaModel.js +0 -1
- package/dist/internal/testSeams.d.ts +17 -0
- package/dist/internal/testSeams.d.ts.map +1 -0
- package/dist/internal/testSeams.js +20 -0
- package/dist/internal/tree.d.ts +225 -0
- package/dist/internal/tree.d.ts.map +1 -0
- package/dist/internal/tree.js +385 -0
- package/dist/internal/turnstile.d.ts +8 -0
- package/dist/internal/turnstile.d.ts.map +1 -0
- package/dist/internal/turnstile.js +43 -0
- package/dist/internal/virtualFileSystem.d.ts +44 -488
- package/dist/internal/virtualFileSystem.d.ts.map +1 -1
- package/dist/internal/virtualFileSystem.js +2111 -2466
- package/dist/internal/volumeState.d.ts +111 -0
- package/dist/internal/volumeState.d.ts.map +1 -0
- package/dist/internal/volumeState.js +202 -0
- package/dist/internal/watchHub.d.ts +15 -6
- package/dist/internal/watchHub.d.ts.map +1 -1
- package/dist/internal/watchHub.js +56 -42
- package/package.json +54 -10
- package/dist/VirtualFileSystemError.d.ts +0 -54
- package/dist/VirtualFileSystemError.d.ts.map +0 -1
- package/dist/VirtualFileSystemError.js +0 -49
- package/dist/internal/overlayContent.d.ts +0 -15
- package/dist/internal/overlayContent.d.ts.map +0 -1
- package/dist/internal/overlayContent.js +0 -29
- package/dist/internal/stagedState.d.ts +0 -22
- package/dist/internal/stagedState.d.ts.map +0 -1
- package/dist/internal/stagedState.js +0 -62
- package/dist/internal/testHooks.d.ts +0 -20
- package/dist/internal/testHooks.d.ts.map +0 -1
- package/dist/internal/testHooks.js +0 -23
|
@@ -12,24 +12,33 @@ import type * as ByteSize from "effect/ByteSize";
|
|
|
12
12
|
import * as Context from "effect/Context";
|
|
13
13
|
import type * as Crypto from "effect/Crypto";
|
|
14
14
|
import * as Effect from "effect/Effect";
|
|
15
|
+
import * as Layer from "effect/Layer";
|
|
15
16
|
import type * as Order from "effect/Order";
|
|
16
17
|
import type * as PlatformError from "effect/PlatformError";
|
|
17
18
|
import * as Schema from "effect/Schema";
|
|
18
19
|
import type * as Scope from "effect/Scope";
|
|
19
|
-
import
|
|
20
|
+
import * as Sink from "effect/Sink";
|
|
21
|
+
import * as Stream from "effect/Stream";
|
|
20
22
|
import type { BytePath } from "./BytePath.js";
|
|
21
|
-
import type {
|
|
23
|
+
import type { CallerId, ObjectReferenceId } from "./Caller.js";
|
|
24
|
+
import * as CallerModule from "./Caller.js";
|
|
25
|
+
import type { DirectoryHandleId, FileHandleId } from "./FileHandle.js";
|
|
26
|
+
import * as FileHandleModule from "./FileHandle.js";
|
|
27
|
+
import * as FixtureModule from "./Fixture.js";
|
|
28
|
+
import * as MetadataModule from "./Metadata.js";
|
|
29
|
+
import type { Entry, EntryInput, Target, TargetInput } from "./Target.js";
|
|
30
|
+
import type { ArgumentFailure, FsFailure, ImageFailure, VfsError } from "./VfsError.js";
|
|
31
|
+
import * as VfsErrorModule from "./VfsError.js";
|
|
32
|
+
import type { VolumeId } from "./Volume.js";
|
|
33
|
+
import * as VolumeModule from "./Volume.js";
|
|
34
|
+
import * as WatchModule from "./Watch.js";
|
|
35
|
+
export { Entry, type EntryInput, isEntry, isTarget, Name, type NameInput, type PathTarget, Target, type TargetInput } from "./Target.js";
|
|
22
36
|
export { BytePath } from "./BytePath.js";
|
|
23
|
-
import type { DecodeLimits,
|
|
24
|
-
export { DecodeLimits,
|
|
25
|
-
import
|
|
37
|
+
import type { DecodeLimits, Snapshot } from "./Snapshot.js";
|
|
38
|
+
export { DecodeLimits, type Snapshot, SnapshotTypeId } from "./Snapshot.js";
|
|
39
|
+
import { type LiveImageStore, type Options as LiveVolumeOptions } from "./LiveVolume.js";
|
|
26
40
|
import * as SnapshotDeltaModel from "./SnapshotDelta.js";
|
|
27
|
-
export { SnapshotChange, SnapshotChangesOptions, type SnapshotDelta,
|
|
28
|
-
declare const VolumeId: typeof VfsModel.VolumeId;
|
|
29
|
-
declare const CallerId: typeof VfsModel.CallerId;
|
|
30
|
-
declare const FileHandleId: typeof VfsModel.FileHandleId;
|
|
31
|
-
declare const DirectoryHandleId: typeof VfsModel.DirectoryHandleId;
|
|
32
|
-
declare const ObjectReferenceId: typeof VfsModel.ObjectReferenceId;
|
|
41
|
+
export { SnapshotChange, SnapshotChangesOptions, type SnapshotDelta, SnapshotDeltaLimits, SnapshotDeltaTypeId, SnapshotDifference, SnapshotNodeKind } from "./SnapshotDelta.js";
|
|
33
42
|
/**
|
|
34
43
|
* A UTF-8 string path or an opaque byte-preserving path.
|
|
35
44
|
*
|
|
@@ -48,6 +57,7 @@ export type PathInput = string | BytePath;
|
|
|
48
57
|
*
|
|
49
58
|
* @example
|
|
50
59
|
* ```ts
|
|
60
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
51
61
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
52
62
|
* import { Effect, Schema } from "effect"
|
|
53
63
|
*
|
|
@@ -66,14 +76,14 @@ export type PathInput = string | BytePath;
|
|
|
66
76
|
* return [known, unknown]
|
|
67
77
|
* })
|
|
68
78
|
*
|
|
69
|
-
* Effect.runPromise(program).then(console.log)
|
|
79
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
70
80
|
* // [ 'NotFound', 'not a code' ]
|
|
71
81
|
* ```
|
|
72
82
|
*
|
|
73
83
|
* @category schemas
|
|
74
84
|
* @since 0.1.0
|
|
75
85
|
*/
|
|
76
|
-
export declare const FsCode: typeof
|
|
86
|
+
export declare const FsCode: typeof VfsErrorModule.FsCode;
|
|
77
87
|
/**
|
|
78
88
|
* A portable virtual filesystem error code.
|
|
79
89
|
*
|
|
@@ -90,8 +100,8 @@ export type FsCode = typeof FsCode.Type;
|
|
|
90
100
|
*
|
|
91
101
|
* @example
|
|
92
102
|
* ```ts
|
|
103
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
93
104
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
94
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
95
105
|
* import { Effect } from "effect"
|
|
96
106
|
*
|
|
97
107
|
* const program = Effect.gen(function*() {
|
|
@@ -100,28 +110,27 @@ export type FsCode = typeof FsCode.Type;
|
|
|
100
110
|
* // Every filesystem operation fails with this one tagged error; `code`
|
|
101
111
|
* // distinguishes the cases, so match on it rather than on the tag alone.
|
|
102
112
|
* return yield* caller.readFile("/missing").pipe(
|
|
103
|
-
* Effect.catchTag("
|
|
113
|
+
* Effect.catchTag("VfsError", (error) =>
|
|
104
114
|
* error.code === "NotFound"
|
|
105
115
|
* ? Effect.succeed(new Uint8Array())
|
|
106
116
|
* : Effect.fail(error))
|
|
107
117
|
* )
|
|
108
118
|
* })
|
|
109
119
|
*
|
|
110
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
120
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
111
121
|
* // Uint8Array(0) []
|
|
112
122
|
* ```
|
|
113
123
|
*
|
|
114
124
|
* @category errors
|
|
115
125
|
* @since 0.1.0
|
|
116
126
|
*/
|
|
117
|
-
export { FsError } from "./VirtualFileSystemError.js";
|
|
118
127
|
/**
|
|
119
128
|
* Describes an invalid volume or caller option and names the rejected field.
|
|
120
129
|
*
|
|
121
130
|
* @example
|
|
122
131
|
* ```ts
|
|
132
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
123
133
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
124
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
125
134
|
* import { Effect } from "effect"
|
|
126
135
|
*
|
|
127
136
|
* // `field` names the rejected option, so the caller learns which key was wrong.
|
|
@@ -131,25 +140,25 @@ export { FsError } from "./VirtualFileSystemError.js";
|
|
|
131
140
|
*
|
|
132
141
|
* return yield* Vfs.make(options).pipe(
|
|
133
142
|
* Effect.as("ok"),
|
|
134
|
-
* Effect.catchTag("
|
|
143
|
+
* Effect.catchTag("VfsError", (error) => Effect.succeed(`rejected ${error.field}`))
|
|
135
144
|
* )
|
|
136
145
|
* })
|
|
137
146
|
*
|
|
138
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
147
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
139
148
|
* // rejected maxEntries
|
|
140
149
|
* ```
|
|
141
150
|
*
|
|
142
151
|
* @category errors
|
|
143
152
|
* @since 0.1.0
|
|
144
153
|
*/
|
|
145
|
-
export {
|
|
154
|
+
export { type ArgumentFailure, DeltaCode, type FsFailure, ImageCode, type ImageFailure, StoreCode, type StoreFailure, VfsCode, VfsError } from "./VfsError.js";
|
|
146
155
|
/**
|
|
147
156
|
* Schema for a caller's numeric identity, supplementary groups, and explicit privilege.
|
|
148
157
|
*
|
|
149
158
|
* @category schemas
|
|
150
159
|
* @since 0.1.0
|
|
151
160
|
*/
|
|
152
|
-
export declare const Identity: typeof
|
|
161
|
+
export declare const Identity: typeof CallerModule.Identity;
|
|
153
162
|
/**
|
|
154
163
|
* A caller identity used for permission checks.
|
|
155
164
|
*
|
|
@@ -162,8 +171,8 @@ export type Identity = typeof Identity.Type;
|
|
|
162
171
|
*
|
|
163
172
|
* @example
|
|
164
173
|
* ```ts
|
|
174
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
165
175
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
166
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
167
176
|
* import { Effect } from "effect"
|
|
168
177
|
*
|
|
169
178
|
* const program = Effect.gen(function*() {
|
|
@@ -184,14 +193,14 @@ export type Identity = typeof Identity.Type;
|
|
|
184
193
|
* return ((yield* user.stat("/home/user")).mode & 0o777).toString(8)
|
|
185
194
|
* })
|
|
186
195
|
*
|
|
187
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
196
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
188
197
|
* // 755
|
|
189
198
|
* ```
|
|
190
199
|
*
|
|
191
200
|
* @category schemas
|
|
192
201
|
* @since 0.1.0
|
|
193
202
|
*/
|
|
194
|
-
export declare const RootCallerOptions: typeof
|
|
203
|
+
export declare const RootCallerOptions: typeof CallerModule.RootCallerOptions;
|
|
195
204
|
/**
|
|
196
205
|
* Options for creating a root caller on a volume.
|
|
197
206
|
*
|
|
@@ -205,7 +214,7 @@ export type RootCallerOptions = typeof RootCallerOptions.Type;
|
|
|
205
214
|
* @category schemas
|
|
206
215
|
* @since 0.1.0
|
|
207
216
|
*/
|
|
208
|
-
export declare const VolumeDurability: typeof
|
|
217
|
+
export declare const VolumeDurability: typeof VolumeModule.VolumeDurability;
|
|
209
218
|
/**
|
|
210
219
|
* The failure boundary survived by an acknowledged volume write.
|
|
211
220
|
*
|
|
@@ -233,7 +242,7 @@ export declare const isVolumeDurabilityAtLeast: (actual: VolumeDurability, requi
|
|
|
233
242
|
* @category schemas
|
|
234
243
|
* @since 0.1.0
|
|
235
244
|
*/
|
|
236
|
-
export declare const VolumeIdentity: typeof
|
|
245
|
+
export declare const VolumeIdentity: typeof VolumeModule.VolumeIdentity;
|
|
237
246
|
/**
|
|
238
247
|
* Stable logical identity of a volume as a branded 128-bit lowercase hexadecimal string.
|
|
239
248
|
*
|
|
@@ -247,7 +256,7 @@ export type VolumeIdentity = typeof VolumeIdentity.Type;
|
|
|
247
256
|
* @category schemas
|
|
248
257
|
* @since 0.1.0
|
|
249
258
|
*/
|
|
250
|
-
export declare const VolumeIncarnation: typeof
|
|
259
|
+
export declare const VolumeIncarnation: typeof VolumeModule.VolumeIncarnation;
|
|
251
260
|
/**
|
|
252
261
|
* One uninterrupted storage lifetime as a branded 128-bit lowercase hexadecimal string.
|
|
253
262
|
*
|
|
@@ -255,13 +264,54 @@ export declare const VolumeIncarnation: typeof VfsModel.VolumeIncarnation;
|
|
|
255
264
|
* @since 0.1.0
|
|
256
265
|
*/
|
|
257
266
|
export type VolumeIncarnation = typeof VolumeIncarnation.Type;
|
|
267
|
+
/**
|
|
268
|
+
* Schema for the serialisable name of one object in one volume: the volume's
|
|
269
|
+
* identity, the epoch of its inode numbers, the object's inode number, and a
|
|
270
|
+
* tag only the volume can compute, so a key cannot be guessed from another.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```ts
|
|
274
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
275
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
276
|
+
* import { Effect, Schema } from "effect"
|
|
277
|
+
*
|
|
278
|
+
* const Json = Schema.fromJsonString(Vfs.ReferenceKey)
|
|
279
|
+
*
|
|
280
|
+
* const program = Effect.gen(function*() {
|
|
281
|
+
* const volume = yield* Vfs.make()
|
|
282
|
+
* const caller = yield* volume.caller()
|
|
283
|
+
* yield* caller.writeFile("/f", new Uint8Array([1]), { access: "write", create: "exclusive" })
|
|
284
|
+
*
|
|
285
|
+
* // The key survives a wire; resolving it returns the same reference.
|
|
286
|
+
* const reference = yield* caller.lookup("/f")
|
|
287
|
+
* const text = yield* Schema.encodeEffect(Json)(yield* volume.referenceKey(reference))
|
|
288
|
+
* const key = yield* Schema.decodeEffect(Json)(text)
|
|
289
|
+
*
|
|
290
|
+
* return (yield* volume.resolveReferenceKey(key)) === reference
|
|
291
|
+
* })
|
|
292
|
+
*
|
|
293
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
294
|
+
* // true
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
297
|
+
* @category schemas
|
|
298
|
+
* @since 0.6.0
|
|
299
|
+
*/
|
|
300
|
+
export declare const ReferenceKey: typeof VolumeModule.ReferenceKey;
|
|
301
|
+
/**
|
|
302
|
+
* The serialisable name of one object in one volume.
|
|
303
|
+
*
|
|
304
|
+
* @category models
|
|
305
|
+
* @since 0.6.0
|
|
306
|
+
*/
|
|
307
|
+
export type ReferenceKey = typeof ReferenceKey.Type;
|
|
258
308
|
/**
|
|
259
309
|
* Schema for optional volume capacity and path limits.
|
|
260
310
|
*
|
|
261
311
|
* @example
|
|
262
312
|
* ```ts
|
|
313
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
263
314
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
264
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
265
315
|
* import { ByteSize, Effect } from "effect"
|
|
266
316
|
*
|
|
267
317
|
* // Every limit is optional, and each one is enforced once set.
|
|
@@ -274,18 +324,18 @@ export type VolumeIncarnation = typeof VolumeIncarnation.Type;
|
|
|
274
324
|
* create: "exclusive"
|
|
275
325
|
* }).pipe(
|
|
276
326
|
* Effect.as("written"),
|
|
277
|
-
* Effect.catchTag("
|
|
327
|
+
* Effect.catchTag("VfsError", (error) => Effect.succeed(error.code))
|
|
278
328
|
* )
|
|
279
329
|
* })
|
|
280
330
|
*
|
|
281
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
331
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
282
332
|
* // FileTooLarge
|
|
283
333
|
* ```
|
|
284
334
|
*
|
|
285
335
|
* @category schemas
|
|
286
336
|
* @since 0.1.0
|
|
287
337
|
*/
|
|
288
|
-
export declare const VolumeOptions: typeof
|
|
338
|
+
export declare const VolumeOptions: typeof VolumeModule.VolumeOptions;
|
|
289
339
|
/**
|
|
290
340
|
* Capacity, admission, watch retention, and path limits for a volume.
|
|
291
341
|
* `maxPendingOperations` defaults to 64 and `maxWatchEvents` defaults to 256.
|
|
@@ -327,8 +377,8 @@ export interface VolumeUsage {
|
|
|
327
377
|
*
|
|
328
378
|
* @example
|
|
329
379
|
* ```ts
|
|
380
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
330
381
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
331
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
332
382
|
* import { Effect } from "effect"
|
|
333
383
|
*
|
|
334
384
|
* // Sizes and inode numbers are bigint; times are nanosecond timestamps.
|
|
@@ -345,14 +395,14 @@ export interface VolumeUsage {
|
|
|
345
395
|
* return [metadata.kind, metadata.size, metadata.nlink]
|
|
346
396
|
* })
|
|
347
397
|
*
|
|
348
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
398
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
349
399
|
* // [ 'file', 3n, 1 ]
|
|
350
400
|
* ```
|
|
351
401
|
*
|
|
352
402
|
* @category schemas
|
|
353
403
|
* @since 0.1.0
|
|
354
404
|
*/
|
|
355
|
-
export declare const Metadata: typeof
|
|
405
|
+
export declare const Metadata: typeof MetadataModule.Metadata;
|
|
356
406
|
/**
|
|
357
407
|
* Metadata for a directory, regular file, or symbolic link.
|
|
358
408
|
*
|
|
@@ -374,8 +424,8 @@ export interface ObjectReference {
|
|
|
374
424
|
*
|
|
375
425
|
* @example
|
|
376
426
|
* ```ts
|
|
427
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
377
428
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
378
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
379
429
|
* import { Effect } from "effect"
|
|
380
430
|
*
|
|
381
431
|
* // References survive renames, and each observation carries the revision it
|
|
@@ -385,20 +435,20 @@ export interface ObjectReference {
|
|
|
385
435
|
*
|
|
386
436
|
* yield* caller.mkdir("/work")
|
|
387
437
|
*
|
|
388
|
-
* const root = yield* caller.
|
|
389
|
-
* const work = yield* caller.
|
|
438
|
+
* const root = yield* caller.root
|
|
439
|
+
* const work = yield* caller.lookup(Vfs.Entry(root, "work"))
|
|
390
440
|
*
|
|
391
|
-
* const before = yield* caller.
|
|
441
|
+
* const before = yield* caller.stat(work)
|
|
392
442
|
*
|
|
393
443
|
* yield* caller.rename("/work", "/moved")
|
|
394
444
|
*
|
|
395
|
-
* const after = yield* caller.
|
|
445
|
+
* const after = yield* caller.stat(work)
|
|
396
446
|
*
|
|
397
|
-
* return [before.
|
|
447
|
+
* return [before.kind, after.kind, after.revision > before.revision]
|
|
398
448
|
* })
|
|
399
449
|
*
|
|
400
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
401
|
-
* // [ 'directory', 'directory' ]
|
|
450
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
451
|
+
* // [ 'directory', 'directory', true ]
|
|
402
452
|
* ```
|
|
403
453
|
*
|
|
404
454
|
* @category models
|
|
@@ -418,13 +468,60 @@ export interface DirectoryEntry {
|
|
|
418
468
|
readonly name: Uint8Array;
|
|
419
469
|
readonly reference: ObjectReference;
|
|
420
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* One entry a walk reached: its path below the walk's root, its name, the
|
|
473
|
+
* object it names and the directory it was listed in, its kind, and its depth.
|
|
474
|
+
*
|
|
475
|
+
* **Details**
|
|
476
|
+
*
|
|
477
|
+
* `path` is relative to the walk's root, with no leading slash (`a/b` for
|
|
478
|
+
* `b` in the root's child `a`), so it reads the same whichever way the root
|
|
479
|
+
* was addressed; the root itself is not an entry. `depth` is 1 for a child of
|
|
480
|
+
* the root. A symbolic link is reported as a link and never followed.
|
|
481
|
+
*
|
|
482
|
+
* @category models
|
|
483
|
+
* @since 0.6.0
|
|
484
|
+
*/
|
|
485
|
+
export interface WalkEntry {
|
|
486
|
+
readonly path: BytePath;
|
|
487
|
+
readonly name: Uint8Array;
|
|
488
|
+
readonly reference: ObjectReference;
|
|
489
|
+
readonly directory: ObjectReference;
|
|
490
|
+
readonly kind: Metadata["kind"];
|
|
491
|
+
readonly depth: number;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* What a walk fails with: a failure of the directory it lists, or
|
|
495
|
+
* `LimitExceeded` when it would pass one of its bounds, which `field` names.
|
|
496
|
+
*
|
|
497
|
+
* @category models
|
|
498
|
+
* @since 0.6.0
|
|
499
|
+
*/
|
|
500
|
+
export type WalkFailure = FsFailure | (VfsError & {
|
|
501
|
+
readonly code: "LimitExceeded";
|
|
502
|
+
});
|
|
503
|
+
/**
|
|
504
|
+
* Settings for walking a directory tree: the order and the optional depth,
|
|
505
|
+
* entry, and byte bounds.
|
|
506
|
+
*
|
|
507
|
+
* @category schemas
|
|
508
|
+
* @since 0.6.0
|
|
509
|
+
*/
|
|
510
|
+
export declare const WalkOptions: typeof CallerModule.WalkOptions;
|
|
511
|
+
/**
|
|
512
|
+
* Settings for walking a directory tree.
|
|
513
|
+
*
|
|
514
|
+
* @category models
|
|
515
|
+
* @since 0.6.0
|
|
516
|
+
*/
|
|
517
|
+
export type WalkOptions = typeof WalkOptions.Type;
|
|
421
518
|
/**
|
|
422
519
|
* A directory revision transition captured inside one coordinated operation.
|
|
423
520
|
*
|
|
424
521
|
* @category schemas
|
|
425
522
|
* @since 0.4.0
|
|
426
523
|
*/
|
|
427
|
-
export declare const DirectoryChange: typeof
|
|
524
|
+
export declare const DirectoryChange: typeof CallerModule.DirectoryChange;
|
|
428
525
|
/**
|
|
429
526
|
* A directory revision transition captured inside one coordinated operation.
|
|
430
527
|
*
|
|
@@ -448,7 +545,7 @@ export interface ReferenceEntryResult {
|
|
|
448
545
|
* @category schemas
|
|
449
546
|
* @since 0.4.0
|
|
450
547
|
*/
|
|
451
|
-
export declare const RenameReferenceResult: typeof
|
|
548
|
+
export declare const RenameReferenceResult: typeof CallerModule.RenameReferenceResult;
|
|
452
549
|
/**
|
|
453
550
|
* The directory transitions produced by a same-directory or cross-directory rename.
|
|
454
551
|
*
|
|
@@ -456,64 +553,13 @@ export declare const RenameReferenceResult: typeof VfsModel.RenameReferenceResul
|
|
|
456
553
|
* @since 0.4.0
|
|
457
554
|
*/
|
|
458
555
|
export type RenameReferenceResult = typeof RenameReferenceResult.Type;
|
|
459
|
-
/**
|
|
460
|
-
* Resolves a relative path from a live directory handle instead of the caller's directory.
|
|
461
|
-
*
|
|
462
|
-
* @category models
|
|
463
|
-
* @since 0.1.0
|
|
464
|
-
*/
|
|
465
|
-
export interface RelativeOptions {
|
|
466
|
-
/** Resolve relative paths from this live, same-volume handle instead of the caller's current directory. */
|
|
467
|
-
readonly relativeTo?: DirectoryHandle;
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Controls the base directory and whether metadata operations follow the final symbolic link.
|
|
471
|
-
*
|
|
472
|
-
* @example
|
|
473
|
-
* ```ts
|
|
474
|
-
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
475
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
476
|
-
* import { Effect } from "effect"
|
|
477
|
-
*
|
|
478
|
-
* const program = Effect.gen(function*() {
|
|
479
|
-
* const caller = yield* (yield* Vfs.make()).caller()
|
|
480
|
-
*
|
|
481
|
-
* yield* caller.writeFile("/target", new Uint8Array([1]), {
|
|
482
|
-
* access: "write",
|
|
483
|
-
* create: "exclusive",
|
|
484
|
-
* mode: 0o644
|
|
485
|
-
* })
|
|
486
|
-
* yield* caller.symlink("/target", "/link")
|
|
487
|
-
*
|
|
488
|
-
* // Metadata operations follow the final link by default, so this reaches the
|
|
489
|
-
* // target; opting out changes the link itself and leaves the target alone.
|
|
490
|
-
* yield* caller.chmod("/link", 0o600)
|
|
491
|
-
* const followed = (yield* caller.stat("/target")).mode & 0o777
|
|
492
|
-
*
|
|
493
|
-
* yield* caller.chmod("/link", 0o777, { followFinalSymlink: false })
|
|
494
|
-
* const unchanged = (yield* caller.stat("/target")).mode & 0o777
|
|
495
|
-
*
|
|
496
|
-
* return [followed.toString(8), unchanged.toString(8)]
|
|
497
|
-
* })
|
|
498
|
-
*
|
|
499
|
-
* Effect.runPromise(program.pipe(Effect.provide(NodeCrypto.layer))).then(console.log)
|
|
500
|
-
* // [ '600', '600' ]
|
|
501
|
-
* ```
|
|
502
|
-
*
|
|
503
|
-
* @category models
|
|
504
|
-
* @since 0.1.0
|
|
505
|
-
*/
|
|
506
|
-
export interface MetadataOptions extends RelativeOptions {
|
|
507
|
-
/** Follow the final symbolic link. Defaults to `true`. */
|
|
508
|
-
readonly followFinalSymlink?: boolean;
|
|
509
|
-
}
|
|
510
556
|
/**
|
|
511
557
|
* Schema for an owner update. Omitted fields retain their existing values.
|
|
512
558
|
*
|
|
513
559
|
* @category schemas
|
|
514
560
|
* @since 0.1.0
|
|
515
561
|
*/
|
|
516
|
-
export declare const OwnerUpdate: typeof
|
|
562
|
+
export declare const OwnerUpdate: typeof MetadataModule.OwnerUpdate;
|
|
517
563
|
/**
|
|
518
564
|
* An owner update for `chown` operations.
|
|
519
565
|
*
|
|
@@ -527,14 +573,14 @@ export type OwnerUpdate = typeof OwnerUpdate.Type;
|
|
|
527
573
|
* @category schemas
|
|
528
574
|
* @since 0.1.0
|
|
529
575
|
*/
|
|
530
|
-
export declare const TimeUpdate: typeof
|
|
576
|
+
export declare const TimeUpdate: typeof MetadataModule.TimeUpdate;
|
|
531
577
|
/**
|
|
532
578
|
* Schema for independent access and modification time updates.
|
|
533
579
|
*
|
|
534
580
|
* @example
|
|
535
581
|
* ```ts
|
|
582
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
536
583
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
537
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
538
584
|
* import { Effect } from "effect"
|
|
539
585
|
*
|
|
540
586
|
* const program = Effect.gen(function*() {
|
|
@@ -556,14 +602,14 @@ export declare const TimeUpdate: typeof VfsModel.TimeUpdate;
|
|
|
556
602
|
* return [metadata.atimeNs, metadata.mtimeNs === 1_000n]
|
|
557
603
|
* })
|
|
558
604
|
*
|
|
559
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
605
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
560
606
|
* // [ 1000n, false ]
|
|
561
607
|
* ```
|
|
562
608
|
*
|
|
563
609
|
* @category schemas
|
|
564
610
|
* @since 0.1.0
|
|
565
611
|
*/
|
|
566
|
-
export declare const Times: typeof
|
|
612
|
+
export declare const Times: typeof MetadataModule.Times;
|
|
567
613
|
/**
|
|
568
614
|
* Access and modification time updates for `utimes` operations.
|
|
569
615
|
*
|
|
@@ -576,8 +622,8 @@ export type Times = typeof Times.Type;
|
|
|
576
622
|
*
|
|
577
623
|
* @example
|
|
578
624
|
* ```ts
|
|
625
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
579
626
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
580
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
581
627
|
* import { Effect } from "effect"
|
|
582
628
|
*
|
|
583
629
|
* // The handle anchors relative paths to the directory itself, so a rename in
|
|
@@ -590,16 +636,15 @@ export type Times = typeof Times.Type;
|
|
|
590
636
|
* const directory = yield* caller.openDirectory("/project")
|
|
591
637
|
*
|
|
592
638
|
* yield* caller.rename("/project", "/renamed")
|
|
593
|
-
* yield* caller.writeFile("notes.txt", new TextEncoder().encode("kept"), {
|
|
639
|
+
* yield* caller.writeFile(Vfs.Target.Path({ path: "notes.txt", relativeTo: directory }), new TextEncoder().encode("kept"), {
|
|
594
640
|
* access: "write",
|
|
595
|
-
* create: "exclusive"
|
|
596
|
-
* relativeTo: directory
|
|
641
|
+
* create: "exclusive"
|
|
597
642
|
* })
|
|
598
643
|
*
|
|
599
|
-
* return yield* caller.readDirectory("/renamed")
|
|
644
|
+
* return (yield* caller.readDirectory("/renamed")).value.map((entry) => new TextDecoder().decode(entry.name))
|
|
600
645
|
* }).pipe(Effect.scoped)
|
|
601
646
|
*
|
|
602
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
647
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
603
648
|
* // [ 'notes.txt' ]
|
|
604
649
|
* ```
|
|
605
650
|
*
|
|
@@ -608,8 +653,8 @@ export type Times = typeof Times.Type;
|
|
|
608
653
|
*/
|
|
609
654
|
export interface DirectoryHandle {
|
|
610
655
|
readonly [DirectoryHandleId]: true;
|
|
611
|
-
readonly stat: Effect.Effect<Metadata,
|
|
612
|
-
readonly close: Effect.Effect<void,
|
|
656
|
+
readonly stat: Effect.Effect<Metadata, FsFailure>;
|
|
657
|
+
readonly close: Effect.Effect<void, FsFailure>;
|
|
613
658
|
}
|
|
614
659
|
/**
|
|
615
660
|
* Schema for file seek origins, including dense-file data and hole queries.
|
|
@@ -617,7 +662,7 @@ export interface DirectoryHandle {
|
|
|
617
662
|
* @category schemas
|
|
618
663
|
* @since 0.1.0
|
|
619
664
|
*/
|
|
620
|
-
export declare const SeekMode: typeof
|
|
665
|
+
export declare const SeekMode: typeof FileHandleModule.SeekMode;
|
|
621
666
|
/**
|
|
622
667
|
* The origin used by a file handle seek operation.
|
|
623
668
|
*
|
|
@@ -630,8 +675,8 @@ export type SeekMode = typeof SeekMode.Type;
|
|
|
630
675
|
*
|
|
631
676
|
* @example
|
|
632
677
|
* ```ts
|
|
678
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
633
679
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
634
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
635
680
|
* import { Effect } from "effect"
|
|
636
681
|
*
|
|
637
682
|
* // `access` is required; `create` decides whether a missing file is an error.
|
|
@@ -649,65 +694,86 @@ export type SeekMode = typeof SeekMode.Type;
|
|
|
649
694
|
* return (yield* handle.stat).size
|
|
650
695
|
* }).pipe(Effect.scoped)
|
|
651
696
|
*
|
|
652
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
697
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
653
698
|
* // 2n
|
|
654
699
|
* ```
|
|
655
700
|
*
|
|
656
701
|
* @category schemas
|
|
657
702
|
* @since 0.1.0
|
|
658
703
|
*/
|
|
659
|
-
export declare const
|
|
704
|
+
export declare const OpenOptions: typeof CallerModule.OpenOptions;
|
|
660
705
|
/**
|
|
661
|
-
* Options
|
|
706
|
+
* Options of `open` on a target.
|
|
662
707
|
*
|
|
663
708
|
* @category models
|
|
664
709
|
* @since 0.1.0
|
|
665
710
|
*/
|
|
666
|
-
export type OpenOptions = typeof
|
|
711
|
+
export type OpenOptions = typeof OpenOptions.Type;
|
|
667
712
|
/**
|
|
668
713
|
* Settings for creating a directory through a parent object reference.
|
|
669
714
|
* `exactMode` skips the caller's umask for an explicit creation mode; permission policy still applies.
|
|
715
|
+
* `recursive` creates every missing directory on a path in one change, as `mkdir -p` does.
|
|
670
716
|
*
|
|
671
717
|
* @category schemas
|
|
672
718
|
* @since 0.4.0
|
|
673
719
|
*/
|
|
674
|
-
export declare const
|
|
720
|
+
export declare const MkdirOptions: typeof CallerModule.MkdirOptions;
|
|
675
721
|
/**
|
|
676
722
|
* Settings for creating a directory through a parent object reference.
|
|
677
723
|
* `exactMode` skips the caller's umask for an explicit creation mode; permission policy still applies.
|
|
724
|
+
* `recursive` creates every missing directory on a path in one change, as `mkdir -p` does.
|
|
678
725
|
*
|
|
679
726
|
* @category models
|
|
680
727
|
* @since 0.4.0
|
|
681
728
|
*/
|
|
682
|
-
export type
|
|
729
|
+
export type MkdirOptions = typeof MkdirOptions.Type;
|
|
730
|
+
/**
|
|
731
|
+
* Settings for removing an entry: whether a directory goes with everything
|
|
732
|
+
* under it, and whether a missing target is success.
|
|
733
|
+
*
|
|
734
|
+
* @category schemas
|
|
735
|
+
* @since 0.6.0
|
|
736
|
+
*/
|
|
737
|
+
export declare const RemoveOptions: typeof CallerModule.RemoveOptions;
|
|
738
|
+
/**
|
|
739
|
+
* Settings for removing an entry.
|
|
740
|
+
*
|
|
741
|
+
* @category models
|
|
742
|
+
* @since 0.6.0
|
|
743
|
+
*/
|
|
744
|
+
export type RemoveOptions = typeof RemoveOptions.Type;
|
|
683
745
|
/**
|
|
684
746
|
* Settings for creating a symbolic link through a parent object reference.
|
|
685
747
|
*
|
|
686
748
|
* @category schemas
|
|
687
749
|
* @since 0.4.0
|
|
688
750
|
*/
|
|
689
|
-
export declare const
|
|
751
|
+
export declare const SymlinkOptions: typeof CallerModule.SymlinkOptions;
|
|
690
752
|
/**
|
|
691
753
|
* Settings for creating a symbolic link through a parent object reference.
|
|
692
754
|
*
|
|
693
755
|
* @category models
|
|
694
756
|
* @since 0.4.0
|
|
695
757
|
*/
|
|
696
|
-
export type
|
|
758
|
+
export type SymlinkOptions = typeof SymlinkOptions.Type;
|
|
697
759
|
/**
|
|
698
|
-
*
|
|
760
|
+
* The attributes `setattr` changes together: a regular file's size, the
|
|
761
|
+
* permission mode, the owner, and the access and modification times. An
|
|
762
|
+
* omitted attribute keeps its current value. `expected` pins the revision the
|
|
763
|
+
* caller last observed and fails as `StaleReference` naming `expected` when
|
|
764
|
+
* the target has moved on.
|
|
699
765
|
*
|
|
700
766
|
* @category schemas
|
|
701
|
-
* @since 0.
|
|
767
|
+
* @since 0.6.0
|
|
702
768
|
*/
|
|
703
|
-
export declare const
|
|
769
|
+
export declare const SetattrOptions: typeof CallerModule.SetattrOptions;
|
|
704
770
|
/**
|
|
705
|
-
*
|
|
771
|
+
* The attributes `setattr` changes together.
|
|
706
772
|
*
|
|
707
773
|
* @category models
|
|
708
|
-
* @since 0.
|
|
774
|
+
* @since 0.6.0
|
|
709
775
|
*/
|
|
710
|
-
export type
|
|
776
|
+
export type SetattrOptions = typeof SetattrOptions.Type;
|
|
711
777
|
/**
|
|
712
778
|
* Settings for atomically looking up or creating and opening one referenced child.
|
|
713
779
|
* `exactMode` skips the caller's umask for an explicit creation mode; permission policy still applies.
|
|
@@ -715,7 +781,7 @@ export type OpenReferenceSettings = typeof OpenReferenceSettings.Type;
|
|
|
715
781
|
* @category schemas
|
|
716
782
|
* @since 0.4.0
|
|
717
783
|
*/
|
|
718
|
-
export declare const
|
|
784
|
+
export declare const OpenEntryOptions: typeof CallerModule.OpenEntryOptions;
|
|
719
785
|
/**
|
|
720
786
|
* Settings for atomically looking up or creating and opening one referenced child.
|
|
721
787
|
* `exactMode` skips the caller's umask for an explicit creation mode; permission policy still applies.
|
|
@@ -728,14 +794,14 @@ export declare const OpenChildReferenceSettings: typeof VfsModel.OpenChildRefere
|
|
|
728
794
|
* @category models
|
|
729
795
|
* @since 0.4.0
|
|
730
796
|
*/
|
|
731
|
-
export type
|
|
797
|
+
export type OpenEntryOptions = typeof OpenEntryOptions.Type;
|
|
732
798
|
/**
|
|
733
799
|
* A scoped child-open result captured inside one coordinated operation.
|
|
734
800
|
*
|
|
735
801
|
* @category models
|
|
736
802
|
* @since 0.4.0
|
|
737
803
|
*/
|
|
738
|
-
export interface
|
|
804
|
+
export interface OpenEntryResult {
|
|
739
805
|
readonly handle: FileHandle;
|
|
740
806
|
readonly reference: ObjectReference;
|
|
741
807
|
readonly created: boolean;
|
|
@@ -746,8 +812,8 @@ export interface OpenChildReferenceResult {
|
|
|
746
812
|
*
|
|
747
813
|
* @example
|
|
748
814
|
* ```ts
|
|
815
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
749
816
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
750
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
751
817
|
* import { Effect } from "effect"
|
|
752
818
|
*
|
|
753
819
|
* const program = Effect.gen(function*() {
|
|
@@ -767,7 +833,7 @@ export interface OpenChildReferenceResult {
|
|
|
767
833
|
* create: "exclusive"
|
|
768
834
|
* }).pipe(
|
|
769
835
|
* Effect.as("replaced"),
|
|
770
|
-
* Effect.catchTag("
|
|
836
|
+
* Effect.catchTag("VfsError", (error) => Effect.succeed(error.code))
|
|
771
837
|
* )
|
|
772
838
|
*
|
|
773
839
|
* yield* caller.writeFile("/app.conf", bytes, { access: "write", truncate: true })
|
|
@@ -775,21 +841,38 @@ export interface OpenChildReferenceResult {
|
|
|
775
841
|
* return [refused, new TextDecoder().decode(yield* caller.readFile("/app.conf"))]
|
|
776
842
|
* })
|
|
777
843
|
*
|
|
778
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
844
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
779
845
|
* // [ 'AlreadyExists', 'v2' ]
|
|
780
846
|
* ```
|
|
781
847
|
*
|
|
782
848
|
* @category models
|
|
783
849
|
* @since 0.1.0
|
|
784
850
|
*/
|
|
785
|
-
export
|
|
851
|
+
export declare const WriteFileOptions: typeof CallerModule.WriteFileOptions;
|
|
852
|
+
/**
|
|
853
|
+
* Options of `writeFile`.
|
|
854
|
+
*
|
|
855
|
+
* @category models
|
|
856
|
+
* @since 0.1.0
|
|
857
|
+
*/
|
|
858
|
+
export type WriteFileOptions = typeof WriteFileOptions.Type;
|
|
859
|
+
/**
|
|
860
|
+
* The bytes a positional read returned and whether they reach the end of the file.
|
|
861
|
+
*
|
|
862
|
+
* @category models
|
|
863
|
+
* @since 0.6.0
|
|
864
|
+
*/
|
|
865
|
+
export interface ReadResult {
|
|
866
|
+
readonly bytes: Uint8Array;
|
|
867
|
+
readonly eof: boolean;
|
|
868
|
+
}
|
|
786
869
|
/**
|
|
787
870
|
* A scoped regular-file capability with an independent bigint cursor.
|
|
788
871
|
*
|
|
789
872
|
* @example
|
|
790
873
|
* ```ts
|
|
874
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
791
875
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
792
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
793
876
|
* import { Effect } from "effect"
|
|
794
877
|
*
|
|
795
878
|
* const program = Effect.gen(function*() {
|
|
@@ -805,11 +888,11 @@ export type WriteFileOptions = VfsModel.WriteFileOptions;
|
|
|
805
888
|
* // `pread` reads at an offset and leaves the cursor where writing left it.
|
|
806
889
|
* const slice = yield* handle.pread(2, 1n)
|
|
807
890
|
*
|
|
808
|
-
* return [slice, yield* handle.seek(0n, "current")]
|
|
891
|
+
* return [slice.bytes, slice.eof, yield* handle.seek(0n, "current")]
|
|
809
892
|
* }).pipe(Effect.scoped)
|
|
810
893
|
*
|
|
811
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
812
|
-
* // [ Uint8Array(2) [ 2, 3 ], 4n ]
|
|
894
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
895
|
+
* // [ Uint8Array(2) [ 2, 3 ], false, 4n ]
|
|
813
896
|
* ```
|
|
814
897
|
*
|
|
815
898
|
* @category models
|
|
@@ -818,31 +901,31 @@ export type WriteFileOptions = VfsModel.WriteFileOptions;
|
|
|
818
901
|
export interface FileHandle {
|
|
819
902
|
readonly [FileHandleId]: true;
|
|
820
903
|
/** Reads up to `maximumBytes` from the cursor and advances it by the returned length. */
|
|
821
|
-
readonly read: (maximumBytes: number) => Effect.Effect<Uint8Array,
|
|
904
|
+
readonly read: (maximumBytes: number) => Effect.Effect<Uint8Array, FsFailure>;
|
|
822
905
|
/** Reads at `offset` without changing the cursor. */
|
|
823
|
-
readonly pread: (maximumBytes: number, offset: bigint) => Effect.Effect<
|
|
906
|
+
readonly pread: (maximumBytes: number, offset: bigint) => Effect.Effect<ReadResult, FsFailure>;
|
|
824
907
|
/** Writes at the cursor and advances it, or writes at end of file when opened for append. */
|
|
825
|
-
readonly write: (bytes: Uint8Array) => Effect.Effect<number,
|
|
908
|
+
readonly write: (bytes: Uint8Array) => Effect.Effect<number, FsFailure>;
|
|
826
909
|
/** Writes at `offset` without changing the cursor. Append mode does not affect positional writes. */
|
|
827
|
-
readonly pwrite: (bytes: Uint8Array, offset: bigint) => Effect.Effect<number,
|
|
910
|
+
readonly pwrite: (bytes: Uint8Array, offset: bigint) => Effect.Effect<number, FsFailure>;
|
|
828
911
|
/** Moves the cursor and returns its new offset. `data` finds content and `hole` finds end of file. */
|
|
829
|
-
readonly seek: (offset: bigint, mode: SeekMode) => Effect.Effect<bigint,
|
|
912
|
+
readonly seek: (offset: bigint, mode: SeekMode) => Effect.Effect<bigint, FsFailure>;
|
|
830
913
|
/** Sets the file length without changing the cursor. */
|
|
831
|
-
readonly truncate: (length: bigint) => Effect.Effect<void,
|
|
914
|
+
readonly truncate: (length: bigint) => Effect.Effect<void, FsFailure>;
|
|
832
915
|
/** Reads metadata for the open file. */
|
|
833
|
-
readonly stat: Effect.Effect<Metadata,
|
|
916
|
+
readonly stat: Effect.Effect<Metadata, FsFailure>;
|
|
834
917
|
/** Checks handle and provider health. Durable mutations have already committed; memory volumes have nothing to flush. */
|
|
835
|
-
readonly sync: Effect.Effect<void,
|
|
918
|
+
readonly sync: Effect.Effect<void, FsFailure>;
|
|
836
919
|
/** Closes the handle. A repeated explicit close fails; scope cleanup remains safe. */
|
|
837
|
-
readonly close: Effect.Effect<void,
|
|
920
|
+
readonly close: Effect.Effect<void, FsFailure>;
|
|
838
921
|
}
|
|
839
922
|
/**
|
|
840
923
|
* A filesystem caller with its own identity, creation mask, and current directory.
|
|
841
924
|
*
|
|
842
925
|
* @example
|
|
843
926
|
* ```ts
|
|
927
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
844
928
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
845
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
846
929
|
* import { Effect } from "effect"
|
|
847
930
|
*
|
|
848
931
|
* // Whole-file reads and writes need no scope. `writeFile` always takes an
|
|
@@ -857,17 +940,17 @@ export interface FileHandle {
|
|
|
857
940
|
* create: "exclusive"
|
|
858
941
|
* })
|
|
859
942
|
*
|
|
860
|
-
* return yield* caller.readDirectory("/work")
|
|
943
|
+
* return (yield* caller.readDirectory("/work")).value.map((entry) => new TextDecoder().decode(entry.name))
|
|
861
944
|
* })
|
|
862
945
|
*
|
|
863
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
946
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
864
947
|
* // [ 'notes.txt' ]
|
|
865
948
|
* ```
|
|
866
949
|
*
|
|
867
950
|
* @example
|
|
868
951
|
* ```ts
|
|
952
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
869
953
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
870
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
871
954
|
* import { Effect } from "effect"
|
|
872
955
|
*
|
|
873
956
|
* // Reach for a handle when a whole-file write will not do. A handle carries a
|
|
@@ -887,14 +970,14 @@ export interface FileHandle {
|
|
|
887
970
|
* return new TextDecoder().decode(yield* handle.read(64))
|
|
888
971
|
* }).pipe(Effect.scoped)
|
|
889
972
|
*
|
|
890
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
973
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
891
974
|
* // first second
|
|
892
975
|
* ```
|
|
893
976
|
*
|
|
894
977
|
* @example
|
|
895
978
|
* ```ts
|
|
979
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
896
980
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
897
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
898
981
|
* import { Effect } from "effect"
|
|
899
982
|
*
|
|
900
983
|
* // A derived caller holds the directory's identity, not its path, so renaming
|
|
@@ -912,10 +995,10 @@ export interface FileHandle {
|
|
|
912
995
|
* create: "exclusive"
|
|
913
996
|
* })
|
|
914
997
|
*
|
|
915
|
-
* return yield* caller.readDirectory("/dist")
|
|
998
|
+
* return (yield* caller.readDirectory("/dist")).value.map((entry) => new TextDecoder().decode(entry.name))
|
|
916
999
|
* }).pipe(Effect.scoped)
|
|
917
1000
|
*
|
|
918
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1001
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
919
1002
|
* // [ 'out.txt' ]
|
|
920
1003
|
* ```
|
|
921
1004
|
*
|
|
@@ -925,124 +1008,114 @@ export interface FileHandle {
|
|
|
925
1008
|
*/
|
|
926
1009
|
export interface Caller {
|
|
927
1010
|
readonly [CallerId]: true;
|
|
928
|
-
/**
|
|
929
|
-
readonly
|
|
930
|
-
/**
|
|
931
|
-
readonly
|
|
932
|
-
/**
|
|
933
|
-
readonly
|
|
934
|
-
/**
|
|
935
|
-
readonly
|
|
936
|
-
/**
|
|
937
|
-
readonly
|
|
938
|
-
/**
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
readonly
|
|
948
|
-
/**
|
|
949
|
-
readonly
|
|
950
|
-
/**
|
|
951
|
-
readonly
|
|
952
|
-
/**
|
|
953
|
-
readonly
|
|
954
|
-
/**
|
|
955
|
-
readonly
|
|
956
|
-
/**
|
|
957
|
-
readonly
|
|
958
|
-
/**
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
/**
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
readonly truncate: (path: PathInput, length: bigint, options?: RelativeOptions) => Effect.Effect<void, FsError>;
|
|
983
|
-
/** Changes permission bits, following the final symbolic link by default. */
|
|
984
|
-
readonly chmod: (path: PathInput, mode: number, options?: MetadataOptions) => Effect.Effect<void, FsError>;
|
|
985
|
-
/** Changes uid, gid, or both, following the final symbolic link by default. */
|
|
986
|
-
readonly chown: (path: PathInput, owner: OwnerUpdate, options?: MetadataOptions) => Effect.Effect<void, FsError>;
|
|
987
|
-
/** Updates access and modification times, following the final symbolic link by default. */
|
|
988
|
-
readonly utimes: (path: PathInput, times: Times, options?: MetadataOptions) => Effect.Effect<void, FsError>;
|
|
989
|
-
/** Changes permission bits through a live, same-volume handle. */
|
|
990
|
-
readonly chmodHandle: (handle: FileHandle | DirectoryHandle, mode: number) => Effect.Effect<void, FsError>;
|
|
991
|
-
/** Changes uid, gid, or both through a live, same-volume handle. */
|
|
992
|
-
readonly chownHandle: (handle: FileHandle | DirectoryHandle, owner: OwnerUpdate) => Effect.Effect<void, FsError>;
|
|
993
|
-
/** Updates access and modification times through a live, same-volume handle. */
|
|
994
|
-
readonly utimesHandle: (handle: FileHandle | DirectoryHandle, times: Times) => Effect.Effect<void, FsError>;
|
|
995
|
-
/** Reads metadata without following the final symbolic link. */
|
|
996
|
-
readonly lstat: (path: PathInput, options?: RelativeOptions) => Effect.Effect<Metadata, FsError>;
|
|
997
|
-
/** Creates a hard link to an existing non-directory entry. */
|
|
998
|
-
readonly link: (source: PathInput, destination: PathInput, options?: {
|
|
999
|
-
readonly sourceRelativeTo?: DirectoryHandle;
|
|
1000
|
-
readonly destinationRelativeTo?: DirectoryHandle;
|
|
1001
|
-
readonly followSourceSymlink?: boolean;
|
|
1002
|
-
}) => Effect.Effect<void, FsError>;
|
|
1003
|
-
/** Creates a symbolic link. The target bytes are stored without resolving them. */
|
|
1004
|
-
readonly symlink: (target: PathInput, path: PathInput, options?: RelativeOptions) => Effect.Effect<void, FsError>;
|
|
1005
|
-
/** Reads a symbolic-link target as UTF-8, failing `UnrepresentableName` for other bytes. See `readLinkBytes`. */
|
|
1006
|
-
readonly readLink: (path: PathInput, options?: RelativeOptions) => Effect.Effect<string, FsError>;
|
|
1007
|
-
/** Reads a symbolic-link target as owned bytes. */
|
|
1008
|
-
readonly readLinkBytes: (path: PathInput, options?: RelativeOptions) => Effect.Effect<Uint8Array, FsError>;
|
|
1009
|
-
/** Reads directory names as UTF-8, failing `UnrepresentableName` for other bytes. See `readDirectoryBytes`. */
|
|
1010
|
-
readonly readDirectory: (path: PathInput, options?: RelativeOptions) => Effect.Effect<ReadonlyArray<string>, FsError>;
|
|
1011
|
-
/** Reads directory names as owned byte arrays. */
|
|
1012
|
-
readonly readDirectoryBytes: (path: PathInput, options?: RelativeOptions) => Effect.Effect<ReadonlyArray<Uint8Array>, FsError>;
|
|
1013
|
-
/** Resolves links and normalizes a path as UTF-8, failing `UnrepresentableName` for other bytes. See `realPathBytes`. */
|
|
1014
|
-
readonly realPath: (path: PathInput, options?: RelativeOptions) => Effect.Effect<string, FsError>;
|
|
1015
|
-
/** Resolves links and normalizes a path without requiring UTF-8 names. */
|
|
1016
|
-
readonly realPathBytes: (path: PathInput, options?: RelativeOptions) => Effect.Effect<BytePath, FsError>;
|
|
1017
|
-
/** Opens a scoped regular-file handle. The surrounding scope closes it automatically. */
|
|
1018
|
-
readonly open: (path: PathInput, options: OpenOptions) => Effect.Effect<FileHandle, FsError, Scope.Scope>;
|
|
1019
|
-
/** Removes a non-directory entry. Open handles remain usable until closed. */
|
|
1020
|
-
readonly unlink: (path: PathInput, options?: RelativeOptions) => Effect.Effect<void, FsError>;
|
|
1011
|
+
/** The reference of the volume's root directory. */
|
|
1012
|
+
readonly root: Effect.Effect<ObjectReference, FsFailure>;
|
|
1013
|
+
/** The reference of a child of a directory, without following it. */
|
|
1014
|
+
readonly lookup: (entry: EntryInput) => Effect.Effect<ObjectReference, FsFailure>;
|
|
1015
|
+
/** The reference of a directory's parent; the root is its own parent. */
|
|
1016
|
+
readonly parent: (directory: TargetInput) => Effect.Effect<ObjectReference, FsFailure>;
|
|
1017
|
+
/** Metadata and revision of a target. A path follows a final symbolic link unless its target says otherwise. */
|
|
1018
|
+
readonly stat: (target: TargetInput) => Effect.Effect<Metadata, FsFailure>;
|
|
1019
|
+
/** The entries of a directory with their references, and the directory's revision. */
|
|
1020
|
+
readonly readDirectory: (directory: TargetInput) => Effect.Effect<ObjectObservation<ReadonlyArray<DirectoryEntry>>, FsFailure>;
|
|
1021
|
+
/**
|
|
1022
|
+
* Every entry below a directory, as a stream that reads one directory at a time and holds no handle. Entries
|
|
1023
|
+
* arrive depth first, each directory's entries in the byte order of their names; symbolic links are reported,
|
|
1024
|
+
* never followed. Each directory is read in one observation, so the walk sees each listing whole but no
|
|
1025
|
+
* snapshot of the tree, and it refreshes no access time. Each directory below the root is reached by name, as a
|
|
1026
|
+
* path lookup reaches it, so it needs search permission on every directory above it, and one that goes away or
|
|
1027
|
+
* is renamed out of the tree before the walk reads it is skipped. A failure below the root names the entry's
|
|
1028
|
+
* path under the path the root was given by, or under the root when it was given by reference or handle.
|
|
1029
|
+
*/
|
|
1030
|
+
readonly walk: (directory: TargetInput, options?: WalkOptions) => Stream.Stream<WalkEntry, WalkFailure>;
|
|
1031
|
+
/** The bytes a symbolic link points at. A path never follows the final link. */
|
|
1032
|
+
readonly readLink: (target: TargetInput) => Effect.Effect<Uint8Array, FsFailure>;
|
|
1033
|
+
/** The canonical absolute path of a target. */
|
|
1034
|
+
readonly realPath: (target: TargetInput) => Effect.Effect<BytePath, FsFailure>;
|
|
1035
|
+
/** The bits of `bits` the caller may exercise on the target: READ, WRITE, EXECUTE as 4, 2, 1. */
|
|
1036
|
+
readonly access: (target: TargetInput, bits?: number) => Effect.Effect<number, FsFailure>;
|
|
1037
|
+
/** The whole content of a regular file. */
|
|
1038
|
+
readonly readFile: (target: TargetInput) => Effect.Effect<Uint8Array, FsFailure>;
|
|
1039
|
+
/** Writes a whole file in one operation, creating or replacing it as the options say. */
|
|
1040
|
+
readonly writeFile: (entry: EntryInput, bytes: Uint8Array, options: WriteFileOptions) => Effect.Effect<void, FsFailure>;
|
|
1041
|
+
/**
|
|
1042
|
+
* Opens a file. On a target, the file must exist and `create` is rejected. On an entry, the name is looked up
|
|
1043
|
+
* and created in one gate hold, and the result reports whether it was created.
|
|
1044
|
+
*/
|
|
1045
|
+
readonly open: {
|
|
1046
|
+
(target: Target | PathInput | ObjectReference | FileHandle, options: OpenOptions): Effect.Effect<FileHandle, FsFailure, Scope.Scope>;
|
|
1047
|
+
(entry: Entry, options: OpenEntryOptions): Effect.Effect<OpenEntryResult, FsFailure, Scope.Scope>;
|
|
1048
|
+
};
|
|
1049
|
+
/**
|
|
1050
|
+
* Creates a directory. With `recursive`, every missing directory on a path is created in one change, so a
|
|
1051
|
+
* failure creates none and a watcher sees them all at once; symbolic links on the way are followed, dot names
|
|
1052
|
+
* are walked, and a final name that is already a directory (or a link to one) succeeds without a change. The
|
|
1053
|
+
* result names the directory the path ends on, with its parent's revision before and after the call, so a path
|
|
1054
|
+
* that leaves a directory it created, such as `new/..`, still reports the change. A name on the way that is not
|
|
1055
|
+
* a directory fails with `NotDirectory`, a final one with `AlreadyExists`, and only names the caller wrote are
|
|
1056
|
+
* created, so a dangling link fails with `NotFound`.
|
|
1057
|
+
*/
|
|
1058
|
+
readonly mkdir: (entry: EntryInput, options?: MkdirOptions) => Effect.Effect<ReferenceEntryResult, FsFailure>;
|
|
1059
|
+
/** Creates a symbolic link to `target`, stored as given. */
|
|
1060
|
+
readonly symlink: (target: PathInput, entry: EntryInput, options?: SymlinkOptions) => Effect.Effect<ReferenceEntryResult, FsFailure>;
|
|
1061
|
+
/** Adds a name for an existing file or symbolic link. A path source follows a final symbolic link only when its target says so. */
|
|
1062
|
+
readonly link: (source: TargetInput, entry: EntryInput) => Effect.Effect<ReferenceEntryResult, FsFailure>;
|
|
1063
|
+
/** Removes a file or symbolic link. */
|
|
1064
|
+
readonly unlink: (entry: EntryInput) => Effect.Effect<DirectoryChange, FsFailure>;
|
|
1021
1065
|
/** Removes an empty directory. */
|
|
1022
|
-
readonly rmdir: (
|
|
1023
|
-
/**
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1066
|
+
readonly rmdir: (entry: EntryInput) => Effect.Effect<DirectoryChange, FsFailure>;
|
|
1067
|
+
/**
|
|
1068
|
+
* Removes a file, a symbolic link, or an empty directory. With `recursive`, a directory that has entries is
|
|
1069
|
+
* emptied first, entries before their directories, each removal its own change; it stops at the first failure,
|
|
1070
|
+
* whose path names the entry it stopped at, and leaves what it has not reached. Each entry is removed by its name
|
|
1071
|
+
* in a directory reached by name, so a subtree renamed out of the target is left alone. A directory with entries
|
|
1072
|
+
* must be readable, and no permission is changed to make it so. With `force`, a missing target is success and the
|
|
1073
|
+
* result is `undefined`; a failure below the target is still a failure.
|
|
1074
|
+
*/
|
|
1075
|
+
readonly remove: {
|
|
1076
|
+
(entry: EntryInput, options?: RemoveOptions & {
|
|
1077
|
+
readonly force?: false;
|
|
1078
|
+
}): Effect.Effect<DirectoryChange, FsFailure>;
|
|
1079
|
+
(entry: EntryInput, options: RemoveOptions): Effect.Effect<DirectoryChange | undefined, FsFailure>;
|
|
1080
|
+
};
|
|
1081
|
+
/** Moves an entry, replacing a compatible destination. */
|
|
1082
|
+
readonly rename: (from: EntryInput, to: EntryInput) => Effect.Effect<RenameReferenceResult, FsFailure>;
|
|
1083
|
+
/** Sets the permission bits of a target. */
|
|
1084
|
+
readonly chmod: (target: TargetInput, mode: number) => Effect.Effect<void, FsFailure>;
|
|
1085
|
+
/** Changes the owner or group of a target. */
|
|
1086
|
+
readonly chown: (target: TargetInput, owner: OwnerUpdate) => Effect.Effect<void, FsFailure>;
|
|
1087
|
+
/** Sets the access and modification times of a target. */
|
|
1088
|
+
readonly utimes: (target: TargetInput, times: Times) => Effect.Effect<void, FsFailure>;
|
|
1089
|
+
/** Sets the size of a regular file. */
|
|
1090
|
+
readonly truncate: (target: TargetInput, length: bigint) => Effect.Effect<void, FsFailure>;
|
|
1091
|
+
/**
|
|
1092
|
+
* Changes a target's size, owner, mode and times as one change. Every check passes before any attribute
|
|
1093
|
+
* applies, so a failure changes nothing. The attributes apply as size, owner, mode, then times, the POSIX
|
|
1094
|
+
* composition of chown then chmod, so a requested mode wins over the set-ID clearing an owner change or a
|
|
1095
|
+
* resize triggers. A protocol adapter that sanitises the requested mode, as NFS does after Linux knfsd,
|
|
1096
|
+
* does so before it calls setattr, and passes the revision it read as `expected` so the change refuses a
|
|
1097
|
+
* target another change has moved.
|
|
1098
|
+
*/
|
|
1099
|
+
readonly setattr: (target: TargetInput, attributes: SetattrOptions) => Effect.Effect<void, FsFailure>;
|
|
1100
|
+
/** A caller whose working directory is the target, released with the scope. */
|
|
1101
|
+
readonly withDirectory: (directory: TargetInput) => Effect.Effect<Caller, FsFailure, Scope.Scope>;
|
|
1102
|
+
/** A handle on a directory, released with the scope. */
|
|
1103
|
+
readonly openDirectory: (directory: TargetInput) => Effect.Effect<DirectoryHandle, FsFailure, Scope.Scope>;
|
|
1031
1104
|
}
|
|
1032
1105
|
/**
|
|
1033
1106
|
* A committed namespace or content change emitted by a volume watch stream.
|
|
1034
1107
|
*
|
|
1035
1108
|
* @example
|
|
1036
1109
|
* ```ts
|
|
1110
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1037
1111
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1038
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1039
1112
|
* import { Effect, Fiber, Stream } from "effect"
|
|
1040
1113
|
*
|
|
1041
1114
|
* const program = Effect.gen(function*() {
|
|
1042
1115
|
* const volume = yield* Vfs.make()
|
|
1043
1116
|
* const caller = yield* volume.caller()
|
|
1044
1117
|
*
|
|
1045
|
-
* const watcher = yield* volume.watch.pipe(
|
|
1118
|
+
* const watcher = yield* volume.watch().pipe(
|
|
1046
1119
|
* Effect.flatMap((stream) => Stream.runCollect(Stream.take(stream, 2))),
|
|
1047
1120
|
* Effect.forkChild({ startImmediately: true })
|
|
1048
1121
|
* )
|
|
@@ -1060,26 +1133,81 @@ export interface Caller {
|
|
|
1060
1133
|
* ))
|
|
1061
1134
|
* }).pipe(Effect.scoped)
|
|
1062
1135
|
*
|
|
1063
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1136
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1064
1137
|
* // [ 'Create /logs', 'Remove /logs' ]
|
|
1065
1138
|
* ```
|
|
1066
1139
|
*
|
|
1140
|
+
* @category schemas
|
|
1141
|
+
* @since 0.1.0
|
|
1142
|
+
*/
|
|
1143
|
+
export declare const Change: typeof WatchModule.Change;
|
|
1144
|
+
/**
|
|
1145
|
+
* One committed change observed through a watch subscription. `Rescan` means
|
|
1146
|
+
* the subscriber lost events; it names `/` for a volume-wide watch and the
|
|
1147
|
+
* scope's current path for a scoped one.
|
|
1148
|
+
*
|
|
1067
1149
|
* @category models
|
|
1068
1150
|
* @since 0.1.0
|
|
1069
1151
|
*/
|
|
1070
|
-
export
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1152
|
+
export type Change = typeof Change.Type;
|
|
1153
|
+
/**
|
|
1154
|
+
* Schema for the options of `Volume.watch`: an object reference to narrow the
|
|
1155
|
+
* watch to, and whether its whole subtree is reported.
|
|
1156
|
+
*
|
|
1157
|
+
* @example
|
|
1158
|
+
* ```ts
|
|
1159
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1160
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1161
|
+
* import { Effect, Fiber, Stream } from "effect"
|
|
1162
|
+
*
|
|
1163
|
+
* const program = Effect.gen(function*() {
|
|
1164
|
+
* const volume = yield* Vfs.make()
|
|
1165
|
+
* const caller = yield* volume.caller()
|
|
1166
|
+
* yield* caller.mkdir("/work")
|
|
1167
|
+
* const work = yield* caller.lookup("/work")
|
|
1168
|
+
*
|
|
1169
|
+
* const watcher = yield* volume.watch({ scope: work }).pipe(
|
|
1170
|
+
* Effect.flatMap((stream) => Stream.runCollect(Stream.take(stream, 3))),
|
|
1171
|
+
* Effect.forkChild({ startImmediately: true })
|
|
1172
|
+
* )
|
|
1173
|
+
*
|
|
1174
|
+
* // Outside the scope, so not reported.
|
|
1175
|
+
* yield* caller.mkdir("/elsewhere")
|
|
1176
|
+
* // The scope is the directory, not its path: the rename is reported and the watch goes on.
|
|
1177
|
+
* yield* caller.rename("/work", "/renamed")
|
|
1178
|
+
* yield* caller.mkdir("/renamed/out")
|
|
1179
|
+
*
|
|
1180
|
+
* const events = yield* Fiber.join(watcher)
|
|
1181
|
+
*
|
|
1182
|
+
* return yield* Effect.forEach(events, (change) =>
|
|
1183
|
+
* Effect.map(
|
|
1184
|
+
* Vfs.pathToBytes(change.path),
|
|
1185
|
+
* (bytes) => `${change._tag} ${new TextDecoder().decode(bytes)}`
|
|
1186
|
+
* ))
|
|
1187
|
+
* }).pipe(Effect.scoped)
|
|
1188
|
+
*
|
|
1189
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1190
|
+
* // [ 'Remove /work', 'Create /renamed', 'Create /renamed/out' ]
|
|
1191
|
+
* ```
|
|
1192
|
+
*
|
|
1193
|
+
* @category schemas
|
|
1194
|
+
* @since 0.6.0
|
|
1195
|
+
*/
|
|
1196
|
+
export declare const WatchOptions: typeof WatchModule.WatchOptions;
|
|
1197
|
+
/**
|
|
1198
|
+
* Options of `Volume.watch`.
|
|
1199
|
+
*
|
|
1200
|
+
* @category models
|
|
1201
|
+
* @since 0.6.0
|
|
1202
|
+
*/
|
|
1203
|
+
export type WatchOptions = typeof WatchOptions.Type;
|
|
1076
1204
|
/**
|
|
1077
1205
|
* Schema for the filesystem entry kinds reported by overlay summaries.
|
|
1078
1206
|
*
|
|
1079
1207
|
* @category schemas
|
|
1080
1208
|
* @since 0.1.0
|
|
1081
1209
|
*/
|
|
1082
|
-
export declare const OverlayNodeKind: typeof
|
|
1210
|
+
export declare const OverlayNodeKind: typeof VolumeModule.OverlayNodeKind;
|
|
1083
1211
|
/**
|
|
1084
1212
|
* A filesystem entry kind reported by an overlay summary.
|
|
1085
1213
|
*
|
|
@@ -1093,7 +1221,7 @@ export type OverlayNodeKind = typeof OverlayNodeKind.Type;
|
|
|
1093
1221
|
* @category schemas
|
|
1094
1222
|
* @since 0.1.0
|
|
1095
1223
|
*/
|
|
1096
|
-
export declare const OverlayDifference: typeof
|
|
1224
|
+
export declare const OverlayDifference: typeof VolumeModule.OverlayDifference;
|
|
1097
1225
|
/**
|
|
1098
1226
|
* A content, ownership, permission, or timestamp field that differs from the overlay base.
|
|
1099
1227
|
*
|
|
@@ -1112,7 +1240,7 @@ export type OverlayDifference = typeof OverlayDifference.Type;
|
|
|
1112
1240
|
* @category schemas
|
|
1113
1241
|
* @since 0.1.0
|
|
1114
1242
|
*/
|
|
1115
|
-
export declare const OverlayChange: typeof
|
|
1243
|
+
export declare const OverlayChange: typeof VolumeModule.OverlayChange;
|
|
1116
1244
|
/**
|
|
1117
1245
|
* A path-oriented final-state difference from an overlay's immutable base.
|
|
1118
1246
|
*
|
|
@@ -1125,8 +1253,8 @@ export type OverlayChange = typeof OverlayChange.Type;
|
|
|
1125
1253
|
*
|
|
1126
1254
|
* @example
|
|
1127
1255
|
* ```ts
|
|
1256
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1128
1257
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1129
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1130
1258
|
* import { Effect } from "effect"
|
|
1131
1259
|
*
|
|
1132
1260
|
* const program = Effect.gen(function*() {
|
|
@@ -1142,14 +1270,14 @@ export type OverlayChange = typeof OverlayChange.Type;
|
|
|
1142
1270
|
* return [plain.length, timed.length]
|
|
1143
1271
|
* })
|
|
1144
1272
|
*
|
|
1145
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1273
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1146
1274
|
* // [ 1, 2 ]
|
|
1147
1275
|
* ```
|
|
1148
1276
|
*
|
|
1149
1277
|
* @category schemas
|
|
1150
1278
|
* @since 0.1.0
|
|
1151
1279
|
*/
|
|
1152
|
-
export declare const OverlayChangesOptions: typeof
|
|
1280
|
+
export declare const OverlayChangesOptions: typeof VolumeModule.OverlayChangesOptions;
|
|
1153
1281
|
/**
|
|
1154
1282
|
* Filtering options for an overlay final-difference summary.
|
|
1155
1283
|
*
|
|
@@ -1162,8 +1290,8 @@ export type OverlayChangesOptions = typeof OverlayChangesOptions.Type;
|
|
|
1162
1290
|
*
|
|
1163
1291
|
* @example
|
|
1164
1292
|
* ```ts
|
|
1293
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1165
1294
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1166
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1167
1295
|
* import { Effect } from "effect"
|
|
1168
1296
|
*
|
|
1169
1297
|
* const program = Effect.gen(function*() {
|
|
@@ -1187,7 +1315,7 @@ export type OverlayChangesOptions = typeof OverlayChangesOptions.Type;
|
|
|
1187
1315
|
* ]
|
|
1188
1316
|
* })
|
|
1189
1317
|
*
|
|
1190
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1318
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1191
1319
|
* // [ [ 'Added' ], 'built' ]
|
|
1192
1320
|
* ```
|
|
1193
1321
|
*
|
|
@@ -1205,8 +1333,8 @@ export interface OverlayCapture {
|
|
|
1205
1333
|
*
|
|
1206
1334
|
* @example
|
|
1207
1335
|
* ```ts
|
|
1336
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1208
1337
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1209
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1210
1338
|
* import { Effect, Fiber, Option, Stream } from "effect"
|
|
1211
1339
|
*
|
|
1212
1340
|
* const program = Effect.gen(function*() {
|
|
@@ -1214,7 +1342,7 @@ export interface OverlayCapture {
|
|
|
1214
1342
|
* const caller = yield* volume.caller()
|
|
1215
1343
|
*
|
|
1216
1344
|
* // `watch` reports future changes only; nothing is replayed.
|
|
1217
|
-
* const watcher = yield* volume.watch.pipe(
|
|
1345
|
+
* const watcher = yield* volume.watch().pipe(
|
|
1218
1346
|
* Effect.flatMap(Stream.runHead),
|
|
1219
1347
|
* Effect.forkChild({ startImmediately: true })
|
|
1220
1348
|
* )
|
|
@@ -1226,7 +1354,7 @@ export interface OverlayCapture {
|
|
|
1226
1354
|
* return Option.getOrElse(Option.map(change, (event) => event._tag), () => "none")
|
|
1227
1355
|
* }).pipe(Effect.scoped)
|
|
1228
1356
|
*
|
|
1229
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1357
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1230
1358
|
* // Create
|
|
1231
1359
|
* ```
|
|
1232
1360
|
*
|
|
@@ -1243,22 +1371,39 @@ export interface Volume {
|
|
|
1243
1371
|
/** Effective static limits, where `undefined` means unlimited. */
|
|
1244
1372
|
readonly limits: VolumeLimits;
|
|
1245
1373
|
/** Samples content bytes and directory entries together from the current committed state. */
|
|
1246
|
-
readonly usage: Effect.Effect<VolumeUsage,
|
|
1247
|
-
/**
|
|
1248
|
-
|
|
1374
|
+
readonly usage: Effect.Effect<VolumeUsage, FsFailure>;
|
|
1375
|
+
/**
|
|
1376
|
+
* Opens a scoped stream of future changes, registered before it returns; events are not replayed. Without a
|
|
1377
|
+
* scope it covers the volume and `Rescan` at `/` requires a full rescan; with one it covers that object (and its
|
|
1378
|
+
* subtree unless `recursive` is `false`), `Rescan` names the object's current path, and the stream ends after
|
|
1379
|
+
* `Remove` for the object once its last name is gone.
|
|
1380
|
+
*/
|
|
1381
|
+
readonly watch: (options?: WatchOptions) => Effect.Effect<Stream.Stream<Change>, FsFailure, Scope.Scope>;
|
|
1249
1382
|
/** Captures an isolated snapshot of the reachable namespace and metadata. */
|
|
1250
|
-
readonly snapshot: Effect.Effect<Snapshot,
|
|
1383
|
+
readonly snapshot: Effect.Effect<Snapshot, VfsError>;
|
|
1384
|
+
/**
|
|
1385
|
+
* The serialisable key of an object this volume issued. Fails with `InvalidReference` for a value that is not a
|
|
1386
|
+
* reference, `ForeignReference` for another volume's, and `StaleReference` once the object is gone.
|
|
1387
|
+
*/
|
|
1388
|
+
readonly referenceKey: (reference: ObjectReference) => Effect.Effect<ReferenceKey, FsFailure>;
|
|
1389
|
+
/**
|
|
1390
|
+
* The object a key names, as the same reference traversal returns. Fails with `InvalidReference` for a malformed
|
|
1391
|
+
* key or one whose tag this volume did not compute, `ForeignReference` for a key another volume or another epoch
|
|
1392
|
+
* of this one minted, and `StaleReference` once the object is gone. It checks no permission: holding the volume
|
|
1393
|
+
* already grants every caller, and the tag keeps a key holder from reaching an object no key was issued for.
|
|
1394
|
+
*/
|
|
1395
|
+
readonly resolveReferenceKey: (key: ReferenceKey) => Effect.Effect<ObjectReference, FsFailure>;
|
|
1251
1396
|
readonly [VolumeId]: true;
|
|
1252
1397
|
/** Creates a caller rooted at `/` with independent credentials, umask, and current directory. */
|
|
1253
|
-
readonly caller: (options?: RootCallerOptions) => Effect.Effect<Caller,
|
|
1398
|
+
readonly caller: (options?: RootCallerOptions) => Effect.Effect<Caller, VfsError>;
|
|
1254
1399
|
}
|
|
1255
1400
|
/**
|
|
1256
1401
|
* An ordinary volume with final-state inspection relative to one immutable snapshot base.
|
|
1257
1402
|
*
|
|
1258
1403
|
* @example
|
|
1259
1404
|
* ```ts
|
|
1405
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1260
1406
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1261
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1262
1407
|
* import { Effect } from "effect"
|
|
1263
1408
|
*
|
|
1264
1409
|
* const program = Effect.gen(function*() {
|
|
@@ -1276,7 +1421,7 @@ export interface Volume {
|
|
|
1276
1421
|
* return captured.changes.map((change) => change._tag)
|
|
1277
1422
|
* })
|
|
1278
1423
|
*
|
|
1279
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1424
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1280
1425
|
* // [ 'Added' ]
|
|
1281
1426
|
* ```
|
|
1282
1427
|
*
|
|
@@ -1285,62 +1430,121 @@ export interface Volume {
|
|
|
1285
1430
|
*/
|
|
1286
1431
|
export interface OverlayVolume extends Volume {
|
|
1287
1432
|
/** Computes final differences from the immutable base when this reusable effect executes. */
|
|
1288
|
-
readonly changes: (options?: OverlayChangesOptions) => Effect.Effect<ReadonlyArray<OverlayChange>,
|
|
1433
|
+
readonly changes: (options?: OverlayChangesOptions) => Effect.Effect<ReadonlyArray<OverlayChange>, VfsError>;
|
|
1289
1434
|
/** Captures one committed state when this reusable effect executes. */
|
|
1290
|
-
readonly capture: (options?: OverlayChangesOptions) => Effect.Effect<OverlayCapture,
|
|
1435
|
+
readonly capture: (options?: OverlayChangesOptions) => Effect.Effect<OverlayCapture, VfsError>;
|
|
1291
1436
|
}
|
|
1292
1437
|
/**
|
|
1293
|
-
*
|
|
1438
|
+
* The volume an application runs against, as an Effect service. The static
|
|
1439
|
+
* layers wrap the explicit constructors; each call builds a fresh layer, so
|
|
1440
|
+
* share one layer value to share one volume.
|
|
1294
1441
|
*
|
|
1295
1442
|
* @example
|
|
1296
1443
|
* ```ts
|
|
1444
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1297
1445
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1298
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1299
1446
|
* import { Effect } from "effect"
|
|
1300
1447
|
*
|
|
1301
|
-
*
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1448
|
+
* const program = Effect.gen(function*() {
|
|
1449
|
+
* const fs = yield* Vfs.Caller
|
|
1450
|
+
* yield* fs.mkdir("/work")
|
|
1304
1451
|
*
|
|
1305
|
-
* return yield*
|
|
1452
|
+
* return (yield* fs.readDirectory("/")).value.map((entry) => new TextDecoder().decode(entry.name))
|
|
1306
1453
|
* })
|
|
1307
1454
|
*
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1455
|
+
* Effect.runPromise(program.pipe(Effect.provide(Vfs.Caller.layer()), Effect.provide(Vfs.Volume.layer()), Effect.provide(BunCrypto.layer)))
|
|
1456
|
+
* .then(console.log)
|
|
1457
|
+
* // [ 'work' ]
|
|
1458
|
+
* ```
|
|
1311
1459
|
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
|
|
1460
|
+
* @category services
|
|
1461
|
+
* @since 0.6.0
|
|
1462
|
+
*/
|
|
1463
|
+
export declare const Volume: Context.Service<Volume, Volume> & {
|
|
1464
|
+
/** A fresh empty volume. */
|
|
1465
|
+
readonly layer: (options?: VolumeOptions) => Layer.Layer<Volume, VfsError, Crypto.Crypto>;
|
|
1466
|
+
/** A fresh volume restored from a snapshot. */
|
|
1467
|
+
readonly layerFromSnapshot: (snapshot: Snapshot, options?: VolumeOptions) => Layer.Layer<Volume, VfsError, Crypto.Crypto>;
|
|
1468
|
+
/** A fresh volume built from a fixture. */
|
|
1469
|
+
readonly layerFromFixture: (fixture: Fixture, options?: VolumeOptions) => Layer.Layer<Volume, VfsError, Crypto.Crypto>;
|
|
1470
|
+
/** A writable overlay over a snapshot base. */
|
|
1471
|
+
readonly layerOverlay: (base: Snapshot, options?: VolumeOptions) => Layer.Layer<Volume, VfsError, Crypto.Crypto>;
|
|
1472
|
+
/** A durable volume opened through the `LiveImageStore` in context; it shuts down with the layer's scope. */
|
|
1473
|
+
readonly layerLive: (options: LiveVolumeOptions) => Layer.Layer<Volume, VfsError, LiveImageStore | Crypto.Crypto>;
|
|
1474
|
+
};
|
|
1475
|
+
/**
|
|
1476
|
+
* The caller an application operates through, as an Effect service. A caller
|
|
1477
|
+
* supplied through the service keeps its own volume, credentials, umask and
|
|
1478
|
+
* working directory; `layer` makes a root caller on the `Volume` in context.
|
|
1479
|
+
*
|
|
1480
|
+
* @category services
|
|
1481
|
+
* @since 0.6.0
|
|
1482
|
+
*/
|
|
1483
|
+
export declare const Caller: Context.Service<Caller, Caller> & {
|
|
1484
|
+
/** A root caller on the volume in context; root callers need no scope. */
|
|
1485
|
+
readonly layer: (options?: RootCallerOptions) => Layer.Layer<Caller, VfsError, Volume>;
|
|
1486
|
+
};
|
|
1487
|
+
/**
|
|
1488
|
+
* Streams a snapshot's version 1 encoding as owned UTF-8 chunks: a header line,
|
|
1489
|
+
* then one line per node, each ending in a newline.
|
|
1490
|
+
*
|
|
1491
|
+
* **Details**
|
|
1492
|
+
*
|
|
1493
|
+
* The encoding is newline-delimited JSON. The first line names the format and
|
|
1494
|
+
* version; each later line is one node in inode order, with names and payloads
|
|
1495
|
+
* as canonical base64. Nodes are encoded as the stream is pulled, so writing a
|
|
1496
|
+
* large snapshot to a file or a socket never holds its whole encoding. A chunk
|
|
1497
|
+
* holds at most 128 lines and 64 KiB, so a pull holds at most that and the next
|
|
1498
|
+
* line; a line longer than 64 KiB is a chunk of its own.
|
|
1499
|
+
*
|
|
1500
|
+
* Given `limits`, the stream fails with `LimitExceeded` at the first line that
|
|
1501
|
+
* `decodeSnapshot` would refuse under the same limits, naming the same field,
|
|
1502
|
+
* so bytes it completes are known to decode without decoding them.
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* ```ts
|
|
1506
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1507
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1508
|
+
* import { Effect, Stream } from "effect"
|
|
1509
|
+
*
|
|
1510
|
+
* const program = Effect.gen(function*() {
|
|
1511
|
+
* const volume = yield* Vfs.fromFixture({
|
|
1512
|
+
* entries: [{ kind: "file", path: "/f", bytes: new Uint8Array([1]) }]
|
|
1315
1513
|
* })
|
|
1316
1514
|
*
|
|
1317
|
-
*
|
|
1515
|
+
* const text = yield* Vfs.encodeSnapshotStream(yield* volume.snapshot).pipe(
|
|
1516
|
+
* Stream.decodeText,
|
|
1517
|
+
* Stream.mkString
|
|
1518
|
+
* )
|
|
1519
|
+
*
|
|
1520
|
+
* // A header line, then the root and the file, each line ending in a newline.
|
|
1521
|
+
* return text.split("\n").map((line) => (line === "" ? "end" : JSON.parse(line)._tag ?? "header"))
|
|
1318
1522
|
* })
|
|
1319
1523
|
*
|
|
1320
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1321
|
-
* //
|
|
1524
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1525
|
+
* // [ 'header', 'directory', 'file', 'end' ]
|
|
1322
1526
|
* ```
|
|
1323
1527
|
*
|
|
1324
|
-
* @see
|
|
1325
|
-
* @
|
|
1326
|
-
* @
|
|
1528
|
+
* @see {@link encodeSnapshot} for the same bytes collected into one array.
|
|
1529
|
+
* @see {@link decodeSnapshotSink} for reading a stream back under limits.
|
|
1530
|
+
* @category serialization
|
|
1531
|
+
* @since 0.6.0
|
|
1327
1532
|
*/
|
|
1328
|
-
export declare const
|
|
1533
|
+
export declare const encodeSnapshotStream: (snapshot: Snapshot, limits?: DecodeLimits) => Stream.Stream<Uint8Array, ImageFailure | ArgumentFailure>;
|
|
1329
1534
|
/**
|
|
1330
|
-
*
|
|
1535
|
+
* Encodes a snapshot as owned UTF-8 bytes in the version 1 snapshot format.
|
|
1331
1536
|
*
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
* Encodes a snapshot as owned UTF-8 JSON bytes using the version 1 snapshot format.
|
|
1537
|
+
* **Details**
|
|
1538
|
+
*
|
|
1539
|
+
* The bytes are the chunks of {@link encodeSnapshotStream} collected into one
|
|
1540
|
+
* array: newline-delimited JSON, a header line and then one line per node.
|
|
1541
|
+
* Given `limits`, encoding fails with `LimitExceeded` wherever `decodeSnapshot`
|
|
1542
|
+
* would refuse the bytes under the same limits.
|
|
1339
1543
|
*
|
|
1340
1544
|
* @example
|
|
1341
1545
|
* ```ts
|
|
1546
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1342
1547
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1343
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1344
1548
|
* import { Effect } from "effect"
|
|
1345
1549
|
*
|
|
1346
1550
|
* // Bytes are portable: store or transmit them, then decode under explicit limits.
|
|
@@ -1355,11 +1559,11 @@ export interface CurrentFileSystem extends Caller {
|
|
|
1355
1559
|
*
|
|
1356
1560
|
* const bytes = yield* Vfs.encodeSnapshot(yield* volume.snapshot)
|
|
1357
1561
|
*
|
|
1358
|
-
* // The
|
|
1359
|
-
* return JSON.parse(new TextDecoder().decode(bytes)).version
|
|
1562
|
+
* // The first line is the header carrying the version 1 snapshot format.
|
|
1563
|
+
* return JSON.parse(new TextDecoder().decode(bytes).split("\n")[0]!).version
|
|
1360
1564
|
* })
|
|
1361
1565
|
*
|
|
1362
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1566
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1363
1567
|
* // 1
|
|
1364
1568
|
* ```
|
|
1365
1569
|
*
|
|
@@ -1367,17 +1571,77 @@ export interface CurrentFileSystem extends Caller {
|
|
|
1367
1571
|
* @category serialization
|
|
1368
1572
|
* @since 0.1.0
|
|
1369
1573
|
*/
|
|
1370
|
-
export declare const encodeSnapshot: (snapshot: Snapshot) => Effect.Effect<Uint8Array,
|
|
1574
|
+
export declare const encodeSnapshot: (snapshot: Snapshot, limits?: DecodeLimits) => Effect.Effect<Uint8Array, ImageFailure | ArgumentFailure>;
|
|
1575
|
+
/**
|
|
1576
|
+
* A sink that decodes a stream of version 1 snapshot chunks while enforcing
|
|
1577
|
+
* explicit input and payload limits.
|
|
1578
|
+
*
|
|
1579
|
+
* **Details**
|
|
1580
|
+
*
|
|
1581
|
+
* Chunks may split lines, and UTF-8 sequences, anywhere. Each line is checked
|
|
1582
|
+
* as it ends, so input that breaks a limit or a rule is refused before the
|
|
1583
|
+
* sink holds more than one line of it: `maxLineBytes` bounds that line, and
|
|
1584
|
+
* the other limits bound what the accepted lines add up to. A line is
|
|
1585
|
+
* refused at the byte where it first crosses `maxLineBytes` or
|
|
1586
|
+
* `maxEncodedBytes`, so the field a refusal names does not depend on how the
|
|
1587
|
+
* input is chunked. Every line must end in a newline, the last included; a
|
|
1588
|
+
* carriage return, an empty line, a byte-order mark and malformed UTF-8 are
|
|
1589
|
+
* refused as `InvalidEncoding`.
|
|
1590
|
+
*
|
|
1591
|
+
* @example
|
|
1592
|
+
* ```ts
|
|
1593
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1594
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1595
|
+
* import { ByteSize, Effect, Stream } from "effect"
|
|
1596
|
+
*
|
|
1597
|
+
* const limits: Vfs.DecodeLimits = {
|
|
1598
|
+
* maxEncodedBytes: ByteSize.megabytes(4),
|
|
1599
|
+
* maxRecords: 10_000,
|
|
1600
|
+
* maxEntries: 10_000,
|
|
1601
|
+
* maxDecodedBytes: ByteSize.megabytes(16),
|
|
1602
|
+
* maxLineBytes: ByteSize.megabytes(1)
|
|
1603
|
+
* }
|
|
1604
|
+
*
|
|
1605
|
+
* const program = Effect.gen(function*() {
|
|
1606
|
+
* const volume = yield* Vfs.fromFixture({
|
|
1607
|
+
* entries: [{ kind: "file", path: "/f", bytes: new Uint8Array([1, 2, 3]) }]
|
|
1608
|
+
* })
|
|
1609
|
+
*
|
|
1610
|
+
* // Rechunked to single bytes: the sink joins lines across chunks.
|
|
1611
|
+
* const snapshot = yield* Vfs.encodeSnapshotStream(yield* volume.snapshot).pipe(
|
|
1612
|
+
* Stream.flattenIterable,
|
|
1613
|
+
* Stream.rechunk(1),
|
|
1614
|
+
* Stream.map((byte) => new Uint8Array([byte])),
|
|
1615
|
+
* Stream.run(Vfs.decodeSnapshotSink(limits))
|
|
1616
|
+
* )
|
|
1617
|
+
*
|
|
1618
|
+
* return yield* (yield* (yield* Vfs.fromSnapshot(snapshot)).caller()).readFile("/f")
|
|
1619
|
+
* })
|
|
1620
|
+
*
|
|
1621
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1622
|
+
* // Uint8Array(3) [ 1, 2, 3 ]
|
|
1623
|
+
* ```
|
|
1624
|
+
*
|
|
1625
|
+
* @see {@link DecodeLimits} for what each bound protects.
|
|
1626
|
+
* @see {@link decodeSnapshot} for decoding bytes already in memory.
|
|
1627
|
+
* @category serialization
|
|
1628
|
+
* @since 0.6.0
|
|
1629
|
+
*/
|
|
1630
|
+
export declare const decodeSnapshotSink: (limits: DecodeLimits) => Sink.Sink<Snapshot, Uint8Array, never, ImageFailure | ArgumentFailure>;
|
|
1371
1631
|
/**
|
|
1372
1632
|
* Decodes version 1 snapshot bytes while enforcing explicit input and payload limits.
|
|
1373
1633
|
*
|
|
1634
|
+
* **Details**
|
|
1635
|
+
*
|
|
1636
|
+
* The same decoder as {@link decodeSnapshotSink}, run over one chunk.
|
|
1637
|
+
*
|
|
1374
1638
|
* @example
|
|
1375
1639
|
* ```ts
|
|
1640
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1376
1641
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1377
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1378
1642
|
* import { ByteSize, Effect } from "effect"
|
|
1379
1643
|
*
|
|
1380
|
-
* // Limits are mandatory: decoding is the boundary where
|
|
1644
|
+
* // Limits are mandatory: decoding is the boundary where outside input arrives.
|
|
1381
1645
|
* const program = Effect.gen(function*() {
|
|
1382
1646
|
* const volume = yield* Vfs.make()
|
|
1383
1647
|
* const bytes = yield* Vfs.encodeSnapshot(yield* volume.snapshot)
|
|
@@ -1389,11 +1653,11 @@ export declare const encodeSnapshot: (snapshot: Snapshot) => Effect.Effect<Uint8
|
|
|
1389
1653
|
* maxDecodedBytes: ByteSize.megabytes(16)
|
|
1390
1654
|
* }).pipe(
|
|
1391
1655
|
* Effect.as("accepted"),
|
|
1392
|
-
* Effect.catchTag("
|
|
1656
|
+
* Effect.catchTag("VfsError", (error) => Effect.succeed([error.code, error.field]))
|
|
1393
1657
|
* )
|
|
1394
1658
|
* })
|
|
1395
1659
|
*
|
|
1396
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1660
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1397
1661
|
* // [ 'LimitExceeded', 'encodedBytes' ]
|
|
1398
1662
|
* ```
|
|
1399
1663
|
*
|
|
@@ -1401,7 +1665,7 @@ export declare const encodeSnapshot: (snapshot: Snapshot) => Effect.Effect<Uint8
|
|
|
1401
1665
|
* @category serialization
|
|
1402
1666
|
* @since 0.1.0
|
|
1403
1667
|
*/
|
|
1404
|
-
export declare const decodeSnapshot: (input: Uint8Array, limits: DecodeLimits) => Effect.Effect<Snapshot,
|
|
1668
|
+
export declare const decodeSnapshot: (input: Uint8Array, limits: DecodeLimits) => Effect.Effect<Snapshot, ImageFailure | ArgumentFailure>;
|
|
1405
1669
|
/**
|
|
1406
1670
|
* Computes an exact portable delta between two immutable snapshots.
|
|
1407
1671
|
* Requires the platform-neutral `Crypto.Crypto` service for base identity. Provide
|
|
@@ -1409,6 +1673,7 @@ export declare const decodeSnapshot: (input: Uint8Array, limits: DecodeLimits) =
|
|
|
1409
1673
|
*
|
|
1410
1674
|
* @example
|
|
1411
1675
|
* ```ts
|
|
1676
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1412
1677
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1413
1678
|
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1414
1679
|
* import { Effect } from "effect"
|
|
@@ -1431,7 +1696,7 @@ export declare const decodeSnapshot: (input: Uint8Array, limits: DecodeLimits) =
|
|
|
1431
1696
|
* return new TextDecoder().decode(yield* Vfs.pathToBytes(changes[0]!.path))
|
|
1432
1697
|
* }).pipe(Effect.provide(NodeCrypto.layer))
|
|
1433
1698
|
*
|
|
1434
|
-
* Effect.runPromise(program).then(console.log)
|
|
1699
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1435
1700
|
* // /added.txt
|
|
1436
1701
|
* ```
|
|
1437
1702
|
*
|
|
@@ -1439,7 +1704,7 @@ export declare const decodeSnapshot: (input: Uint8Array, limits: DecodeLimits) =
|
|
|
1439
1704
|
* @category snapshots
|
|
1440
1705
|
* @since 0.1.0
|
|
1441
1706
|
*/
|
|
1442
|
-
export declare const diffSnapshots: (base: Snapshot, target: Snapshot, limits?: SnapshotDeltaModel.SnapshotDeltaLimits) => Effect.Effect<SnapshotDeltaModel.SnapshotDelta,
|
|
1707
|
+
export declare const diffSnapshots: (base: Snapshot, target: Snapshot, limits?: SnapshotDeltaModel.SnapshotDeltaLimits) => Effect.Effect<SnapshotDeltaModel.SnapshotDelta, VfsError | PlatformError.PlatformError, Crypto.Crypto>;
|
|
1443
1708
|
/**
|
|
1444
1709
|
* Verifies an exact snapshot delta against its base and derives an owned path-oriented summary.
|
|
1445
1710
|
* Requires the platform-neutral `Crypto.Crypto` service for base identity. Provide
|
|
@@ -1447,6 +1712,7 @@ export declare const diffSnapshots: (base: Snapshot, target: Snapshot, limits?:
|
|
|
1447
1712
|
*
|
|
1448
1713
|
* @example
|
|
1449
1714
|
* ```ts
|
|
1715
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1450
1716
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1451
1717
|
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1452
1718
|
* import { Effect } from "effect"
|
|
@@ -1466,7 +1732,7 @@ export declare const diffSnapshots: (base: Snapshot, target: Snapshot, limits?:
|
|
|
1466
1732
|
* change._tag === "Updated" ? change.afterKind : change.kind)
|
|
1467
1733
|
* }).pipe(Effect.provide(NodeCrypto.layer))
|
|
1468
1734
|
*
|
|
1469
|
-
* Effect.runPromise(program).then(console.log)
|
|
1735
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1470
1736
|
* // [ 'directory' ]
|
|
1471
1737
|
* ```
|
|
1472
1738
|
*
|
|
@@ -1474,7 +1740,7 @@ export declare const diffSnapshots: (base: Snapshot, target: Snapshot, limits?:
|
|
|
1474
1740
|
* @category snapshots
|
|
1475
1741
|
* @since 0.1.0
|
|
1476
1742
|
*/
|
|
1477
|
-
export declare const inspectSnapshotDelta: (base: Snapshot, delta: SnapshotDeltaModel.SnapshotDelta, options?: SnapshotDeltaModel.SnapshotChangesOptions, limits?: SnapshotDeltaModel.SnapshotDeltaLimits) => Effect.Effect<ReadonlyArray<SnapshotDeltaModel.SnapshotChange>,
|
|
1743
|
+
export declare const inspectSnapshotDelta: (base: Snapshot, delta: SnapshotDeltaModel.SnapshotDelta, options?: SnapshotDeltaModel.SnapshotChangesOptions, limits?: SnapshotDeltaModel.SnapshotDeltaLimits) => Effect.Effect<ReadonlyArray<SnapshotDeltaModel.SnapshotChange>, VfsError | PlatformError.PlatformError, Crypto.Crypto>;
|
|
1478
1744
|
/**
|
|
1479
1745
|
* Applies an exact delta to its semantically matching base and returns a new snapshot.
|
|
1480
1746
|
* Requires the platform-neutral `Crypto.Crypto` service for base identity. Provide
|
|
@@ -1482,6 +1748,7 @@ export declare const inspectSnapshotDelta: (base: Snapshot, delta: SnapshotDelta
|
|
|
1482
1748
|
*
|
|
1483
1749
|
* @example
|
|
1484
1750
|
* ```ts
|
|
1751
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1485
1752
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1486
1753
|
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1487
1754
|
* import { Effect } from "effect"
|
|
@@ -1506,7 +1773,7 @@ export declare const inspectSnapshotDelta: (base: Snapshot, delta: SnapshotDelta
|
|
|
1506
1773
|
* return yield* reader.readFile("/f")
|
|
1507
1774
|
* }).pipe(Effect.provide(NodeCrypto.layer))
|
|
1508
1775
|
*
|
|
1509
|
-
* Effect.runPromise(program).then(console.log)
|
|
1776
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1510
1777
|
* // Uint8Array(1) [ 7 ]
|
|
1511
1778
|
* ```
|
|
1512
1779
|
*
|
|
@@ -1514,13 +1781,14 @@ export declare const inspectSnapshotDelta: (base: Snapshot, delta: SnapshotDelta
|
|
|
1514
1781
|
* @category snapshots
|
|
1515
1782
|
* @since 0.1.0
|
|
1516
1783
|
*/
|
|
1517
|
-
export declare const applySnapshotDelta: (base: Snapshot, delta: SnapshotDeltaModel.SnapshotDelta, limits?: SnapshotDeltaModel.SnapshotDeltaLimits) => Effect.Effect<Snapshot,
|
|
1784
|
+
export declare const applySnapshotDelta: (base: Snapshot, delta: SnapshotDeltaModel.SnapshotDelta, limits?: SnapshotDeltaModel.SnapshotDeltaLimits) => Effect.Effect<Snapshot, VfsError | PlatformError.PlatformError, Crypto.Crypto>;
|
|
1518
1785
|
/**
|
|
1519
1786
|
* Creates an Effect Schema codec between owned bytes and opaque snapshot deltas.
|
|
1520
1787
|
* Omission uses `SnapshotDeltaLimits.default`.
|
|
1521
1788
|
*
|
|
1522
1789
|
* @example
|
|
1523
1790
|
* ```ts
|
|
1791
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1524
1792
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1525
1793
|
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1526
1794
|
* import { Effect, Schema } from "effect"
|
|
@@ -1543,7 +1811,7 @@ export declare const applySnapshotDelta: (base: Snapshot, delta: SnapshotDeltaMo
|
|
|
1543
1811
|
* return (yield* Vfs.inspectSnapshotDelta(base, decoded)).map((change) => change._tag)
|
|
1544
1812
|
* }).pipe(Effect.provide(NodeCrypto.layer))
|
|
1545
1813
|
*
|
|
1546
|
-
* Effect.runPromise(program).then(console.log)
|
|
1814
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1547
1815
|
* // [ 'Added' ]
|
|
1548
1816
|
* ```
|
|
1549
1817
|
*
|
|
@@ -1560,6 +1828,7 @@ export declare const SnapshotDeltaFromBytes: (limits?: SnapshotDeltaModel.Snapsh
|
|
|
1560
1828
|
*
|
|
1561
1829
|
* @example
|
|
1562
1830
|
* ```ts
|
|
1831
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1563
1832
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1564
1833
|
* import { Effect } from "effect"
|
|
1565
1834
|
*
|
|
@@ -1570,27 +1839,27 @@ export declare const SnapshotDeltaFromBytes: (limits?: SnapshotDeltaModel.Snapsh
|
|
|
1570
1839
|
*
|
|
1571
1840
|
* const rejected = yield* Vfs.pathFromBytes(new Uint8Array([47, 0])).pipe(
|
|
1572
1841
|
* Effect.as("accepted"),
|
|
1573
|
-
* Effect.catchTag("
|
|
1842
|
+
* Effect.catchTag("VfsError", (error) => Effect.succeed(error.code))
|
|
1574
1843
|
* )
|
|
1575
1844
|
*
|
|
1576
1845
|
* return [yield* Vfs.pathToBytes(path), rejected]
|
|
1577
1846
|
* })
|
|
1578
1847
|
*
|
|
1579
|
-
* Effect.runPromise(program).then(console.log)
|
|
1848
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1580
1849
|
* // [ Uint8Array(4) [ 47, 116, 109, 112 ], 'InvalidArgument' ]
|
|
1581
1850
|
* ```
|
|
1582
1851
|
*
|
|
1583
1852
|
* @category constructors
|
|
1584
1853
|
* @since 0.1.0
|
|
1585
1854
|
*/
|
|
1586
|
-
export declare const pathFromBytes: (bytes: Uint8Array) => Effect.Effect<BytePath,
|
|
1855
|
+
export declare const pathFromBytes: (bytes: Uint8Array) => Effect.Effect<BytePath, FsFailure>;
|
|
1587
1856
|
/**
|
|
1588
1857
|
* Copies the bytes held by an opaque byte path.
|
|
1589
1858
|
*
|
|
1590
1859
|
* @category getters
|
|
1591
1860
|
* @since 0.1.0
|
|
1592
1861
|
*/
|
|
1593
|
-
export declare const pathToBytes: (path: BytePath) => Effect.Effect<Uint8Array,
|
|
1862
|
+
export declare const pathToBytes: (path: BytePath) => Effect.Effect<Uint8Array, FsFailure>;
|
|
1594
1863
|
/**
|
|
1595
1864
|
* Schema for a complete fixture namespace with optional metadata and forward hard links.
|
|
1596
1865
|
*
|
|
@@ -1600,8 +1869,8 @@ export declare const pathToBytes: (path: BytePath) => Effect.Effect<Uint8Array,
|
|
|
1600
1869
|
*
|
|
1601
1870
|
* @example
|
|
1602
1871
|
* ```ts
|
|
1872
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1603
1873
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1604
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1605
1874
|
* import { Effect, Schema } from "effect"
|
|
1606
1875
|
*
|
|
1607
1876
|
* // Fixtures must list every parent directory before its children.
|
|
@@ -1612,17 +1881,17 @@ export declare const pathToBytes: (path: BytePath) => Effect.Effect<Uint8Array,
|
|
|
1612
1881
|
* }).pipe(
|
|
1613
1882
|
* Effect.flatMap(Vfs.fromFixture),
|
|
1614
1883
|
* Effect.as("built"),
|
|
1615
|
-
* Effect.catchTag("
|
|
1884
|
+
* Effect.catchTag("VfsError", (error) => Effect.succeed(`rejected: ${error.code}`))
|
|
1616
1885
|
* )
|
|
1617
1886
|
*
|
|
1618
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1887
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1619
1888
|
* // rejected: InvalidStructure
|
|
1620
1889
|
* ```
|
|
1621
1890
|
*
|
|
1622
1891
|
* @category schemas
|
|
1623
1892
|
* @since 0.1.0
|
|
1624
1893
|
*/
|
|
1625
|
-
export declare const Fixture: typeof
|
|
1894
|
+
export declare const Fixture: typeof FixtureModule.Fixture;
|
|
1626
1895
|
/**
|
|
1627
1896
|
* A complete filesystem fixture accepted by `fromFixture`.
|
|
1628
1897
|
*
|
|
@@ -1637,11 +1906,12 @@ export type Fixture = typeof Fixture.Type;
|
|
|
1637
1906
|
*
|
|
1638
1907
|
* Each execution creates independent storage. Snapshot image failures cannot
|
|
1639
1908
|
* arise because this constructor does not accept persisted input.
|
|
1909
|
+
* Provide `Crypto.Crypto` to generate the volume identity and reference-key secret.
|
|
1640
1910
|
*
|
|
1641
1911
|
* @example
|
|
1642
1912
|
* ```ts
|
|
1913
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1643
1914
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1644
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1645
1915
|
* import { Effect } from "effect"
|
|
1646
1916
|
*
|
|
1647
1917
|
* const program = Effect.gen(function*() {
|
|
@@ -1654,7 +1924,7 @@ export type Fixture = typeof Fixture.Type;
|
|
|
1654
1924
|
* return yield* caller.readFile("/work/notes.txt")
|
|
1655
1925
|
* })
|
|
1656
1926
|
*
|
|
1657
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1927
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1658
1928
|
* // Uint8Array(2) [ 104, 105 ]
|
|
1659
1929
|
* ```
|
|
1660
1930
|
*
|
|
@@ -1662,14 +1932,61 @@ export type Fixture = typeof Fixture.Type;
|
|
|
1662
1932
|
* @category constructors
|
|
1663
1933
|
* @since 0.1.0
|
|
1664
1934
|
*/
|
|
1665
|
-
export declare const make: (options?: VolumeOptions) => Effect.Effect<Volume,
|
|
1935
|
+
export declare const make: (options?: VolumeOptions) => Effect.Effect<Volume, VfsError, Crypto.Crypto>;
|
|
1936
|
+
/**
|
|
1937
|
+
* Streams the tree at `root` in a snapshot as fixture entries, read from the
|
|
1938
|
+
* snapshot itself without restoring a volume.
|
|
1939
|
+
*
|
|
1940
|
+
* **Details**
|
|
1941
|
+
*
|
|
1942
|
+
* `root` resolves as a privileged caller at `/` of a volume restored from the
|
|
1943
|
+
* snapshot with default options would resolve it, following intermediate
|
|
1944
|
+
* symbolic links but not a final one and applying no path byte limit. Entries come in sorted
|
|
1945
|
+
* pre-order, children in the byte order of their names, with paths rooted at
|
|
1946
|
+
* `root`, so the root entry's path is `/`. A path stays a string while every
|
|
1947
|
+
* name on it is UTF-8 and is a `BytePath` otherwise. A file or symbolic link
|
|
1948
|
+
* that more than one name reaches is an entry at its first path and a
|
|
1949
|
+
* `hardLink` to that path at the others. Each file's bytes are an owned copy,
|
|
1950
|
+
* made when the stream pulls its entry. Every entry after the root's is a
|
|
1951
|
+
* fixture entry for a volume holding the same tree.
|
|
1952
|
+
*
|
|
1953
|
+
* @example
|
|
1954
|
+
* ```ts
|
|
1955
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1956
|
+
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1957
|
+
* import { Effect, Stream } from "effect"
|
|
1958
|
+
*
|
|
1959
|
+
* const program = Effect.gen(function*() {
|
|
1960
|
+
* const volume = yield* Vfs.fromFixture({
|
|
1961
|
+
* entries: [
|
|
1962
|
+
* { kind: "directory", path: "/src" },
|
|
1963
|
+
* { kind: "file", path: "/src/b.txt", bytes: new Uint8Array([2]) },
|
|
1964
|
+
* { kind: "file", path: "/src/a.txt", bytes: new Uint8Array([1]) },
|
|
1965
|
+
* { kind: "hardLink", path: "/src/c.txt", target: "/src/a.txt" }
|
|
1966
|
+
* ]
|
|
1967
|
+
* })
|
|
1968
|
+
*
|
|
1969
|
+
* const entries = yield* Stream.runCollect(Vfs.snapshotEntries(yield* volume.snapshot, "/src"))
|
|
1970
|
+
*
|
|
1971
|
+
* return entries.map((entry) => `${entry.kind} ${String(entry.path)}`)
|
|
1972
|
+
* })
|
|
1973
|
+
*
|
|
1974
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1975
|
+
* // [ 'directory /', 'file /a.txt', 'file /b.txt', 'hardLink /c.txt' ]
|
|
1976
|
+
* ```
|
|
1977
|
+
*
|
|
1978
|
+
* @see {@link fromFixture} for building a volume from the entries.
|
|
1979
|
+
* @category snapshots
|
|
1980
|
+
* @since 0.6.0
|
|
1981
|
+
*/
|
|
1982
|
+
export declare const snapshotEntries: (snapshot: Snapshot, root: PathInput) => Stream.Stream<Fixture["entries"][number], FsFailure | ImageFailure>;
|
|
1666
1983
|
/**
|
|
1667
1984
|
* Restores a fresh volume from an opaque snapshot under the supplied destination limits.
|
|
1668
1985
|
*
|
|
1669
1986
|
* @example
|
|
1670
1987
|
* ```ts
|
|
1988
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1671
1989
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1672
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1673
1990
|
* import { Effect } from "effect"
|
|
1674
1991
|
*
|
|
1675
1992
|
* const program = Effect.gen(function*() {
|
|
@@ -1696,15 +2013,16 @@ export declare const make: (options?: VolumeOptions) => Effect.Effect<Volume, Co
|
|
|
1696
2013
|
* ]
|
|
1697
2014
|
* })
|
|
1698
2015
|
*
|
|
1699
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
2016
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1700
2017
|
* // [ 'one', 'two' ]
|
|
1701
2018
|
* ```
|
|
1702
2019
|
*
|
|
1703
2020
|
* @see {@link makeOverlay} for a copy-on-write workspace over the same base.
|
|
2021
|
+
* @see `Crypto.Crypto` for the required secure random-byte service.
|
|
1704
2022
|
* @category constructors
|
|
1705
2023
|
* @since 0.1.0
|
|
1706
2024
|
*/
|
|
1707
|
-
export declare const fromSnapshot: (snapshot: Snapshot, options?: VolumeOptions) => Effect.Effect<Volume,
|
|
2025
|
+
export declare const fromSnapshot: (snapshot: Snapshot, options?: VolumeOptions) => Effect.Effect<Volume, VfsError, Crypto.Crypto>;
|
|
1708
2026
|
/**
|
|
1709
2027
|
* Creates an isolated writable volume relative to one immutable snapshot base.
|
|
1710
2028
|
*
|
|
@@ -1715,13 +2033,13 @@ export declare const fromSnapshot: (snapshot: Snapshot, options?: VolumeOptions)
|
|
|
1715
2033
|
* storage. Metadata, namespace state, coordination, handles, and watches are
|
|
1716
2034
|
* always private to the new workspace.
|
|
1717
2035
|
*
|
|
1718
|
-
* Invalid base snapshots
|
|
1719
|
-
*
|
|
2036
|
+
* Invalid base snapshots and invalid volume limits fail with `VfsError`. Each
|
|
2037
|
+
* execution creates a fresh workspace.
|
|
1720
2038
|
*
|
|
1721
2039
|
* @example
|
|
1722
2040
|
* ```ts
|
|
2041
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1723
2042
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1724
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1725
2043
|
* import { Effect } from "effect"
|
|
1726
2044
|
*
|
|
1727
2045
|
* const program = Effect.gen(function*() {
|
|
@@ -1747,28 +2065,29 @@ export declare const fromSnapshot: (snapshot: Snapshot, options?: VolumeOptions)
|
|
|
1747
2065
|
* ]
|
|
1748
2066
|
* })
|
|
1749
2067
|
*
|
|
1750
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
2068
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
1751
2069
|
* // [ '{}', [ 'Updated' ] ]
|
|
1752
2070
|
* ```
|
|
1753
2071
|
*
|
|
1754
2072
|
* @see The overlay guide at `/guides/overlay-filesystems`.
|
|
2073
|
+
* @see `Crypto.Crypto` for the required secure random-byte service.
|
|
1755
2074
|
* @category constructors
|
|
1756
2075
|
* @since 0.1.0
|
|
1757
2076
|
*/
|
|
1758
|
-
export declare const makeOverlay: (base: Snapshot, options?: VolumeOptions) => Effect.Effect<OverlayVolume,
|
|
2077
|
+
export declare const makeOverlay: (base: Snapshot, options?: VolumeOptions) => Effect.Effect<OverlayVolume, VfsError, Crypto.Crypto>;
|
|
1759
2078
|
/**
|
|
1760
2079
|
* Builds a fresh volume from a validated final-state fixture.
|
|
1761
2080
|
*
|
|
1762
2081
|
* @example
|
|
1763
2082
|
* ```ts
|
|
2083
|
+
* import * as BunCrypto from "@effect/platform-bun/BunCrypto"
|
|
1764
2084
|
* import { VirtualFileSystem as Vfs } from "@effect-vfs/core"
|
|
1765
|
-
* import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto"
|
|
1766
2085
|
* import { Effect } from "effect"
|
|
1767
2086
|
*
|
|
1768
2087
|
* const encoder = new TextEncoder()
|
|
1769
2088
|
*
|
|
1770
2089
|
* const program = Effect.gen(function*() {
|
|
1771
|
-
* // Parent directories must be listed explicitly,
|
|
2090
|
+
* // Parent directories must be listed explicitly, in any order.
|
|
1772
2091
|
* const volume = yield* Vfs.fromFixture({
|
|
1773
2092
|
* entries: [
|
|
1774
2093
|
* { kind: "directory", path: "/project" },
|
|
@@ -1781,16 +2100,20 @@ export declare const makeOverlay: (base: Snapshot, options?: VolumeOptions) => E
|
|
|
1781
2100
|
* ]
|
|
1782
2101
|
* })
|
|
1783
2102
|
*
|
|
1784
|
-
*
|
|
2103
|
+
* // A fixture's directories list their entries in the byte order of their names.
|
|
2104
|
+
* const listing = yield* (yield* volume.caller()).readDirectory("/project")
|
|
2105
|
+
*
|
|
2106
|
+
* return listing.value.map((entry) => new TextDecoder().decode(entry.name))
|
|
1785
2107
|
* })
|
|
1786
2108
|
*
|
|
1787
|
-
* Effect.runPromise(program.pipe(Effect.provide(
|
|
1788
|
-
* // [ '
|
|
2109
|
+
* Effect.runPromise(program.pipe(Effect.provide(BunCrypto.layer))).then(console.log)
|
|
2110
|
+
* // [ 'latest', 'package.json' ]
|
|
1789
2111
|
* ```
|
|
1790
2112
|
*
|
|
1791
2113
|
* @see The fixtures guide at `/guides/fixtures-and-snapshots`.
|
|
2114
|
+
* @see `Crypto.Crypto` for the required secure random-byte service.
|
|
1792
2115
|
* @category constructors
|
|
1793
2116
|
* @since 0.1.0
|
|
1794
2117
|
*/
|
|
1795
|
-
export declare const fromFixture: (fixture: Fixture, options?: VolumeOptions) => Effect.Effect<Volume,
|
|
2118
|
+
export declare const fromFixture: (fixture: Fixture, options?: VolumeOptions) => Effect.Effect<Volume, VfsError, Crypto.Crypto>;
|
|
1796
2119
|
//# sourceMappingURL=VirtualFileSystem.d.ts.map
|