@openclaw/fs-safe 0.16.0 → 0.17.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 (180) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +8 -1
  3. package/dist/absolute-path.d.ts.map +1 -1
  4. package/dist/absolute-path.js +2 -8
  5. package/dist/advanced.d.ts +2 -0
  6. package/dist/advanced.d.ts.map +1 -1
  7. package/dist/advanced.js +2 -0
  8. package/dist/archive-deadline.d.ts.map +1 -1
  9. package/dist/archive-deadline.js +22 -23
  10. package/dist/archive-merge.d.ts +1 -0
  11. package/dist/archive-merge.d.ts.map +1 -1
  12. package/dist/archive-merge.js +4 -4
  13. package/dist/archive-native.d.ts +1 -0
  14. package/dist/archive-native.d.ts.map +1 -1
  15. package/dist/archive-native.js +1 -0
  16. package/dist/archive-options.d.ts +2 -0
  17. package/dist/archive-options.d.ts.map +1 -1
  18. package/dist/archive-parser.wasm +0 -0
  19. package/dist/archive-zip-count.d.ts.map +1 -1
  20. package/dist/archive-zip-count.js +21 -1
  21. package/dist/archive-zip-directory.d.ts.map +1 -1
  22. package/dist/archive-zip-directory.js +23 -1
  23. package/dist/archive-zip-loader.d.ts +2 -0
  24. package/dist/archive-zip-loader.d.ts.map +1 -1
  25. package/dist/archive-zip-loader.js +7 -0
  26. package/dist/archive-zip-names.d.ts.map +1 -1
  27. package/dist/archive-zip-names.js +7 -2
  28. package/dist/archive.d.ts.map +1 -1
  29. package/dist/archive.js +9 -3
  30. package/dist/byte-view.d.ts +3 -0
  31. package/dist/byte-view.d.ts.map +1 -0
  32. package/dist/byte-view.js +13 -0
  33. package/dist/creation-darwin.d.ts +0 -1
  34. package/dist/creation-darwin.d.ts.map +1 -1
  35. package/dist/creation-darwin.js +0 -9
  36. package/dist/directory-durability.d.ts +6 -6
  37. package/dist/directory-durability.d.ts.map +1 -1
  38. package/dist/directory-receipt.d.ts +2 -2
  39. package/dist/directory-receipt.d.ts.map +1 -1
  40. package/dist/directory-receipt.js +15 -19
  41. package/dist/file-cleanup.d.ts +1 -0
  42. package/dist/file-cleanup.d.ts.map +1 -1
  43. package/dist/file-cleanup.js +7 -4
  44. package/dist/file-contents.d.ts +6 -0
  45. package/dist/file-contents.d.ts.map +1 -0
  46. package/dist/file-contents.js +40 -0
  47. package/dist/file-hash.d.ts.map +1 -1
  48. package/dist/file-hash.js +16 -4
  49. package/dist/file-lock-sync-root-acquire.d.ts.map +1 -1
  50. package/dist/file-lock-sync-root-acquire.js +3 -0
  51. package/dist/file-lock-sync-root-held.d.ts +1 -2
  52. package/dist/file-lock-sync-root-held.d.ts.map +1 -1
  53. package/dist/file-lock-sync-root-held.js +7 -5
  54. package/dist/file-lock-sync-stale-admission.d.ts.map +1 -1
  55. package/dist/file-lock-sync-stale-admission.js +3 -0
  56. package/dist/file-lock-sync.d.ts.map +1 -1
  57. package/dist/file-lock-sync.js +8 -11
  58. package/dist/file-store.js +3 -3
  59. package/dist/guarded-mkdir.d.ts.map +1 -1
  60. package/dist/guarded-mkdir.js +6 -27
  61. package/dist/install-path.d.ts.map +1 -1
  62. package/dist/install-path.js +2 -5
  63. package/dist/json-durable-queue-ownership.d.ts.map +1 -1
  64. package/dist/json-durable-queue-ownership.js +2 -6
  65. package/dist/json-durable-queue-paths.d.ts.map +1 -1
  66. package/dist/json-durable-queue-paths.js +2 -24
  67. package/dist/json-durable-queue.d.ts.map +1 -1
  68. package/dist/json-durable-queue.js +10 -9
  69. package/dist/json.d.ts.map +1 -1
  70. package/dist/json.js +32 -75
  71. package/dist/local-roots.d.ts.map +1 -1
  72. package/dist/local-roots.js +19 -21
  73. package/dist/move-path-cleanup.d.ts +5 -19
  74. package/dist/move-path-cleanup.d.ts.map +1 -1
  75. package/dist/move-path-cleanup.js +57 -21
  76. package/dist/move-path.d.ts.map +1 -1
  77. package/dist/move-path.js +62 -39
  78. package/dist/native-staged-file.d.ts +2 -1
  79. package/dist/native-staged-file.d.ts.map +1 -1
  80. package/dist/native-staged-file.js +8 -5
  81. package/dist/native.js +2 -2
  82. package/dist/opened-realpath.d.ts.map +1 -1
  83. package/dist/opened-realpath.js +11 -2
  84. package/dist/path.d.ts.map +1 -1
  85. package/dist/path.js +2 -1
  86. package/dist/permissions.d.ts.map +1 -1
  87. package/dist/permissions.js +3 -17
  88. package/dist/pinned-write-input.d.ts.map +1 -1
  89. package/dist/pinned-write-input.js +11 -1
  90. package/dist/pinned-write-mode.d.ts +3 -3
  91. package/dist/pinned-write-mode.d.ts.map +1 -1
  92. package/dist/pinned-write-mode.js +15 -8
  93. package/dist/pinned-write-staged.d.ts.map +1 -1
  94. package/dist/pinned-write-staged.js +10 -11
  95. package/dist/pinned-write.d.ts.map +1 -1
  96. package/dist/pinned-write.js +17 -13
  97. package/dist/publish-file.d.ts +2 -2
  98. package/dist/publish-file.d.ts.map +1 -1
  99. package/dist/publish-file.js +56 -96
  100. package/dist/regular-file.d.ts.map +1 -1
  101. package/dist/regular-file.js +35 -44
  102. package/dist/replace-file-copy-fallback.d.ts.map +1 -1
  103. package/dist/replace-file-copy-fallback.js +28 -26
  104. package/dist/replace-file-copy-source.d.ts.map +1 -1
  105. package/dist/replace-file-copy-source.js +13 -22
  106. package/dist/replace-file-descriptor.d.ts.map +1 -1
  107. package/dist/replace-file-descriptor.js +10 -16
  108. package/dist/replace-file-temp-owner.js +6 -6
  109. package/dist/replace-file.d.ts.map +1 -1
  110. package/dist/replace-file.js +9 -13
  111. package/dist/root-directory-list.d.ts.map +1 -1
  112. package/dist/root-directory-list.js +20 -3
  113. package/dist/root-file-final-admission.d.ts +1 -1
  114. package/dist/root-file-final-admission.d.ts.map +1 -1
  115. package/dist/root-file-final-admission.js +5 -2
  116. package/dist/root-file.d.ts.map +1 -1
  117. package/dist/root-file.js +3 -2
  118. package/dist/root-impl.d.ts.map +1 -1
  119. package/dist/root-impl.js +50 -20
  120. package/dist/root-move-noreplace.d.ts +2 -0
  121. package/dist/root-move-noreplace.d.ts.map +1 -1
  122. package/dist/root-move-noreplace.js +2 -2
  123. package/dist/root-read-admission.d.ts.map +1 -1
  124. package/dist/root-read-admission.js +7 -2
  125. package/dist/root-remove.d.ts.map +1 -1
  126. package/dist/root-remove.js +15 -1
  127. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  128. package/dist/sidecar-lock-acquire.js +4 -6
  129. package/dist/sidecar-lock-handle.d.ts +3 -0
  130. package/dist/sidecar-lock-handle.d.ts.map +1 -1
  131. package/dist/sidecar-lock-handle.js +6 -0
  132. package/dist/sidecar-lock-reclaim.d.ts +1 -1
  133. package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
  134. package/dist/sidecar-lock-reclaim.js +11 -8
  135. package/dist/sidecar-lock.d.ts.map +1 -1
  136. package/dist/sidecar-lock.js +3 -5
  137. package/dist/staged-directory.d.ts +2 -2
  138. package/dist/staged-directory.d.ts.map +1 -1
  139. package/dist/strict-file-identity.d.ts +1 -1
  140. package/dist/strict-file-identity.d.ts.map +1 -1
  141. package/dist/strict-file-identity.js +9 -9
  142. package/dist/symlink-parents.d.ts.map +1 -1
  143. package/dist/symlink-parents.js +2 -27
  144. package/dist/temp-workspace-owner.js +4 -4
  145. package/dist/unicode-path.d.ts.map +1 -1
  146. package/dist/unicode-path.js +3 -0
  147. package/dist/walk.d.ts.map +1 -1
  148. package/dist/walk.js +4 -2
  149. package/dist/write-file-handle.d.ts +7 -0
  150. package/dist/write-file-handle.d.ts.map +1 -1
  151. package/dist/write-file-handle.js +23 -0
  152. package/dist/write-open-flags.d.ts.map +1 -1
  153. package/dist/write-open-flags.js +1 -8
  154. package/dist/write-queue.d.ts.map +1 -1
  155. package/dist/write-queue.js +1 -4
  156. package/docs/advanced.md +68 -1
  157. package/docs/archive.md +41 -2
  158. package/docs/atomic.md +29 -5
  159. package/docs/contributing.md +4 -0
  160. package/docs/creation.md +8 -4
  161. package/docs/durability.md +35 -0
  162. package/docs/file-contents.md +68 -0
  163. package/docs/json.md +5 -4
  164. package/docs/local-roots.md +2 -0
  165. package/docs/mutation-policy-proof.md +5 -3
  166. package/docs/native.md +9 -8
  167. package/docs/path.md +4 -4
  168. package/docs/public-api.md +5 -0
  169. package/docs/quickstart.md +1 -1
  170. package/docs/reading.md +2 -2
  171. package/docs/regular-file.md +3 -0
  172. package/docs/root.md +9 -0
  173. package/docs/sidecar-lock.md +9 -1
  174. package/docs/staged-file.md +4 -3
  175. package/docs/store.md +3 -1
  176. package/docs/temp.md +4 -1
  177. package/docs/types.md +18 -2
  178. package/docs/walk.md +7 -0
  179. package/docs/writing.md +9 -2
  180. package/package.json +8 -8
