@effect-vfs/core 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +29 -21
  2. package/dist/BytePath.d.ts +115 -4
  3. package/dist/BytePath.d.ts.map +1 -1
  4. package/dist/BytePath.js +155 -0
  5. package/dist/Caller.d.ts +391 -0
  6. package/dist/Caller.d.ts.map +1 -0
  7. package/dist/Caller.js +199 -0
  8. package/dist/FileHandle.d.ts +50 -0
  9. package/dist/FileHandle.d.ts.map +1 -0
  10. package/dist/FileHandle.js +28 -0
  11. package/dist/Fixture.d.ts +155 -0
  12. package/dist/Fixture.d.ts.map +1 -0
  13. package/dist/Fixture.js +65 -0
  14. package/dist/LiveVolume.d.ts +13 -20
  15. package/dist/LiveVolume.d.ts.map +1 -1
  16. package/dist/LiveVolume.js +19 -14
  17. package/dist/Metadata.d.ts +186 -0
  18. package/dist/Metadata.d.ts.map +1 -0
  19. package/dist/Metadata.js +125 -0
  20. package/dist/Snapshot.d.ts +32 -53
  21. package/dist/Snapshot.d.ts.map +1 -1
  22. package/dist/Snapshot.js +27 -49
  23. package/dist/SnapshotDelta.d.ts +24 -39
  24. package/dist/SnapshotDelta.d.ts.map +1 -1
  25. package/dist/SnapshotDelta.js +14 -35
  26. package/dist/Target.d.ts +225 -0
  27. package/dist/Target.d.ts.map +1 -0
  28. package/dist/Target.js +92 -0
  29. package/dist/Testing.d.ts +132 -0
  30. package/dist/Testing.d.ts.map +1 -0
  31. package/dist/Testing.js +100 -0
  32. package/dist/VfsError.d.ts +200 -0
  33. package/dist/VfsError.d.ts.map +1 -0
  34. package/dist/VfsError.js +165 -0
  35. package/dist/VirtualFileSystem.d.ts +676 -353
  36. package/dist/VirtualFileSystem.d.ts.map +1 -1
  37. package/dist/VirtualFileSystem.js +487 -121
  38. package/dist/Volume.d.ts +211 -0
  39. package/dist/Volume.d.ts.map +1 -0
  40. package/dist/Volume.js +172 -0
  41. package/dist/Watch.d.ts +68 -0
  42. package/dist/Watch.d.ts.map +1 -0
  43. package/dist/Watch.js +46 -0
  44. package/dist/index.d.ts +56 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +56 -1
  47. package/dist/internal/budget.d.ts +90 -0
  48. package/dist/internal/budget.d.ts.map +1 -0
  49. package/dist/internal/budget.js +70 -0
  50. package/dist/internal/bytePath.d.ts +2 -0
  51. package/dist/internal/bytePath.d.ts.map +1 -1
  52. package/dist/internal/bytePath.js +3 -2
  53. package/dist/internal/bytes.d.ts +3 -0
  54. package/dist/internal/bytes.d.ts.map +1 -1
  55. package/dist/internal/bytes.js +4 -2
  56. package/dist/internal/canonicalBase64.d.ts +1 -4
  57. package/dist/internal/canonicalBase64.d.ts.map +1 -1
  58. package/dist/internal/canonicalBase64.js +9 -13
  59. package/dist/internal/errors.d.ts +47 -5
  60. package/dist/internal/errors.d.ts.map +1 -1
  61. package/dist/internal/errors.js +80 -36
  62. package/dist/internal/fixture.d.ts +2 -2
  63. package/dist/internal/fixture.d.ts.map +1 -1
  64. package/dist/internal/fixture.js +57 -74
  65. package/dist/internal/hex128.d.ts +12 -0
  66. package/dist/internal/hex128.d.ts.map +1 -0
  67. package/dist/internal/hex128.js +7 -0
  68. package/dist/internal/hmac.d.ts +5 -0
  69. package/dist/internal/hmac.d.ts.map +1 -0
  70. package/dist/internal/hmac.js +150 -0
  71. package/dist/internal/image.d.ts +14 -117
  72. package/dist/internal/image.d.ts.map +1 -1
  73. package/dist/internal/image.js +137 -167
  74. package/dist/internal/inodeTable.d.ts +20 -0
  75. package/dist/internal/inodeTable.d.ts.map +1 -0
  76. package/dist/internal/inodeTable.js +48 -0
  77. package/dist/internal/lines.d.ts +36 -0
  78. package/dist/internal/lines.d.ts.map +1 -0
  79. package/dist/internal/lines.js +115 -0
  80. package/dist/internal/liveImage.d.ts +19 -278
  81. package/dist/internal/liveImage.d.ts.map +1 -1
  82. package/dist/internal/liveImage.js +75 -166
  83. package/dist/internal/merkle.d.ts +45 -0
  84. package/dist/internal/merkle.d.ts.map +1 -0
  85. package/dist/internal/merkle.js +179 -0
  86. package/dist/internal/metadata.d.ts +2 -13
  87. package/dist/internal/metadata.d.ts.map +1 -1
  88. package/dist/internal/metadata.js +5 -15
  89. package/dist/internal/overlayDiff.d.ts +2 -2
  90. package/dist/internal/overlayDiff.d.ts.map +1 -1
  91. package/dist/internal/overlayDiff.js +4 -15
  92. package/dist/internal/path.d.ts +17 -5
  93. package/dist/internal/path.d.ts.map +1 -1
  94. package/dist/internal/path.js +38 -24
  95. package/dist/internal/snapshotDelta.d.ts +61 -60
  96. package/dist/internal/snapshotDelta.d.ts.map +1 -1
  97. package/dist/internal/snapshotDelta.js +605 -503
  98. package/dist/internal/snapshotDeltaModel.d.ts.map +1 -1
  99. package/dist/internal/snapshotDeltaModel.js +0 -1
  100. package/dist/internal/testSeams.d.ts +17 -0
  101. package/dist/internal/testSeams.d.ts.map +1 -0
  102. package/dist/internal/testSeams.js +20 -0
  103. package/dist/internal/tree.d.ts +225 -0
  104. package/dist/internal/tree.d.ts.map +1 -0
  105. package/dist/internal/tree.js +385 -0
  106. package/dist/internal/turnstile.d.ts +8 -0
  107. package/dist/internal/turnstile.d.ts.map +1 -0
  108. package/dist/internal/turnstile.js +43 -0
  109. package/dist/internal/virtualFileSystem.d.ts +44 -488
  110. package/dist/internal/virtualFileSystem.d.ts.map +1 -1
  111. package/dist/internal/virtualFileSystem.js +2111 -2466
  112. package/dist/internal/volumeState.d.ts +111 -0
  113. package/dist/internal/volumeState.d.ts.map +1 -0
  114. package/dist/internal/volumeState.js +202 -0
  115. package/dist/internal/watchHub.d.ts +15 -6
  116. package/dist/internal/watchHub.d.ts.map +1 -1
  117. package/dist/internal/watchHub.js +56 -42
  118. package/package.json +54 -10
  119. package/dist/VirtualFileSystemError.d.ts +0 -54
  120. package/dist/VirtualFileSystemError.d.ts.map +0 -1
  121. package/dist/VirtualFileSystemError.js +0 -49
  122. package/dist/internal/overlayContent.d.ts +0 -15
  123. package/dist/internal/overlayContent.d.ts.map +0 -1
  124. package/dist/internal/overlayContent.js +0 -29
  125. package/dist/internal/stagedState.d.ts +0 -22
  126. package/dist/internal/stagedState.d.ts.map +0 -1
  127. package/dist/internal/stagedState.js +0 -62
  128. package/dist/internal/testHooks.d.ts +0 -20
  129. package/dist/internal/testHooks.d.ts.map +0 -1
  130. package/dist/internal/testHooks.js +0 -23
