@effect-vfs/core 0.5.0 → 0.6.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 +34 -31
  2. package/dist/BytePath.d.ts +114 -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 +11 -21
  15. package/dist/LiveVolume.d.ts.map +1 -1
  16. package/dist/LiveVolume.js +17 -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 +31 -53
  21. package/dist/Snapshot.d.ts.map +1 -1
  22. package/dist/Snapshot.js +26 -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 +128 -0
  30. package/dist/Testing.d.ts.map +1 -0
  31. package/dist/Testing.js +111 -0
  32. package/dist/VfsError.d.ts +199 -0
  33. package/dist/VfsError.d.ts.map +1 -0
  34. package/dist/VfsError.js +164 -0
  35. package/dist/VirtualFileSystem.d.ts +628 -347
  36. package/dist/VirtualFileSystem.d.ts.map +1 -1
  37. package/dist/VirtualFileSystem.js +448 -115
  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 +0 -3
  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 +612 -504
  98. package/dist/internal/snapshotDeltaModel.d.ts.map +1 -1
  99. package/dist/internal/snapshotDeltaModel.js +0 -1
  100. package/dist/internal/stagedState.d.ts +11 -15
  101. package/dist/internal/stagedState.d.ts.map +1 -1
  102. package/dist/internal/stagedState.js +15 -59
  103. package/dist/internal/testSeams.d.ts +17 -0
  104. package/dist/internal/testSeams.d.ts.map +1 -0
  105. package/dist/internal/testSeams.js +20 -0
  106. package/dist/internal/tree.d.ts +225 -0
  107. package/dist/internal/tree.d.ts.map +1 -0
  108. package/dist/internal/tree.js +385 -0
  109. package/dist/internal/turnstile.d.ts +8 -0
  110. package/dist/internal/turnstile.d.ts.map +1 -0
  111. package/dist/internal/turnstile.js +43 -0
  112. package/dist/internal/virtualFileSystem.d.ts +39 -489
  113. package/dist/internal/virtualFileSystem.d.ts.map +1 -1
  114. package/dist/internal/virtualFileSystem.js +2112 -2465
  115. package/dist/internal/volumeState.d.ts +110 -0
  116. package/dist/internal/volumeState.d.ts.map +1 -0
  117. package/dist/internal/volumeState.js +204 -0
  118. package/dist/internal/watchHub.d.ts +15 -6
  119. package/dist/internal/watchHub.d.ts.map +1 -1
  120. package/dist/internal/watchHub.js +56 -42
  121. package/package.json +48 -4
  122. package/dist/VirtualFileSystemError.d.ts +0 -54
  123. package/dist/VirtualFileSystemError.d.ts.map +0 -1
  124. package/dist/VirtualFileSystemError.js +0 -49
  125. package/dist/internal/overlayContent.d.ts +0 -15
  126. package/dist/internal/overlayContent.d.ts.map +0 -1
  127. package/dist/internal/overlayContent.js +0 -29
  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