@@ -0,0 +1,3 @@
1
+ /** Snapshot intrinsic view bounds without copying the borrowed payload. */
2
+ export declare function snapshotByteView(bytes: Uint8Array): Uint8Array;
3
+ //# sourceMappingURL=byte-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte-view.d.ts","sourceRoot":"","sources":["../src/byte-view.ts"],"names":[],"mappings":"AAMA,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAK9D"}
@@ -0,0 +1,13 @@
1
+ const ByteView = Uint8Array;
2
+ const typedArray = Object.getPrototypeOf(ByteView.prototype);
3
+ const viewLength = Object.getOwnPropertyDescriptor(typedArray, "byteLength").get;
4
+ const viewOffset = Object.getOwnPropertyDescriptor(typedArray, "byteOffset").get;
5
+ const viewBuffer = Object.getOwnPropertyDescriptor(typedArray, "buffer").get;
6
+ /** Snapshot intrinsic view bounds without copying the borrowed payload. */
7
+ export function snapshotByteView(bytes) {
8
+ const length = Reflect.apply(viewLength, bytes, []);
9
+ // Preserve empty, detached, and out-of-bounds views as zero-byte inputs.
10
+ if (length === 0)
11
+ return new ByteView(0);
12
+ return new ByteView(Reflect.apply(viewBuffer, bytes, []), Reflect.apply(viewOffset, bytes, []), length);
13
+ }
@@ -3,5 +3,4 @@ export declare function assertDarwinPrivateCreationAvailable(): void;
3
3
  export declare function assertDarwinPrivateDirectoryMode(mode: number): void;
4
4
  export declare function assertDarwinCreationAcl(fd: number, inheritanceTarget?: "file" | "directory"): void;
5
5
  export declare function assertDarwinCreationDirectoryAcl(pathname: string, expected: BigIntStats, inheritanceTarget?: "file" | "directory"): void;
6
- export declare function privateFileMutationAssertion(fd: number, assertion?: () => void): (() => void) | undefined;
7
6
  //# sourceMappingURL=creation-darwin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"creation-darwin.d.ts","sourceRoot":"","sources":["../src/creation-darwin.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAgB/C,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAInE;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAYlG;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAChF,IAAI,CAqBN;AAED,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAMzG"}