@@ -1,286 +1,27 @@
1
1
  import * as ByteSize from "effect/ByteSize";
2
2
  import * as Effect from "effect/Effect";
3
- import * as Schema from "effect/Schema";
4
- import { ImageError } from "../Snapshot.js";
3
+ import type { VolumeLimits } from "../VirtualFileSystem.js";
4
+ import type { VolumeIdentity } from "../Volume.js";
5
+ import type { KeySecret, VolumeEpoch } from "./hex128.js";
6
+ import * as Tree from "./tree.js";
7
+ import { type RegularFile, type VolumeState } from "./volumeState.js";
5
8
  /** @internal */
6
- export declare const Record: Schema.TaggedUnion<{
7
- readonly directory: Schema.TaggedStruct<"directory", {
8
- readonly ino: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
9
- readonly revision: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
10
- readonly lineage: Schema.optionalKey<Schema.String>;
11
- readonly metadata: Schema.Struct<{
12
- readonly uid: Schema.Natural;
13
- readonly gid: Schema.Natural;
14
- readonly mode: Schema.Natural;
15
- readonly atimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
16
- readonly mtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
17
- readonly ctimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
18
- readonly birthtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
19
- readonly nlink: Schema.Natural;
20
- readonly size: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
21
- }>;
22
- readonly entries: Schema.$Array<Schema.Struct<{
23
- readonly name: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
24
- readonly target: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
25
- }>>;
26
- }>;
27
- readonly file: Schema.TaggedStruct<"file", {
28
- readonly ino: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
29
- readonly revision: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
30
- readonly lineage: Schema.optionalKey<Schema.String>;
31
- readonly metadata: Schema.Struct<{
32
- readonly uid: Schema.Natural;
33
- readonly gid: Schema.Natural;
34
- readonly mode: Schema.Natural;
35
- readonly atimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
36
- readonly mtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
37
- readonly ctimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
38
- readonly birthtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
39
- readonly nlink: Schema.Natural;
40
- readonly size: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
41
- }>;
42
- readonly data: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
43
- }>;
44
- readonly symlink: Schema.TaggedStruct<"symlink", {
45
- readonly ino: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
46
- readonly revision: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
47
- readonly lineage: Schema.optionalKey<Schema.String>;
48
- readonly metadata: Schema.Struct<{
49
- readonly uid: Schema.Natural;
50
- readonly gid: Schema.Natural;
51
- readonly mode: Schema.Natural;
52
- readonly atimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
53
- readonly mtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
54
- readonly ctimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
55
- readonly birthtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
56
- readonly nlink: Schema.Natural;
57
- readonly size: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
58
- }>;
59
- readonly target: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
60
- }>;
61
- }>;
9
+ export declare const retainedFiles: (state: VolumeState) => Array<RegularFile>;
10
+ type StoredLimits = Tree.Runtime["limits"];
62
11
  /** @internal */
