@openclaw/fs-safe 0.6.0 → 0.7.1

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 (202) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +7 -0
  3. package/dist/archive-deadline.d.ts +3 -0
  4. package/dist/archive-deadline.d.ts.map +1 -1
  5. package/dist/archive-deadline.js +44 -8
  6. package/dist/archive-entry.d.ts.map +1 -1
  7. package/dist/archive-entry.js +1 -0
  8. package/dist/archive-errors.d.ts +1 -0
  9. package/dist/archive-errors.d.ts.map +1 -1
  10. package/dist/archive-errors.js +3 -0
  11. package/dist/archive-input.d.ts.map +1 -1
  12. package/dist/archive-input.js +26 -16
  13. package/dist/archive-limits.d.ts +11 -3
  14. package/dist/archive-limits.d.ts.map +1 -1
  15. package/dist/archive-limits.js +24 -0
  16. package/dist/archive-native.d.ts +3 -2
  17. package/dist/archive-native.d.ts.map +1 -1
  18. package/dist/archive-native.js +24 -9
  19. package/dist/archive-policy.d.ts +2 -0
  20. package/dist/archive-policy.d.ts.map +1 -1
  21. package/dist/archive-policy.js +9 -1
  22. package/dist/archive-read.d.ts.map +1 -1
  23. package/dist/archive-read.js +69 -41
  24. package/dist/archive-staging.d.ts +3 -0
  25. package/dist/archive-staging.d.ts.map +1 -1
  26. package/dist/archive-staging.js +91 -43
  27. package/dist/archive-tar-admission.d.ts +7 -0
  28. package/dist/archive-tar-admission.d.ts.map +1 -0
  29. package/dist/archive-tar-admission.js +43 -0
  30. package/dist/archive-tar-gnu.d.ts +2 -0
  31. package/dist/archive-tar-gnu.d.ts.map +1 -0
  32. package/dist/archive-tar-gnu.js +20 -0
  33. package/dist/archive-tar-header.d.ts +8 -0
  34. package/dist/archive-tar-header.d.ts.map +1 -0
  35. package/dist/archive-tar-header.js +47 -0
  36. package/dist/archive-tar-meta.d.ts +29 -1
  37. package/dist/archive-tar-meta.d.ts.map +1 -1
  38. package/dist/archive-tar-meta.js +104 -35
  39. package/dist/archive-tar-runtime.d.ts +3 -0
  40. package/dist/archive-tar-runtime.d.ts.map +1 -1
  41. package/dist/archive-tar-runtime.js +3 -0
  42. package/dist/archive-tar.d.ts.map +1 -1
  43. package/dist/archive-tar.js +8 -2
  44. package/dist/archive-zip-names.js +2 -2
  45. package/dist/archive.d.ts.map +1 -1
  46. package/dist/archive.js +38 -27
  47. package/dist/atomic.d.ts +1 -1
  48. package/dist/atomic.d.ts.map +1 -1
  49. package/dist/bounded-read-stream.d.ts.map +1 -1
  50. package/dist/bounded-read-stream.js +2 -4
  51. package/dist/bounded-read.d.ts.map +1 -1
  52. package/dist/bounded-read.js +3 -10
  53. package/dist/byte-budget.d.ts +5 -0
  54. package/dist/byte-budget.d.ts.map +1 -0
  55. package/dist/byte-budget.js +9 -0
  56. package/dist/directory-guard.d.ts +2 -1
  57. package/dist/directory-guard.d.ts.map +1 -1
  58. package/dist/directory-guard.js +10 -0
  59. package/dist/file-lock-sync.d.ts.map +1 -1
  60. package/dist/file-lock-sync.js +81 -30
  61. package/dist/file-observation.d.ts +9 -0
  62. package/dist/file-observation.d.ts.map +1 -0
  63. package/dist/file-observation.js +22 -0
  64. package/dist/file-store-boundary.d.ts.map +1 -1
  65. package/dist/file-store-boundary.js +9 -5
  66. package/dist/file-store-limit.d.ts +2 -0
  67. package/dist/file-store-limit.d.ts.map +1 -0
  68. package/dist/file-store-limit.js +8 -0
  69. package/dist/file-store-sync-write.d.ts.map +1 -1
  70. package/dist/file-store-sync-write.js +38 -8
  71. package/dist/file-store.d.ts.map +1 -1
  72. package/dist/file-store.js +26 -26
  73. package/dist/json-durable-queue-directory.d.ts +2 -0
  74. package/dist/json-durable-queue-directory.d.ts.map +1 -0
  75. package/dist/json-durable-queue-directory.js +20 -0
  76. package/dist/json-durable-queue-ownership.d.ts +14 -0
  77. package/dist/json-durable-queue-ownership.d.ts.map +1 -0
  78. package/dist/json-durable-queue-ownership.js +168 -0
  79. package/dist/json-durable-queue-retirement.d.ts +9 -0
  80. package/dist/json-durable-queue-retirement.d.ts.map +1 -0
  81. package/dist/json-durable-queue-retirement.js +126 -0
  82. package/dist/json-durable-queue-transfer-lock.d.ts +2 -0
  83. package/dist/json-durable-queue-transfer-lock.d.ts.map +1 -0
  84. package/dist/json-durable-queue-transfer-lock.js +19 -0
  85. package/dist/json-durable-queue.d.ts +1 -0
  86. package/dist/json-durable-queue.d.ts.map +1 -1
  87. package/dist/json-durable-queue.js +90 -57
  88. package/dist/json.d.ts.map +1 -1
  89. package/dist/json.js +32 -13
  90. package/dist/local-roots.d.ts.map +1 -1
  91. package/dist/local-roots.js +4 -2
  92. package/dist/native-binding.d.ts +12 -3
  93. package/dist/native-binding.d.ts.map +1 -1
  94. package/dist/native-pinned-write-windows.js +1 -1
  95. package/dist/opened-file-failure.d.ts +7 -0
  96. package/dist/opened-file-failure.d.ts.map +1 -0
  97. package/dist/opened-file-failure.js +41 -0
  98. package/dist/opened-realpath.d.ts.map +1 -1
  99. package/dist/opened-realpath.js +8 -2
  100. package/dist/output-sibling.d.ts.map +1 -1
  101. package/dist/output-sibling.js +11 -110
  102. package/dist/output.d.ts.map +1 -1
  103. package/dist/output.js +4 -2
  104. package/dist/pinned-open.d.ts.map +1 -1
  105. package/dist/pinned-open.js +27 -48
  106. package/dist/pinned-write.d.ts.map +1 -1
  107. package/dist/pinned-write.js +10 -10
  108. package/dist/private-temp-workspace.d.ts +3 -1
  109. package/dist/private-temp-workspace.d.ts.map +1 -1
  110. package/dist/private-temp-workspace.js +81 -56
  111. package/dist/publish-file.d.ts.map +1 -1
  112. package/dist/publish-file.js +2 -4
  113. package/dist/read-opened-file.d.ts.map +1 -1
  114. package/dist/read-opened-file.js +6 -4
  115. package/dist/regular-file.d.ts.map +1 -1
  116. package/dist/regular-file.js +136 -82
  117. package/dist/replace-file-copy-fallback.d.ts +3 -1
  118. package/dist/replace-file-copy-fallback.d.ts.map +1 -1
  119. package/dist/replace-file-copy-fallback.js +21 -36
  120. package/dist/replace-file-copy-source.d.ts +21 -0
  121. package/dist/replace-file-copy-source.d.ts.map +1 -0
  122. package/dist/replace-file-copy-source.js +112 -0
  123. package/dist/replace-file-descriptor.d.ts +13 -3
  124. package/dist/replace-file-descriptor.d.ts.map +1 -1
  125. package/dist/replace-file-descriptor.js +32 -7
  126. package/dist/replace-file-rename-policy.d.ts +7 -0
  127. package/dist/replace-file-rename-policy.d.ts.map +1 -0
  128. package/dist/replace-file-rename-policy.js +30 -0
  129. package/dist/replace-file-temp-owner.d.ts +46 -0
  130. package/dist/replace-file-temp-owner.d.ts.map +1 -0
  131. package/dist/replace-file-temp-owner.js +346 -0
  132. package/dist/replace-file.d.ts +6 -1
  133. package/dist/replace-file.d.ts.map +1 -1
  134. package/dist/replace-file.js +72 -58
  135. package/dist/root-impl.d.ts.map +1 -1
  136. package/dist/root-impl.js +113 -82
  137. package/dist/secret-file.d.ts.map +1 -1
  138. package/dist/secret-file.js +6 -3
  139. package/dist/secret-read-async.d.ts.map +1 -1
  140. package/dist/secret-read-async.js +6 -5
  141. package/dist/secure-file.d.ts.map +1 -1
  142. package/dist/secure-file.js +17 -13
  143. package/dist/sibling-staged-file.d.ts +15 -0
  144. package/dist/sibling-staged-file.d.ts.map +1 -0
  145. package/dist/sibling-staged-file.js +148 -0
  146. package/dist/sibling-temp.d.ts +3 -0
  147. package/dist/sibling-temp.d.ts.map +1 -1
  148. package/dist/sibling-temp.js +30 -74
  149. package/dist/sidecar-lock-acquire.d.ts.map +1 -1
  150. package/dist/sidecar-lock-acquire.js +91 -37
  151. package/dist/sidecar-lock-handle.d.ts +6 -2
  152. package/dist/sidecar-lock-handle.d.ts.map +1 -1
  153. package/dist/sidecar-lock-handle.js +17 -3
  154. package/dist/sidecar-lock-policy.d.ts +2 -0
  155. package/dist/sidecar-lock-policy.d.ts.map +1 -1
  156. package/dist/sidecar-lock-policy.js +29 -0
  157. package/dist/sidecar-lock-reclaim.d.ts +16 -5
  158. package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
  159. package/dist/sidecar-lock-reclaim.js +60 -28
  160. package/dist/sidecar-lock-root.d.ts +3 -0
  161. package/dist/sidecar-lock-root.d.ts.map +1 -0
  162. package/dist/sidecar-lock-root.js +76 -0
  163. package/dist/sidecar-lock.d.ts.map +1 -1
  164. package/dist/sidecar-lock.js +28 -16
  165. package/dist/strict-file-identity.d.ts.map +1 -1
  166. package/dist/strict-file-identity.js +4 -1
  167. package/dist/suppressed-error.d.ts +6 -0
  168. package/dist/suppressed-error.d.ts.map +1 -0
  169. package/dist/suppressed-error.js +15 -0
  170. package/dist/temp-cleanup.d.ts +2 -0
  171. package/dist/temp-cleanup.d.ts.map +1 -1
  172. package/dist/temp-cleanup.js +25 -10
  173. package/dist/temp-workspace-owner.d.ts +23 -0
  174. package/dist/temp-workspace-owner.d.ts.map +1 -0
  175. package/dist/temp-workspace-owner.js +320 -0
  176. package/dist/temp.d.ts +1 -1
  177. package/dist/temp.d.ts.map +1 -1
  178. package/dist/test-hooks.d.ts +5 -0
  179. package/dist/test-hooks.d.ts.map +1 -1
  180. package/docs/advanced.md +8 -1
  181. package/docs/archive.md +202 -26
  182. package/docs/atomic.md +11 -2
  183. package/docs/durability.md +1 -1
  184. package/docs/file-store.md +2 -0
  185. package/docs/install.md +8 -4
  186. package/docs/json.md +11 -4
  187. package/docs/native-helper.md +15 -3
  188. package/docs/native.md +33 -6
  189. package/docs/output.md +16 -3
  190. package/docs/public-api.md +6 -3
  191. package/docs/quickstart.md +1 -1
  192. package/docs/reading.md +1 -1
  193. package/docs/regular-file.md +9 -2
  194. package/docs/root.md +2 -0
  195. package/docs/secret-file.md +5 -1
  196. package/docs/secure-file.md +4 -2
  197. package/docs/security-model.md +18 -0
  198. package/docs/sidecar-lock.md +60 -4
  199. package/docs/store.md +13 -0
  200. package/docs/temp.md +128 -14
  201. package/docs/writing.md +6 -0
  202. package/package.json +10 -10
