@openclaw/fs-safe 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/README.md +8 -1
- package/dist/absolute-path.d.ts +0 -1
- package/dist/absolute-path.js +2 -8
- package/dist/advanced.d.ts +2 -1
- package/dist/advanced.js +2 -0
- package/dist/archive-crc32.d.ts +0 -1
- package/dist/archive-deadline.d.ts +0 -1
- package/dist/archive-deadline.js +22 -23
- package/dist/archive-durability.d.ts +0 -1
- package/dist/archive-entry.d.ts +0 -1
- package/dist/archive-errors.d.ts +0 -1
- package/dist/archive-gzip-tail.d.ts +0 -1
- package/dist/archive-input.d.ts +0 -1
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-limits.d.ts +0 -1
- package/dist/archive-merge.d.ts +3 -4
- package/dist/archive-merge.js +17 -7
- package/dist/archive-native.d.ts +3 -14
- package/dist/archive-native.js +46 -70
- package/dist/archive-options.d.ts +9 -2
- package/dist/archive-parser-errors.d.ts +0 -1
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-plan.d.ts +10 -1
- package/dist/archive-plan.js +31 -21
- package/dist/archive-policy.d.ts +0 -1
- package/dist/archive-read.d.ts +0 -1
- package/dist/archive-staging.d.ts +0 -1
- package/dist/archive-tar-inspect.d.ts +0 -1
- package/dist/archive-tar-stream.d.ts +0 -1
- package/dist/archive-tar-wasm.d.ts +0 -1
- package/dist/archive-tar.d.ts +0 -1
- package/dist/archive-zip-admission.d.ts +0 -1
- package/dist/archive-zip-count.d.ts +0 -1
- package/dist/archive-zip-count.js +21 -1
- package/dist/archive-zip-directory.d.ts +0 -1
- package/dist/archive-zip-directory.js +23 -1
- package/dist/archive-zip-entry.d.ts +0 -1
- package/dist/archive-zip-integrity.d.ts +0 -1
- package/dist/archive-zip-loader.d.ts +2 -1
- package/dist/archive-zip-loader.js +7 -0
- package/dist/archive-zip-manifest.d.ts +0 -1
- package/dist/archive-zip-names.d.ts +0 -1
- package/dist/archive-zip-names.js +7 -2
- package/dist/archive-zip-preflight.d.ts +0 -1
- package/dist/archive.d.ts +0 -1
- package/dist/archive.js +93 -164
- package/dist/async-lock.d.ts +0 -1
- package/dist/atomic.d.ts +0 -1
- package/dist/bounded-read-stream.d.ts +0 -1
- package/dist/bounded-read.d.ts +0 -1
- package/dist/byte-budget.d.ts +0 -1
- package/dist/byte-view.d.ts +2 -0
- package/dist/byte-view.js +13 -0
- package/dist/clone-metadata.d.ts +0 -1
- package/dist/config.d.ts +0 -1
- package/dist/containment.d.ts +0 -1
- package/dist/copy-file-input.d.ts +0 -1
- package/dist/copy-policy.d.ts +0 -1
- package/dist/copy-publication.d.ts +0 -1
- package/dist/copy-tree-portable.d.ts +0 -1
- package/dist/copy-tree-portable.js +9 -6
- package/dist/copy.d.ts +0 -1
- package/dist/copy.js +5 -5
- package/dist/create-directory.d.ts +0 -2
- package/dist/create-directory.js +3 -22
- package/dist/create-file-async.d.ts +0 -1
- package/dist/create-file.d.ts +0 -1
- package/dist/create-file.js +3 -14
- package/dist/create-owned-file.d.ts +0 -1
- package/dist/create.d.ts +1 -2
- package/dist/create.js +1 -1
- package/dist/creation-darwin.d.ts +0 -2
- package/dist/creation-darwin.js +0 -9
- package/dist/creation-file-state.d.ts +0 -1
- package/dist/creation-path.d.ts +2 -1
- package/dist/creation-path.js +12 -0
- package/dist/creation-permissions.d.ts +0 -1
- package/dist/creation-permissions.js +28 -38
- package/dist/deny-mutations.d.ts +2 -3
- package/dist/deny-mutations.js +55 -35
- package/dist/device-path.d.ts +0 -1
- package/dist/directory-durability.d.ts +6 -7
- package/dist/directory-entry-path.d.ts +0 -1
- package/dist/directory-guard.d.ts +2 -7
- package/dist/directory-guard.js +25 -56
- package/dist/directory-mode-node.d.ts +0 -1
- package/dist/directory-mode-owner.d.ts +0 -1
- package/dist/directory-receipt.d.ts +2 -3
- package/dist/directory-receipt.js +15 -19
- package/dist/durability.d.ts +0 -1
- package/dist/effective-uid.d.ts +0 -1
- package/dist/error-detail.d.ts +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/file-cleanup.d.ts +1 -1
- package/dist/file-cleanup.js +7 -4
- package/dist/file-contents.d.ts +5 -0
- package/dist/file-contents.js +40 -0
- package/dist/file-handle-transfer.d.ts +0 -1
- package/dist/file-hash.d.ts +0 -1
- package/dist/file-hash.js +186 -70
- package/dist/file-identity.d.ts +0 -1
- package/dist/file-lock-sync-acquisition.d.ts +22 -0
- package/dist/file-lock-sync-acquisition.js +98 -0
- package/dist/file-lock-sync-admission.d.ts +0 -2
- package/dist/file-lock-sync-admission.js +9 -48
- package/dist/file-lock-sync-root-acquire.d.ts +0 -1
- package/dist/file-lock-sync-root-acquire.js +35 -98
- package/dist/file-lock-sync-root-arbitration.d.ts +0 -1
- package/dist/file-lock-sync-root-held.d.ts +1 -3
- package/dist/file-lock-sync-root-held.js +7 -5
- package/dist/file-lock-sync-root-io.d.ts +0 -1
- package/dist/file-lock-sync-root-mutation.d.ts +4 -5
- package/dist/file-lock-sync-root-mutation.js +7 -9
- package/dist/file-lock-sync-root-options.d.ts +0 -1
- package/dist/file-lock-sync-root-registration.d.ts +0 -1
- package/dist/file-lock-sync-root.d.ts +1 -2
- package/dist/file-lock-sync-root.js +14 -87
- package/dist/file-lock-sync-stale-admission.d.ts +2 -7
- package/dist/file-lock-sync-stale-admission.js +24 -23
- package/dist/file-lock-sync.d.ts +0 -1
- package/dist/file-lock-sync.js +46 -128
- package/dist/file-lock.d.ts +0 -1
- package/dist/file-observation.d.ts +0 -1
- package/dist/file-store-boundary.d.ts +0 -2
- package/dist/file-store-boundary.js +6 -26
- package/dist/file-store-copy-source.d.ts +1 -2
- package/dist/file-store-copy-source.js +1 -1
- package/dist/file-store-limit.d.ts +1 -2
- package/dist/file-store-limit.js +2 -3
- package/dist/file-store-path.d.ts +0 -1
- package/dist/file-store-prune.d.ts +0 -1
- package/dist/file-store-sync-directory.d.ts +0 -1
- package/dist/file-store-sync-directory.js +194 -231
- package/dist/file-store-sync-write.d.ts +0 -1
- package/dist/file-store-sync-write.js +16 -26
- package/dist/file-store.d.ts +0 -1
- package/dist/file-store.js +6 -7
- package/dist/file-sync.d.ts +0 -1
- package/dist/filename.d.ts +0 -1
- package/dist/filename.js +1 -7
- package/dist/fs.d.ts +0 -1
- package/dist/guarded-mkdir.d.ts +0 -1
- package/dist/guarded-mkdir.js +6 -27
- package/dist/guarded-mutation.d.ts +0 -7
- package/dist/guarded-mutation.js +6 -11
- package/dist/guest-dispatch-python.d.ts +0 -1
- package/dist/guest-dispatch-python.js +41 -90
- package/dist/guest-native-python.d.ts +0 -1
- package/dist/guest.d.ts +0 -1
- package/dist/home-dir.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/install-path.d.ts +0 -1
- package/dist/install-path.js +2 -5
- package/dist/json-document-store.d.ts +0 -1
- package/dist/json-durable-queue-directory.d.ts +13 -1
- package/dist/json-durable-queue-directory.js +134 -0
- package/dist/json-durable-queue-ownership.d.ts +0 -1
- package/dist/json-durable-queue-ownership.js +43 -66
- package/dist/json-durable-queue-read.d.ts +0 -1
- package/dist/json-durable-queue-read.js +6 -6
- package/dist/json-durable-queue.d.ts +0 -1
- package/dist/json-durable-queue.js +17 -139
- package/dist/json-store.d.ts +0 -1
- package/dist/json-stringify.d.ts +0 -1
- package/dist/json.d.ts +0 -1
- package/dist/json.js +38 -90
- package/dist/local-file-access.d.ts +0 -1
- package/dist/local-file-access.js +3 -10
- package/dist/local-file-descriptor.d.ts +0 -1
- package/dist/local-roots.d.ts +0 -1
- package/dist/local-roots.js +19 -21
- package/dist/lock-config.d.ts +0 -1
- package/dist/move-path-cleanup.d.ts +5 -20
- package/dist/move-path-cleanup.js +57 -21
- package/dist/move-path-stage.d.ts +0 -1
- package/dist/move-path.d.ts +0 -1
- package/dist/move-path.js +62 -39
- package/dist/mutation-authority.d.ts +0 -1
- package/dist/native-binding.d.ts +0 -1
- package/dist/native-config.d.ts +0 -1
- package/dist/native-directory-observation.d.ts +0 -1
- package/dist/native-fallback-warning.d.ts +0 -1
- package/dist/native-operations.d.ts +1 -5
- package/dist/native-operations.js +2 -6
- package/dist/native-parent-admission.d.ts +0 -1
- package/dist/native-pinned-write-windows.d.ts +0 -1
- package/dist/native-pinned-write.d.ts +0 -1
- package/dist/native-pinned-write.js +4 -10
- package/dist/native-policy-directory-observation.d.ts +0 -1
- package/dist/native-policy-parent-windows.d.ts +0 -1
- package/dist/native-rename-outcome.d.ts +0 -1
- package/dist/native-staged-file.d.ts +17 -4
- package/dist/native-staged-file.js +63 -68
- package/dist/native.d.ts +0 -1
- package/dist/native.js +2 -2
- package/dist/opened-file-failure.d.ts +0 -1
- package/dist/opened-realpath.d.ts +0 -1
- package/dist/opened-realpath.js +11 -2
- package/dist/output.d.ts +0 -1
- package/dist/overwrite-file-handle.d.ts +0 -1
- package/dist/owner-dacl.d.ts +0 -1
- package/dist/path-case.d.ts +0 -1
- package/dist/path-policy.d.ts +0 -1
- package/dist/path-prefix.d.ts +0 -1
- package/dist/path-scope-lexical.d.ts +0 -1
- package/dist/path-segment-route.d.ts +0 -1
- package/dist/path-suffix-aliases.d.ts +0 -1
- package/dist/path.d.ts +0 -1
- package/dist/path.js +2 -1
- package/dist/permission-exec.d.ts +0 -1
- package/dist/permission-exec.js +19 -25
- package/dist/permissions-public.d.ts +0 -1
- package/dist/permissions-windows.d.ts +2 -10
- package/dist/permissions-windows.js +10 -30
- package/dist/permissions.d.ts +0 -1
- package/dist/permissions.js +11 -33
- package/dist/pinned-mutation-admission.d.ts +0 -1
- package/dist/pinned-mutation-observation.d.ts +0 -1
- package/dist/pinned-mutation-shared-route.d.ts +0 -1
- package/dist/pinned-open.d.ts +1 -1
- package/dist/pinned-open.js +1 -1
- package/dist/pinned-operation.d.ts +0 -1
- package/dist/pinned-write-input.d.ts +0 -1
- package/dist/pinned-write-input.js +11 -1
- package/dist/pinned-write-mode.d.ts +3 -4
- package/dist/pinned-write-mode.js +15 -8
- package/dist/pinned-write-staged.d.ts +0 -1
- package/dist/pinned-write-staged.js +10 -11
- package/dist/pinned-write-types.d.ts +9 -21
- package/dist/pinned-write.d.ts +0 -1
- package/dist/pinned-write.js +17 -13
- package/dist/positional-read.d.ts +0 -1
- package/dist/private-directory.d.ts +0 -1
- package/dist/private-producer-handoff-sync.d.ts +0 -1
- package/dist/private-producer-handoff-sync.js +9 -51
- package/dist/private-producer-handoff.d.ts +20 -1
- package/dist/private-producer-handoff.js +69 -46
- package/dist/private-temp-workspace.d.ts +0 -1
- package/dist/private-temp-workspace.js +11 -36
- package/dist/publish-copy-stage.d.ts +0 -1
- package/dist/publish-file-failure.d.ts +0 -1
- package/dist/publish-file.d.ts +2 -3
- package/dist/publish-file.js +56 -96
- package/dist/read-open-flags.d.ts +0 -1
- package/dist/read-opened-file.d.ts +0 -1
- package/dist/realpath.d.ts +0 -1
- package/dist/recursive-mkdir-path.d.ts +0 -1
- package/dist/regular-file.d.ts +0 -1
- package/dist/regular-file.js +107 -178
- package/dist/replace-directory.d.ts +0 -1
- package/dist/replace-file-copy-fallback.d.ts +0 -1
- package/dist/replace-file-copy-fallback.js +42 -29
- package/dist/replace-file-copy-source.d.ts +0 -1
- package/dist/replace-file-copy-source.js +19 -23
- package/dist/replace-file-descriptor.d.ts +0 -1
- package/dist/replace-file-descriptor.js +16 -17
- package/dist/replace-file-mode.d.ts +0 -1
- package/dist/replace-file-rename-policy.d.ts +0 -1
- package/dist/replace-file-temp-owner.d.ts +12 -13
- package/dist/replace-file-temp-owner.js +72 -91
- package/dist/replace-file.d.ts +0 -1
- package/dist/replace-file.js +9 -13
- package/dist/retained-directory-replacement.d.ts +0 -1
- package/dist/root-boundary.d.ts +0 -1
- package/dist/root-context.d.ts +0 -1
- package/dist/root-create-input.d.ts +0 -1
- package/dist/root-directory-creation.d.ts +0 -1
- package/dist/root-directory-list.d.ts +0 -1
- package/dist/root-directory-list.js +20 -3
- package/dist/root-directory.d.ts +0 -1
- package/dist/root-entries.d.ts +0 -1
- package/dist/root-errors.d.ts +0 -1
- package/dist/root-file-final-admission.d.ts +1 -2
- package/dist/root-file-final-admission.js +5 -2
- package/dist/root-file.d.ts +0 -1
- package/dist/root-file.js +3 -2
- package/dist/root-impl.d.ts +2 -10
- package/dist/root-impl.js +164 -111
- package/dist/root-move-noreplace.d.ts +2 -1
- package/dist/root-move-noreplace.js +2 -2
- package/dist/root-move-preflight.d.ts +0 -1
- package/dist/root-observed-path.d.ts +0 -1
- package/dist/root-options.d.ts +0 -1
- package/dist/root-path-errors.d.ts +0 -1
- package/dist/root-path-existing.d.ts +3 -1
- package/dist/root-path-existing.js +39 -18
- package/dist/root-path-observation.d.ts +0 -1
- package/dist/root-path-stat.d.ts +0 -1
- package/dist/root-path.d.ts +0 -1
- package/dist/root-path.js +60 -188
- package/dist/root-paths-lexical.d.ts +0 -1
- package/dist/root-paths.d.ts +0 -1
- package/dist/root-read-admission.d.ts +0 -1
- package/dist/root-read-admission.js +31 -39
- package/dist/root-remove-identity.d.ts +0 -1
- package/dist/root-remove-receipt.d.ts +0 -1
- package/dist/root-remove.d.ts +0 -1
- package/dist/root-remove.js +15 -1
- package/dist/root-symlink-policy.d.ts +0 -1
- package/dist/root-walk.d.ts +0 -1
- package/dist/root-write-admission.d.ts +0 -1
- package/dist/root-write-compatibility.d.ts +0 -1
- package/dist/root-write-complete-parent.d.ts +0 -1
- package/dist/root-write-lock-binding.d.ts +0 -1
- package/dist/root-write-mode.d.ts +0 -1
- package/dist/root-write-publication.d.ts +0 -1
- package/dist/root-write-verification.d.ts +0 -1
- package/dist/root.d.ts +0 -1
- package/dist/safe-path-segment.d.ts +1 -2
- package/dist/safe-path-segment.js +2 -5
- package/dist/secret-file.d.ts +0 -1
- package/dist/secret-file.js +7 -17
- package/dist/secret-read-async.d.ts +0 -1
- package/dist/secret-read-async.js +5 -5
- package/dist/secret-read-policy.d.ts +0 -1
- package/dist/secret.d.ts +0 -1
- package/dist/secure-file-windows.d.ts +0 -6
- package/dist/secure-file-windows.js +13 -28
- package/dist/secure-file.d.ts +0 -1
- package/dist/secure-file.js +9 -9
- package/dist/secure-temp-dir.d.ts +0 -1
- package/dist/secure-temp-repair.d.ts +0 -1
- package/dist/sibling-staged-file.d.ts +0 -1
- package/dist/sibling-staged-file.js +32 -39
- package/dist/sibling-temp.d.ts +0 -1
- package/dist/sidecar-lock-acquire.d.ts +1 -2
- package/dist/sidecar-lock-acquire.js +35 -58
- package/dist/sidecar-lock-admission-context.d.ts +0 -1
- package/dist/sidecar-lock-admission-parser.d.ts +0 -1
- package/dist/sidecar-lock-admission.d.ts +1 -5
- package/dist/sidecar-lock-admission.js +1 -7
- package/dist/sidecar-lock-handle.d.ts +3 -1
- package/dist/sidecar-lock-handle.js +6 -0
- package/dist/sidecar-lock-policy.d.ts +3 -1
- package/dist/sidecar-lock-policy.js +16 -0
- package/dist/sidecar-lock-reclaim.d.ts +1 -2
- package/dist/sidecar-lock-reclaim.js +11 -8
- package/dist/sidecar-lock-registration.d.ts +13 -0
- package/dist/sidecar-lock-registration.js +47 -0
- package/dist/sidecar-lock-root.d.ts +0 -1
- package/dist/sidecar-lock-stale-admission.d.ts +0 -1
- package/dist/sidecar-lock-target.d.ts +0 -1
- package/dist/sidecar-lock-types.d.ts +0 -1
- package/dist/sidecar-lock.d.ts +0 -1
- package/dist/sidecar-lock.js +19 -88
- package/dist/staged-directory.d.ts +2 -3
- package/dist/staged-file-settlement.d.ts +0 -1
- package/dist/staged-file-types.d.ts +0 -1
- package/dist/standalone-publication-path.d.ts +0 -1
- package/dist/stat-observation.d.ts +0 -1
- package/dist/store.d.ts +0 -1
- package/dist/strict-file-identity.d.ts +1 -2
- package/dist/strict-file-identity.js +9 -9
- package/dist/string-coerce.d.ts +0 -1
- package/dist/suppressed-error.d.ts +0 -1
- package/dist/symlink-parents.d.ts +0 -1
- package/dist/symlink-parents.js +2 -27
- package/dist/temp-cleanup.d.ts +0 -1
- package/dist/temp-target.d.ts +0 -1
- package/dist/temp-target.js +7 -46
- package/dist/temp-workspace-admission.d.ts +0 -8
- package/dist/temp-workspace-admission.js +0 -4
- package/dist/temp-workspace-child-admission.d.ts +0 -4
- package/dist/temp-workspace-child-admission.js +0 -12
- package/dist/temp-workspace-descriptor.d.ts +0 -6
- package/dist/temp-workspace-descriptor.js +0 -2
- package/dist/temp-workspace-identity.d.ts +0 -1
- package/dist/temp-workspace-owner.d.ts +1 -1
- package/dist/temp-workspace-owner.js +49 -26
- package/dist/temp-workspace-permissions.d.ts +0 -1
- package/dist/temp-workspace-types.d.ts +0 -1
- package/dist/temp.d.ts +0 -1
- package/dist/test-hooks.d.ts +0 -1
- package/dist/text-atomic.d.ts +0 -1
- package/dist/timing.d.ts +0 -1
- package/dist/trash.d.ts +0 -1
- package/dist/types.d.ts +0 -1
- package/dist/unicode-path.d.ts +0 -1
- package/dist/unicode-path.js +3 -0
- package/dist/walk.d.ts +0 -1
- package/dist/walk.js +4 -2
- package/dist/windows-command.d.ts +0 -1
- package/dist/windows-owner.d.ts +0 -1
- package/dist/windows-owner.js +4 -1
- package/dist/windows-path-alias.d.ts +0 -1
- package/dist/windows-path-alias.js +7 -43
- package/dist/windows-path-syntax.d.ts +5 -0
- package/dist/windows-path-syntax.js +21 -0
- package/dist/windows-security-command.d.ts +0 -1
- package/dist/windows-security-facts.d.ts +0 -1
- package/dist/write-file-handle.d.ts +7 -1
- package/dist/write-file-handle.js +23 -0
- package/dist/write-open-flags.d.ts +0 -1
- package/dist/write-open-flags.js +1 -8
- package/dist/write-queue.d.ts +0 -1
- package/dist/write-queue.js +1 -4
- package/docs/advanced.md +68 -1
- package/docs/archive.md +41 -2
- package/docs/atomic.md +43 -5
- package/docs/contributing.md +4 -0
- package/docs/copy.md +2 -0
- package/docs/creation.md +8 -4
- package/docs/durability.md +35 -0
- package/docs/file-contents.md +68 -0
- package/docs/json.md +5 -4
- package/docs/local-roots.md +2 -0
- package/docs/mutation-policy-proof.md +11 -7
- package/docs/native.md +9 -8
- package/docs/path.md +4 -4
- package/docs/permissions.md +6 -0
- package/docs/public-api.md +5 -0
- package/docs/quickstart.md +1 -1
- package/docs/reading.md +2 -2
- package/docs/regular-file.md +3 -0
- package/docs/root.md +19 -0
- package/docs/secret-file.md +4 -0
- package/docs/sidecar-lock.md +9 -1
- package/docs/staged-file.md +4 -3
- package/docs/store.md +3 -1
- package/docs/temp.md +4 -1
- package/docs/types.md +18 -2
- package/docs/walk.md +7 -0
- package/docs/writing.md +18 -5
- package/package.json +8 -9
- package/dist/absolute-path.d.ts.map +0 -1
- package/dist/advanced.d.ts.map +0 -1
- package/dist/archive-crc32.d.ts.map +0 -1
- package/dist/archive-deadline.d.ts.map +0 -1
- package/dist/archive-durability.d.ts.map +0 -1
- package/dist/archive-entry.d.ts.map +0 -1
- package/dist/archive-errors.d.ts.map +0 -1
- package/dist/archive-gzip-tail.d.ts.map +0 -1
- package/dist/archive-input.d.ts.map +0 -1
- package/dist/archive-kind.d.ts.map +0 -1
- package/dist/archive-limits.d.ts.map +0 -1
- package/dist/archive-merge.d.ts.map +0 -1
- package/dist/archive-native.d.ts.map +0 -1
- package/dist/archive-options.d.ts.map +0 -1
- package/dist/archive-parser-errors.d.ts.map +0 -1
- package/dist/archive-plan.d.ts.map +0 -1
- package/dist/archive-policy.d.ts.map +0 -1
- package/dist/archive-read.d.ts.map +0 -1
- package/dist/archive-staging.d.ts.map +0 -1
- package/dist/archive-tar-inspect.d.ts.map +0 -1
- package/dist/archive-tar-stream.d.ts.map +0 -1
- package/dist/archive-tar-wasm.d.ts.map +0 -1
- package/dist/archive-tar.d.ts.map +0 -1
- package/dist/archive-zip-admission.d.ts.map +0 -1
- package/dist/archive-zip-count.d.ts.map +0 -1
- package/dist/archive-zip-directory.d.ts.map +0 -1
- package/dist/archive-zip-entry.d.ts.map +0 -1
- package/dist/archive-zip-integrity.d.ts.map +0 -1
- package/dist/archive-zip-loader.d.ts.map +0 -1
- package/dist/archive-zip-manifest.d.ts.map +0 -1
- package/dist/archive-zip-names.d.ts.map +0 -1
- package/dist/archive-zip-preflight.d.ts.map +0 -1
- package/dist/archive.d.ts.map +0 -1
- package/dist/async-lock.d.ts.map +0 -1
- package/dist/atomic.d.ts.map +0 -1
- package/dist/bounded-read-stream.d.ts.map +0 -1
- package/dist/bounded-read.d.ts.map +0 -1
- package/dist/byte-budget.d.ts.map +0 -1
- package/dist/clone-metadata.d.ts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/containment.d.ts.map +0 -1
- package/dist/copy-file-input.d.ts.map +0 -1
- package/dist/copy-policy.d.ts.map +0 -1
- package/dist/copy-publication.d.ts.map +0 -1
- package/dist/copy-tree-portable.d.ts.map +0 -1
- package/dist/copy.d.ts.map +0 -1
- package/dist/create-directory.d.ts.map +0 -1
- package/dist/create-file-async.d.ts.map +0 -1
- package/dist/create-file.d.ts.map +0 -1
- package/dist/create-owned-file.d.ts.map +0 -1
- package/dist/create.d.ts.map +0 -1
- package/dist/creation-darwin.d.ts.map +0 -1
- package/dist/creation-file-state.d.ts.map +0 -1
- package/dist/creation-path.d.ts.map +0 -1
- package/dist/creation-permissions.d.ts.map +0 -1
- package/dist/deny-mutations.d.ts.map +0 -1
- package/dist/device-path.d.ts.map +0 -1
- package/dist/directory-durability.d.ts.map +0 -1
- package/dist/directory-entry-path.d.ts.map +0 -1
- package/dist/directory-guard.d.ts.map +0 -1
- package/dist/directory-mode-node.d.ts.map +0 -1
- package/dist/directory-mode-owner.d.ts.map +0 -1
- package/dist/directory-receipt.d.ts.map +0 -1
- package/dist/durability.d.ts.map +0 -1
- package/dist/effective-uid.d.ts.map +0 -1
- package/dist/error-detail.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/file-cleanup.d.ts.map +0 -1
- package/dist/file-handle-transfer.d.ts.map +0 -1
- package/dist/file-hash.d.ts.map +0 -1
- package/dist/file-identity.d.ts.map +0 -1
- package/dist/file-lock-sync-admission.d.ts.map +0 -1
- package/dist/file-lock-sync-root-acquire.d.ts.map +0 -1
- package/dist/file-lock-sync-root-arbitration.d.ts.map +0 -1
- package/dist/file-lock-sync-root-held.d.ts.map +0 -1
- package/dist/file-lock-sync-root-io.d.ts.map +0 -1
- package/dist/file-lock-sync-root-mutation.d.ts.map +0 -1
- package/dist/file-lock-sync-root-options.d.ts.map +0 -1
- package/dist/file-lock-sync-root-registration.d.ts.map +0 -1
- package/dist/file-lock-sync-root.d.ts.map +0 -1
- package/dist/file-lock-sync-stale-admission.d.ts.map +0 -1
- package/dist/file-lock-sync.d.ts.map +0 -1
- package/dist/file-lock.d.ts.map +0 -1
- package/dist/file-observation.d.ts.map +0 -1
- package/dist/file-store-boundary.d.ts.map +0 -1
- package/dist/file-store-copy-source.d.ts.map +0 -1
- package/dist/file-store-limit.d.ts.map +0 -1
- package/dist/file-store-path.d.ts.map +0 -1
- package/dist/file-store-prune.d.ts.map +0 -1
- package/dist/file-store-sync-directory.d.ts.map +0 -1
- package/dist/file-store-sync-write.d.ts.map +0 -1
- package/dist/file-store.d.ts.map +0 -1
- package/dist/file-sync.d.ts.map +0 -1
- package/dist/filename.d.ts.map +0 -1
- package/dist/fs.d.ts.map +0 -1
- package/dist/guarded-mkdir.d.ts.map +0 -1
- package/dist/guarded-mutation.d.ts.map +0 -1
- package/dist/guest-dispatch-python.d.ts.map +0 -1
- package/dist/guest-native-python.d.ts.map +0 -1
- package/dist/guest.d.ts.map +0 -1
- package/dist/home-dir.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/install-path.d.ts.map +0 -1
- package/dist/json-document-store.d.ts.map +0 -1
- package/dist/json-durable-queue-directory.d.ts.map +0 -1
- package/dist/json-durable-queue-ownership.d.ts.map +0 -1
- package/dist/json-durable-queue-paths.d.ts +0 -11
- package/dist/json-durable-queue-paths.d.ts.map +0 -1
- package/dist/json-durable-queue-paths.js +0 -42
- package/dist/json-durable-queue-read.d.ts.map +0 -1
- package/dist/json-durable-queue.d.ts.map +0 -1
- package/dist/json-store.d.ts.map +0 -1
- package/dist/json-stringify.d.ts.map +0 -1
- package/dist/json.d.ts.map +0 -1
- package/dist/local-file-access.d.ts.map +0 -1
- package/dist/local-file-descriptor.d.ts.map +0 -1
- package/dist/local-roots.d.ts.map +0 -1
- package/dist/lock-config.d.ts.map +0 -1
- package/dist/move-path-cleanup.d.ts.map +0 -1
- package/dist/move-path-stage.d.ts.map +0 -1
- package/dist/move-path.d.ts.map +0 -1
- package/dist/mutation-authority.d.ts.map +0 -1
- package/dist/native-binding.d.ts.map +0 -1
- package/dist/native-config.d.ts.map +0 -1
- package/dist/native-directory-observation.d.ts.map +0 -1
- package/dist/native-fallback-warning.d.ts.map +0 -1
- package/dist/native-operations.d.ts.map +0 -1
- package/dist/native-parent-admission.d.ts.map +0 -1
- package/dist/native-pinned-write-windows.d.ts.map +0 -1
- package/dist/native-pinned-write.d.ts.map +0 -1
- package/dist/native-policy-directory-observation.d.ts.map +0 -1
- package/dist/native-policy-parent-windows.d.ts.map +0 -1
- package/dist/native-rename-outcome.d.ts.map +0 -1
- package/dist/native-staged-file.d.ts.map +0 -1
- package/dist/native.d.ts.map +0 -1
- package/dist/opened-file-failure.d.ts.map +0 -1
- package/dist/opened-realpath.d.ts.map +0 -1
- package/dist/output.d.ts.map +0 -1
- package/dist/overwrite-file-handle.d.ts.map +0 -1
- package/dist/owner-dacl.d.ts.map +0 -1
- package/dist/path-case.d.ts.map +0 -1
- package/dist/path-policy.d.ts.map +0 -1
- package/dist/path-prefix.d.ts.map +0 -1
- package/dist/path-scope-lexical.d.ts.map +0 -1
- package/dist/path-segment-route.d.ts.map +0 -1
- package/dist/path-suffix-aliases.d.ts.map +0 -1
- package/dist/path.d.ts.map +0 -1
- package/dist/permission-exec.d.ts.map +0 -1
- package/dist/permissions-public.d.ts.map +0 -1
- package/dist/permissions-windows.d.ts.map +0 -1
- package/dist/permissions.d.ts.map +0 -1
- package/dist/pinned-mutation-admission.d.ts.map +0 -1
- package/dist/pinned-mutation-observation.d.ts.map +0 -1
- package/dist/pinned-mutation-shared-route.d.ts.map +0 -1
- package/dist/pinned-open.d.ts.map +0 -1
- package/dist/pinned-operation.d.ts.map +0 -1
- package/dist/pinned-write-input.d.ts.map +0 -1
- package/dist/pinned-write-mode.d.ts.map +0 -1
- package/dist/pinned-write-staged.d.ts.map +0 -1
- package/dist/pinned-write-types.d.ts.map +0 -1
- package/dist/pinned-write.d.ts.map +0 -1
- package/dist/positional-read.d.ts.map +0 -1
- package/dist/private-directory.d.ts.map +0 -1
- package/dist/private-producer-handoff-sync.d.ts.map +0 -1
- package/dist/private-producer-handoff.d.ts.map +0 -1
- package/dist/private-temp-workspace.d.ts.map +0 -1
- package/dist/publish-copy-stage.d.ts.map +0 -1
- package/dist/publish-file-failure.d.ts.map +0 -1
- package/dist/publish-file.d.ts.map +0 -1
- package/dist/read-open-flags.d.ts.map +0 -1
- package/dist/read-opened-file.d.ts.map +0 -1
- package/dist/realpath.d.ts.map +0 -1
- package/dist/recursive-mkdir-path.d.ts.map +0 -1
- package/dist/regular-file.d.ts.map +0 -1
- package/dist/replace-directory.d.ts.map +0 -1
- package/dist/replace-file-copy-fallback.d.ts.map +0 -1
- package/dist/replace-file-copy-source.d.ts.map +0 -1
- package/dist/replace-file-descriptor.d.ts.map +0 -1
- package/dist/replace-file-mode.d.ts.map +0 -1
- package/dist/replace-file-rename-policy.d.ts.map +0 -1
- package/dist/replace-file-temp-owner.d.ts.map +0 -1
- package/dist/replace-file.d.ts.map +0 -1
- package/dist/retained-directory-replacement.d.ts.map +0 -1
- package/dist/root-boundary.d.ts.map +0 -1
- package/dist/root-context.d.ts.map +0 -1
- package/dist/root-create-input.d.ts.map +0 -1
- package/dist/root-directory-creation.d.ts.map +0 -1
- package/dist/root-directory-list.d.ts.map +0 -1
- package/dist/root-directory.d.ts.map +0 -1
- package/dist/root-entries.d.ts.map +0 -1
- package/dist/root-errors.d.ts.map +0 -1
- package/dist/root-file-final-admission.d.ts.map +0 -1
- package/dist/root-file.d.ts.map +0 -1
- package/dist/root-impl.d.ts.map +0 -1
- package/dist/root-move-noreplace.d.ts.map +0 -1
- package/dist/root-move-preflight.d.ts.map +0 -1
- package/dist/root-observed-path.d.ts.map +0 -1
- package/dist/root-options.d.ts.map +0 -1
- package/dist/root-path-errors.d.ts.map +0 -1
- package/dist/root-path-existing.d.ts.map +0 -1
- package/dist/root-path-observation.d.ts.map +0 -1
- package/dist/root-path-stat.d.ts.map +0 -1
- package/dist/root-path-symlink.d.ts +0 -7
- package/dist/root-path-symlink.d.ts.map +0 -1
- package/dist/root-path-symlink.js +0 -55
- package/dist/root-path.d.ts.map +0 -1
- package/dist/root-paths-lexical.d.ts.map +0 -1
- package/dist/root-paths.d.ts.map +0 -1
- package/dist/root-read-admission.d.ts.map +0 -1
- package/dist/root-remove-identity.d.ts.map +0 -1
- package/dist/root-remove-receipt.d.ts.map +0 -1
- package/dist/root-remove.d.ts.map +0 -1
- package/dist/root-symlink-policy.d.ts.map +0 -1
- package/dist/root-walk.d.ts.map +0 -1
- package/dist/root-write-admission.d.ts.map +0 -1
- package/dist/root-write-compatibility.d.ts.map +0 -1
- package/dist/root-write-complete-parent.d.ts.map +0 -1
- package/dist/root-write-lock-binding.d.ts.map +0 -1
- package/dist/root-write-mode.d.ts.map +0 -1
- package/dist/root-write-publication.d.ts.map +0 -1
- package/dist/root-write-verification.d.ts.map +0 -1
- package/dist/root.d.ts.map +0 -1
- package/dist/safe-path-segment.d.ts.map +0 -1
- package/dist/secret-file.d.ts.map +0 -1
- package/dist/secret-read-async.d.ts.map +0 -1
- package/dist/secret-read-policy.d.ts.map +0 -1
- package/dist/secret.d.ts.map +0 -1
- package/dist/secure-file-windows.d.ts.map +0 -1
- package/dist/secure-file.d.ts.map +0 -1
- package/dist/secure-temp-dir.d.ts.map +0 -1
- package/dist/secure-temp-repair.d.ts.map +0 -1
- package/dist/sibling-staged-file.d.ts.map +0 -1
- package/dist/sibling-temp.d.ts.map +0 -1
- package/dist/sidecar-lock-acquire.d.ts.map +0 -1
- package/dist/sidecar-lock-admission-context.d.ts.map +0 -1
- package/dist/sidecar-lock-admission-parser.d.ts.map +0 -1
- package/dist/sidecar-lock-admission.d.ts.map +0 -1
- package/dist/sidecar-lock-handle.d.ts.map +0 -1
- package/dist/sidecar-lock-policy.d.ts.map +0 -1
- package/dist/sidecar-lock-reclaim.d.ts.map +0 -1
- package/dist/sidecar-lock-root.d.ts.map +0 -1
- package/dist/sidecar-lock-stale-admission.d.ts.map +0 -1
- package/dist/sidecar-lock-target.d.ts.map +0 -1
- package/dist/sidecar-lock-types.d.ts.map +0 -1
- package/dist/sidecar-lock.d.ts.map +0 -1
- package/dist/staged-directory.d.ts.map +0 -1
- package/dist/staged-file-settlement.d.ts.map +0 -1
- package/dist/staged-file-types.d.ts.map +0 -1
- package/dist/standalone-publication-path.d.ts.map +0 -1
- package/dist/stat-observation.d.ts.map +0 -1
- package/dist/store.d.ts.map +0 -1
- package/dist/strict-file-identity.d.ts.map +0 -1
- package/dist/string-coerce.d.ts.map +0 -1
- package/dist/suppressed-error.d.ts.map +0 -1
- package/dist/symlink-parents.d.ts.map +0 -1
- package/dist/temp-cleanup.d.ts.map +0 -1
- package/dist/temp-target.d.ts.map +0 -1
- package/dist/temp-workspace-admission.d.ts.map +0 -1
- package/dist/temp-workspace-child-admission.d.ts.map +0 -1
- package/dist/temp-workspace-descriptor.d.ts.map +0 -1
- package/dist/temp-workspace-identity.d.ts.map +0 -1
- package/dist/temp-workspace-owner.d.ts.map +0 -1
- package/dist/temp-workspace-permissions.d.ts.map +0 -1
- package/dist/temp-workspace-types.d.ts.map +0 -1
- package/dist/temp.d.ts.map +0 -1
- package/dist/test-hooks.d.ts.map +0 -1
- package/dist/text-atomic.d.ts.map +0 -1
- package/dist/timing.d.ts.map +0 -1
- package/dist/trash.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/unicode-path.d.ts.map +0 -1
- package/dist/walk.d.ts.map +0 -1
- package/dist/windows-command.d.ts.map +0 -1
- package/dist/windows-owner.d.ts.map +0 -1
- package/dist/windows-path-alias.d.ts.map +0 -1
- package/dist/windows-security-command.d.ts.map +0 -1
- package/dist/windows-security-facts.d.ts.map +0 -1
- package/dist/write-file-handle.d.ts.map +0 -1
- package/dist/write-open-flags.d.ts.map +0 -1
- package/dist/write-queue.d.ts.map +0 -1
|
@@ -6,7 +6,7 @@ import path from "node:path";
|
|
|
6
6
|
import { syncDirectory } from "./directory-durability.js";
|
|
7
7
|
import { FsSafeError } from "./errors.js";
|
|
8
8
|
import { sameFileIdentityForCleanup, sha256Hex } from "./file-identity.js";
|
|
9
|
-
import {
|
|
9
|
+
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
10
10
|
import { serializePathWrite } from "./write-queue.js";
|
|
11
11
|
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
12
12
|
const validatedDurableQueueEntryPaths = new WeakSet();
|
|
@@ -45,12 +45,14 @@ function processingPathFromJsonPath(jsonPath) {
|
|
|
45
45
|
? `${jsonPath.slice(0, -".json".length)}.processing`
|
|
46
46
|
: `${jsonPath}.processing`;
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
const identity =
|
|
48
|
+
function regularQueueFileIdentity(filePath, subject = "entry") {
|
|
49
|
+
const identity = lstatOrNull(filePath);
|
|
50
50
|
if (!identity)
|
|
51
51
|
return null;
|
|
52
52
|
if (identity.isSymbolicLink() || !identity.isFile()) {
|
|
53
|
-
throw
|
|
53
|
+
throw subject === "retirement"
|
|
54
|
+
? new FsSafeError("path-mismatch", "queue retirement path is not a regular file")
|
|
55
|
+
: new Error(`queue entry is not a regular file: ${filePath}`);
|
|
54
56
|
}
|
|
55
57
|
return identity;
|
|
56
58
|
}
|
|
@@ -62,9 +64,9 @@ async function withQueueEntryLock(paths, run) {
|
|
|
62
64
|
async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
63
65
|
const processingPath = paths.processingPath;
|
|
64
66
|
await recoverDurableQueueRetirement({ jsonPath: paths.jsonPath, processingPath });
|
|
65
|
-
const existingProcessing =
|
|
67
|
+
const existingProcessing = regularQueueFileIdentity(processingPath);
|
|
66
68
|
if (existingProcessing) {
|
|
67
|
-
const pending =
|
|
69
|
+
const pending = lstatOrNull(paths.jsonPath);
|
|
68
70
|
const retiresPending = pending !== null &&
|
|
69
71
|
!pending.isSymbolicLink() &&
|
|
70
72
|
pending.isFile() &&
|
|
@@ -80,7 +82,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
|
80
82
|
}
|
|
81
83
|
return processingPath;
|
|
82
84
|
}
|
|
83
|
-
const pending =
|
|
85
|
+
const pending = lstatOrNull(paths.jsonPath);
|
|
84
86
|
if (!pending || pending.isSymbolicLink() || !pending.isFile())
|
|
85
87
|
return null;
|
|
86
88
|
if (pending.nlink > 1n || !sameFileIdentityForCleanup(pending, pending)) {
|
|
@@ -94,7 +96,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
|
94
96
|
}
|
|
95
97
|
catch (error) {
|
|
96
98
|
if (getErrorCode(error) === "EEXIST") {
|
|
97
|
-
if (!
|
|
99
|
+
if (!regularQueueFileIdentity(processingPath))
|
|
98
100
|
return null;
|
|
99
101
|
await syncDirectory(path.dirname(processingPath));
|
|
100
102
|
return processingPath;
|
|
@@ -104,7 +106,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
|
104
106
|
throw error;
|
|
105
107
|
}
|
|
106
108
|
await syncDirectory(path.dirname(processingPath));
|
|
107
|
-
const claimed =
|
|
109
|
+
const claimed = regularQueueFileIdentity(processingPath);
|
|
108
110
|
if (!claimed || claimed.nlink > 2n) {
|
|
109
111
|
throw new FsSafeError("path-mismatch", "queue claim is not an owned regular file");
|
|
110
112
|
}
|
|
@@ -113,7 +115,7 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
|
113
115
|
}
|
|
114
116
|
export async function claimDurableQueueEntry(paths, options = {}) {
|
|
115
117
|
const validatedPaths = ownDurableQueueEntryPaths(paths);
|
|
116
|
-
if (!
|
|
118
|
+
if (!lstatOrNull(path.dirname(validatedPaths.jsonPath)))
|
|
117
119
|
return null;
|
|
118
120
|
return await withQueueEntryLock(validatedPaths, async () => await claimDurableQueueEntryUnlocked(validatedPaths, options));
|
|
119
121
|
}
|
|
@@ -122,9 +124,9 @@ export async function migrateDurableQueueEntry(paths, expected, releaseReadPin,
|
|
|
122
124
|
const validatedPaths = ownDurableQueueEntryPaths(paths);
|
|
123
125
|
return await withQueueEntryLock(validatedPaths, async () => {
|
|
124
126
|
const processingPath = validatedPaths.processingPath;
|
|
125
|
-
const assertCurrent =
|
|
127
|
+
const assertCurrent = () => {
|
|
126
128
|
try {
|
|
127
|
-
|
|
129
|
+
inspectFileIdentitySync(() => {
|
|
128
130
|
const current = fsSync.lstatSync(processingPath, { bigint: true });
|
|
129
131
|
if (current.isSymbolicLink() || !current.isFile() || current.nlink !== 1n) {
|
|
130
132
|
throw new FsSafeError("path-mismatch", "queue migration requires its original processing claim");
|
|
@@ -139,49 +141,45 @@ export async function migrateDurableQueueEntry(paths, expected, releaseReadPin,
|
|
|
139
141
|
throw error;
|
|
140
142
|
}
|
|
141
143
|
};
|
|
142
|
-
|
|
144
|
+
assertCurrent();
|
|
143
145
|
return await run(processingPath, async () => {
|
|
144
|
-
|
|
146
|
+
assertCurrent();
|
|
145
147
|
if (process.platform === "win32") {
|
|
146
148
|
// Windows cannot replace our still-open target. Keep the transfer lock
|
|
147
149
|
// across release and reject changes made while the async close settles.
|
|
148
150
|
await releaseReadPin();
|
|
149
|
-
|
|
151
|
+
assertCurrent();
|
|
150
152
|
}
|
|
151
153
|
});
|
|
152
154
|
});
|
|
153
155
|
}
|
|
154
156
|
export async function completeDeliveredQueueEntry(paths) {
|
|
155
157
|
const validatedPaths = ownDurableQueueEntryPaths(paths);
|
|
156
|
-
if (!
|
|
158
|
+
if (!lstatOrNull(path.dirname(validatedPaths.deliveredPath)))
|
|
157
159
|
return false;
|
|
158
160
|
return await withQueueEntryLock(validatedPaths, async () => {
|
|
159
|
-
if (!
|
|
161
|
+
if (!regularQueueFileIdentity(validatedPaths.deliveredPath))
|
|
160
162
|
return false;
|
|
161
|
-
|
|
162
|
-
await fs.unlink(validatedPaths.deliveredPath);
|
|
163
|
-
await syncDirectory(path.dirname(validatedPaths.deliveredPath));
|
|
164
|
-
return false;
|
|
165
|
-
}
|
|
163
|
+
const processing = regularQueueFileIdentity(validatedPaths.processingPath);
|
|
166
164
|
await fs.unlink(validatedPaths.deliveredPath);
|
|
167
165
|
await syncDirectory(path.dirname(validatedPaths.deliveredPath));
|
|
168
|
-
return
|
|
166
|
+
return !processing;
|
|
169
167
|
});
|
|
170
168
|
}
|
|
171
169
|
export async function acknowledgeDurableQueueEntry(paths) {
|
|
172
170
|
const validatedPaths = ownDurableQueueEntryPaths(paths);
|
|
173
|
-
if (!
|
|
171
|
+
if (!lstatOrNull(path.dirname(validatedPaths.jsonPath)))
|
|
174
172
|
return;
|
|
175
173
|
await withQueueEntryLock(validatedPaths, async () => {
|
|
176
174
|
const processingPath = validatedPaths.processingPath;
|
|
177
|
-
const processing =
|
|
178
|
-
const delivered =
|
|
175
|
+
const processing = regularQueueFileIdentity(processingPath);
|
|
176
|
+
const delivered = regularQueueFileIdentity(validatedPaths.deliveredPath);
|
|
179
177
|
if (!processing) {
|
|
180
178
|
if (delivered) {
|
|
181
179
|
await fs.unlink(validatedPaths.deliveredPath);
|
|
182
180
|
}
|
|
183
181
|
await syncDirectory(path.dirname(validatedPaths.deliveredPath));
|
|
184
|
-
if (
|
|
182
|
+
if (regularQueueFileIdentity(validatedPaths.jsonPath)) {
|
|
185
183
|
throw new FsSafeError("path-mismatch", "queue acknowledgement requires a processing claim");
|
|
186
184
|
}
|
|
187
185
|
return;
|
|
@@ -202,17 +200,17 @@ export async function moveDurableQueueEntryToFailed(params) {
|
|
|
202
200
|
assertNoWindowsPathAlias(failedPath);
|
|
203
201
|
await withQueueEntryLock(paths, async () => {
|
|
204
202
|
const processingPath = paths.processingPath;
|
|
205
|
-
const processing =
|
|
206
|
-
const existingFailed =
|
|
203
|
+
const processing = regularQueueFileIdentity(processingPath);
|
|
204
|
+
const existingFailed = regularQueueFileIdentity(failedPath);
|
|
207
205
|
if (!processing && existingFailed) {
|
|
208
206
|
await syncDirectory(path.dirname(failedPath));
|
|
209
207
|
await syncDirectory(path.dirname(processingPath));
|
|
210
|
-
const recoveredFailed =
|
|
208
|
+
const recoveredFailed = regularQueueFileIdentity(failedPath);
|
|
211
209
|
if (!recoveredFailed ||
|
|
212
210
|
!sameFileIdentityForCleanup(existingFailed, recoveredFailed)) {
|
|
213
211
|
throw new FsSafeError("path-mismatch", "failed queue destination changed during recovery");
|
|
214
212
|
}
|
|
215
|
-
if (
|
|
213
|
+
if (regularQueueFileIdentity(paths.jsonPath)) {
|
|
216
214
|
throw new FsSafeError("already-exists", "failed queue destination already exists");
|
|
217
215
|
}
|
|
218
216
|
return;
|
|
@@ -223,18 +221,13 @@ export async function moveDurableQueueEntryToFailed(params) {
|
|
|
223
221
|
if (!sourcePath) {
|
|
224
222
|
throw Object.assign(new Error("queue entry does not exist"), { code: "ENOENT" });
|
|
225
223
|
}
|
|
226
|
-
const source =
|
|
227
|
-
const failed =
|
|
228
|
-
if (failed) {
|
|
229
|
-
if (source && sameFileIdentityForCleanup(source, failed)) {
|
|
230
|
-
await syncDirectory(path.dirname(failedPath));
|
|
231
|
-
await fs.unlink(sourcePath);
|
|
232
|
-
await syncDirectory(path.dirname(sourcePath));
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
224
|
+
const source = regularQueueFileIdentity(sourcePath);
|
|
225
|
+
const failed = regularQueueFileIdentity(failedPath);
|
|
226
|
+
if (failed && (!source || !sameFileIdentityForCleanup(source, failed))) {
|
|
235
227
|
throw new FsSafeError("already-exists", "failed queue destination already exists");
|
|
236
228
|
}
|
|
237
|
-
|
|
229
|
+
if (!failed)
|
|
230
|
+
await fs.link(sourcePath, failedPath);
|
|
238
231
|
await syncDirectory(path.dirname(failedPath));
|
|
239
232
|
await fs.unlink(sourcePath);
|
|
240
233
|
await syncDirectory(path.dirname(sourcePath));
|
|
@@ -247,7 +240,7 @@ export function getErrorCode(error) {
|
|
|
247
240
|
? String(error.code)
|
|
248
241
|
: null;
|
|
249
242
|
}
|
|
250
|
-
|
|
243
|
+
function lstatOrNull(filePath) {
|
|
251
244
|
try {
|
|
252
245
|
return fsSync.lstatSync(filePath, { bigint: true });
|
|
253
246
|
}
|
|
@@ -262,28 +255,11 @@ function assertDirectory(identity, label) {
|
|
|
262
255
|
throw new FsSafeError("path-mismatch", `${label} is not an owned directory`);
|
|
263
256
|
}
|
|
264
257
|
}
|
|
265
|
-
async function regularFileIdentity(filePath) {
|
|
266
|
-
const identity = await lstatOrNull(filePath);
|
|
267
|
-
if (!identity)
|
|
268
|
-
return null;
|
|
269
|
-
if (identity.isSymbolicLink() || !identity.isFile()) {
|
|
270
|
-
throw new FsSafeError("path-mismatch", "queue retirement path is not a regular file");
|
|
271
|
-
}
|
|
272
|
-
return identity;
|
|
273
|
-
}
|
|
274
258
|
function retirementPaths(jsonPath) {
|
|
275
259
|
const rootPath = path.join(path.dirname(jsonPath), RETIREMENT_ROOT_NAME);
|
|
276
260
|
const dirPath = path.join(rootPath, path.basename(jsonPath));
|
|
277
261
|
return { dirPath, entryPath: path.join(dirPath, RETIREMENT_ENTRY_NAME), rootPath };
|
|
278
262
|
}
|
|
279
|
-
async function inspectRetirementRoot(jsonPath) {
|
|
280
|
-
const rootPath = retirementPaths(jsonPath).rootPath;
|
|
281
|
-
const root = await lstatOrNull(rootPath);
|
|
282
|
-
if (!root)
|
|
283
|
-
return null;
|
|
284
|
-
assertDirectory(root, "queue retirement root");
|
|
285
|
-
return rootPath;
|
|
286
|
-
}
|
|
287
263
|
async function ensureRetirementRoot(jsonPath) {
|
|
288
264
|
const parentPath = path.dirname(jsonPath);
|
|
289
265
|
const rootPath = retirementPaths(jsonPath).rootPath;
|
|
@@ -304,11 +280,12 @@ async function removeRetirementRecord(params) {
|
|
|
304
280
|
await syncDirectory(params.rootPath);
|
|
305
281
|
}
|
|
306
282
|
async function recoverDurableQueueRetirement(params) {
|
|
307
|
-
const rootPath =
|
|
308
|
-
|
|
283
|
+
const { rootPath, dirPath, entryPath } = retirementPaths(params.jsonPath);
|
|
284
|
+
const root = lstatOrNull(rootPath);
|
|
285
|
+
if (!root)
|
|
309
286
|
return;
|
|
310
|
-
|
|
311
|
-
const dir =
|
|
287
|
+
assertDirectory(root, "queue retirement root");
|
|
288
|
+
const dir = lstatOrNull(dirPath);
|
|
312
289
|
if (!dir)
|
|
313
290
|
return;
|
|
314
291
|
assertDirectory(dir, "queue retirement record");
|
|
@@ -320,13 +297,13 @@ async function recoverDurableQueueRetirement(params) {
|
|
|
320
297
|
if (names.length !== 1 || names[0] !== RETIREMENT_ENTRY_NAME) {
|
|
321
298
|
throw new FsSafeError("path-mismatch", "queue retirement record is ambiguous");
|
|
322
299
|
}
|
|
323
|
-
const entry =
|
|
324
|
-
const processing =
|
|
300
|
+
const entry = regularQueueFileIdentity(entryPath, "retirement");
|
|
301
|
+
const processing = regularQueueFileIdentity(params.processingPath, "retirement");
|
|
325
302
|
if (!entry || !processing) {
|
|
326
303
|
throw new FsSafeError("path-mismatch", "queue retirement ownership is incomplete");
|
|
327
304
|
}
|
|
328
305
|
if (!sameFileIdentityForCleanup(entry, processing)) {
|
|
329
|
-
const pending =
|
|
306
|
+
const pending = regularQueueFileIdentity(params.jsonPath, "retirement");
|
|
330
307
|
if (!pending) {
|
|
331
308
|
await fs.link(entryPath, params.jsonPath);
|
|
332
309
|
await syncDirectory(path.dirname(params.jsonPath));
|
|
@@ -3,4 +3,3 @@ export declare const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES: number;
|
|
|
3
3
|
export declare function withJsonDurableQueueEntry<T, R>(filePath: string, options: {
|
|
4
4
|
maxBytes?: number;
|
|
5
5
|
}, run: (entry: T, identity: BigIntStats, releaseReadPin: () => Promise<void>) => Promise<R>): Promise<R>;
|
|
6
|
-
//# sourceMappingURL=json-durable-queue-read.d.ts.map
|
|
@@ -2,13 +2,13 @@ import fs, {} from "node:fs";
|
|
|
2
2
|
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
3
3
|
import { readBoundedAsync } from "./bounded-read.js";
|
|
4
4
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
5
|
-
import {
|
|
5
|
+
import { inspectFileIdentitySync } from "./strict-file-identity.js";
|
|
6
6
|
import { assertNoWindowsPathAlias } from "./windows-path-alias.js";
|
|
7
7
|
export const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES = 16 * 1024 * 1024;
|
|
8
|
-
|
|
8
|
+
function inspectQueueEntry(inspect, maxBytes, expected) {
|
|
9
9
|
let inspectionFailed = false;
|
|
10
10
|
try {
|
|
11
|
-
return
|
|
11
|
+
return inspectFileIdentitySync(() => {
|
|
12
12
|
try {
|
|
13
13
|
const stat = inspect();
|
|
14
14
|
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
@@ -39,13 +39,13 @@ export async function withJsonDurableQueueEntry(filePath, options, run) {
|
|
|
39
39
|
});
|
|
40
40
|
assertNoWindowsPathAlias(filePath);
|
|
41
41
|
const inspectPath = () => fs.lstatSync(filePath, { bigint: true });
|
|
42
|
-
const initialStat =
|
|
42
|
+
const initialStat = inspectQueueEntry(inspectPath, maxBytes);
|
|
43
43
|
const handle = await fs.promises.open(filePath, resolveReadOpenFlags());
|
|
44
44
|
let closePromise;
|
|
45
45
|
const releaseReadPin = () => closePromise ??= (async () => { await handle.close(); })();
|
|
46
46
|
try {
|
|
47
|
-
const openedStat =
|
|
48
|
-
|
|
47
|
+
const openedStat = inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), maxBytes, initialStat);
|
|
48
|
+
inspectQueueEntry(inspectPath, maxBytes, openedStat);
|
|
49
49
|
const bytes = await readBoundedAsync(maxBytes, async (buffer, length) => (await handle.read(buffer, 0, length, null)).bytesRead, {
|
|
50
50
|
initialSize: openedStat.size >= 0n && Number.isSafeInteger(Number(openedStat.size))
|
|
51
51
|
? Number(openedStat.size) : undefined,
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import fs, {} from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { syncDirectory } from "./directory-durability.js";
|
|
4
|
-
import {
|
|
5
|
-
import { queueValidationRoot, queueValidationRoots, resolveQueueFilesystemPath, } from "./json-durable-queue-paths.js";
|
|
4
|
+
import { queueDirectories } from "./json-durable-queue-directory.js";
|
|
6
5
|
import { getErrorCode, acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, migrateDurableQueueEntry, moveDurableQueueEntryToFailed, validateDurableQueueEntryPaths, } from "./json-durable-queue-ownership.js";
|
|
7
6
|
import { withJsonDurableQueueEntry } from "./json-durable-queue-read.js";
|
|
8
7
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
9
|
-
import { realpathSync } from "./realpath.js";
|
|
10
|
-
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
11
8
|
import { replaceFileAtomicWithDirectorySync } from "./replace-file.js";
|
|
12
9
|
import { assertSafePathSegment } from "./safe-path-segment.js";
|
|
13
10
|
import { admitStandalonePublicationPath } from "./standalone-publication-path.js";
|
|
@@ -61,129 +58,9 @@ export async function ensureJsonDurableQueueDirs(params) {
|
|
|
61
58
|
const failedDir = params.failedDir;
|
|
62
59
|
assertNoWindowsPathAlias(queueDir);
|
|
63
60
|
assertNoWindowsPathAlias(failedDir);
|
|
64
|
-
const
|
|
65
|
-
await
|
|
66
|
-
await
|
|
67
|
-
}
|
|
68
|
-
async function ensureJsonDurableQueueDir(dir, validationRoot) {
|
|
69
|
-
const root = validationRoot
|
|
70
|
-
? validationRoot
|
|
71
|
-
: queueValidationRoot(dir);
|
|
72
|
-
await assertNoSymlinkDirectorySegments(root, dir, true);
|
|
73
|
-
await fs.promises.mkdir(recursiveMkdirPath(dir), { recursive: true, mode: 0o700 });
|
|
74
|
-
await assertNoSymlinkDirectorySegments(root, dir, false);
|
|
75
|
-
await chmodQueueDirectory(dir);
|
|
76
|
-
await syncQueueDirectoryCreation(dir, root.path);
|
|
77
|
-
}
|
|
78
|
-
async function assertJsonDurableQueueDir(dir, validationRoot) {
|
|
79
|
-
const root = validationRoot
|
|
80
|
-
? validationRoot
|
|
81
|
-
: queueValidationRoot(dir);
|
|
82
|
-
await assertNoSymlinkDirectorySegments(root, dir, false);
|
|
83
|
-
}
|
|
84
|
-
async function isDarwinSystemAlias(dir, stat) {
|
|
85
|
-
if (process.platform !== "darwin" || !stat.isSymbolicLink()) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
const resolved = path.resolve(dir);
|
|
89
|
-
if (resolved !== "/tmp" && resolved !== "/var") {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
try {
|
|
93
|
-
return realpathSync.native(resolved) === `/private${resolved}`;
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async function assertNoSymlinkDirectorySegments(validationRoot, dir, allowMissing) {
|
|
100
|
-
let base = resolveQueueFilesystemPath(validationRoot.path);
|
|
101
|
-
let target = resolveQueueFilesystemPath(dir);
|
|
102
|
-
let current = base;
|
|
103
|
-
let baseStat = fs.lstatSync(base);
|
|
104
|
-
if (baseStat.isSymbolicLink() && validationRoot.allowSymlinkBase) {
|
|
105
|
-
const relative = path.relative(base, target);
|
|
106
|
-
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
107
|
-
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
108
|
-
}
|
|
109
|
-
base = realpathSync.native(base);
|
|
110
|
-
target = path.join(base, ...relative.split(path.sep).filter(Boolean));
|
|
111
|
-
current = base;
|
|
112
|
-
baseStat = fs.lstatSync(base);
|
|
113
|
-
}
|
|
114
|
-
if (baseStat.isSymbolicLink() || !baseStat.isDirectory()) {
|
|
115
|
-
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
116
|
-
}
|
|
117
|
-
const segments = path.relative(base, target).split(path.sep).filter(Boolean);
|
|
118
|
-
for (let index = 0; index < segments.length; index++) {
|
|
119
|
-
const segment = segments[index];
|
|
120
|
-
if (segment === undefined) {
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
current = path.join(current, segment);
|
|
124
|
-
let stat;
|
|
125
|
-
try {
|
|
126
|
-
stat = fs.lstatSync(current);
|
|
127
|
-
}
|
|
128
|
-
catch (error) {
|
|
129
|
-
if (allowMissing && error.code === "ENOENT") {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
134
|
-
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
135
|
-
if (stat.isSymbolicLink() && validationRoot.allowSymlinkBase) {
|
|
136
|
-
if (await isDarwinSystemAlias(current, stat)) {
|
|
137
|
-
current = realpathSync.native(current);
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
async function chmodQueueDirectory(dir) {
|
|
146
|
-
const noFollow = typeof fs.constants.O_NOFOLLOW === "number" && process.platform !== "win32"
|
|
147
|
-
? fs.constants.O_NOFOLLOW
|
|
148
|
-
: 0;
|
|
149
|
-
const directoryFlag = typeof fs.constants.O_DIRECTORY === "number" && process.platform !== "win32"
|
|
150
|
-
? fs.constants.O_DIRECTORY
|
|
151
|
-
: 0;
|
|
152
|
-
if (noFollow || directoryFlag) {
|
|
153
|
-
let handle;
|
|
154
|
-
try {
|
|
155
|
-
handle = await fs.promises.open(dir, fs.constants.O_RDONLY | noFollow | directoryFlag);
|
|
156
|
-
const stat = fs.fstatSync(handle.fd);
|
|
157
|
-
if (!stat.isDirectory()) {
|
|
158
|
-
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
await handle.chmod(0o700);
|
|
162
|
-
}
|
|
163
|
-
catch {
|
|
164
|
-
// Best-effort on platforms that do not enforce POSIX modes.
|
|
165
|
-
}
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
finally {
|
|
169
|
-
try {
|
|
170
|
-
await handle?.close();
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
// Best-effort cleanup after chmod/open failures.
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
const stat = fs.lstatSync(dir);
|
|
178
|
-
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
179
|
-
throw new Error(`durable queue path is not a directory: ${dir}`);
|
|
180
|
-
}
|
|
181
|
-
try {
|
|
182
|
-
await fs.promises.chmod(dir, 0o700);
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
// Best-effort on platforms that do not enforce POSIX modes.
|
|
186
|
-
}
|
|
61
|
+
const directories = await queueDirectories(queueDir, failedDir);
|
|
62
|
+
await directories.queue.ensure();
|
|
63
|
+
await directories.failed.ensure();
|
|
187
64
|
}
|
|
188
65
|
export async function writeJsonDurableQueueEntry(params) {
|
|
189
66
|
await writeQueueEntry(params);
|
|
@@ -213,15 +90,16 @@ export async function ackJsonDurableQueueEntry(paths) {
|
|
|
213
90
|
await acknowledgeDurableQueueEntry(paths);
|
|
214
91
|
}
|
|
215
92
|
export async function loadJsonDurableQueueEntry(params) {
|
|
93
|
+
const pathsInput = params.paths;
|
|
94
|
+
const paths = validateDurableQueueEntryPaths(pathsInput);
|
|
95
|
+
const claimedPath = await claimDurableQueueEntry(paths);
|
|
96
|
+
if (!claimedPath)
|
|
97
|
+
return null;
|
|
98
|
+
const readOptions = { maxBytes: params.maxBytes };
|
|
99
|
+
let processingStarted = false;
|
|
216
100
|
try {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const claimedPath = await claimDurableQueueEntry(paths);
|
|
220
|
-
if (!claimedPath)
|
|
221
|
-
return null;
|
|
222
|
-
return await withJsonDurableQueueEntry(claimedPath, {
|
|
223
|
-
maxBytes: params.maxBytes,
|
|
224
|
-
}, async (raw, identity, releaseReadPin) => {
|
|
101
|
+
return await withJsonDurableQueueEntry(claimedPath, readOptions, async (raw, identity, releaseReadPin) => {
|
|
102
|
+
processingStarted = true;
|
|
225
103
|
const read = params.read;
|
|
226
104
|
const result = read ? await Reflect.apply(read, params, [raw, paths.jsonPath]) : { entry: raw };
|
|
227
105
|
if (result.migrated) {
|
|
@@ -233,7 +111,7 @@ export async function loadJsonDurableQueueEntry(params) {
|
|
|
233
111
|
});
|
|
234
112
|
}
|
|
235
113
|
catch (error) {
|
|
236
|
-
if (getErrorCode(error) === "ENOENT") {
|
|
114
|
+
if (!processingStarted && getErrorCode(error) === "ENOENT") {
|
|
237
115
|
return null;
|
|
238
116
|
}
|
|
239
117
|
throw error;
|
|
@@ -327,9 +205,9 @@ export async function moveJsonDurableQueueEntryToFailed(params) {
|
|
|
327
205
|
assertSafeQueueEntryId(id);
|
|
328
206
|
assertNoWindowsPathAlias(queueDir);
|
|
329
207
|
assertNoWindowsPathAlias(failedDir);
|
|
330
|
-
const
|
|
331
|
-
await
|
|
332
|
-
await
|
|
208
|
+
const directories = await queueDirectories(queueDir, failedDir);
|
|
209
|
+
await directories.queue.assert();
|
|
210
|
+
await directories.failed.ensure();
|
|
333
211
|
const paths = validateDurableQueueEntryPaths(resolveJsonDurableQueueEntryPaths(queueDir, id));
|
|
334
212
|
await moveDurableQueueEntryToFailed({
|
|
335
213
|
paths,
|
package/dist/json-store.d.ts
CHANGED
package/dist/json-stringify.d.ts
CHANGED
package/dist/json.d.ts
CHANGED
|
@@ -47,4 +47,3 @@ export declare function readJsonIfExists<T>(filePath: string, options?: ReadJson
|
|
|
47
47
|
export declare function readJsonSync<T = unknown>(filePath: string, options?: ReadJsonOptions): T;
|
|
48
48
|
export type WriteJsonOptions = Pick<WriteTextAtomicOptions, "dirMode" | "durable" | "mode" | "trailingNewline">;
|
|
49
49
|
export declare function writeJson(filePath: string, value: unknown, options?: WriteJsonOptions): Promise<void>;
|
|
50
|
-
//# sourceMappingURL=json.d.ts.map
|