@@ -0,0 +1,90 @@
1
+ import * as Schema from "effect/Schema";
2
+ /** @internal */
3
+ export declare const Budget: Schema.Struct<{
4
+ readonly encodedBytes: Schema.ByteSize;
5
+ readonly records: Schema.Natural;
6
+ readonly entries: Schema.Natural;
7
+ readonly decodedBytes: Schema.ByteSize;
8
+ readonly lineBytes: Schema.ByteSize;
9
+ }>;
10
+ /** @internal */
11
+ export type Budget = typeof Budget.Type;
12
+ /** @internal */
13
+ export declare const DeltaBudget: Schema.Struct<{
14
+ readonly encodedBytes: Schema.ByteSize;
15
+ readonly records: Schema.Natural;
16
+ readonly entries: Schema.Natural;
17
+ readonly decodedBytes: Schema.ByteSize;
18
+ readonly identityBytes: Schema.ByteSize;
19
+ readonly baseRecords: Schema.Natural;
20
+ readonly targetRecords: Schema.Natural;
21
+ readonly outputRecords: Schema.Natural;
22
+ readonly outputBytes: Schema.ByteSize;
23
+ readonly inheritedRecords: Schema.Natural;
24
+ }>;
25
+ /** @internal */
26
+ export type DeltaBudget = typeof DeltaBudget.Type;
27
+ /** @internal */
28
+ export declare const BudgetFromDecodeLimits: Schema.decodeTo<Schema.Struct<{
29
+ readonly encodedBytes: Schema.ByteSize;
30
+ readonly records: Schema.Natural;
31
+ readonly entries: Schema.Natural;
32
+ readonly decodedBytes: Schema.ByteSize;
33
+ readonly lineBytes: Schema.ByteSize;
34
+ }>, Schema.Struct<{
35
+ readonly maxEncodedBytes: Schema.ByteSize;
36
+ readonly maxRecords: Schema.Natural;
37
+ readonly maxEntries: Schema.Natural;
38
+ readonly maxDecodedBytes: Schema.ByteSize;
39
+ readonly maxLineBytes: Schema.optionalKey<Schema.ByteSize>;
40
+ }>, never, never>;
41
+ /** @internal */
42
+ export declare const DeltaBudgetFromLimits: Schema.decodeTo<Schema.Struct<{
43
+ readonly encodedBytes: Schema.ByteSize;
44
+ readonly records: Schema.Natural;
45
+ readonly entries: Schema.Natural;
46
+ readonly decodedBytes: Schema.ByteSize;
47
+ readonly identityBytes: Schema.ByteSize;
48
+ readonly baseRecords: Schema.Natural;
49
+ readonly targetRecords: Schema.Natural;
50
+ readonly outputRecords: Schema.Natural;
51
+ readonly outputBytes: Schema.ByteSize;
52
+ readonly inheritedRecords: Schema.Natural;
53
+ }>, Schema.Struct<{
54
+ readonly maxEncodedBytes: Schema.ByteSize;
55
+ readonly maxIdentityBytes: Schema.ByteSize;
56
+ readonly maxDeltaRecords: Schema.Natural;
57
+ readonly maxDecodedDeltaBytes: Schema.ByteSize;
58
+ readonly maxBaseRecords: Schema.Natural;
59
+ readonly maxTargetRecords: Schema.Natural;
60
+ readonly maxEntries: Schema.Natural;
61
+ readonly maxOutputRecords: Schema.Natural;
62
+ readonly maxOutputBytes: Schema.ByteSize;
63
+ readonly maxInheritedRecords: Schema.Natural;
64
+ }> & {
65
+ constrained: {
66
+ readonly maxEncodedBytes: import("effect/ByteSize").ByteSize;
67
+ readonly maxIdentityBytes: import("effect/ByteSize").ByteSize;
68
+ readonly maxDeltaRecords: number;
69
+ readonly maxDecodedDeltaBytes: import("effect/ByteSize").ByteSize;
70
+ readonly maxBaseRecords: number;
71
+ readonly maxTargetRecords: number;
72
+ readonly maxEntries: number;
73
+ readonly maxOutputRecords: number;
74
+ readonly maxOutputBytes: import("effect/ByteSize").ByteSize;
75
+ readonly maxInheritedRecords: number;
76
+ };
77
+ default: {
78
+ readonly maxEncodedBytes: import("effect/ByteSize").ByteSize;
79
+ readonly maxIdentityBytes: import("effect/ByteSize").ByteSize;
80
+ readonly maxDeltaRecords: number;
81
+ readonly maxDecodedDeltaBytes: import("effect/ByteSize").ByteSize;
82
+ readonly maxBaseRecords: number;
83
+ readonly maxTargetRecords: number;
84
+ readonly maxEntries: number;
85
+ readonly maxOutputRecords: number;
86
+ readonly maxOutputBytes: import("effect/ByteSize").ByteSize;
87
+ readonly maxInheritedRecords: number;
88
+ };
89
+ }, never, never>;
90
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/internal/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAYvC,gBAAgB;AAChB,eAAO,MAAM,MAAM;;;;;;EAGjB,CAAA;AAEF,gBAAgB;AAChB,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC,gBAAgB;AAChB,eAAO,MAAM,WAAW;;;;;;;;;;;EAQtB,CAAA;AAEF,gBAAgB;AAChB,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD,gBAAgB;AAChB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;iBAmBjC,CAAA;AAEF,gBAAgB;AAChB,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA4BhC,CAAA"}
@@ -0,0 +1,70 @@
1
+ import * as Schema from "effect/Schema";
2
+ import * as SchemaTransformation from "effect/SchemaTransformation";
3
+ import { DecodeLimits } from "../Snapshot.js";
4
+ import { SnapshotDeltaLimits } from "../SnapshotDelta.js";
5
+ const documentFields = {
6
+ encodedBytes: Schema.ByteSize,
7
+ records: Schema.Natural,
8
+ entries: Schema.Natural,
9
+ decodedBytes: Schema.ByteSize
10
+ };
11
+ /** @internal */
12
+ export const Budget = Schema.Struct({
13
+ ...documentFields,
14
+ lineBytes: Schema.ByteSize
15
+ });
16
+ /** @internal */
17
+ export const DeltaBudget = Schema.Struct({
18
+ ...documentFields,
19
+ identityBytes: Schema.ByteSize,
20
+ baseRecords: Schema.Natural,
21
+ targetRecords: Schema.Natural,
22
+ outputRecords: Schema.Natural,
23
+ outputBytes: Schema.ByteSize,
24
+ inheritedRecords: Schema.Natural
25
+ });
26
+ /** @internal */
27
+ export const BudgetFromDecodeLimits = DecodeLimits.pipe(Schema.decodeTo(Budget, SchemaTransformation.transform({
28
+ decode: (limits) => ({
29
+ encodedBytes: limits.maxEncodedBytes,
30
+ records: limits.maxRecords,
31
+ entries: limits.maxEntries,
32
+ decodedBytes: limits.maxDecodedBytes,
33
+ // The encoded input bounds any line when maxLineBytes is absent.
34
+ lineBytes: limits.maxLineBytes ?? limits.maxEncodedBytes
35
+ }),
36
+ encode: (budget) => ({
37
+ maxEncodedBytes: budget.encodedBytes,
38
+ maxRecords: budget.records,
39
+ maxEntries: budget.entries,
40
+ maxDecodedBytes: budget.decodedBytes,
41
+ maxLineBytes: budget.lineBytes
42
+ })
43
+ })));
44
+ /** @internal */
45
+ export const DeltaBudgetFromLimits = SnapshotDeltaLimits.pipe(Schema.decodeTo(DeltaBudget, SchemaTransformation.transform({
46
+ decode: (limits) => ({
47
+ encodedBytes: limits.maxEncodedBytes,
48
+ records: limits.maxDeltaRecords,
49
+ entries: limits.maxEntries,
50
+ decodedBytes: limits.maxDecodedDeltaBytes,
51
+ identityBytes: limits.maxIdentityBytes,
52
+ baseRecords: limits.maxBaseRecords,
53
+ targetRecords: limits.maxTargetRecords,
54
+ outputRecords: limits.maxOutputRecords,
55
+ outputBytes: limits.maxOutputBytes,
56
+ inheritedRecords: limits.maxInheritedRecords
57
+ }),
58
+ encode: (budget) => ({
59
+ maxEncodedBytes: budget.encodedBytes,
60
+ maxIdentityBytes: budget.identityBytes,
61
+ maxDeltaRecords: budget.records,
62
+ maxDecodedDeltaBytes: budget.decodedBytes,
63
+ maxBaseRecords: budget.baseRecords,
64
+ maxTargetRecords: budget.targetRecords,
65
+ maxEntries: budget.entries,
66
+ maxOutputRecords: budget.outputRecords,
67
+ maxOutputBytes: budget.outputBytes,
68
+ maxInheritedRecords: budget.inheritedRecords
69
+ })
70
+ })));
@@ -4,6 +4,8 @@ export declare const BytePathId: "@effect-vfs/core/BytePath";
4
4
  /** @internal */