@@ -3,11 +3,13 @@ import fsp from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { canonicalPathFromExistingAncestor } from "./absolute-path.js";
5
5
  import { readFileDescriptorBoundedSync } from "./bounded-read.js";
6
+ import { normalizeMaxBytes } from "./byte-budget.js";
6
7
  import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard } from "./directory-guard.js";
7
8
  import { FsSafeError } from "./errors.js";
8
9
  import { sameFileIdentity } from "./file-identity.js";
9
10
  import { resolveHomeRelativePath } from "./home-dir.js";
10
11
  import { openPinnedFileSync } from "./pinned-open.js";
12
+ import { resolveReadOpenFlags } from "./read-open-flags.js";
11
13
  import { runPinnedWriteHelper } from "./pinned-write.js";
12
14
  import { assertSecretFilePreview, DEFAULT_SECRET_FILE_MAX_BYTES, secretPathErrorCode, secretReadError, trimSecretFileContent, } from "./secret-read-policy.js";
13
15
  import { inspectFileIdentitySync } from "./strict-file-identity.js";
@@ -19,7 +21,9 @@ export function readSecretFileSync(filePath, label, options = {}) {
19
21
  if (!resolvedPath) {
20
22
  throw new FsSafeError("invalid-path", `${label} file path is empty.`, { cause: undefined });
21
23
  }
22
- const maxBytes = options.maxBytes ?? DEFAULT_SECRET_FILE_MAX_BYTES;
24
+ const maxBytes = normalizeMaxBytes(options.maxBytes, {
25
+ defaultValue: DEFAULT_SECRET_FILE_MAX_BYTES,
26
+ });
23
27
  function inspectInput(symlinkMessage) {
24
28
  const stat = options.rejectSymlink
25
29
  ? fs.lstatSync(resolvedPath, { bigint: true })
@@ -112,8 +116,7 @@ async function enforcePrivatePathMode(resolvedPath, expectedMode, kind) {
112
116
  }
113
117
  }
114
118
  async function enforcePrivateFileIdentityAndMode(resolvedPath, expectedIdentity, expectedMode) {
115
- const noFollowFlag = process.platform !== "win32" && "O_NOFOLLOW" in fs.constants ? fs.constants.O_NOFOLLOW : 0;
116
- const handle = await fsp.open(resolvedPath, fs.constants.O_RDONLY | noFollowFlag);
119
+ const handle = await fsp.open(resolvedPath, resolveReadOpenFlags());
117
120
  try {
118
121
  const openedStat = await handle.stat();
119
122
  if (!openedStat.isFile() || !sameFileIdentity(openedStat, expectedIdentity)) {
@@ -1 +1 @@
1
- {"version":3,"file":"secret-read-async.d.ts","sourceRoot":"","sources":["../src/secret-read-async.ts"],"names":[],"mappings":"AAMA,OAAO,EAML,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAEjC,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,CAgEjB;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B"}
1
+ {"version":3,"file":"secret-read-async.d.ts","sourceRoot":"","sources":["../src/secret-read-async.ts"],"names":[],"mappings":"AAQA,OAAO,EAML,KAAK,qBAAqB,EAC3B,MAAM,yBAAyB,CAAC;AAEjC,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,CA8DjB;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAQ7B"}
@@ -1,8 +1,10 @@
1
1
  import fsSync from "node:fs";
2
2
  import fs from "node:fs/promises";
3
3
  import { readFileHandleBounded } from "./bounded-read.js";
4
+ import { normalizeMaxBytes } from "./byte-budget.js";
4
5
  import { FsSafeError } from "./errors.js";
5
6
  import { resolveHomeRelativePath } from "./home-dir.js";
7
+ import { resolveReadOpenFlags } from "./read-open-flags.js";
6
8
  import { inspectFileIdentity } from "./strict-file-identity.js";
7
9
  import { assertSecretFilePreview, DEFAULT_SECRET_FILE_MAX_BYTES, secretPathErrorCode, secretReadError, trimSecretFileContent, } from "./secret-read-policy.js";
8
10
  export async function readSecretFile(filePath, label, options = {}) {
@@ -10,7 +12,9 @@ export async function readSecretFile(filePath, label, options = {}) {
10
12
  if (!resolvedPath) {
11
13
  throw new FsSafeError("invalid-path", `${label} file path is empty.`, { cause: undefined });
12
14
  }
13
- const maxBytes = options.maxBytes ?? DEFAULT_SECRET_FILE_MAX_BYTES;
15
+ const maxBytes = normalizeMaxBytes(options.maxBytes, {
16
+ defaultValue: DEFAULT_SECRET_FILE_MAX_BYTES,
17
+ });
14
18
  async function inspectInput(symlinkMessage) {
15
19
  const stat = options.rejectSymlink
16
20
  ? await fs.lstat(resolvedPath, { bigint: true })
@@ -32,10 +36,7 @@ export async function readSecretFile(filePath, label, options = {}) {
32
36
  let raw;
33
37
  try {
34
38
  const realPath = await fs.realpath(resolvedPath);
35
- const noFollow = process.platform !== "win32" && "O_NOFOLLOW" in fsSync.constants
36
- ? fsSync.constants.O_NOFOLLOW
37
- : 0;
38
- handle = await fs.open(realPath, fsSync.constants.O_RDONLY | noFollow);
39
+ handle = await fs.open(realPath, resolveReadOpenFlags());
39
40
  const openedHandle = handle;
40
41
  const openedStat = await inspectFileIdentity(async () => {
41
42
  const stat = await openedHandle.stat({ bigint: true });
@@ -1 +1 @@
1
- {"version":3,"file":"secure-file.d.ts","sourceRoot":"","sources":["../src/secure-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAYrC,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAM1B,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,sBAAsB,CAAC;IAC/B,WAAW,CAAC,EAAE,2BAA2B,CAAC;IAC1C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,EAAE,CAAC,EAAE,mBAAmB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,CAAC;AAE7D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAyLF,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAc/B"}
1
+ {"version":3,"file":"secure-file.d.ts","sourceRoot":"","sources":["../src/secure-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAarC,OAAO,EAOL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,kBAAkB,CAAC;AAG1B,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,sBAAsB,CAAC;IAC/B,WAAW,CAAC,EAAE,2BAA2B,CAAC;IAC1C,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,EAAE,CAAC,EAAE,mBAAmB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,CAAC;AAE7D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AA4LF,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAe/B"}
@@ -1,16 +1,15 @@
1
- import { constants as fsConstants } from "node:fs";
2
1
  import fs from "node:fs/promises";
3
2
  import path from "node:path";
4
3
  import { readFileHandleBounded } from "./bounded-read.js";
4
+ import { normalizeMaxBytes } from "./byte-budget.js";
5
5
  import { assertNoUnsafeDeviceReadPath } from "./device-path.js";
6
6
  import { FsSafeError } from "./errors.js";
7
7
  import { isWindowsDriveLetterPath, isWindowsNetworkPath } from "./local-file-access.js";
8
8
  import { isPathInside, isSymlinkOpenError } from "./path.js";
9
9
  import { formatPermissionErrorDetail } from "./permission-exec.js";
10
+ import { resolveReadOpenFlags } from "./read-open-flags.js";
10
11
  import { inspectPathPermissions, isGroupReadable, isGroupWritable, isWorldReadable, isWorldWritable, modeBits, } from "./permissions.js";
11
12
  import { inspectFileIdentity } from "./strict-file-identity.js";
12
- const SUPPORTS_NOFOLLOW = process.platform !== "win32" && "O_NOFOLLOW" in fsConstants;
13
- const OPEN_READ_FLAGS = fsConstants.O_RDONLY | (SUPPORTS_NOFOLLOW ? fsConstants.O_NOFOLLOW : 0);
14
13
  function isAbsolutePathname(value) {
15
14
  return (path.isAbsolute(value) ||
16
15
  (process.platform === "win32" &&
@@ -19,7 +18,7 @@ function isAbsolutePathname(value) {
19
18
  function label(options) {
20
19
  return options.label ?? "Secure file";
21
20
  }
22
- async function openSecureHandle(options) {
21
+ async function openSecureHandle(options, maxBytes) {
23
22
  assertNoUnsafeDeviceReadPath(options.filePath);
24
23
  if (isWindowsNetworkPath(options.filePath, "win32") && !options.trust?.allowNetworkPath) {
25
24
  throw new FsSafeError("invalid-path", `${label(options)} must be a local absolute path.`);
@@ -32,15 +31,19 @@ async function openSecureHandle(options) {
32
31
  cause: err,
33
32
  });
34
33
  });
35
- if (preStat.isDirectory()) {
36
- throw new FsSafeError("not-file", `${label(options)} must be a file: ${options.filePath}`);
34
+ if (preStat.isSymbolicLink()) {
35
+ if (!options.trust?.allowSymlink) {
36
+ throw new FsSafeError("symlink", `${label(options)} must not be a symlink: ${options.filePath}`);
37
+ }
37
38
  }
38
- if (preStat.isSymbolicLink() && !options.trust?.allowSymlink) {
39
- throw new FsSafeError("symlink", `${label(options)} must not be a symlink: ${options.filePath}`);
39
+ else if (!preStat.isFile()) {
40
+ throw new FsSafeError("not-file", `${label(options)} must be a file: ${options.filePath}`);
40
41
  }
41
42
  let handle;
42
43
  try {
43
- handle = await fs.open(options.filePath, options.trust?.allowSymlink ? fsConstants.O_RDONLY : OPEN_READ_FLAGS);
44
+ handle = await fs.open(options.filePath, resolveReadOpenFlags({
45
+ followSymlinks: options.trust?.allowSymlink === true,
46
+ }));
44
47
  }
45
48
  catch (err) {
46
49
  if (isSymlinkOpenError(err)) {
@@ -65,8 +68,8 @@ async function openSecureHandle(options) {
65
68
  }, openedIdentity);
66
69
  const realPath = await fs.realpath(options.filePath);
67
70
  await inspectFileIdentity(() => fs.stat(realPath, { bigint: true }), openedIdentity);
68
- if (options.io?.maxBytes !== undefined && openedStat.size > options.io.maxBytes) {
69
- throw new FsSafeError("too-large", `${label(options)} exceeded maxBytes (${options.io.maxBytes}).`);
71
+ if (maxBytes !== undefined && openedStat.size > maxBytes) {
72
+ throw new FsSafeError("too-large", `${label(options)} exceeded maxBytes (${maxBytes}).`);
70
73
  }
71
74
  return { handle, pathStat: openedStat, realPath };
72
75
  }
@@ -165,11 +168,12 @@ async function readHandleWithTimeout(handle, timeoutMs, maxBytes) {
165
168
  }
166
169
  }
167
170
  export async function readSecureFile(options) {
168
- const opened = await openSecureHandle(options);
171
+ const maxBytes = normalizeMaxBytes(options.io?.maxBytes);
172
+ const opened = await openSecureHandle(options, maxBytes);
169
173
  try {
170
174
  await assertTrustedDirs(options, opened.realPath);
171
175
  const permissions = await assertSecurePermissions(options, opened.pathStat, opened.realPath);
172
- const buffer = await readHandleWithTimeout(opened.handle, options.io?.timeoutMs, options.io?.maxBytes);
176
+ const buffer = await readHandleWithTimeout(opened.handle, options.io?.timeoutMs, maxBytes);
173
177
  return { buffer, realPath: opened.realPath, stat: opened.pathStat, permissions };
174
178
  }
175
179
  finally {
@@ -0,0 +1,15 @@
1
+ export declare function writeCallbackSibling<T>(params: {
2
+ tempPath: string;
3
+ write: (tempPath: string) => Promise<T>;
4
+ resolveFinalPath: (result: T) => string;
5
+ mode?: number;
6
+ /** Preserve the caller's historical best-effort mode behavior. */
7
+ ignoreModeError?: boolean;
8
+ maxBytes?: number;
9
+ syncTempFile: boolean;
10
+ syncParentDir: boolean;
11
+ }): Promise<{
12
+ filePath: string;
13
+ result: T;
14
+ }>;
15
+ //# sourceMappingURL=sibling-staged-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sibling-staged-file.d.ts","sourceRoot":"","sources":["../src/sibling-staged-file.ts"],"names":[],"mappings":"AAkCA,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACxC,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;CACxB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAAC,CA6G3C"}
@@ -0,0 +1,148 @@
1
+ import fsSync, {} from "node:fs";
2
+ import fs, {} from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard } from "./directory-guard.js";
5
+ import { syncDirectoryBestEffort } from "./directory-durability.js";
6
+ import { FsSafeError } from "./errors.js";
7
+ import { resolveReadOpenFlags } from "./read-open-flags.js";
8
+ import { inspectFileIdentity } from "./strict-file-identity.js";
9
+ import { registerTempPathForExit } from "./temp-cleanup.js";
10
+ import { serializePathWrite } from "./write-queue.js";
11
+ function assertRegularFile(stat) {
12
+ if (stat.isSymbolicLink()) {
13
+ throw new FsSafeError("symlink", "symlink sibling temp not allowed");
14
+ }
15
+ if (!stat.isFile()) {
16
+ throw new FsSafeError("not-file", "sibling temp must be a regular file");
17
+ }
18
+ if (stat.nlink !== 1n) {
19
+ throw new FsSafeError("hardlink", "sibling temp must have exactly one link");
20
+ }
21
+ }
22
+ async function inspectStage(inspect, expected) {
23
+ return await inspectFileIdentity(async () => {
24
+ const stat = await inspect();
25
+ assertRegularFile(stat);
26
+ return stat;
27
+ }, expected);
28
+ }
29
+ // Callback paths are not owned until all three admission observations agree.
30
+ // Keep one descriptor and one exact identity through mode, sync, rename and cleanup.
31
+ // Read/write access is needed only when the caller requests file synchronization.
32
+ export async function writeCallbackSibling(params) {
33
+ const parent = path.dirname(params.tempPath);
34
+ const guard = await createAsyncDirectoryGuard(parent);
35
+ const parentIdentity = await inspectFileIdentity(() => fs.lstat(parent, { bigint: true }));
36
+ const assertParent = async () => {
37
+ await assertAsyncDirectoryGuard(guard);
38
+ await inspectFileIdentity(() => fs.lstat(parent, { bigint: true }), parentIdentity);
39
+ };
40
+ let handle;
41
+ let identity;
42
+ let unregister;
43
+ let renamed = false;
44
+ let failure;
45
+ const inspectPath = (pathname, expected) => inspectStage(() => fs.lstat(pathname, { bigint: true }), expected);
46
+ const assertCurrent = async (pathname) => {
47
+ await assertParent();
48
+ const opened = await inspectStage(() => handle.stat({ bigint: true }), identity);
49
+ const current = await inspectPath(pathname, opened);
50
+ if (params.maxBytes !== undefined &&
51
+ (opened.size > params.maxBytes || current.size > params.maxBytes)) {
52
+ throw new FsSafeError("too-large", `sibling temp exceeds maxBytes (${params.maxBytes})`);
53
+ }
54
+ };
55
+ try {
56
+ const result = await params.write(params.tempPath);
57
+ await assertParent();
58
+ const before = await inspectPath(params.tempPath);
59
+ try {
60
+ // No create/truncate flags; O_NONBLOCK also bounds a FIFO swap during open.
61
+ const access = params.syncTempFile ? fsSync.constants.O_RDWR : fsSync.constants.O_RDONLY;
62
+ handle = await fs.open(params.tempPath, access | resolveReadOpenFlags());
63
+ }
64
+ catch (error) {
65
+ if (error?.code === "ELOOP") {
66
+ throw new FsSafeError("symlink", "symlink sibling temp not allowed", { cause: error });
67
+ }
68
+ throw error;
69
+ }
70
+ const opened = await inspectStage(() => handle.stat({ bigint: true }), before);
71
+ await inspectPath(params.tempPath, opened);
72
+ await assertParent();
73
+ identity = opened;
74
+ unregister = registerTempPathForExit(params.tempPath, { identity, singleLinkFile: true });
75
+ const filePath = path.resolve(params.resolveFinalPath(result));
76
+ if (path.dirname(filePath) !== parent) {
77
+ throw new Error("Final path must be in the sibling temp directory.");
78
+ }
79
+ if (filePath === params.tempPath) {
80
+ throw new FsSafeError("invalid-path", "final path must differ from the sibling temp path");
81
+ }
82
+ await serializePathWrite(filePath, async () => {
83
+ await assertCurrent(params.tempPath);
84
+ if (params.mode !== undefined) {
85
+ try {
86
+ await handle.chmod(params.mode);
87
+ }
88
+ catch (error) {
89
+ if (!params.ignoreModeError)
90
+ throw error;
91
+ }
92
+ }
93
+ if (params.syncTempFile) {
94
+ await assertCurrent(params.tempPath);
95
+ try {
96
+ await handle.sync();
97
+ }
98
+ catch (error) {
99
+ if (error?.code !== "EPERM")
100
+ throw error;
101
+ }
102
+ }
103
+ await assertCurrent(params.tempPath);
104
+ await fs.rename(params.tempPath, filePath);
105
+ // A later verification failure never authorizes rollback of the final name.
106
+ renamed = true;
107
+ unregister();
108
+ await assertCurrent(filePath);
109
+ if (params.syncParentDir)
110
+ await syncDirectoryBestEffort(parent);
111
+ await assertCurrent(filePath);
112
+ });
113
+ return { filePath, result };
114
+ }
115
+ catch (error) {
116
+ failure = { error };
117
+ throw error;
118
+ }
119
+ finally {
120
+ try {
121
+ if (!renamed && identity) {
122
+ try {
123
+ await assertParent();
124
+ await inspectStage(() => handle.stat({ bigint: true }), identity);
125
+ await inspectPath(params.tempPath, identity);
126
+ await fs.unlink(params.tempPath);
127
+ unregister?.();
128
+ }
129
+ catch (error) {
130
+ // Preserve observed substitutes; retry only operational cleanup failures.
131
+ if (error instanceof FsSafeError || error?.code === "ENOENT") {
132
+ unregister?.();
133
+ }
134
+ }
135
+ }
136
+ }
137
+ finally {
138
+ try {
139
+ await handle?.close();
140
+ }
141
+ catch (error) {
142
+ if (failure)
143
+ throw new AggregateError([failure.error, error], "sibling publication and close failed");
144
+ throw error;
145
+ }
146
+ }
147
+ }
148
+ }
@@ -5,8 +5,11 @@ export type WriteSiblingTempFileOptions<T> = {
5
5
  tempPrefix?: string;
6
6
  dirMode?: number;
7
7
  chmodDir?: boolean;
8
+ /** Final file mode; omitted preserves the producer's mode. Applied through the retained descriptor. */
8
9
  mode?: number;
10
+ /** Sync the staged descriptor before rename; defaults to false. */
9
11
  syncTempFile?: boolean;
12
+ /** Best-effort parent directory sync after rename; defaults to false. */
10
13
  syncParentDir?: boolean;
11
14
  };
12
15
  export type WriteSiblingTempFileResult<T> = {
@@ -1 +1 @@
1
- {"version":3,"file":"sibling-temp.d.ts","sourceRoot":"","sources":["../src/sibling-temp.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AA8BF,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,OAAO,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CA0CxC;AAkBD,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8ChB"}
1
+ {"version":3,"file":"sibling-temp.d.ts","sourceRoot":"","sources":["../src/sibling-temp.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,gBAAgB,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uGAAuG;IACvG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,CAAC;CACX,CAAC;AASF,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,OAAO,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAoBxC;AAkBD,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ChB"}
@@ -2,85 +2,40 @@ import crypto, { randomUUID } from "node:crypto";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard } from "./directory-guard.js";
5
- import { syncDirectoryBestEffort } from "./directory-durability.js";
6
- import { withAsyncDirectoryGuards } from "./guarded-mutation.js";
7
5
  import { sanitizeUntrustedFileName } from "./filename.js";
6
+ import { applyDirectoryMode } from "./replace-file-descriptor.js";
8
7
  import { root } from "./root.js";
9
8
  import { assertSafePathPrefix } from "./safe-path-segment.js";
10
9
  import { resolveSecureTempRoot } from "./secure-temp-dir.js";
11
- import { registerTempPathForExit } from "./temp-cleanup.js";
10
+ import { writeCallbackSibling } from "./sibling-staged-file.js";
11
+ import { tempFile } from "./temp-target.js";
12
12
  import { getFsSafeTestHooks } from "./test-hooks.js";
13
- import { serializePathWrite } from "./write-queue.js";
14
13
  function buildTempPath(dir, tempPrefix) {
15
14
  const safePrefix = assertSafePathPrefix(tempPrefix ?? ".fs-safe-stream", {
16
15
  label: "sibling temp prefix",
17
16
  });
18
17
  return path.join(dir, `${safePrefix}.${process.pid}.${randomUUID()}.tmp`);
19
18
  }
20
- async function syncFileBestEffort(filePath) {
21
- const handle = await fs.open(filePath, "r+");
22
- try {
23
- await handle.sync();
24
- }
25
- catch (error) {
26
- if (error.code !== "EPERM") {
27
- throw error;
28
- }
29
- }
30
- finally {
31
- await handle.close();
32
- }
33
- }
34
- function assertFinalPathIsSibling(dir, filePath) {
35
- const resolvedDir = path.resolve(dir);
36
- const resolvedFile = path.resolve(filePath);
37
- if (path.dirname(resolvedFile) !== resolvedDir) {
38
- throw new Error("Final path must be in the sibling temp directory.");
39
- }
40
- }
41
19
  export async function writeSiblingTempFile(options) {
42
20
  const dir = path.resolve(options.dir);
43
21
  await fs.mkdir(dir, { recursive: true, mode: options.dirMode ?? 0o700 });
44
22
  if (options.chmodDir !== false) {
45
- await fs.chmod(dir, options.dirMode ?? 0o700).catch(() => undefined);
46
- }
47
- const dirGuard = await createAsyncDirectoryGuard(dir);
48
- const tempPath = buildTempPath(dir, options.tempPrefix);
49
- const unregisterTempPath = registerTempPathForExit(tempPath);
50
- let tempExists = false;
51
- try {
52
- tempExists = true;
53
- const result = await options.writeTemp(tempPath);
54
- unregisterTempPath.setIdentity(await fs.lstat(tempPath, { bigint: true }));
55
- if (options.mode !== undefined) {
56
- await fs.chmod(tempPath, options.mode).catch(() => undefined);
57
- }
58
- if (options.syncTempFile) {
59
- await syncFileBestEffort(tempPath);
60
- }
61
- const filePath = path.resolve(options.resolveFinalPath(result));
62
- assertFinalPathIsSibling(dir, filePath);
63
- await serializePathWrite(filePath, async () => {
64
- await withAsyncDirectoryGuards([dirGuard], async () => {
65
- await fs.rename(tempPath, filePath);
66
- });
67
- tempExists = false;
68
- unregisterTempPath();
69
- if (options.mode !== undefined) {
70
- await fs.chmod(filePath, options.mode).catch(() => undefined);
71
- }
72
- if (options.syncParentDir) {
73
- await syncDirectoryBestEffort(dir);
74
- }
23
+ await applyDirectoryMode({
24
+ fsModule: fs,
25
+ dirPath: dir,
26
+ mode: options.dirMode ?? 0o700,
27
+ ignoreChmodError: true,
75
28
  });
76
- return { filePath, result };
77
- }
78
- finally {
79
- if (tempExists) {
80
- await fs.rm(tempPath, { force: true }).catch(() => undefined);
81
- }
82
- unregisterTempPath();
83
29
  }
30
+ return await writeCallbackSibling({
31
+ tempPath: buildTempPath(dir, options.tempPrefix),
32
+ write: options.writeTemp,
33
+ resolveFinalPath: options.resolveFinalPath,
34
+ mode: options.mode,
35
+ ignoreModeError: true,
36
+ syncTempFile: options.syncTempFile === true,
37
+ syncParentDir: options.syncParentDir === true,
38
+ });
84
39
  }
85
40
  function buildSiblingTempPath(params) {
86
41
  const id = crypto.randomUUID();
@@ -107,18 +62,20 @@ export async function writeViaSiblingTempPath(params) {
107
62
  throw new Error("Target path is outside the allowed root");
108
63
  }
109
64
  const rootGuard = await createAsyncDirectoryGuard(rootDir);
110
- const tempDir = await fs.mkdtemp(path.join(resolveSecureTempRoot({
111
- fallbackPrefix: "fs-safe-output",
112
- unsafeFallbackLabel: "sibling temp output dir",
113
- warn: () => undefined,
114
- }), "fs-safe-output-"));
115
- const tempPath = buildSiblingTempPath({
116
- targetPath: path.join(tempDir, path.basename(targetPath)),
117
- fallbackFileName: params.fallbackFileName ?? "output.bin",
118
- tempPrefix: params.tempPrefix ?? ".fs-safe-output-",
65
+ const workspace = await tempFile({
66
+ rootDir: resolveSecureTempRoot({
67
+ fallbackPrefix: "fs-safe-output",
68
+ unsafeFallbackLabel: "sibling temp output dir",
69
+ warn: () => undefined,
70
+ }),
71
+ prefix: "fs-safe-output",
119
72
  });
120
- const unregisterTempPath = registerTempPathForExit(tempDir, { recursive: true });
121
73
  try {
74
+ const tempPath = buildSiblingTempPath({
75
+ targetPath: path.join(workspace.dir, path.basename(targetPath)),
76
+ fallbackFileName: params.fallbackFileName ?? "output.bin",
77
+ tempPrefix: params.tempPrefix ?? ".fs-safe-output-",
78
+ });
122
79
  await getFsSafeTestHooks()?.beforeSiblingTempWrite?.(tempPath);
123
80
  await params.writeTemp(tempPath);
124
81
  await assertAsyncDirectoryGuard(rootGuard);
@@ -127,7 +84,6 @@ export async function writeViaSiblingTempPath(params) {
127
84
  await assertAsyncDirectoryGuard(rootGuard);
128
85
  }
129
86
  finally {
130
- await fs.rm(tempDir, { recursive: true, force: true }).catch(() => { });
131
- unregisterTempPath();
87
+ await workspace.cleanup();
132
88
  }
133
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sidecar-lock-acquire.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-acquire.ts"],"names":[],"mappings":"AAGA,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAO3C,OAAO,EAUL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5F,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAEhF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CAClC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,2BAA2B,IAAI,IAAI,CAAC;IACpC,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAC1F,eAAe,CACb,oBAAoB,EAAE,MAAM,EAC5B,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB,CAAC;AAaF,wBAAsB,kBAAkB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EAC5C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CAsP5B"}
1
+ {"version":3,"file":"sidecar-lock-acquire.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-acquire.ts"],"names":[],"mappings":"AAKA,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAS3C,OAAO,EAWL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG5F,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAEhF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CAClC,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACnC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,2BAA2B,IAAI,IAAI,CAAC;IACpC,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAC1F,eAAe,CACb,oBAAoB,EAAE,MAAM,EAC5B,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC5B,OAAO,CAAC,OAAO,CAAC,CAAC;CACrB,CAAC;AAaF,wBAAsB,kBAAkB,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,EAC5C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CA4S5B"}