1
+ {"version":3,"file":"creation-darwin.d.ts","sourceRoot":"","sources":["../src/creation-darwin.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAe/C,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAInE;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAYlG;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,WAAW,GAChF,IAAI,CAqBN"}
@@ -2,7 +2,6 @@ import fs, {} from "node:fs";
2
2
  import { inspectDirectoryIdentitySync } from "./directory-guard.js";
3
3
  import { nodeDarwinDirectoryMetadataFlags, nodeDirectorySearchOnlyFlags } from "./directory-mode-node.js";
4
4
  import { FsSafeError } from "./errors.js";
5
- import { assertSynchronousCallbackResult } from "./mutation-authority.js";
6
5
  import { getNativeBinding } from "./native.js";
7
6
  import { inspectFileIdentitySync } from "./strict-file-identity.js";
8
7
  function inspector() {
@@ -69,11 +68,3 @@ export function assertDarwinCreationDirectoryAcl(pathname, expected, inheritance
69
68
  fs.closeSync(fd);
70
69
  }
71
70
  }
72
- export function privateFileMutationAssertion(fd, assertion) {
73
- if (process.platform !== "darwin")
74
- return assertion;
75
- return () => {
76
- assertSynchronousCallbackResult(assertion?.(), "assertBeforeMutation");
77
- assertDarwinCreationAcl(fd);
78
- };
79
- }
@@ -1,4 +1,4 @@
1
- import { type Stats } from "node:fs";
1
+ import { type BigIntStats, type Stats } from "node:fs";
2
2
  import type { FileIdentityStat } from "./file-identity.js";
3
3
  export type DirectorySyncOutcome = {
4
4
  status: "synced";
@@ -6,10 +6,10 @@ export type DirectorySyncOutcome = {
6
6
  status: "unsupported";
7
7
  code?: string;
8
8
  };
9
- export type DirectoryReceipt = {
9
+ export type DirectoryReceipt<T extends Stats | BigIntStats = Stats> = {
10
10
  path: string;
11
11
  realPath: string;
12
- identity: Stats;
12
+ identity: T;
13
13
  };
14
14
  export type DurableDirectoryReceipt = DirectoryReceipt & {
15
15
  parentSync: DirectorySyncOutcome | {
@@ -29,13 +29,13 @@ export type EnsureDurableDirectoryOptions = {
29
29
  expectedExistingIdentity?: FileIdentityStat;
30
30
  create?: (directoryPath: string) => Promise<void>;
31
31
  };
32
- export declare function pinDirectory(directory: string | DirectoryReceipt, options?: {
32
+ export declare function pinDirectory(directory: string | DirectoryReceipt<Stats | BigIntStats>, options?: {
33
33
  label?: string;
34
34
  }): Promise<PinnedDirectory>;
35
- export declare function syncDirectory(directory: string | DirectoryReceipt, options?: {
35
+ export declare function syncDirectory(directory: string | DirectoryReceipt<Stats | BigIntStats>, options?: {
36
36
  label?: string;
37
37
  }): Promise<DirectorySyncOutcome>;
38
- export declare function syncDirectorySync(directory: string | DirectoryReceipt, options?: {
38
+ export declare function syncDirectorySync(directory: string | DirectoryReceipt<Stats | BigIntStats>, options?: {
39
39
  label?: string;
40
40
  }): DirectorySyncOutcome;
41
41
  export declare function syncDirectoryBestEffort(directoryPath: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"directory-durability.d.ts","sourceRoot":"","sources":["../src/directory-durability.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAM7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAa3D,MAAM,MAAM,oBAAoB,GAC5B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACvD,UAAU,EAAE,oBAAoB,GAAG;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAkHF,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,gBAAgB,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,oBAAoB,CAkCtB;AAED,wBAAsB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAMvE;AAiCD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CA6FlC"}
1
+ {"version":3,"file":"directory-durability.d.ts","sourceRoot":"","sources":["../src/directory-durability.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAM/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAa3D,MAAM,MAAM,oBAAoB,GAC5B;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,KAAK,GAAG,WAAW,GAAG,KAAK,IAAI;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,GAAG;IACvD,UAAU,EAAE,oBAAoB,GAAG;QAAE,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wBAAwB,CAAC,EAAE,gBAAgB,CAAC;IAC5C,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD,CAAC;AAkHF,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC,KAAK,GAAG,WAAW,CAAC,EACzD,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC,KAAK,GAAG,WAAW,CAAC,EACzD,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAqB/B;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC,KAAK,GAAG,WAAW,CAAC,EACzD,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,oBAAoB,CAkCtB;AAED,wBAAsB,uBAAuB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAElF;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAMvE;AAiCD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CA6FlC"}
@@ -14,8 +14,8 @@ type DirectoryAuthority = DirectoryProvenance & Readonly<{
14
14
  realPath: string;
15
15
  }>;
16
16
  export declare function directoryReceiptIdentity(identity: FileIdentityStat): ExactIdentity;
17
- export declare function directoryReceiptAuthority(receipt: DirectoryReceipt): DirectoryAuthority;
18
- export declare function ownDirectoryReceipt(receipt: DirectoryReceipt): DirectoryReceipt;
17
+ export declare function directoryReceiptAuthority(receipt: DirectoryReceipt<Stats | BigIntStats>): DirectoryAuthority;
18
+ export declare function ownDirectoryReceipt(receipt: DirectoryReceipt<Stats | BigIntStats>): DirectoryReceipt;
19
19
  export declare function copyRetainedDirectoryReceipt(receipt: DirectoryReceipt): DirectoryReceipt;
20
20
  export declare function createDirectoryReceiptFromIdentity(pathname: string, realPath: string, exactStat: BigIntStats): DirectoryReceipt;
21
21
  export declare function createDirectoryReceiptSync(directoryPath: string, label: string, canonicalize?: (pathname: string) => string): DirectoryReceipt;
@@ -1 +1 @@
1
- {"version":3,"file":"directory-receipt.d.ts","sourceRoot":"","sources":["../src/directory-receipt.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAQ3D,KAAK,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;AAChE,QAAA,MAAM,aAAa,YAAI,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAClH,QAAA,MAAM,UAAU,YAAI,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAU,CAAC;AACrE,KAAK,iBAAiB,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACtG,KAAK,mBAAmB,GAAG,QAAQ,CAAC;IAClC,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC;CACvC,CAAC,CAAC;AACH,KAAK,kBAAkB,GAAG,mBAAmB,GAAG,QAAQ,CAAC;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAOH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,aAAa,CAuBlF;AA8BD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAEvF;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAE/E;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAGxF;AA0BD,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,WAAW,GACrB,gBAAgB,CAOlB;AAED,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,YAAY,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAqB,GACxD,gBAAgB,CASlB;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,MAAM,EACb,YAAY,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAqB,GACxD,IAAI,CAUN"}
1
+ {"version":3,"file":"directory-receipt.d.ts","sourceRoot":"","sources":["../src/directory-receipt.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAQ3D,KAAK,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;AAChE,QAAA,MAAM,aAAa,YAAI,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAClH,QAAA,MAAM,UAAU,YAAI,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAU,CAAC;AACrE,KAAK,iBAAiB,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACtG,KAAK,mBAAmB,GAAG,QAAQ,CAAC;IAClC,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC;CACvC,CAAC,CAAC;AACH,KAAK,kBAAkB,GAAG,mBAAmB,GAAG,QAAQ,CAAC;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAOH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,aAAa,CAuBlF;AAsCD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,kBAAkB,CAE5G;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,gBAAgB,CAEpG;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAGxF;AAWD,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,WAAW,GACrB,gBAAgB,CASlB;AAED,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,YAAY,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAqB,GACxD,gBAAgB,CASlB;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,MAAM,EACb,YAAY,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAqB,GACxD,IAAI,CAUN"}
@@ -53,10 +53,18 @@ function snapshotDirectoryReceipt(receipt) {
53
53
  function snapshotDirectoryMetadata(stat, identity) {
54
54
  const metadata = {};
55
55
  for (const field of numericFields) {
56
- metadata[field] = field === "dev" || field === "ino" ? Number(identity[field]) : stat[field];
56
+ metadata[field] = Number(field === "dev" || field === "ino" ? identity[field] : stat[field]);
57
+ }
58
+ for (const field of timeFields) {
59
+ if ("atimeNs" in stat) {
60
+ const nanoseconds = stat[`${field}Ns`];
61
+ const remainder = ((nanoseconds % 1000000000n) + 1000000000n) % 1000000000n;
62
+ metadata[`${field}Ms`] = Number((nanoseconds - remainder) / 1000000000n) * 1_000 + Number(remainder) / 1_000_000;
63
+ }
64
+ else {
65
+ metadata[`${field}Ms`] = stat[`${field}Ms`];
66
+ }
57
67
  }
58
- for (const field of timeFields)
59
- metadata[`${field}Ms`] = stat[`${field}Ms`];
60
68
  return Object.freeze(metadata);
61
69
  }
62
70
  export function directoryReceiptAuthority(receipt) {
@@ -81,27 +89,15 @@ function receiptFromAuthority(authority) {
81
89
  identity: Object.assign(Object.create(fs.Stats.prototype), authority.metadata),
82
90
  }, authority);
83
91
  }
84
- function numericDirectoryMetadata(exact) {
85
- // Keep metadata and authority from one observation. A second pathname stat
86
- // can describe a replacement even when a later fence sees the original again.
87
- const metadata = {};
88
- for (const field of numericFields) {
89
- metadata[field] = Number(exact[field]);
90
- }
91
- for (const field of timeFields) {
92
- const nanoseconds = exact[`${field}Ns`];
93
- const remainder = ((nanoseconds % 1000000000n) + 1000000000n) % 1000000000n;
94
- metadata[`${field}Ms`] = Number((nanoseconds - remainder) / 1000000000n) * 1_000 + Number(remainder) / 1_000_000;
95
- }
96
- return Object.freeze(metadata);
97
- }
98
92
  // The caller already admitted the exact observation and its paths.
99
93
  export function createDirectoryReceiptFromIdentity(pathname, realPath, exactStat) {
94
+ const identity = Object.freeze({ dev: exactStat.dev, ino: exactStat.ino });
100
95
  return receiptFromAuthority(Object.freeze({
101
96
  path: pathname,
102
97
  realPath,
103
- identity: Object.freeze({ dev: exactStat.dev, ino: exactStat.ino }),
104
- metadata: numericDirectoryMetadata(exactStat),
98
+ identity,
99
+ // Project metadata from the admitted observation, never a fresh pathname stat.
100
+ metadata: snapshotDirectoryMetadata(exactStat, identity),
105
101
  }));
106
102
  }
107
103
  export function createDirectoryReceiptSync(directoryPath, label, canonicalize = realpathSync) {
@@ -1,6 +1,7 @@
1
1
  import { type BigIntStats } from "node:fs";
2
2
  import fs, { type FileHandle } from "node:fs/promises";
3
3
  import { type AnyAsyncDirectoryGuard } from "./directory-guard.js";
4
+ export declare function readErrorCode(error: unknown): unknown;
4
5
  export declare function hasErrorCode(error: unknown, expected: string): boolean;
5
6
  type OwnedPathCleanupStatus = "removed" | "name-absent" | "preserved";
6
7
  export declare function removeOwnedPath(params: {
@@ -1 +1 @@
1
- {"version":3,"file":"file-cleanup.d.ts","sourceRoot":"","sources":["../src/file-cleanup.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAI9F,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAStE;AAED,KAAK,sBAAsB,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAEtE,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAoBlC;AAGD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,sBAAsB,CAAC;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAgClC"}
1
+ {"version":3,"file":"file-cleanup.d.ts","sourceRoot":"","sources":["../src/file-cleanup.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAA6B,KAAK,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAI9F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASrD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,KAAK,sBAAsB,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;AAEtE,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAoBlC;AAGD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,WAAW,EAAE,sBAAsB,CAAC;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAgClC"}
@@ -3,17 +3,20 @@ import fs, {} from "node:fs/promises";
3
3
  import { assertAsyncDirectoryGuard } from "./directory-guard.js";
4
4
  import { FsSafeError } from "./errors.js";
5
5
  import { sameFileIdentityForCleanup } from "./file-identity.js";
6
- export function hasErrorCode(error, expected) {
6
+ export function readErrorCode(error) {
7
7
  if ((typeof error !== "object" || error === null) && typeof error !== "function") {
8
- return false;
8
+ return undefined;
9
9
  }
10
10
  try {
11
- return Reflect.get(error, "code") === expected;
11
+ return Reflect.get(error, "code");
12
12
  }
13
13
  catch {
14
- return false;
14
+ return undefined;
15
15
  }
16
16
  }
17
+ export function hasErrorCode(error, expected) {
18
+ return readErrorCode(error) === expected;
19
+ }
17
20
  export async function removeOwnedPath(params) {
18
21
  if (!params.identity)
19
22
  return "preserved";
@@ -0,0 +1,6 @@
1
+ export type SameFileContentsOptions = {
2
+ maxBytes?: number;
3
+ };
4
+ /** Compares borrowed regular files from offset zero without moving or closing either descriptor. */
5
+ export declare function sameFileContentsSync(leftFd: number, rightFd: number, options?: SameFileContentsOptions): boolean;
6
+ //# sourceMappingURL=file-contents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-contents.d.ts","sourceRoot":"","sources":["../src/file-contents.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,oGAAoG;AACpG,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAgCT"}
@@ -0,0 +1,40 @@
1
+ import fs from "node:fs";
2
+ import { normalizeMaxBytes } from "./byte-budget.js";
3
+ import { FsSafeError } from "./errors.js";
4
+ import { readFileWindowFullySync } from "./positional-read.js";
5
+ /** Compares borrowed regular files from offset zero without moving or closing either descriptor. */
6
+ export function sameFileContentsSync(leftFd, rightFd, options = {}) {
7
+ const maxBytes = normalizeMaxBytes(options.maxBytes) ?? Infinity;
8
+ const limit = Math.min(maxBytes, Number.MAX_SAFE_INTEGER);
9
+ const tooLarge = () => new FsSafeError("too-large", `file comparison exceeds ${limit} bytes`);
10
+ for (const fd of [leftFd, rightFd]) {
11
+ const stat = fs.fstatSync(fd, { bigint: true });
12
+ if (!stat.isFile()) {
13
+ throw new FsSafeError("not-file", "file comparison requires regular-file descriptors");
14
+ }
15
+ if (stat.size > BigInt(limit))
16
+ throw tooLarge();
17
+ }
18
+ const left = Buffer.allocUnsafe(Math.min(1024 * 1024, Math.max(1, limit)));
19
+ const right = Buffer.allocUnsafe(left.length);
20
+ let position = 0;
21
+ while (true) {
22
+ const length = Math.min(left.length, limit - position);
23
+ if (length === 0) {
24
+ // Probe EOF at the limit without forming an unsafe exclusive window end.
25
+ const leftExtra = fs.readSync(leftFd, left, 0, 1, position);
26
+ const rightExtra = fs.readSync(rightFd, right, 0, 1, position);
27
+ if (leftExtra !== 0 || rightExtra !== 0)
28
+ throw tooLarge();
29
+ return true;
30
+ }
31
+ const leftRead = readFileWindowFullySync(leftFd, left.subarray(0, length), position);
32
+ const rightRead = readFileWindowFullySync(rightFd, right.subarray(0, length), position);
33
+ if (leftRead !== rightRead || !left.subarray(0, leftRead).equals(right.subarray(0, rightRead))) {
34
+ return false;
35
+ }
36
+ if (leftRead < length)
37
+ return true;
38
+ position += leftRead;
39
+ }
40
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"file-hash.d.ts","sourceRoot":"","sources":["../src/file-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAKnE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAClD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,aAAa,GAAG,SAA8B,EACtD,EAAE,QAAmB,EAAE,MAAM,EAAE,GAAE,iBAAsB,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAwD3B;AA0DD,wBAAsB,UAAU,CAC9B,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AAwDD,8FAA8F;AAC9F,wBAAgB,cAAc,CAC5B,KAAK,EAAE,mBAAmB,EAC1B,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAMlB"}
1
+ {"version":3,"file":"file-hash.d.ts","sourceRoot":"","sources":["../src/file-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAKnE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAClD,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,MAAM,GAAE,aAAa,GAAG,SAA8B,EACtD,EAAE,QAAmB,EAAE,MAAM,EAAE,GAAE,iBAAsB,GACtD,OAAO,CAAC,gBAAgB,CAAC,CAwD3B;AA8DD,wBAAsB,UAAU,CAC9B,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAM3B;AA2DD,8FAA8F;AAC9F,wBAAgB,cAAc,CAC5B,KAAK,EAAE,mBAAmB,EAC1B,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAMlB"}
package/dist/file-hash.js CHANGED
@@ -99,14 +99,20 @@ async function hashPath(filePath, options) {
99
99
  catch (error) {
100
100
  rethrowHashOpenError(error);
101
101
  }
102
+ let completed = false;
102
103
  try {
103
104
  options.signal?.throwIfAborted();
104
105
  const opened = await inspectFileIdentity(() => hashDescriptorIdentity(handle.fd), before);
105
106
  await inspectFileIdentity(() => hashPathIdentity(filePath, true), opened);
106
- return await hashFileHandle(handle, getNativeBinding(), options);
107
+ const result = await hashFileHandle(handle, getNativeBinding(), options);
108
+ completed = true;
109
+ return result;
107
110
  }
108
111
  finally {
109
- await handle.close().catch(() => undefined);
112
+ if (completed)
113
+ await handle.close();
114
+ else
115
+ await handle.close().catch(() => undefined);
110
116
  }
111
117
  }
112
118
  export async function sha256File(input, options = {}) {
@@ -157,17 +163,23 @@ function hashPathSync(filePath, options) {
157
163
  catch (error) {
158
164
  rethrowHashOpenError(error);
159
165
  }
166
+ let completed = false;
160
167
  try {
161
168
  options.signal?.throwIfAborted();
162
169
  const opened = inspectFileIdentitySync(() => hashDescriptorIdentity(fd), before);
163
170
  inspectFileIdentitySync(() => hashPathIdentity(filePath, true), opened);
164
- return hashDescriptorSync(fd, options);
171
+ const result = hashDescriptorSync(fd, options);
172
+ completed = true;
173
+ return result;
165
174
  }
166
175
  finally {
167
176
  try {
168
177
  fsSync.closeSync(fd);
169
178
  }
170
- catch { /* Preserve the hashing outcome. */ }
179
+ catch (error) {
180
+ if (completed)
181
+ throw error;
182
+ }
171
183
  }
172
184
  }
173
185
  /** Hash synchronously from offset zero, retaining ownership and position of a borrowed fd. */
@@ -1 +1 @@
1
- {"version":3,"file":"file-lock-sync-root-acquire.d.ts","sourceRoot":"","sources":["../src/file-lock-sync-root-acquire.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAgD3C,wBAAgB,2BAA2B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClF,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,0BAA0B,CAAC,QAAQ,CAAC,EAClD,QAAQ,EAAE,IAAI,GACb,kBAAkB,CA8VpB"}
1
+ {"version":3,"file":"file-lock-sync-root-acquire.d.ts","sourceRoot":"","sources":["../src/file-lock-sync-root-acquire.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAiD3C,wBAAgB,2BAA2B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClF,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,0BAA0B,CAAC,QAAQ,CAAC,EAClD,QAAQ,EAAE,IAAI,GACb,kBAAkB,CAgWpB"}
@@ -7,6 +7,7 @@ import { computeSidecarLockDelayMs, isTransientLockFileDenial, maxTransientLockD
7
7
  import { serializeSidecarLockPayload, } from "./sidecar-lock-reclaim.js";
8
8
  import { createSuppressedError } from "./suppressed-error.js";
9
9
  import { sleepSync } from "./timing.js";
10
+ import { assertSynchronousCallbackResult } from "./mutation-authority.js";
10
11
  import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
11
12
  import { admitFileLockSyncRootPath, assertFileLockSyncRootPathsCurrent, captureFileLockSyncRootAuthority, normalizeFileLockSyncTargetWithRoot, } from "./file-lock-sync-root.js";
12
13
  import { cleanupCreatedRootSyncLock, FileLockSyncRootArbitrationCollision, tryReuseCurrentRootSyncHeldLock, } from "./file-lock-sync-root-arbitration.js";
@@ -299,6 +300,7 @@ export function acquireFileLockSyncWithRoot(targetPath, inputOptions, lockRoot)
299
300
  nowMs,
300
301
  heldByThisProcess: false,
301
302
  }]);
303
+ assertSynchronousCallbackResult(reclaim, "shouldReclaim");
302
304
  assertAdmission();
303
305
  if (!fileLockSyncRootSnapshotStillCurrent(lockRootPath, current)) {
304
306
  throw new FsSafeError("path-mismatch", "sidecar changed during reclaim policy callback");
@@ -324,6 +326,7 @@ export function acquireFileLockSyncWithRoot(targetPath, inputOptions, lockRoot)
324
326
  raw: snapshot.raw,
325
327
  payload: snapshot.payload,
326
328
  }]);
329
+ assertSynchronousCallbackResult(approved, "shouldRemoveStaleLock");
327
330
  assertAdmission();
328
331
  assertOwnedReclaimGuardCurrent();
329
332
  if (approved) {
@@ -28,7 +28,6 @@ export declare function getRootSyncHeldLocks(): Map<string, RootSyncHeldLock>;
28
28
  export declare function ensureRootSyncExitCleanupRegistered(): void;
29
29
  export declare function verifyRootSyncHeldLock(held: RootSyncHeldLock): boolean;
30
30
  export declare function createRootSyncHeldLockHandle(held: RootSyncHeldLock): FileLockSyncHandle;
31
- export declare function isRootSyncHeldLockHandle(handle: FileLockSyncHandle): boolean;
32
- export declare function withRootSyncHeldLockHandle<T>(lock: FileLockSyncHandle, fn: () => T): T;
31
+ export declare function withSyncHeldLockHandle<T>(lock: FileLockSyncHandle, fn: () => T): T;
33
32
  export {};
34
33
  //# sourceMappingURL=file-lock-sync-root-held.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-lock-sync-root-held.d.ts","sourceRoot":"","sources":["../src/file-lock-sync-root-held.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAIL,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AAQrC,KAAK,4BAA4B,GAAG,QAAQ,GAAG,WAAW,GAAG,eAAe,GAAG,UAAU,CAAC;AAE1F,KAAK,iCAAiC,GAAG;IACvC,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAOF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,oBAAoB,CAAC,EAAE,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC9D,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,4BAA4B,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,yBAAyB,CAAC;IACzC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,2BAA2B,CAAC;IACzC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CACxB,CAAC;AAQF,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,oBAAoB,EAC9B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,EACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACxC,eAAe,CAAC,EAAE,2BAA2B,GAC5C,wBAAwB,GAAG,IAAI,CAmCjC;AAED,wBAAgB,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAQpE;AA+KD,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAWtE;AAsHD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,CAqBvF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAE5E;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,IAAI,EAAE,kBAAkB,EACxB,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAoBH"}
1
+ {"version":3,"file":"file-lock-sync-root-held.d.ts","sourceRoot":"","sources":["../src/file-lock-sync-root-held.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAIL,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AAQrC,KAAK,4BAA4B,GAAG,QAAQ,GAAG,WAAW,GAAG,eAAe,GAAG,UAAU,CAAC;AAE1F,KAAK,iCAAiC,GAAG;IACvC,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAOF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,oBAAoB,CAAC,EAAE,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC9D,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,4BAA4B,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,yBAAyB,CAAC;IACzC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,2BAA2B,CAAC;IACzC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CACxB,CAAC;AAQF,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,oBAAoB,EAC9B,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,EACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACxC,eAAe,CAAC,EAAE,2BAA2B,GAC5C,wBAAwB,GAAG,IAAI,CAmCjC;AAED,wBAAgB,oBAAoB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAQpE;AA+KD,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAWtE;AAsHD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,gBAAgB,GAAG,kBAAkB,CAqBvF;AAED,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,IAAI,EAAE,kBAAkB,EACxB,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAoBH"}
@@ -223,7 +223,12 @@ export function ensureRootSyncExitCleanupRegistered() {
223
223
  ensureFileLockSyncRootExitCleanupRegistered(releaseAllRootSyncHeldLocks);
224
224
  }
225
225
  export function verifyRootSyncHeldLock(held) {
226
- const current = readRootSidecarSnapshotSync(held.rootPath, held.parsePayload, undefined, held.rootReceipt);
226
+ const rootPath = held.rootPath;
227
+ const parsePayload = held.parsePayload;
228
+ const rootReceipt = held.rootReceipt;
229
+ const current = parsePayload
230
+ ? readRootSidecarSnapshotSync(rootPath, parsePayload, undefined, rootReceipt)
231
+ : readFileLockSyncRootSnapshot(rootPath, { expectedReceipt: rootReceipt });
227
232
  if (!current)
228
233
  return false;
229
234
  return current.receipt.identity.dev === held.rootReceipt.identity.dev &&
@@ -369,10 +374,7 @@ export function createRootSyncHeldLockHandle(held) {
369
374
  rootSyncHandleDispositions.set(handle, disposition);
370
375
  return handle;
371
376
  }
372
- export function isRootSyncHeldLockHandle(handle) {
373
- return rootSyncHandleDispositions.has(handle);
374
- }
375
- export function withRootSyncHeldLockHandle(lock, fn) {
377
+ export function withSyncHeldLockHandle(lock, fn) {
376
378
  let result;
377
379
  try {
378
380
  result = fn();
@@ -1 +1 @@
1
- {"version":3,"file":"file-lock-sync-stale-admission.d.ts","sourceRoot":"","sources":["../src/file-lock-sync-stale-admission.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAQtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAExE,MAAM,MAAM,qBAAqB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC5E,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC;IACtE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,YAAY,CAAC,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC,uBAAuB,CAAC,CAAC;CAC9E,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE;IACzF,QAAQ,IAAI,OAAO,CAAC;IACpB,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC9C,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,YAAY,IAAI,IAAI,CAAC;CACtB,GAAG,IAAI,CAiLP"}
1
+ {"version":3,"file":"file-lock-sync-stale-admission.d.ts","sourceRoot":"","sources":["../src/file-lock-sync-stale-admission.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAQtE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAGxE,MAAM,MAAM,qBAAqB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC5E,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC;IACtE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,YAAY,CAAC,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC,uBAAuB,CAAC,CAAC;CAC9E,CAAC;AAEF,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE;IACzF,QAAQ,IAAI,OAAO,CAAC;IACpB,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IAC9C,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,YAAY,IAAI,IAAI,CAAC;CACtB,GAAG,IAAI,CAmLP"}
@@ -1,6 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import { defaultSyncShouldReclaim, syncLockTimeout } from "./file-lock-sync-admission.js";
3
3
  import { parseSidecarLockSnapshot, readSidecarLockRawSnapshotSync, removeSidecarLockIfUnchangedSync, } from "./sidecar-lock-reclaim.js";
4
+ import { assertSynchronousCallbackResult } from "./mutation-authority.js";
4
5
  /** Handle one exclusive-create conflict without surrendering canonical admission. */
5
6
  export function handleSyncStaleAdmission(params) {
6
7
  const holderChanged = {};
@@ -110,6 +111,7 @@ export function handleSyncStaleAdmission(params) {
110
111
  heldByThisProcess: false,
111
112
  }])
112
113
  : defaultSyncShouldReclaim(snapshot, params.staleMs, nowMs);
114
+ assertSynchronousCallbackResult(reclaim, "shouldReclaim");
113
115
  }
114
116
  finally {
115
117
  assertUnheld();
@@ -137,6 +139,7 @@ export function handleSyncStaleAdmission(params) {
137
139
  raw: snapshot.raw,
138
140
  payload: snapshot.payload,
139
141
  }]);
142
+ assertSynchronousCallbackResult(approved, "shouldRemoveStaleLock");
140
143
  }
141
144
  finally {
142
145
  assertUnheld();
@@ -1 +1 @@
1
- {"version":3,"file":"file-lock-sync.d.ts","sourceRoot":"","sources":["../src/file-lock-sync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAML,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAUnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AAqBjC,MAAM,MAAM,0BAA0B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,QAAQ,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,iBAAiB,EAAE,KAAK,CAAC;KAC1B,KAAK,OAAO,CAAC;IACd,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,wBAAwB,KAAK,OAAO,CAAC;IACxE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC3D,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,IAAI,OAAO,CAAC;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;AAyFF,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC5C,kBAAkB,CAyRpB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,EAC7C,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAQH"}
1
+ {"version":3,"file":"file-lock-sync.d.ts","sourceRoot":"","sources":["../src/file-lock-sync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAOL,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAUnC,OAAO,KAAK,EACV,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,yBAAyB,CAAC;AAqBjC,MAAM,MAAM,0BAA0B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,uBAAuB,CAAC;IAChC,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,QAAQ,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,iBAAiB,EAAE,KAAK,CAAC;KAC1B,KAAK,OAAO,CAAC;IACd,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,wBAAwB,KAAK,OAAO,CAAC;IACxE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,0BAA0B,KAAK,IAAI,CAAC;IAC3D,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,eAAe,IAAI,OAAO,CAAC;IAC3B,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;AA6FF,wBAAgB,mBAAmB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAC5C,kBAAkB,CAyRpB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,0BAA0B,CAAC,QAAQ,CAAC,EAC7C,EAAE,EAAE,MAAM,CAAC,GACV,CAAC,CAGH"}
@@ -1,8 +1,8 @@
1
1
  import fs from "node:fs";
2
2
  import { acquireFileLockSyncWithRoot } from "./file-lock-sync-root-acquire.js";
3
- import { isRootSyncHeldLockHandle, withRootSyncHeldLockHandle } from "./file-lock-sync-root-held.js";
3
+ import { withSyncHeldLockHandle } from "./file-lock-sync-root-held.js";
4
4
  import path from "node:path";
5
- import { readSidecarLockSnapshotSync, removeSidecarLockIfUnchangedSync, serializeSidecarLockPayload, sidecarLockSnapshotMatches, } from "./sidecar-lock-reclaim.js";
5
+ import { readSidecarLockRawSnapshotSync, readSidecarLockSnapshotSync, removeSidecarLockIfUnchangedSync, serializeSidecarLockPayload, sidecarLockSnapshotMatches, } from "./sidecar-lock-reclaim.js";
6
6
  import { computeSidecarLockDelayMs, isTransientLockFileDenial, maxTransientLockDenials, validateSidecarLockStaleMs, validateSidecarLockCompromiseCheckIntervalMs, validateSidecarLockRetryOptions, validateSidecarLockTimeoutMs, } from "./sidecar-lock-policy.js";
7
7
  import { getFsSafeLockConfig } from "./lock-config.js";
8
8
  import { sleepSync } from "./timing.js";
@@ -37,7 +37,11 @@ function releaseAllSyncHeldLocks() {
37
37
  getSyncLockAdmissions().clear();
38
38
  }
39
39
  function verifySyncHeldLock(held) {
40
- const current = readSidecarLockSnapshotSync(held.lockPath, held.parsePayload);
40
+ const lockPath = held.lockPath;
41
+ const parsePayload = held.parsePayload;
42
+ const current = parsePayload
43
+ ? readSidecarLockSnapshotSync(lockPath, parsePayload)
44
+ : readSidecarLockRawSnapshotSync(lockPath);
41
45
  return !!current && sidecarLockSnapshotMatches(current, held.snapshot);
42
46
  }
43
47
  function releaseSyncHeldLock(held) {
@@ -412,12 +416,5 @@ export function acquireFileLockSync(targetPath, options) {
412
416
  }
413
417
  export function withFileLockSync(targetPath, options, fn) {
414
418
  const lock = acquireFileLockSync(targetPath, options);
415
- if (isRootSyncHeldLockHandle(lock))
416
- return withRootSyncHeldLockHandle(lock, fn);
417
- try {
418
- return fn();
419
- }
420
- finally {
421
- lock.release();
422
- }
419
+ return withSyncHeldLockHandle(lock, fn);
423
420
  }
@@ -321,10 +321,11 @@ export function fileStoreSync(options) {
321
321
  mode: writeOptions?.mode ?? mode,
322
322
  });
323
323
  }
324
+ let readTextIfExists;
324
325
  return {
325
326
  rootDir,
326
327
  path: (relativePath) => resolveStorePath(rootDir, relativePath),
327
- readTextIfExists: (relativePath, readOptions) => {
328
+ readTextIfExists: readTextIfExists = (relativePath, readOptions) => {
328
329
  const limit = normalizeMaxBytes(readOptions?.maxBytes, { defaultValue: maxBytes });
329
330
  const targetPath = resolveStorePath(rootDir, relativePath);
330
331
  const opened = openRootFileSync({
@@ -352,8 +353,7 @@ export function fileStoreSync(options) {
352
353
  }
353
354
  },
354
355
  readJsonIfExists: (relativePath, readOptions) => {
355
- const raw = fileStoreSync({ rootDir, private: privateMode, dirMode, mode, maxBytes })
356
- .readTextIfExists(relativePath, readOptions);
356
+ const raw = readTextIfExists(relativePath, readOptions);
357
357
  return raw === null ? null : JSON.parse(raw);
358
358
  },
359
359
  write,
@@ -1 +1 @@
1
- {"version":3,"file":"guarded-mkdir.d.ts","sourceRoot":"","sources":["../src/guarded-mkdir.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAA4B,KAAK,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAC/G,OAAO,KAAK,EACV,6BAA6B,EAC7B,8BAA8B,EAC9B,gCAAgC,EACjC,MAAM,mBAAmB,CAAC;AA4G3B;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,qBAAqB,CAAC,EAAE,CACtB,aAAa,EAAE,MAAM,EACrB,qBAAqB,EAAE,MAAM,EAC7B,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,MAAM,EAAE,4BAA4B,KACjC,OAAO,CAAC,8BAA8B,GAAG,SAAS,CAAC,GAAG,8BAA8B,GAAG,SAAS,CAAC;IACtG,kBAAkB,CAAC,EAAE,CACnB,aAAa,EAAE,MAAM,EACrB,qBAAqB,EAAE,MAAM,EAC7B,kBAAkB,EAAE,MAAM,GAAG,SAAS,KACnC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,oBAAoB,CAAC,EAAE,CACrB,OAAO,EAAE,6BAA6B,KACnC,gCAAgC,GAAG,SAAS,CAAC;IAClD,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oCAAoC,CAAC,EAAE,OAAO,CAAC;IAC/C,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,GAAG,OAAO,CAAC,MAAM,CAAC,CA6NlB"}
1
+ {"version":3,"file":"guarded-mkdir.d.ts","sourceRoot":"","sources":["../src/guarded-mkdir.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAA4B,KAAK,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAC/G,OAAO,KAAK,EACV,6BAA6B,EAC7B,8BAA8B,EAC9B,gCAAgC,EACjC,MAAM,mBAAmB,CAAC;AA4G3B;;;;;GAKG;AACH,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClE,qBAAqB,CAAC,EAAE,CACtB,aAAa,EAAE,MAAM,EACrB,qBAAqB,EAAE,MAAM,EAC7B,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,MAAM,EAAE,4BAA4B,KACjC,OAAO,CAAC,8BAA8B,GAAG,SAAS,CAAC,GAAG,8BAA8B,GAAG,SAAS,CAAC;IACtG,kBAAkB,CAAC,EAAE,CACnB,aAAa,EAAE,MAAM,EACrB,qBAAqB,EAAE,MAAM,EAC7B,kBAAkB,EAAE,MAAM,GAAG,SAAS,KACnC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,oBAAoB,CAAC,EAAE,CACrB,OAAO,EAAE,6BAA6B,KACnC,gCAAgC,GAAG,SAAS,CAAC;IAClD,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oCAAoC,CAAC,EAAE,OAAO,CAAC;IAC/C,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,GAAG,OAAO,CAAC,MAAM,CAAC,CA4MlB"}
@@ -149,6 +149,7 @@ export async function mkdirPathComponentsWithGuards(params) {
149
149
  if (params.revalidateParentAfterBeforeComponent) {
150
150
  await assertAsyncDirectoryGuard(parentGuard);
151
151
  }
152
+ let shouldCreate = true;
152
153
  if (params.beforeCreateComponent) {
153
154
  let missing = false;
154
155
  try {
@@ -159,6 +160,7 @@ export async function mkdirPathComponentsWithGuards(params) {
159
160
  throw error;
160
161
  missing = true;
161
162
  }
163
+ shouldCreate = missing;
162
164
  if (missing) {
163
165
  let prospectiveParent = retainedParentPath;
164
166
  if (!prospectiveParent) {
@@ -177,36 +179,12 @@ export async function mkdirPathComponentsWithGuards(params) {
177
179
  if (!params.synchronousAuthorizationIncludesFence)
178
180
  inspectGuardCurrent(parentGuard);
179
181
  }
180
- params.assertBeforeMutation?.();
181
- // Authority callbacks are an explicit freshness boundary. Recheck the
182
- // exact parent synchronously so no callback-observed authority is
183
- // carried into a pathname mkdir after the parent was swapped.
184
- inspectGuardCurrent(parentGuard);
185
- try {
186
- if (params.private) {
187
- await createDirectoryWithAdmission(next, {
188
- private: true,
189
- mode: params.mode,
190
- assertBeforeMutation: params.assertBeforeMutation,
191
- }, {
192
- expectedParentIdentity: {
193
- dev: parentGuard.stat.dev, ino: parentGuard.stat.ino, realPath: parentGuard.realPath,
194
- },
195
- });
196
- }
197
- else {
198
- await fs.mkdir(next, { mode: params.mode });
199
- }
200
- created = true;
201
- }
202
- catch (error) {
203
- if (!isDirectoryCollision(error))
204
- throw error;
205
- }
206
182
  }
207
183
  }
208
- else {
184
+ if (shouldCreate) {
209
185
  params.assertBeforeMutation?.();
186
+ // Both policy and ordinary mkdir must renew the parent after callbacks.
187
+ inspectGuardCurrent(parentGuard);
210
188
  try {
211
189
  if (params.private) {
212
190
  await createDirectoryWithAdmission(next, {
@@ -222,6 +200,7 @@ export async function mkdirPathComponentsWithGuards(params) {
222
200
  else {
223
201
  await fs.mkdir(next, { mode: params.mode });
224
202
  }
203
+ created = true;
225
204
  }
226
205
  catch (error) {
227
206
  if (!isDirectoryCollision(error))
@@ -1 +1 @@
1
- {"version":3,"file":"install-path.d.ts","sourceRoot":"","sources":["../src/install-path.ts"],"names":[],"mappings":"AAWA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB3D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA+B5D;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEhB"}
1
+ {"version":3,"file":"install-path.d.ts","sourceRoot":"","sources":["../src/install-path.ts"],"names":[],"mappings":"AAWA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc3D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA+B5D;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEhB"}
@@ -15,11 +15,8 @@ export function safeDirName(input) {
15
15
  export function safePathSegmentHashed(input) {
16
16
  const trimmed = input.trim();
17
17
  const base = trimmed
18
- .replaceAll(/[\\/]/g, "-")
19
- .replaceAll(/[^a-zA-Z0-9._-]/g, "-")
20
- .replaceAll(/-+/g, "-")
21
- .replaceAll(/^-+/g, "")
22
- .replaceAll(/-+$/g, "");
18
+ .replaceAll(/[^a-zA-Z0-9._]+/g, "-")
19
+ .replaceAll(/^-|-$/g, "");
23
20
  const normalized = base.length > 0 ? base : "skill";
24
21
  const safe = normalized === "." || normalized === ".." ? "skill" : normalized;
25
22
  if (safe !== trimmed || safe.length > 60) {
@@ -1 +1 @@
1
- {"version":3,"file":"json-durable-queue-ownership.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-ownership.ts"],"names":[],"mappings":"AAEA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAUnD,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,QAAQ,CAAC;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAUH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,0BAA0B,GAChC,+BAA+B,CAkBjC;AAyFD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,0BAA0B,EACjC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAGD,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,KAAK,EAAE,0BAA0B,EACjC,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACnC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACxE,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,OAAO,CAAC,CAclB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhB;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI1D"}
1
+ {"version":3,"file":"json-durable-queue-ownership.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-ownership.ts"],"names":[],"mappings":"AAEA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAUnD,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG,QAAQ,CAAC;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAUH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,0BAA0B,GAChC,+BAA+B,CAkBjC;AAyFD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,0BAA0B,EACjC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB;AAGD,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,KAAK,EAAE,0BAA0B,EACjC,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACnC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACxE,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhB;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI1D"}