5
5
  export declare const isBytePath: (value: unknown) => value is BytePath;
6
6
  /** @internal */
7
+ export declare const isPathBytes: (bytes: Uint8Array) => boolean;
8
+ /** @internal */
7
9
  export declare const make: (bytes: Uint8Array) => BytePath;
8
10
  /** @internal */
9
11
  export declare const getBytes: (path: BytePath) => Uint8Array | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"bytePath.d.ts","sourceRoot":"","sources":["../../src/internal/bytePath.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAG9C,gBAAgB;AAChB,eAAO,MAAM,UAAU,EAAG,2BAAoC,CAAA;AA6B9D,gBAAgB;AAChB,eAAO,MAAM,UAAU,UAAW,OAAO,KAAG,KAAK,IAAI,QAA6D,CAAA;AAElH,gBAAgB;AAChB,eAAO,MAAM,IAAI,UAAW,UAAU,KAAG,QAMxC,CAAA;AAED,gBAAgB;AAChB,eAAO,MAAM,QAAQ,SAAU,QAAQ,KAAG,UAAU,GAAG,SAAgC,CAAA"}
1
+ {"version":3,"file":"bytePath.d.ts","sourceRoot":"","sources":["../../src/internal/bytePath.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAG9C,gBAAgB;AAChB,eAAO,MAAM,UAAU,EAAG,2BAAoC,CAAA;AA6B9D,gBAAgB;AAChB,eAAO,MAAM,UAAU,UAAW,OAAO,KAAG,KAAK,IAAI,QAA6D,CAAA;AAElH,gBAAgB;AAChB,eAAO,MAAM,WAAW,UAAW,UAAU,KAAG,OAAiD,CAAA;AAEjG,gBAAgB;AAChB,eAAO,MAAM,IAAI,UAAW,UAAU,KAAG,QAMxC,CAAA;AAED,gBAAgB;AAChB,eAAO,MAAM,QAAQ,SAAU,QAAQ,KAAG,UAAU,GAAG,SAAgC,CAAA"}
@@ -1,4 +1,3 @@
1
- // Opaque byte path representation and value protocols.
2
1
  import * as Equal from "effect/Equal";
3
2
  import * as Hash from "effect/Hash";
4
3
  import { pipeArguments } from "effect/Pipeable";
@@ -31,8 +30,10 @@ const BytePathProto = {
31
30
  /** @internal */
32
31
  export const isBytePath = (value) => Predicate.isObject(value) && bytePaths.has(value);
33
32
  /** @internal */
33
+ export const isPathBytes = (bytes) => bytes.length > 0 && !bytes.includes(0);
34
+ /** @internal */
34
35
  export const make = (bytes) => {
35
- // SAFETY: BytePathProto implements every member of the opaque BytePath contract.
36
+ // SAFETY: BytePathProto implements the opaque BytePath contract.
36
37
  const path = Object.create(BytePathProto);
37
38
  bytePaths.set(path, bytes);
38
39
  return Object.freeze(path);
@@ -1,6 +1,9 @@
1
+ import * as Effect from "effect/Effect";
1
2
  import * as Order from "effect/Order";
2
3
  /** @internal */
3
4
  export declare const bytesOrder: Order.Order<Uint8Array>;
4
5
  /** @internal */
5
6
  export declare const sameBytes: (left: Uint8Array | undefined, right: Uint8Array | undefined) => boolean;
7
+ /** @internal */
8
+ export declare const decodeUtf8: <E>(bytes: Uint8Array, onInvalid: (cause: unknown) => E) => Effect.Effect<string, E>;
6
9
  //# sourceMappingURL=bytes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/internal/bytes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAerC,gBAAgB;AAChB,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAA4B,CAAA;AAG3E,gBAAgB;AAChB,eAAO,MAAM,SAAS,SAAU,UAAU,GAAG,SAAS,SAAS,UAAU,GAAG,SAAS,KAAG,OACU,CAAA"}
1
+ {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/internal/bytes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAerC,gBAAgB;AAChB,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAA4B,CAAA;AAE3E,gBAAgB;AAChB,eAAO,MAAM,SAAS,SAAU,UAAU,GAAG,SAAS,SAAS,UAAU,GAAG,SAAS,KAAG,OACU,CAAA;AAGlG,gBAAgB;AAChB,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,UAAU,aAAa,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CACW,CAAA"}
@@ -1,4 +1,4 @@
1
- // Byte-array comparison shared by the overlay diff, the snapshot delta, and BytePath equality.
1
+ import * as Effect from "effect/Effect";
2
2
  import * as Order from "effect/Order";
3
3
  const compareBytes = (left, right) => {
4
4
  const length = Math.min(left.length, right.length);
@@ -12,6 +12,8 @@ const compareBytes = (left, right) => {
12
12
  };
13
13
  /** @internal */
14
14
  export const bytesOrder = Order.make(compareBytes);
15
- // A plain loop: Equal.equals would hash both arrays and memoise the pair in a WeakMap first.
16
15
  /** @internal */
17
16
  export const sameBytes = (left, right) => left === right || (left !== undefined && right !== undefined && compareBytes(left, right) === 0);
17
+ // Copy the input to prevent a shared buffer changing during decoding.
18
+ /** @internal */
19
+ export const decodeUtf8 = (bytes, onInvalid) => Effect.try({ try: () => new TextDecoder("utf-8", { fatal: true }).decode(new Uint8Array(bytes)), catch: onInvalid });
@@ -1,15 +1,12 @@
1
- import * as Effect from "effect/Effect";
2
1
  import * as Schema from "effect/Schema";
3
2
  declare const Encoded: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
4
3
  type Encoded = typeof Encoded.Type;
5
4
  /** @internal */
6
5
  export declare const CanonicalBase64: {
7
6
  Encoded: Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">;
8
- Bytes: Schema.decodeTo<Schema.Uint8Array, Schema.brand<Schema.refine<string, Schema.String>, "CanonicalBase64">, never, never>;
9
- decode: (input: Encoded) => Effect.Effect<Uint8Array<ArrayBufferLike>, never, never>;
7
+ toBytes: (input: Encoded) => Uint8Array;
10
8
  encode: (input: Uint8Array) => Encoded;
11
9
  decodedLength: (value: Encoded) => number;
12
- is: (value: string) => value is Encoded;
13
10
  };
14
11
  export {};
15
12
  //# sourceMappingURL=canonicalBase64.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canonicalBase64.d.ts","sourceRoot":"","sources":["../../src/internal/canonicalBase64.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AA0BvC,QAAA,MAAM,OAAO,uEAGZ,CAAA;AASD,KAAK,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAElC,gBAAgB;AAChB,eAAO,MAAM,eAAe;;;oBAGV,OAAO;oBACP,UAAU,KAAG,OAAO;2BACb,OAAO,KAAG,MAAM;gBAC3B,MAAM,KAAG,KAAK,IAAI,OAAO;CACtC,CAAA"}
1
+ {"version":3,"file":"canonicalBase64.d.ts","sourceRoot":"","sources":["../../src/internal/canonicalBase64.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAyBvC,QAAA,MAAM,OAAO,uEAMZ,CAAA;AAED,KAAK,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAElC,gBAAgB;AAChB,eAAO,MAAM,eAAe;;qBAET,OAAO,KAAG,UAAU;oBACrB,UAAU,KAAG,OAAO;2BACb,OAAO,KAAG,MAAM;CACxC,CAAA"}
@@ -1,15 +1,14 @@
1
- import * as Effect from "effect/Effect";
2
1
  import * as Encoding from "effect/Encoding";
2
+ import * as Result from "effect/Result";
3
3
  import * as Schema from "effect/Schema";
4
- import * as SchemaGetter from "effect/SchemaGetter";
4
+ import { ENCODING_CHECK } from "./errors.js";
5
5
  const canonicalTail = /^(?:[A-Za-z0-9+/]{4}|[A-Za-z0-9+/][AQgw]==|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=)?(?![\s\S])/;
6
6
  const isCanonical = (value) => value.length % 4 === 0 &&
7
7
  !/[^A-Za-z0-9+/]/.test(value.slice(0, -4)) &&
8
8
  canonicalTail.test(value.slice(-4));
9
9
  const decodedLength = (value) => value.length / 4 * 3 - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0);
10
10
  const encode = (input) => {
11
- // Join bounded chunks to avoid the encoder's intermediate string chains. Three-byte
12
- // boundaries keep padding in the final chunk, preserving the canonical representation.
11
+ // Chunk boundaries must be multiples of three to keep padding in the final chunk.
13
12
  const chunkBytes = 12_288;
14
13
  const chunks = [];
15
14
  for (let offset = 0; offset < input.length; offset += chunkBytes) {
@@ -17,17 +16,14 @@ const encode = (input) => {
17
16
  }
18
17
  return Encoded.make(chunks.join(""));
19
18
  };
20
- const Encoded = Schema.String.pipe(Schema.refine((value) => isCanonical(value), { expected: "canonical padded base64" }), Schema.brand("CanonicalBase64"));
21
- const Bytes = Encoded.pipe(Schema.decodeTo(Schema.Uint8Array, {
22
- decode: SchemaGetter.decodeBase64(),
23
- encode: SchemaGetter.transform((input) => encode(input))
24
- }));
19
+ const Encoded = Schema.String.pipe(Schema.refine((value) => isCanonical(value), {
20
+ expected: "canonical padded base64",
21
+ [ENCODING_CHECK]: true
22
+ }), Schema.brand("CanonicalBase64"));
25
23
  /** @internal */
26
24
  export const CanonicalBase64 = {
27
25
  Encoded,
28
- Bytes,
29
- decode: (input) => Schema.decodeEffect(Bytes)(input).pipe(Effect.orDie),
26
+ toBytes: (input) => Result.getOrThrow(Encoding.decodeBase64(input)),
30
27
  encode: (input) => encode(input),
31
- decodedLength: (value) => decodedLength(value),
32
- is: (value) => isCanonical(value)
28
+ decodedLength: (value) => decodedLength(value)
33
29
  };
@@ -1,12 +1,54 @@
1
1
  import * as Result from "effect/Result";
2
2
  import * as Schema from "effect/Schema";
3
- import { ConfigurationError, FsError } from "../VirtualFileSystemError.js";
3
+ import type * as SchemaAST from "effect/SchemaAST";
4
+ import type * as SchemaIssue from "effect/SchemaIssue";
5
+ import type { BytePath } from "../BytePath.js";
6
+ import { type ArgumentFailure, type FsCode, type FsFailure, type ImageCode, type ImageFailure, VfsError } from "../VfsError.js";
7
+ import type { PathInput } from "../VirtualFileSystem.js";
4
8
  /** @internal */
5
- export { ConfigurationError, FsError };
9
+ export { VfsError };
6
10
  /** @internal */
7
- export declare const FsCode: Schema.Literals<readonly ["NotFound", "AlreadyExists", "NotEmpty", "NotDirectory", "AccessDenied", "InvalidHandle", "ForeignHandle", "InvalidReference", "ForeignReference", "StaleReference", "ClosedCaller", "InvalidArgument", "InvalidPathEncoding", "PathTooLong", "NoSpace", "IsDirectory", "FileTooLarge", "NoData", "SymlinkLoop", "UnrepresentableName", "StorageRejected", "OutcomeUnknown", "VolumeUnavailable", "VolumeBusy"]>;
11
+ export declare const errorPath: (input: PathInput) => BytePath | undefined;
12
+ interface Details {
13
+ readonly path?: PathInput;
14
+ readonly field?: string;
15
+ readonly cause?: unknown;
16
+ }
8
17
  /** @internal */
9
- export type FsCode = typeof FsCode.Type;
18
+ export declare const argumentFailure: (operation: string, field: string, cause?: unknown) => ArgumentFailure;
10
19
  /** @internal */
11
- export declare const decodeConfiguration: <A>(schema: Schema.Codec<A>, value: typeof Schema.Unknown.Type) => Result.Result<A, ConfigurationError>;
20
+ export declare const decodeConfiguration: <A, I>(schema: Schema.Codec<A, I>, value: typeof Schema.Unknown.Type, operation: string) => Result.Result<A, ArgumentFailure>;
21
+ /** @internal */
22
+ export declare const ENCODING_CHECK = "@effect-vfs/core/encodingCheck";
23
+ /** @internal */
24
+ export interface IssueSite {
25
+ readonly path: ReadonlyArray<PropertyKey>;
26
+ readonly checks: ReadonlyArray<SchemaAST.Filter<unknown>>;
27
+ }
28
+ /** @internal */
29
+ export declare const issueSite: (issue: SchemaIssue.Issue) => IssueSite;
30
+ /** @internal */
31
+ export declare const isEncodingIssue: (site: IssueSite) => boolean;
32
+ /** @internal */
33
+ export declare const fsFailure: (code: FsCode, operation: string, details?: Details) => FsFailure;
34
+ /** @internal */
35
+ export declare const imageFailure: (operation: string, code: ImageCode, details?: {
36
+ readonly field?: string;
37
+ readonly cause?: unknown;
38
+ }) => ImageFailure;
39
+ /** @internal */
40
+ export declare const retargetFailure: <E>(operation: string, error: E) => E;
41
+ /** @internal */
42
+ export interface OpContext {
43
+ readonly operation: string;
44
+ readonly fail: (code: FsCode, details?: {
45
+ readonly cause?: unknown;
46
+ readonly field?: string;
47
+ }) => FsFailure;
48
+ readonly at: (path: PathInput) => OpContext;
49
+ }
50
+ /** @internal */
51
+ export declare const OpContext: {
52
+ make: (operation: string) => OpContext;
53
+ };
12
54
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAE1E,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAA;AAEtC,gBAAgB;AAChB,eAAO,MAAM,MAAM,4aA4BjB,CAAA;AAEF,gBAAgB;AAChB,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAWvC,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,GAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,yCAG9F,CAAA"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,SAAS,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,KAAK,WAAW,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,YAAY,EAGjB,QAAQ,EACT,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGxD,gBAAgB;AAChB,OAAO,EAAE,QAAQ,EAAE,CAAA;AAKnB,gBAAgB;AAChB,eAAO,MAAM,SAAS,UAAW,SAAS,KAAG,QAAQ,GAAG,SAMvD,CAAA;AAYD,UAAU,OAAO;IACf,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB;AAWD,gBAAgB;AAChB,eAAO,MAAM,eAAe,cAAe,MAAM,SAAS,MAAM,UAAU,OAAO,KAAG,eAC7B,CAAA;AAEvD,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAE,CAAC,UAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,SACnB,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,aACtB,MAAM,KAChB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,CAGhC,CAAA;AAGH,gBAAgB;AAChB,eAAO,MAAM,cAAc,mCAAmC,CAAA;AAE9D,gBAAgB;AAChB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;IACzC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;CAC1D;AAGD,gBAAgB;AAChB,eAAO,MAAM,SAAS,UAAW,WAAW,CAAC,KAAK,KAAG,SAmBpD,CAAA;AAED,gBAAgB;AAChB,eAAO,MAAM,eAAe,SAAU,SAAS,KAAG,OACyB,CAAA;AAE3E,gBAAgB;AAChB,eAAO,MAAM,SAAS,SAAU,MAAM,aAAa,MAAM,YAAY,OAAO,KAAG,SAC9C,CAAA;AAEjC,gBAAgB;AAChB,eAAO,MAAM,YAAY,cACZ,MAAM,QACX,SAAS,YACL;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KAC9D,YAA+C,CAAA;AAQlD,gBAAgB;AAChB,eAAO,MAAM,eAAe,GAAI,CAAC,aAAa,MAAM,SAAS,CAAC,KAAG,CAMhE,CAAA;AAED,gBAAgB;AAChB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAA;IAC3G,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,SAAS,CAAA;CAC5C;AAQD,gBAAgB;AAChB,eAAO,MAAM,SAAS;IACpB,IAAI,cAAc,MAAM,KAAG,SAAS;CACrC,CAAA"}
@@ -1,47 +1,91 @@
1
- // Virtual filesystem failure schemas and identities shared by the runtime implementation.
2
1
  import * as Predicate from "effect/Predicate";
3
2
  import * as Result from "effect/Result";
4
3
  import * as Schema from "effect/Schema";
5
- import { ConfigurationError, FsError } from "../VirtualFileSystemError.js";
6
- /** @internal */
7
- export { ConfigurationError, FsError };
8
- /** @internal */
9
- export const FsCode = Schema.Literals([
10
- "NotFound",
11
- "AlreadyExists",
12
- "NotEmpty",
13
- "NotDirectory",
14
- "AccessDenied",
15
- "InvalidHandle",
16
- "ForeignHandle",
17
- "InvalidReference",
18
- "ForeignReference",
19
- "StaleReference",
20
- "ClosedCaller",
21
- "InvalidArgument",
22
- "InvalidPathEncoding",
23
- "PathTooLong",
24
- "NoSpace",
25
- "IsDirectory",
26
- "FileTooLarge",
27
- "NoData",
28
- "SymlinkLoop",
29
- "UnrepresentableName",
30
- // A durable provider knows the mutation was not committed.
31
- "StorageRejected",
32
- // A commit or publication failed after its outcome ceased to be knowable to the caller.
33
- "OutcomeUnknown",
34
- // The provider stopped serving operations until recovery establishes its state.
35
- "VolumeUnavailable",
36
- "VolumeBusy"
37
- ]);
38
- // Names the offending option so the caller learns which key it got wrong, not just that decoding failed.
4
+ import { make as makeError, VfsError } from "../VfsError.js";
5
+ import { getBytes, isBytePath, isPathBytes, make } from "./bytePath.js";
6
+ /** @internal */
7
+ export { VfsError };
8
+ const encoder = new TextEncoder();
9
+ // Omit invalid paths rather than attach a BytePath that breaks its invariant.
10
+ /** @internal */
11
+ export const errorPath = (input) => {
12
+ const bytes = Predicate.isString(input) ? encoder.encode(input) : isBytePath(input) ? getBytes(input) : undefined;
13
+ if (bytes === undefined || !isPathBytes(bytes))
14
+ return undefined;
15
+ return isBytePath(input) ? input : make(bytes);
16
+ };
39
17
  const configurationField = (issue) => {
40
18
  if (Predicate.isTagged("Pointer")(issue))
41
19
  return issue.path.map(String).join(".");
42
20
  if (Predicate.isTagged("Composite")(issue))
43
21
  return configurationField(issue.issues[0]);
22
+ if (Predicate.isTagged("Encoding")(issue))
23
+ return configurationField(issue.issue);
44
24
  return "options";
45
25
  };
26
+ const build = (code, operation, details) => makeError({
27
+ code,
28
+ operation,
29
+ field: details?.field,
30
+ path: details?.path === undefined ? undefined : errorPath(details.path),
31
+ cause: details?.cause
32
+ });
33
+ /** @internal */
34
+ export const argumentFailure = (operation, field, cause) => build("InvalidArgument", operation, { field, cause });
35
+ /** @internal */
36
+ export const decodeConfiguration = (schema, value, operation) => Schema.decodeUnknownResult(schema, { onExcessProperty: "error" })(value).pipe(Result.mapError((error) => argumentFailure(operation, configurationField(error.issue), error)));
37
+ // Distinguishes invalid value encoding from invalid structure.
38
+ /** @internal */
39
+ export const ENCODING_CHECK = "@effect-vfs/core/encodingCheck";
40
+ // Decoding stops at the first failure; composite issues put it in their first branch.
41
+ /** @internal */
42
+ export const issueSite = (issue) => {
43
+ const path = [];
44
+ const checks = [];
45
+ let current = issue;
46
+ while (current !== undefined) {
47
+ if (Predicate.isTagged("Pointer")(current)) {
48
+ path.push(...current.path);
49
+ current = current.issue;
50
+ }
51
+ else if (Predicate.isTagged("Filter")(current)) {
52
+ checks.push(current.filter);
53
+ current = current.issue;
54
+ }
55
+ else if (Predicate.isTagged("Encoding")(current))
56
+ current = current.issue;
57
+ else if (Predicate.isTagged("Composite")(current) || Predicate.isTagged("AnyOf")(current)) {
58
+ current = current.issues[0];
59
+ }
60
+ else
61
+ current = undefined;
62
+ }
63
+ return { path, checks };
64
+ };
46
65
  /** @internal */
47
- export const decodeConfiguration = (schema, value) => Schema.decodeUnknownResult(schema, { onExcessProperty: "error" })(value).pipe(Result.mapError((error) => new ConfigurationError({ field: configurationField(error.issue) })));
66
+ export const isEncodingIssue = (site) => site.checks.some((check) => check.annotations?.[ENCODING_CHECK] === true);
67
+ /** @internal */
68
+ export const fsFailure = (code, operation, details) => build(code, operation, details);
69
+ /** @internal */
70
+ export const imageFailure = (operation, code, details) => build(code, operation, details);
71
+ /** @internal */
72
+ const retarget = (operation, error) => error.operation === operation
73
+ ? error
74
+ : makeError({ code: error.code, operation, field: error.field, path: error.path, cause: error.cause });
75
+ /** @internal */
76
+ export const retargetFailure = (operation, error) => {
77
+ if (!Schema.is(VfsError)(error))
78
+ return error;
79
+ // SAFETY: retarget changes only the operation, preserving E's error variant.
80
+ // oxlint-disable-next-line effecttsgo/unsafe-effect-type-assertion -- see the invariant above.
81
+ return retarget(operation, error);
82
+ };
83
+ const makeOpContext = (operation, located) => ({
84
+ operation,
85
+ fail: (code, details) => fsFailure(code, operation, located === undefined ? details : { ...details, path: located }),
86
+ at: (path) => makeOpContext(operation, Predicate.isString(path) || isBytePath(path) ? path : undefined)
87
+ });
88
+ /** @internal */
89
+ export const OpContext = {
90
+ make: (operation) => makeOpContext(operation)
91
+ };
@@ -1,5 +1,5 @@
1
1
  import * as Effect from "effect/Effect";
2
- import { ImageError } from "../Snapshot.js";
2
+ import { VfsError } from "./errors.js";
3
3
  /** @internal */
4
4
  export declare const fromFixture: (fixture: {
5
5
  readonly rootMetadata?: {
@@ -62,5 +62,5 @@ export declare const fromFixture: (fixture: {
62
62
  readonly maxBytes?: import("effect/ByteSize").ByteSize;
63
63
  readonly maxFileBytes?: import("effect/ByteSize").ByteSize;
64
64
  readonly maxPathBytes?: import("effect/ByteSize").ByteSize;
65
- } | undefined) => Effect.Effect<import("../VirtualFileSystem.js").Volume, import("./errors.js").ConfigurationError | ImageError | import("effect/PlatformError").PlatformError, import("effect/Crypto").Crypto>;
65
+ } | undefined) => Effect.Effect<import("../VirtualFileSystem.js").Volume, import("../VfsError.js").ArgumentFailure | import("../VfsError.js").ImageFailure | (void & VfsError), never>;
66
66
  //# sourceMappingURL=fixture.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/internal/fixture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAoB3C,gBAAgB;AAChB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+MAwLvB,CAAA"}
1
+ {"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../../src/internal/fixture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAMvC,OAAO,EAAgD,QAAQ,EAAE,MAAM,aAAa,CAAA;AAgBpF,gBAAgB;AAChB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sLAiLvB,CAAA"}