63
- export type Record = typeof Record.Type;
12
+ export interface Naming {
13
+ readonly identity: VolumeIdentity;
14
+ readonly epoch: VolumeEpoch;
15
+ readonly keySecret: KeySecret;
16
+ }
64
17
  /** @internal */
65
- export declare const Document: Schema.Struct<{
66
- readonly format: Schema.Literal<"effect-vfs-live">;
67
- readonly version: Schema.Literal<1>;
68
- readonly identity: Schema.String;
69
- readonly root: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
70
- readonly nextInode: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
71
- readonly revisionCounter: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
72
- readonly entries: Schema.Natural;
73
- readonly usedBytes: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
74
- readonly limits: Schema.Struct<{
75
- readonly maxEntries: Schema.optionalKey<Schema.Natural>;
76
- readonly maxBytes: Schema.optionalKey<Schema.decodeTo<Schema.BigInt, Schema.String, never, never>>;
77
- readonly maxFileBytes: Schema.optionalKey<Schema.decodeTo<Schema.BigInt, Schema.String, never, never>>;
78
- readonly maxPathBytes: Schema.optionalKey<Schema.decodeTo<Schema.BigInt, Schema.String, never, never>>;
79
- }>;
80
- readonly retainedFiles: Schema.$Array<Schema.decodeTo<Schema.BigInt, Schema.String, never, never>>;
81
- readonly records: Schema.$Array<Schema.TaggedUnion<{
82
- readonly directory: Schema.TaggedStruct<"directory", {
83
- readonly ino: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
84
- readonly revision: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
85
- readonly lineage: Schema.optionalKey<Schema.String>;
86
- readonly metadata: Schema.Struct<{
87
- readonly uid: Schema.Natural;
88
- readonly gid: Schema.Natural;
89
- readonly mode: Schema.Natural;
90
- readonly atimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
91
- readonly mtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
92
- readonly ctimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
93
- readonly birthtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
94
- readonly nlink: Schema.Natural;
95
- readonly size: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
96
- }>;
97
- readonly entries: Schema.$Array<Schema.Struct<{
98
- readonly name: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
99
- readonly target: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
100
- }>>;
101
- }>;
102
- readonly file: Schema.TaggedStruct<"file", {
103
- readonly ino: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
104
- readonly revision: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
105
- readonly lineage: Schema.optionalKey<Schema.String>;
106
- readonly metadata: Schema.Struct<{
107
- readonly uid: Schema.Natural;
108
- readonly gid: Schema.Natural;
109
- readonly mode: Schema.Natural;
110
- readonly atimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
111
- readonly mtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
112
- readonly ctimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
113
- readonly birthtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
114
- readonly nlink: Schema.Natural;
115
- readonly size: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
116
- }>;
117
- readonly data: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
118
- }>;
119
- readonly symlink: Schema.TaggedStruct<"symlink", {
120
- readonly ino: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
121
- readonly revision: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
122
- readonly lineage: Schema.optionalKey<Schema.String>;
123
- readonly metadata: Schema.Struct<{
124
- readonly uid: Schema.Natural;
125
- readonly gid: Schema.Natural;
126
- readonly mode: Schema.Natural;
127
- readonly atimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
128
- readonly mtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
129
- readonly ctimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
130
- readonly birthtimeNs: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
131
- readonly nlink: Schema.Natural;
132
- readonly size: Schema.decodeTo<Schema.BigInt, Schema.String, never, never>;
133
- }>;
134
- readonly target: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
135
- }>;
136
- }>>;
137
- }>;
18
+ export interface Restored extends Naming {
19
+ readonly value: VolumeState;
20
+ readonly limits: StoredLimits;
21
+ }
138
22
  /** @internal */
139
- export type Document = typeof Document.Type;
23
+ export declare const encode: (state: VolumeState, args_1: Naming, limits: VolumeLimits) => Effect.Effect<Uint8Array<ArrayBufferLike>, import("../VfsError.js").ImageFailure, never>;
140
24
  /** @internal */
141
- export declare const encode: (document: {
142
- readonly format: "effect-vfs-live";
143
- readonly version: 1;
144
- readonly identity: string;
145
- readonly root: bigint;
146
- readonly nextInode: bigint;
147
- readonly revisionCounter: bigint;
148
- readonly entries: number;
149
- readonly usedBytes: bigint;
150
- readonly limits: {
151
- readonly maxEntries?: number;
152
- readonly maxBytes?: bigint;
153
- readonly maxFileBytes?: bigint;
154
- readonly maxPathBytes?: bigint;
155
- };
156
- readonly retainedFiles: readonly bigint[];
157
- readonly records: readonly ({
158
- readonly _tag: "directory";
159
- readonly ino: bigint;
160
- readonly revision: bigint;
161
- readonly lineage?: string;
162
- readonly metadata: {
163
- readonly uid: number;
164
- readonly gid: number;
165
- readonly mode: number;
166
- readonly atimeNs: bigint;
167
- readonly mtimeNs: bigint;
168
- readonly ctimeNs: bigint;
169
- readonly birthtimeNs: bigint;
170
- readonly nlink: number;
171
- readonly size: bigint;
172
- };
173
- readonly entries: readonly {
174
- readonly name: string & import("effect/Brand").Brand<"CanonicalBase64">;
175
- readonly target: bigint;
176
- }[];
177
- } | {
178
- readonly _tag: "file";
179
- readonly ino: bigint;
180
- readonly revision: bigint;
181
- readonly lineage?: string;
182
- readonly metadata: {
183
- readonly uid: number;
184
- readonly gid: number;
185
- readonly mode: number;
186
- readonly atimeNs: bigint;
187
- readonly mtimeNs: bigint;
188
- readonly ctimeNs: bigint;
189
- readonly birthtimeNs: bigint;
190
- readonly nlink: number;
191
- readonly size: bigint;
192
- };
193
- readonly data: string & import("effect/Brand").Brand<"CanonicalBase64">;
194
- } | {
195
- readonly _tag: "symlink";
196
- readonly ino: bigint;
197
- readonly revision: bigint;
198
- readonly lineage?: string;
199
- readonly metadata: {
200
- readonly uid: number;
201
- readonly gid: number;
202
- readonly mode: number;
203
- readonly atimeNs: bigint;
204
- readonly mtimeNs: bigint;
205
- readonly ctimeNs: bigint;
206
- readonly birthtimeNs: bigint;
207
- readonly nlink: number;
208
- readonly size: bigint;
209
- };
210
- readonly target: string & import("effect/Brand").Brand<"CanonicalBase64">;
211
- })[];
212
- }) => Effect.Effect<Uint8Array<ArrayBuffer>, ImageError, never>;
213
- /** @internal */
214
- export declare const decode: (bytes: Uint8Array<ArrayBufferLike>, maxEncodedBytes: ByteSize.ByteSize) => Effect.Effect<{
215
- readonly format: "effect-vfs-live";
216
- readonly version: 1;
217
- readonly identity: string;
218
- readonly root: bigint;
219
- readonly nextInode: bigint;
220
- readonly revisionCounter: bigint;
221
- readonly entries: number;
222
- readonly usedBytes: bigint;
223
- readonly limits: {
224
- readonly maxEntries?: number;
225
- readonly maxBytes?: bigint;
226
- readonly maxFileBytes?: bigint;
227
- readonly maxPathBytes?: bigint;
228
- };
229
- readonly retainedFiles: readonly bigint[];
230
- readonly records: readonly ({
231
- readonly _tag: "directory";
232
- readonly ino: bigint;
233
- readonly revision: bigint;
234
- readonly lineage?: string;
235
- readonly metadata: {
236
- readonly uid: number;
237
- readonly gid: number;
238
- readonly mode: number;
239
- readonly atimeNs: bigint;
240
- readonly mtimeNs: bigint;
241
- readonly ctimeNs: bigint;
242
- readonly birthtimeNs: bigint;
243
- readonly nlink: number;
244
- readonly size: bigint;
245
- };
246
- readonly entries: readonly {
247
- readonly name: string & import("effect/Brand").Brand<"CanonicalBase64">;
248
- readonly target: bigint;
249
- }[];
250
- } | {
251
- readonly _tag: "file";
252
- readonly ino: bigint;
253
- readonly revision: bigint;
254
- readonly lineage?: string;
255
- readonly metadata: {
256
- readonly uid: number;
257
- readonly gid: number;
258
- readonly mode: number;
259
- readonly atimeNs: bigint;
260
- readonly mtimeNs: bigint;
261
- readonly ctimeNs: bigint;
262
- readonly birthtimeNs: bigint;
263
- readonly nlink: number;
264
- readonly size: bigint;
265
- };
266
- readonly data: string & import("effect/Brand").Brand<"CanonicalBase64">;
267
- } | {
268
- readonly _tag: "symlink";
269
- readonly ino: bigint;
270
- readonly revision: bigint;
271
- readonly lineage?: string;
272
- readonly metadata: {
273
- readonly uid: number;
274
- readonly gid: number;
275
- readonly mode: number;
276
- readonly atimeNs: bigint;
277
- readonly mtimeNs: bigint;
278
- readonly ctimeNs: bigint;
279
- readonly birthtimeNs: bigint;
280
- readonly nlink: number;
281
- readonly size: bigint;
282
- };
283
- readonly target: string & import("effect/Brand").Brand<"CanonicalBase64">;
284
- })[];
285
- }, ImageError, never>;
25
+ export declare const decode: (bytes: Uint8Array, maxEncodedBytes: ByteSize.ByteSize) => Effect.Effect<Restored, import("../VfsError.js").ImageFailure, never>;
26
+ export {};
286
27
  //# sourceMappingURL=liveImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"liveImage.d.ts","sourceRoot":"","sources":["../../src/internal/liveImage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAmB3C,gBAAgB;AAChB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOjB,CAAA;AAEF,gBAAgB;AAChB,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC,gBAAgB;AAChB,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBnB,CAAA;AAEF,gBAAgB;AAChB,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAgI3C,gBAAgB;AAChB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DAMjB,CAAA;AAEF,gBAAgB;AAChB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAuBjB,CAAA"}
1
+ {"version":3,"file":"liveImage.d.ts","sourceRoot":"","sources":["../../src/internal/liveImage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAIvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAqC,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAKxG,gBAAgB;AAChB,eAAO,MAAM,aAAa,UAAW,WAAW,KAAG,KAAK,CAAC,WAAW,CAUnE,CAAA;AAED,KAAK,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE1C,gBAAgB;AAChB,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;CAC9B;AAED,gBAAgB;AAChB,MAAM,WAAW,QAAS,SAAQ,MAAM;IACtC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAC9B;AAQD,gBAAgB;AAChB,eAAO,MAAM,MAAM,wJAwCjB,CAAA;AAWF,gBAAgB;AAChB,eAAO,MAAM,MAAM,UAAW,UAAU,mBAAmB,QAAQ,CAAC,QAAQ,0EAyBzE,CAAA"}
@@ -1,176 +1,85 @@
1
- // Private, versioned image for a live volume. Unlike a public snapshot, this
2
- // retains inode numbers, revisions, allocator state, and open unlinked files.
1
+ // Live images persist runtime identity and revisions along with the tree, including unlinked open files.
3
2
  import * as ByteSize from "effect/ByteSize";
4
3
  import * as Effect from "effect/Effect";
5
4
  import * as Result from "effect/Result";
6
5
  import * as Schema from "effect/Schema";
7
- import * as SchemaTransformation from "effect/SchemaTransformation";
8
- import { ImageError } from "../Snapshot.js";
9
- import { CanonicalBase64 } from "./canonicalBase64.js";
10
- import { StoredMetadata } from "./metadata.js";
11
- const NaturalBigInt = Schema.String.check(Schema.isPattern(/^(0|[1-9][0-9]{0,127})$/)).pipe(Schema.decodeTo(Schema.BigInt, SchemaTransformation.bigintFromString));
12
- const Common = {
13
- ino: NaturalBigInt,
14
- revision: NaturalBigInt,
15
- lineage: Schema.optionalKey(Schema.String),
16
- metadata: Schema.Struct({
17
- ...StoredMetadata.fields,
18
- nlink: Schema.Natural,
19
- size: NaturalBigInt
20
- })
21
- };
22
- /** @internal */
23
- export const Record = Schema.TaggedUnion({
24
- directory: {
25
- ...Common,
26
- entries: Schema.Array(Schema.Struct({ name: CanonicalBase64.Encoded, target: NaturalBigInt }))
27
- },
28
- file: { ...Common, data: CanonicalBase64.Encoded },
29
- symlink: { ...Common, target: CanonicalBase64.Encoded }
30
- });
6
+ import * as Stream from "effect/Stream";
7
+ import * as Lines from "./lines.js";
8
+ import * as Tree from "./tree.js";
9
+ import { assemble, getNode, Ino } from "./volumeState.js";
10
+ const OPERATION = "openImage";
11
+ const DOCUMENT_FIELD = "liveImage";
31
12
  /** @internal */
32
- export const Document = Schema.Struct({
33
- format: Schema.Literal("effect-vfs-live"),
34
- version: Schema.Literal(1),
35
- identity: Schema.String.check(Schema.isPattern(/^[0-9a-f]{32}$/)),
36
- root: NaturalBigInt,
37
- nextInode: NaturalBigInt,
38
- revisionCounter: NaturalBigInt,
39
- entries: Schema.Natural,
40
- usedBytes: NaturalBigInt,
41
- limits: Schema.Struct({
42
- maxEntries: Schema.optionalKey(Schema.Natural),
43
- maxBytes: Schema.optionalKey(NaturalBigInt),
44
- maxFileBytes: Schema.optionalKey(NaturalBigInt),
45
- maxPathBytes: Schema.optionalKey(NaturalBigInt)
46
- }),
47
- retainedFiles: Schema.Array(NaturalBigInt),
48
- records: Schema.Array(Record)
49
- });
50
- const invalid = () => new ImageError({ code: "InvalidStructure", field: "liveImage" });
51
- const validate = Effect.fnUntraced(function* (document) {
52
- const records = new Map();
53
- for (const record of document.records) {
54
- if (record.ino < 1n || records.has(record.ino) || record.revision < 1n ||
55
- record.revision > document.revisionCounter || record.ino >= document.nextInode)
56
- return yield* invalid();
57
- records.set(record.ino, record);
58
- }
59
- const root = records.get(document.root);
60
- if (document.root !== 1n || root?._tag !== "directory" || document.revisionCounter < 1n) {
61
- return yield* invalid();
13
+ export const retainedFiles = (state) => {
14
+ const retained = [];
15
+ for (const ino of state.open.keys()) {
16
+ const node = getNode(state, ino);
17
+ if (node?.kind === "file" && node.links.length === 0)
18
+ retained.push(node);
62
19
  }
63
- const links = new Map();
64
- const pending = [[root, 1n]];
65
- const seenDirectories = new Set();
66
- const reachable = new Set();
67
- let entries = 0;
68
- for (let index = 0; index < pending.length; index++) {
69
- const current = pending[index];
70
- if (current === undefined)
71
- return yield* invalid();
72
- const [directory, pathBytes] = current;
73
- if (seenDirectories.has(directory.ino))
74
- return yield* invalid();
75
- seenDirectories.add(directory.ino);
76
- reachable.add(directory.ino);
77
- const names = new Set();
78
- for (const entry of directory.entries) {
79
- if (names.has(entry.name) || entry.target === document.root)
80
- return yield* invalid();
81
- names.add(entry.name);
82
- const name = yield* CanonicalBase64.decode(entry.name);
83
- if (name.length < 1 || name.length > 255 || name.includes(0) || name.includes(47) ||
84
- (name.length === 1 && name[0] === 46) ||
85
- (name.length === 2 && name[0] === 46 && name[1] === 46))
86
- return yield* invalid();
87
- const childPathBytes = pathBytes + BigInt(name.length) + (pathBytes === 1n ? 0n : 1n);
88
- if (document.limits.maxPathBytes !== undefined && childPathBytes > document.limits.maxPathBytes) {
89
- return yield* invalid();
90
- }
91
- const target = records.get(entry.target);
92
- if (target === undefined)
93
- return yield* invalid();
94
- entries++;
95
- links.set(target.ino, (links.get(target.ino) ?? 0) + 1);
96
- reachable.add(target.ino);
97
- if (Record.guards.directory(target))
98
- pending.push([target, childPathBytes]);
99
- }
100
- }
101
- if (entries !== document.entries || links.has(root.ino))
102
- return yield* invalid();
103
- const retained = new Set(document.retainedFiles);
104
- if (retained.size !== document.retainedFiles.length)
105
- return yield* invalid();
106
- let usedBytes = 0n;
107
- for (const record of document.records) {
108
- const actualLinks = links.get(record.ino) ?? 0;
109
- if (Record.guards.directory(record)) {
110
- const childDirectories = record.entries.filter((entry) => {
111
- const child = records.get(entry.target);
112
- return child !== undefined && Record.guards.directory(child);
113
- }).length;
114
- if (!seenDirectories.has(record.ino) || (record.ino !== root.ino && actualLinks !== 1) ||
115
- record.metadata.nlink !== 2 + childDirectories || record.metadata.size !== 0n)
116
- return yield* invalid();
117
- }
118
- else {
119
- const payload = Record.guards.file(record) ? record.data : record.target;
120
- const length = BigInt(CanonicalBase64.decodedLength(payload));
121
- if (record.metadata.size !== length || record.metadata.nlink !== actualLinks)
122
- return yield* invalid();
123
- if (Record.guards.file(record)) {
124
- if (document.limits.maxFileBytes !== undefined && length > document.limits.maxFileBytes) {
125
- return yield* invalid();
126
- }
127
- if (actualLinks === 0 && !retained.has(record.ino))
128
- return yield* invalid();
129
- if (actualLinks > 0 && retained.has(record.ino))
130
- return yield* invalid();
131
- }
132
- else {
133
- if (actualLinks === 0 || retained.has(record.ino) || (yield* CanonicalBase64.decode(record.target)).includes(0)) {
134
- return yield* invalid();
135
- }
136
- }
137
- usedBytes += length;
20
+ return retained;
21
+ };
22
+ const headerText = Schema.encodeResult(Schema.fromJsonString(Tree.LiveHeader));
23
+ const nodeText = Schema.encodeResult(Schema.fromJsonString(Tree.LiveTreeNode));
24
+ const liveNode = (node) => ({ ...Tree.treeNode(node), rev: node.revision });
25
+ /** @internal */
26
+ export const encode = Effect.fnUntraced(function* (state, { epoch, identity, keySecret }, limits) {
27
+ const nodes = yield* Tree.treeNodes(state, retainedFiles(state));
28
+ const stored = {};
29
+ if (limits.maxEntries !== undefined)
30
+ stored.maxEntries = limits.maxEntries;
31
+ if (limits.maxBytes !== undefined)
32
+ stored.maxBytes = ByteSize.toBigInt(limits.maxBytes);
33
+ stored.maxFileBytes = ByteSize.toBigInt(limits.maxFileBytes);
34
+ if (limits.maxPathBytes !== undefined)
35
+ stored.maxPathBytes = ByteSize.toBigInt(limits.maxPathBytes);
36
+ const header = yield* Effect.fromResult(headerText({
37
+ format: "effect-vfs-live",
38
+ version: 1,
39
+ runtime: {
40
+ identity,
41
+ epoch,
42
+ keySecret,
43
+ nextInode: state.nextInode,
44
+ revision: state.revision,
45
+ limits: stored,
46
+ usage: { entries: state.entries, usedBytes: state.usedBytes }
138
47
  }
139
- if (!reachable.has(record.ino) && !retained.has(record.ino))
140
- return yield* invalid();
141
- }
142
- if (document.limits.maxPathBytes !== undefined && document.limits.maxPathBytes < 1n)
143
- return yield* invalid();
144
- if (usedBytes !== document.usedBytes ||
145
- (document.limits.maxEntries !== undefined && entries > document.limits.maxEntries) ||
146
- (document.limits.maxBytes !== undefined && usedBytes > document.limits.maxBytes))
147
- return yield* invalid();
148
- for (const ino of retained) {
149
- if (records.get(ino)?._tag !== "file" || reachable.has(ino))
150
- return yield* invalid();
151
- }
152
- return document;
48
+ })).pipe(Effect.mapError((cause) => Tree.encodeFailure(OPERATION, DOCUMENT_FIELD, cause)));
49
+ return yield* Lines.collect(Tree.writeTree({
50
+ operation: OPERATION,
51
+ documentField: DOCUMENT_FIELD,
52
+ header,
53
+ node: liveNode,
54
+ text: nodeText,
55
+ meter: undefined
56
+ }, nodes));
153
57
  });
154
- /** @internal */
155
- export const encode = Effect.fnUntraced(function* (document) {
156
- const text = yield* Schema.encodeEffect(Schema.fromJsonString(Document))(yield* validate(document)).pipe(Effect.mapError(() => new ImageError({ code: "InvalidStructure", field: "liveImage" })));
157
- return new TextEncoder().encode(text);
58
+ // The store's byte bound covers this whole image; no separate decode budget is needed.
59
+ const imageBudget = (maxEncodedBytes) => ({
60
+ encodedBytes: maxEncodedBytes,
61
+ lineBytes: maxEncodedBytes,
62
+ decodedBytes: maxEncodedBytes,
63
+ records: Number.MAX_SAFE_INTEGER,
64
+ entries: Number.MAX_SAFE_INTEGER
158
65
  });
159
66
  /** @internal */
160
- export const decode = Effect.fnUntraced(function* (bytes, maxEncodedBytes) {
161
- if (!(bytes instanceof Uint8Array) || !(bytes.buffer instanceof ArrayBuffer)) {
162
- return yield* new ImageError({ code: "InvalidEncoding", field: "liveImage" });
163
- }
164
- if (ByteSize.isGreaterThan(ByteSize.bytes(bytes.byteLength), maxEncodedBytes)) {
165
- return yield* new ImageError({ code: "LimitExceeded", field: "encodedBytes" });
166
- }
167
- const text = yield* Effect.try({
168
- try: () => new TextDecoder("utf-8", { fatal: true }).decode(new Uint8Array(bytes)),
169
- catch: () => new ImageError({ code: "InvalidEncoding", field: "liveImage" })
170
- });
171
- const parsed = yield* Schema.decodeEffect(Schema.fromJsonString(Schema.Unknown))(text).pipe(Effect.mapError(() => new ImageError({ code: "InvalidEncoding", field: "liveImage" })));
172
- const document = Schema.decodeUnknownResult(Document, { onExcessProperty: "error" })(parsed);
173
- if (Result.isFailure(document))
174
- return yield* new ImageError({ code: "InvalidStructure", field: "liveImage" });
175
- return yield* validate(document.success);
176
- });
67
+ export const decode = (bytes, maxEncodedBytes) => Stream.run(Stream.succeed(bytes), Lines.sink({ operation: OPERATION, inputField: DOCUMENT_FIELD, textField: DOCUMENT_FIELD }, () => {
68
+ const reader = Tree.liveReader({ operation: OPERATION, documentField: DOCUMENT_FIELD });
69
+ return {
70
+ meter: Tree.meter(imageBudget(maxEncodedBytes), OPERATION),
71
+ fold: {
72
+ line: reader.line,
73
+ end: () => Result.map(reader.end(), ({ header: { runtime }, specs }) => {
74
+ const value = assemble(specs);
75
+ return {
76
+ value: { ...value, nextInode: Ino(runtime.nextInode), revision: runtime.revision },
77
+ identity: runtime.identity,
78
+ epoch: runtime.epoch,
79
+ keySecret: runtime.keySecret,
80
+ limits: runtime.limits
81
+ };
82
+ })
83
+ }
84
+ };
85
+ }));
@@ -0,0 +1,45 @@
1
+ import * as ByteSize from "effect/ByteSize";
2
+ import * as Crypto from "effect/Crypto";
3
+ import * as Effect from "effect/Effect";
4
+ import type * as PlatformError from "effect/PlatformError";
5
+ import type { ImageFailure } from "../VfsError.js";
6
+ import { type Ino, type Node, type VolumeState } from "./volumeState.js";
7
+ /** @internal */
8
+ export declare const DIGEST_BYTES = 32;
9
+ /** @internal */
10
+ export interface WalkBudget {
11
+ readonly operation: string;
12
+ readonly records: number;
13
+ readonly recordsField: string;
14
+ readonly entries: number;
15
+ readonly identityBytes: ByteSize.ByteSize;
16
+ readonly payloadBytes?: {
17
+ readonly limit: ByteSize.ByteSize;
18
+ readonly field: string;
19
+ };
20
+ }
21
+ /** @internal */
22
+ export interface Identity {
23
+ readonly digest: Uint8Array;
24
+ readonly digests: ReadonlyMap<Ino, Uint8Array>;
25
+ readonly groups: ReadonlyMap<Ino, ReadonlyArray<Uint8Array>>;
26
+ readonly records: number;
27
+ readonly payloadBytes: number;
28
+ readonly nodeBytes: number;
29
+ }
30
+ /** @internal */
31
+ export declare const nodeBytes: (node: Node) => number;
32
+ /** @internal */
33
+ export interface Meter {
34
+ readonly charge: (bytes: number) => Effect.Effect<void, ImageFailure>;
35
+ readonly spent: () => number;
36
+ }
37
+ /** @internal */
38
+ export declare const meter: (budget: WalkBudget) => Meter;
39
+ /** @internal */
40
+ export declare const nodeDigest: (node: Node, childDigest: (ino: Ino) => Uint8Array, meter: Meter) => Effect.Effect<Uint8Array<ArrayBufferLike>, PlatformError.PlatformError | ImageFailure, Crypto.Crypto>;
41
+ /** @internal */
42
+ export declare const identityDigest: (root: Uint8Array<ArrayBufferLike>, groups: Iterable<readonly Uint8Array<ArrayBufferLike>[]>, meter: Meter) => Effect.Effect<Uint8Array<ArrayBufferLike>, PlatformError.PlatformError | ImageFailure, Crypto.Crypto>;
43
+ /** @internal */
44
+ export declare const identify: (state: VolumeState, budget: WalkBudget) => Effect.Effect<Identity, PlatformError.PlatformError | ImageFailure, Crypto.Crypto>;
45
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../../src/internal/merkle.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,aAAa,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAIlD,OAAO,EAAwB,KAAK,GAAG,EAAE,KAAK,IAAI,EAAuB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAGnH,gBAAgB;AAChB,eAAO,MAAM,YAAY,KAAK,CAAA;AAQ9B,gBAAgB;AAChB,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,QAAQ,CAAA;IAEzC,QAAQ,CAAC,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACtF;AAED,gBAAgB;AAChB,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;IAC9C,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,CAAA;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AA4CD,gBAAgB;AAChB,eAAO,MAAM,SAAS,SAAU,IAAI,KAAG,MAA6B,CAAA;AAyBpE,gBAAgB;AAChB,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;IACrE,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAA;CAC7B;AAED,gBAAgB;AAChB,eAAO,MAAM,KAAK,WAAY,UAAU,KAAG,KAc1C,CAAA;AAED,gBAAgB;AAChB,eAAO,MAAM,UAAU,kCAA8D,GAAG,KAAK,UAAU,wHAOrG,CAAA;AAEF,gBAAgB;AAChB,eAAO,MAAM,cAAc,sNAsB1B,CAAA;AAGD,gBAAgB;AAChB,eAAO,MAAM,QAAQ,gIAmGpB,CAAA"}