@openclaw/openshell-sandbox 2026.9.1 → 2026.9.3
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/dist/index.js +87 -47
- package/node_modules/@openclaw/fs-safe/CHANGELOG.md +700 -0
- package/node_modules/@openclaw/fs-safe/LICENSE +21 -0
- package/node_modules/@openclaw/fs-safe/README.md +564 -0
- package/node_modules/@openclaw/fs-safe/SECURITY.md +45 -0
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.d.ts +33 -0
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/absolute-path.js +307 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts +26 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/advanced.js +28 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-crc32.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-crc32.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-crc32.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-deadline.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-deadline.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-deadline.js +103 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-entry.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-entry.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-entry.js +85 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-errors.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-errors.js +23 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-gzip-tail.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-gzip-tail.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-gzip-tail.js +74 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.d.ts +19 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-input.js +92 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-kind.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-kind.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-kind.js +82 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-limits.d.ts +57 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-limits.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-limits.js +131 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-merge.js +157 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-native.d.ts +20 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-native.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-native.js +107 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-options.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-options.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-options.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser-errors.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser-errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser-errors.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-parser.wasm +0 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.d.ts +20 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-plan.js +55 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-policy.d.ts +22 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-policy.js +38 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-read.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-read.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-read.js +225 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-staging.js +250 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-inspect.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-inspect.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-inspect.js +59 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-stream.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-stream.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-stream.js +95 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-wasm.d.ts +18 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-wasm.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar-wasm.js +99 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar.d.ts +19 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-tar.js +21 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-admission.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-admission.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-admission.js +60 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-count.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-count.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-count.js +140 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-directory.js +228 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-entry.js +27 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-integrity.js +41 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-names.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-names.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-names.js +100 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive-zip-preflight.js +44 -0
- package/node_modules/@openclaw/fs-safe/dist/archive.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/archive.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/archive.js +275 -0
- package/node_modules/@openclaw/fs-safe/dist/async-lock.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/async-lock.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/async-lock.js +17 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/atomic.js +4 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read-stream.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read-stream.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read-stream.js +21 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/bounded-read.js +106 -0
- package/node_modules/@openclaw/fs-safe/dist/byte-budget.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/byte-budget.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/byte-budget.js +9 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/config.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/config.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/containment.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/containment.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/containment.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/deny-mutations.js +69 -0
- package/node_modules/@openclaw/fs-safe/dist/device-path.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/device-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/device-path.js +137 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-durability.d.ts +44 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-durability.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-durability.js +299 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-guard.js +82 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-node.js +93 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/directory-mode-owner.js +78 -0
- package/node_modules/@openclaw/fs-safe/dist/durability.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/durability.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/durability.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/error-detail.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/error-detail.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/error-detail.js +10 -0
- package/node_modules/@openclaw/fs-safe/dist/errors.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/errors.js +26 -0
- package/node_modules/@openclaw/fs-safe/dist/file-hash.d.ts +10 -0
- package/node_modules/@openclaw/fs-safe/dist/file-hash.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-hash.js +73 -0
- package/node_modules/@openclaw/fs-safe/dist/file-identity.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-identity.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-identity.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock-sync.js +349 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock.d.ts +24 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-lock.js +46 -0
- package/node_modules/@openclaw/fs-safe/dist/file-observation.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-observation.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-observation.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.d.ts +33 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-boundary.js +189 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-limit.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-limit.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-limit.js +8 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-prune.js +95 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store-sync-write.js +127 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store.d.ts +62 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-store.js +357 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/file-sync.js +19 -0
- package/node_modules/@openclaw/fs-safe/dist/filename.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/filename.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/filename.js +91 -0
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts +13 -0
- package/node_modules/@openclaw/fs-safe/dist/fs.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/fs.js +30 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mkdir.js +87 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mutation.d.ts +37 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mutation.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/guarded-mutation.js +82 -0
- package/node_modules/@openclaw/fs-safe/dist/home-dir.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/home-dir.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/home-dir.js +84 -0
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/index.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/index.js +5 -0
- package/node_modules/@openclaw/fs-safe/dist/install-path.d.ts +20 -0
- package/node_modules/@openclaw/fs-safe/dist/install-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/install-path.js +94 -0
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.d.ts +35 -0
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-document-store.js +97 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-directory.js +20 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.d.ts +17 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue-ownership.js +292 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.d.ts +46 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-durable-queue.js +383 -0
- package/node_modules/@openclaw/fs-safe/dist/json-store.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/json-store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-store.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/json-stringify.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/json-stringify.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json-stringify.js +7 -0
- package/node_modules/@openclaw/fs-safe/dist/json.d.ts +50 -0
- package/node_modules/@openclaw/fs-safe/dist/json.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/json.js +343 -0
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.d.ts +9 -0
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/local-file-access.js +87 -0
- package/node_modules/@openclaw/fs-safe/dist/local-roots.d.ts +26 -0
- package/node_modules/@openclaw/fs-safe/dist/local-roots.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/local-roots.js +135 -0
- package/node_modules/@openclaw/fs-safe/dist/lock-config.d.ts +10 -0
- package/node_modules/@openclaw/fs-safe/dist/lock-config.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/lock-config.js +12 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.d.ts +43 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path-cleanup.js +161 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/move-path.js +334 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts +93 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-binding.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts +17 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-config.js +71 -0
- package/node_modules/@openclaw/fs-safe/dist/native-operations.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/native-operations.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-operations.js +132 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write-windows.js +96 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-pinned-write.js +161 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native-staged-file.js +362 -0
- package/node_modules/@openclaw/fs-safe/dist/native.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/native.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/native.js +204 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-file-failure.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-file-failure.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-file-failure.js +45 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-realpath.d.ts +16 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-realpath.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/opened-realpath.js +92 -0
- package/node_modules/@openclaw/fs-safe/dist/output.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/output.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/output.js +123 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/owner-dacl.js +28 -0
- package/node_modules/@openclaw/fs-safe/dist/path-policy.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/path-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path-policy.js +44 -0
- package/node_modules/@openclaw/fs-safe/dist/path.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/path.js +136 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permission-exec.js +74 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-public.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts +59 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions-windows.js +296 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions.d.ts +60 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/permissions.js +125 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts +24 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-open.js +74 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-operation.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-operation.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-operation.js +35 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.d.ts +36 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/pinned-write.js +252 -0
- package/node_modules/@openclaw/fs-safe/dist/private-directory.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/private-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/private-directory.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.d.ts +45 -0
- package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/private-temp-workspace.js +299 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.d.ts +28 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file-failure.js +22 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/publish-file.js +366 -0
- package/node_modules/@openclaw/fs-safe/dist/read-open-flags.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/read-open-flags.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/read-open-flags.js +13 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/read-opened-file.js +18 -0
- package/node_modules/@openclaw/fs-safe/dist/regular-file.d.ts +38 -0
- package/node_modules/@openclaw/fs-safe/dist/regular-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/regular-file.js +391 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-directory.js +42 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts +39 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-fallback.js +331 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts +21 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-copy-source.js +107 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts +51 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-descriptor.js +161 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-rename-policy.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-rename-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-rename-policy.js +30 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts +53 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file-temp-owner.js +376 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.d.ts +58 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/replace-file.js +329 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts +38 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-context.js +141 -0
- package/node_modules/@openclaw/fs-safe/dist/root-errors.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/root-errors.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-errors.js +75 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.d.ts +45 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-file.js +120 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts +163 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-impl.js +1230 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-existing.js +68 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-symlink.d.ts +7 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-symlink.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path-symlink.js +35 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path.d.ts +40 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-path.js +481 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths.d.ts +89 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-paths.js +381 -0
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts +41 -0
- package/node_modules/@openclaw/fs-safe/dist/root-walk.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-walk.js +133 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-mode.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-mode.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-mode.js +61 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-verification.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-verification.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root-write-verification.js +97 -0
- package/node_modules/@openclaw/fs-safe/dist/root.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/root.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/root.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/safe-path-segment.js +75 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-file.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-file.js +329 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-async.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-async.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-async.js +73 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.d.ts +17 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret-read-policy.js +40 -0
- package/node_modules/@openclaw/fs-safe/dist/secret.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/secret.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secret.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-file.d.ts +32 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-file.js +182 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts +27 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/secure-temp-dir.js +160 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.d.ts +15 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-staged-file.js +143 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.d.ts +27 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sibling-temp.js +95 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.d.ts +31 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-acquire.js +336 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.d.ts +24 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-handle.js +42 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-policy.js +71 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts +63 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-reclaim.js +305 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-root.d.ts +3 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-root.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-root.js +76 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-types.d.ts +63 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-types.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/sidecar-lock.js +265 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-directory.d.ts +16 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-directory.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-directory.js +60 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-file-types.d.ts +56 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-file-types.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/staged-file-types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/store.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/store.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/store.js +3 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/strict-file-identity.js +51 -0
- package/node_modules/@openclaw/fs-safe/dist/string-coerce.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/string-coerce.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/string-coerce.js +16 -0
- package/node_modules/@openclaw/fs-safe/dist/suppressed-error.d.ts +6 -0
- package/node_modules/@openclaw/fs-safe/dist/suppressed-error.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/suppressed-error.js +15 -0
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.d.ts +12 -0
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/symlink-parents.js +78 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-cleanup.js +87 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-target.d.ts +28 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-target.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-target.js +137 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.d.ts +23 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp-workspace-owner.js +320 -0
- package/node_modules/@openclaw/fs-safe/dist/temp.d.ts +4 -0
- package/node_modules/@openclaw/fs-safe/dist/temp.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/temp.js +2 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts +25 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/test-hooks.js +13 -0
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts +14 -0
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/text-atomic.js +14 -0
- package/node_modules/@openclaw/fs-safe/dist/timing.d.ts +8 -0
- package/node_modules/@openclaw/fs-safe/dist/timing.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/timing.js +40 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/trash.js +171 -0
- package/node_modules/@openclaw/fs-safe/dist/types.d.ts +23 -0
- package/node_modules/@openclaw/fs-safe/dist/types.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/types.js +1 -0
- package/node_modules/@openclaw/fs-safe/dist/walk.d.ts +37 -0
- package/node_modules/@openclaw/fs-safe/dist/walk.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/walk.js +207 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-command.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-command.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-command.js +34 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts +32 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/windows-owner.js +126 -0
- package/node_modules/@openclaw/fs-safe/dist/write-open-flags.d.ts +5 -0
- package/node_modules/@openclaw/fs-safe/dist/write-open-flags.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/write-open-flags.js +35 -0
- package/node_modules/@openclaw/fs-safe/dist/write-queue.d.ts +2 -0
- package/node_modules/@openclaw/fs-safe/dist/write-queue.d.ts.map +1 -0
- package/node_modules/@openclaw/fs-safe/dist/write-queue.js +18 -0
- package/node_modules/@openclaw/fs-safe/docs/advanced.md +153 -0
- package/node_modules/@openclaw/fs-safe/docs/archive.md +658 -0
- package/node_modules/@openclaw/fs-safe/docs/assets/readme-banner.jpg +0 -0
- package/node_modules/@openclaw/fs-safe/docs/atomic.md +334 -0
- package/node_modules/@openclaw/fs-safe/docs/config.md +131 -0
- package/node_modules/@openclaw/fs-safe/docs/contributing.md +180 -0
- package/node_modules/@openclaw/fs-safe/docs/durability.md +313 -0
- package/node_modules/@openclaw/fs-safe/docs/errors.md +232 -0
- package/node_modules/@openclaw/fs-safe/docs/file-store.md +258 -0
- package/node_modules/@openclaw/fs-safe/docs/filename.md +96 -0
- package/node_modules/@openclaw/fs-safe/docs/index.md +84 -0
- package/node_modules/@openclaw/fs-safe/docs/install-path.md +170 -0
- package/node_modules/@openclaw/fs-safe/docs/install.md +163 -0
- package/node_modules/@openclaw/fs-safe/docs/json-store.md +221 -0
- package/node_modules/@openclaw/fs-safe/docs/json.md +213 -0
- package/node_modules/@openclaw/fs-safe/docs/local-roots.md +141 -0
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.5.md +196 -0
- package/node_modules/@openclaw/fs-safe/docs/migrating-to-0.6.md +43 -0
- package/node_modules/@openclaw/fs-safe/docs/native-helper.md +118 -0
- package/node_modules/@openclaw/fs-safe/docs/native.md +196 -0
- package/node_modules/@openclaw/fs-safe/docs/output.md +139 -0
- package/node_modules/@openclaw/fs-safe/docs/path-scope.md +159 -0
- package/node_modules/@openclaw/fs-safe/docs/path.md +208 -0
- package/node_modules/@openclaw/fs-safe/docs/permissions.md +200 -0
- package/node_modules/@openclaw/fs-safe/docs/private-file-store.md +54 -0
- package/node_modules/@openclaw/fs-safe/docs/public-api.md +112 -0
- package/node_modules/@openclaw/fs-safe/docs/quickstart.md +154 -0
- package/node_modules/@openclaw/fs-safe/docs/reading.md +183 -0
- package/node_modules/@openclaw/fs-safe/docs/regular-file.md +190 -0
- package/node_modules/@openclaw/fs-safe/docs/root.md +266 -0
- package/node_modules/@openclaw/fs-safe/docs/secret-file.md +273 -0
- package/node_modules/@openclaw/fs-safe/docs/secure-file.md +100 -0
- package/node_modules/@openclaw/fs-safe/docs/security-model.md +188 -0
- package/node_modules/@openclaw/fs-safe/docs/sidecar-lock.md +439 -0
- package/node_modules/@openclaw/fs-safe/docs/staged-file.md +182 -0
- package/node_modules/@openclaw/fs-safe/docs/store.md +94 -0
- package/node_modules/@openclaw/fs-safe/docs/temp.md +476 -0
- package/node_modules/@openclaw/fs-safe/docs/test-hooks.md +96 -0
- package/node_modules/@openclaw/fs-safe/docs/testing.md +189 -0
- package/node_modules/@openclaw/fs-safe/docs/timing.md +121 -0
- package/node_modules/@openclaw/fs-safe/docs/types.md +188 -0
- package/node_modules/@openclaw/fs-safe/docs/walk.md +128 -0
- package/node_modules/@openclaw/fs-safe/docs/writing.md +347 -0
- package/node_modules/@openclaw/fs-safe/package.json +187 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-arm64/package.json +29 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-darwin-x64/package.json +29 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-gnu/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-arm64-musl/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-gnu/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-linux-x64-musl/package.json +32 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/fs-safe-native.node +0 -0
- package/node_modules/@openclaw/fs-safe-win32-x64-msvc/package.json +29 -0
- package/node_modules/core-util-is/LICENSE +19 -0
- package/node_modules/core-util-is/README.md +3 -0
- package/node_modules/core-util-is/lib/util.js +107 -0
- package/node_modules/core-util-is/package.json +38 -0
- package/node_modules/immediate/LICENSE.txt +20 -0
- package/node_modules/immediate/README.md +93 -0
- package/node_modules/immediate/dist/immediate.js +75 -0
- package/node_modules/immediate/dist/immediate.min.js +1 -0
- package/node_modules/immediate/lib/browser.js +69 -0
- package/node_modules/immediate/lib/index.js +73 -0
- package/node_modules/immediate/package.json +42 -0
- package/node_modules/inherits/LICENSE +16 -0
- package/node_modules/inherits/README.md +42 -0
- package/node_modules/inherits/inherits.js +9 -0
- package/node_modules/inherits/inherits_browser.js +27 -0
- package/node_modules/inherits/package.json +29 -0
- package/node_modules/isarray/.npmignore +1 -0
- package/node_modules/isarray/.travis.yml +4 -0
- package/node_modules/isarray/Makefile +6 -0
- package/node_modules/isarray/README.md +60 -0
- package/node_modules/isarray/component.json +19 -0
- package/node_modules/isarray/index.js +5 -0
- package/node_modules/isarray/package.json +45 -0
- package/node_modules/isarray/test.js +20 -0
- package/node_modules/jszip/.codeclimate.yml +16 -0
- package/node_modules/jszip/.editorconfig +8 -0
- package/node_modules/jszip/.eslintrc.js +43 -0
- package/node_modules/jszip/.github/workflows/pr.yaml +58 -0
- package/node_modules/jszip/.jekyll-metadata +0 -0
- package/node_modules/jszip/.travis.yml +17 -0
- package/node_modules/jszip/CHANGES.md +204 -0
- package/node_modules/jszip/LICENSE.markdown +651 -0
- package/node_modules/jszip/README.markdown +33 -0
- package/node_modules/jszip/deps.js +37 -0
- package/node_modules/jszip/dist/jszip.js +11577 -0
- package/node_modules/jszip/dist/jszip.min.js +13 -0
- package/node_modules/jszip/graph.svg +601 -0
- package/node_modules/jszip/index.d.ts +330 -0
- package/node_modules/jszip/lib/base64.js +106 -0
- package/node_modules/jszip/lib/compressedObject.js +74 -0
- package/node_modules/jszip/lib/compressions.js +14 -0
- package/node_modules/jszip/lib/crc32.js +77 -0
- package/node_modules/jszip/lib/defaults.js +11 -0
- package/node_modules/jszip/lib/external.js +18 -0
- package/node_modules/jszip/lib/flate.js +85 -0
- package/node_modules/jszip/lib/generate/ZipFileWorker.js +539 -0
- package/node_modules/jszip/lib/generate/index.js +57 -0
- package/node_modules/jszip/lib/index.js +55 -0
- package/node_modules/jszip/lib/license_header.js +11 -0
- package/node_modules/jszip/lib/load.js +88 -0
- package/node_modules/jszip/lib/nodejs/NodejsStreamInputAdapter.js +74 -0
- package/node_modules/jszip/lib/nodejs/NodejsStreamOutputAdapter.js +42 -0
- package/node_modules/jszip/lib/nodejsUtils.js +57 -0
- package/node_modules/jszip/lib/object.js +384 -0
- package/node_modules/jszip/lib/readable-stream-browser.js +10 -0
- package/node_modules/jszip/lib/reader/ArrayReader.js +57 -0
- package/node_modules/jszip/lib/reader/DataReader.js +116 -0
- package/node_modules/jszip/lib/reader/NodeBufferReader.js +19 -0
- package/node_modules/jszip/lib/reader/StringReader.js +38 -0
- package/node_modules/jszip/lib/reader/Uint8ArrayReader.js +22 -0
- package/node_modules/jszip/lib/reader/readerFor.js +28 -0
- package/node_modules/jszip/lib/signature.js +7 -0
- package/node_modules/jszip/lib/stream/ConvertWorker.js +26 -0
- package/node_modules/jszip/lib/stream/Crc32Probe.js +24 -0
- package/node_modules/jszip/lib/stream/DataLengthProbe.js +29 -0
- package/node_modules/jszip/lib/stream/DataWorker.js +116 -0
- package/node_modules/jszip/lib/stream/GenericWorker.js +263 -0
- package/node_modules/jszip/lib/stream/StreamHelper.js +214 -0
- package/node_modules/jszip/lib/support.js +38 -0
- package/node_modules/jszip/lib/utf8.js +275 -0
- package/node_modules/jszip/lib/utils.js +501 -0
- package/node_modules/jszip/lib/zipEntries.js +261 -0
- package/node_modules/jszip/lib/zipEntry.js +293 -0
- package/node_modules/jszip/lib/zipObject.js +133 -0
- package/node_modules/jszip/package.json +67 -0
- package/node_modules/jszip/sponsors.md +21 -0
- package/node_modules/jszip/tsconfig.json +101 -0
- package/node_modules/jszip/vendor/FileSaver.js +247 -0
- package/node_modules/lie/README.md +62 -0
- package/node_modules/lie/dist/lie.js +350 -0
- package/node_modules/lie/dist/lie.min.js +1 -0
- package/node_modules/lie/dist/lie.polyfill.js +358 -0
- package/node_modules/lie/dist/lie.polyfill.min.js +1 -0
- package/node_modules/lie/lib/browser.js +273 -0
- package/node_modules/lie/lib/index.js +298 -0
- package/node_modules/lie/license.md +7 -0
- package/node_modules/lie/lie.d.ts +244 -0
- package/node_modules/lie/package.json +69 -0
- package/node_modules/lie/polyfill.js +4 -0
- package/node_modules/pako/CHANGELOG.md +164 -0
- package/node_modules/pako/LICENSE +21 -0
- package/node_modules/pako/README.md +191 -0
- package/node_modules/pako/dist/pako.js +6818 -0
- package/node_modules/pako/dist/pako.min.js +1 -0
- package/node_modules/pako/dist/pako_deflate.js +3997 -0
- package/node_modules/pako/dist/pako_deflate.min.js +1 -0
- package/node_modules/pako/dist/pako_inflate.js +3300 -0
- package/node_modules/pako/dist/pako_inflate.min.js +1 -0
- package/node_modules/pako/index.js +14 -0
- package/node_modules/pako/lib/deflate.js +400 -0
- package/node_modules/pako/lib/inflate.js +423 -0
- package/node_modules/pako/lib/utils/common.js +105 -0
- package/node_modules/pako/lib/utils/strings.js +187 -0
- package/node_modules/pako/lib/zlib/README +59 -0
- package/node_modules/pako/lib/zlib/adler32.js +51 -0
- package/node_modules/pako/lib/zlib/constants.js +68 -0
- package/node_modules/pako/lib/zlib/crc32.js +59 -0
- package/node_modules/pako/lib/zlib/deflate.js +1874 -0
- package/node_modules/pako/lib/zlib/gzheader.js +58 -0
- package/node_modules/pako/lib/zlib/inffast.js +345 -0
- package/node_modules/pako/lib/zlib/inflate.js +1556 -0
- package/node_modules/pako/lib/zlib/inftrees.js +343 -0
- package/node_modules/pako/lib/zlib/messages.js +32 -0
- package/node_modules/pako/lib/zlib/trees.js +1222 -0
- package/node_modules/pako/lib/zlib/zstream.js +47 -0
- package/node_modules/pako/package.json +44 -0
- package/node_modules/process-nextick-args/index.js +45 -0
- package/node_modules/process-nextick-args/license.md +19 -0
- package/node_modules/process-nextick-args/package.json +25 -0
- package/node_modules/process-nextick-args/readme.md +18 -0
- package/node_modules/readable-stream/.travis.yml +34 -0
- package/node_modules/readable-stream/CONTRIBUTING.md +38 -0
- package/node_modules/readable-stream/GOVERNANCE.md +136 -0
- package/node_modules/readable-stream/LICENSE +47 -0
- package/node_modules/readable-stream/README.md +58 -0
- package/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md +60 -0
- package/node_modules/readable-stream/duplex-browser.js +1 -0
- package/node_modules/readable-stream/duplex.js +1 -0
- package/node_modules/readable-stream/lib/_stream_duplex.js +131 -0
- package/node_modules/readable-stream/lib/_stream_passthrough.js +47 -0
- package/node_modules/readable-stream/lib/_stream_readable.js +1019 -0
- package/node_modules/readable-stream/lib/_stream_transform.js +214 -0
- package/node_modules/readable-stream/lib/_stream_writable.js +685 -0
- package/node_modules/readable-stream/lib/internal/streams/BufferList.js +78 -0
- package/node_modules/readable-stream/lib/internal/streams/destroy.js +84 -0
- package/node_modules/readable-stream/lib/internal/streams/stream-browser.js +1 -0
- package/node_modules/readable-stream/lib/internal/streams/stream.js +1 -0
- package/node_modules/readable-stream/package.json +52 -0
- package/node_modules/readable-stream/passthrough.js +1 -0
- package/node_modules/readable-stream/readable-browser.js +7 -0
- package/node_modules/readable-stream/readable.js +19 -0
- package/node_modules/readable-stream/transform.js +1 -0
- package/node_modules/readable-stream/writable-browser.js +1 -0
- package/node_modules/readable-stream/writable.js +8 -0
- package/node_modules/safe-buffer/LICENSE +21 -0
- package/node_modules/safe-buffer/README.md +584 -0
- package/node_modules/safe-buffer/index.d.ts +187 -0
- package/node_modules/safe-buffer/index.js +62 -0
- package/node_modules/safe-buffer/package.json +37 -0
- package/node_modules/setimmediate/LICENSE.txt +20 -0
- package/node_modules/setimmediate/package.json +30 -0
- package/node_modules/setimmediate/setImmediate.js +186 -0
- package/node_modules/string_decoder/.travis.yml +50 -0
- package/node_modules/string_decoder/LICENSE +48 -0
- package/node_modules/string_decoder/README.md +47 -0
- package/node_modules/string_decoder/lib/string_decoder.js +296 -0
- package/node_modules/string_decoder/package.json +31 -0
- package/node_modules/util-deprecate/History.md +16 -0
- package/node_modules/util-deprecate/LICENSE +24 -0
- package/node_modules/util-deprecate/README.md +53 -0
- package/node_modules/util-deprecate/browser.js +67 -0
- package/node_modules/util-deprecate/node.js +6 -0
- package/node_modules/util-deprecate/package.json +27 -0
- package/package.json +6 -4
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/index.d.ts +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/index.js +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/license +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/package.json +0 -0
- /package/node_modules/{p-limit/node_modules/yocto-queue → yocto-queue}/readme.md +0 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# File store
|
|
2
|
+
|
|
3
|
+
`fileStore` is exported from `@openclaw/fs-safe/store`. It is a managed wrapper around `root()` for the common "store files under a directory at known modes, prune old ones, hand back absolute paths" pattern. Useful for caches, ingest staging, generated artifacts, anywhere the consumer wants object-style access plus stream and copy primitives.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import {
|
|
7
|
+
fileStore,
|
|
8
|
+
type FileStore,
|
|
9
|
+
type FileStoreOptions,
|
|
10
|
+
type FileStoreWriteOptions,
|
|
11
|
+
type FileStorePruneOptions,
|
|
12
|
+
} from "@openclaw/fs-safe/store";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## When to reach for it
|
|
16
|
+
|
|
17
|
+
- You want a single directory holding files written by your code, with consistent mode bits and atomic placement.
|
|
18
|
+
- You want a `FileStore.write(rel, data)` / `read(rel)` / `pruneExpired(...)` interface.
|
|
19
|
+
- You want to feed a stream into the store with a byte cap.
|
|
20
|
+
- You don't need the full `Root` surface (move, list, mkdir, …); the store can hand you a real `Root` via `.root()` when you do.
|
|
21
|
+
|
|
22
|
+
## Factory: `fileStore(options)`
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
const cache = fileStore({
|
|
26
|
+
rootDir: "/var/cache/app",
|
|
27
|
+
mode: 0o600, // file mode for writes (default 0o600)
|
|
28
|
+
dirMode: 0o700, // mode for parent directories created on demand (default 0o700)
|
|
29
|
+
maxBytes: 64 * 1024 * 1024, // optional: refuse writes/reads larger than this
|
|
30
|
+
private: true, // use secret-file atomic writes for private state
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Store and per-call `maxBytes` values must be non-negative safe integers or positive `Infinity`. Zero is an active zero-byte cap; `Infinity` disables the cap. An omitted or explicitly `undefined` per-call value preserves the store-level limit. The same rule applies to buffer writes, streams, copies, async reads, and synchronous reads/writes.
|
|
35
|
+
|
|
36
|
+
Use `private: true` for credentials, auth profiles, tokens, and other private
|
|
37
|
+
state. Private mode keeps the same `FileStore` shape but routes writes through
|
|
38
|
+
the secret-file atomic path, refusing symlink parent components and re-asserting
|
|
39
|
+
mode after rename.
|
|
40
|
+
|
|
41
|
+
Returns a `FileStore`:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
type FileStore = {
|
|
45
|
+
readonly rootDir: string;
|
|
46
|
+
path(relativePath: string): string;
|
|
47
|
+
root(): Promise<Root>;
|
|
48
|
+
write(rel, data: string | Uint8Array, options?): Promise<string>;
|
|
49
|
+
writeStream(rel, stream: Readable, options?): Promise<string>;
|
|
50
|
+
copyIn(rel, sourcePath: string, options?): Promise<string>;
|
|
51
|
+
open(rel, options?): Promise<OpenResult>;
|
|
52
|
+
read(rel, options?): Promise<ReadResult>;
|
|
53
|
+
readBytes(rel, options?): Promise<Buffer>;
|
|
54
|
+
readText(rel, options?): Promise<string>;
|
|
55
|
+
readTextIfExists(rel, options?): Promise<string | null>;
|
|
56
|
+
readJson<T = unknown>(rel, options?): Promise<T>;
|
|
57
|
+
readJsonIfExists<T = unknown>(rel, options?): Promise<T | null>;
|
|
58
|
+
writeText(rel, data: string | Uint8Array, options?): Promise<string>;
|
|
59
|
+
writeJson(rel, data: unknown, options?): Promise<string>;
|
|
60
|
+
json<T = unknown>(rel, options?): JsonStore<T>;
|
|
61
|
+
remove(rel): Promise<void>;
|
|
62
|
+
exists(rel): Promise<boolean>;
|
|
63
|
+
pruneExpired(options: FileStorePruneOptions): Promise<void>;
|
|
64
|
+
};
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`path()` returns the absolute path the store would use, after asserting it stays inside `rootDir`. Useful for logging or for handing to other libraries.
|
|
68
|
+
|
|
69
|
+
Every `relativePath` is a portable store key. The same lexical policy applies
|
|
70
|
+
to every keyed async and sync method, including reads, `exists`, `remove`,
|
|
71
|
+
`path()`, and `json()` construction, with either `private: false` or `true`.
|
|
72
|
+
Keys must use their exact canonical spelling; the store never trims, normalizes,
|
|
73
|
+
or converts one caller-supplied key onto another:
|
|
74
|
+
|
|
75
|
+
- Keys are nonempty NFC Unicode strings without surrounding whitespace or NUL.
|
|
76
|
+
- Segments are separated by a single forward slash. Empty segments, repeated or
|
|
77
|
+
trailing slashes, and complete `.` or `..` segments are rejected, including
|
|
78
|
+
`./b`, `a/./b`, and `a/../b`.
|
|
79
|
+
- Every backslash is rejected on every platform, including a literal POSIX
|
|
80
|
+
`a\b` filename. POSIX and Windows absolute, rooted, UNC, and extended paths
|
|
81
|
+
are rejected.
|
|
82
|
+
- Windows drive-relative segments such as `C:name` or `C:` are rejected
|
|
83
|
+
anywhere in a key, including `a/C:name`.
|
|
84
|
+
- No segment may end in an ASCII dot or space.
|
|
85
|
+
|
|
86
|
+
Violations report `invalid-path` when key validation is reached. Ordinary nested
|
|
87
|
+
keys, NFC Unicode such as `café/日本語.txt`, `.hidden`, `a..b`, and internal spaces
|
|
88
|
+
such as `internal space/a b.txt` are accepted. Colons elsewhere, such as the
|
|
89
|
+
timestamp in `logs/2026-08-02T10:30:00Z.log`, remain lexically valid; filesystem
|
|
90
|
+
success still depends on the platform and the underlying Root policies.
|
|
91
|
+
|
|
92
|
+
Validation retains each method's operation order. Async reads, `exists`, and
|
|
93
|
+
`remove` open the root first: if the root is missing, strict methods report
|
|
94
|
+
`not-found` and `readTextIfExists` / `readJsonIfExists` return `null`, even for an
|
|
95
|
+
invalid key. With an existing root, those same invalid keys report `invalid-path`.
|
|
96
|
+
Private `copyIn` checks and reads its source before validating the destination
|
|
97
|
+
key, and `writeJson` serializes its value before validating the key. Key rejection
|
|
98
|
+
therefore does not imply that no filesystem access or serialization occurred.
|
|
99
|
+
|
|
100
|
+
`root()` returns a [`Root`](root.md) handle for the same directory when you need the full surface (move, list, mkdir). It's a fresh handle per call and is safe to call frequently.
|
|
101
|
+
|
|
102
|
+
## Writes
|
|
103
|
+
|
|
104
|
+
Every write goes through `writeSiblingTempFile` — temp + rename, mode applied to file and parent dir, both `fsync`'d.
|
|
105
|
+
|
|
106
|
+
### `write(rel, data, options?)`
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const path = await cache.write("entries/2026/05/05.json", JSON.stringify(entry));
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Buffer or string. Returns the final absolute path. Throws `too-large` if `data.byteLength` exceeds `maxBytes`.
|
|
113
|
+
|
|
114
|
+
### `writeText(rel, data, options?)` / `writeJson(rel, data, options?)`
|
|
115
|
+
|
|
116
|
+
Convenience wrappers over `write`. `writeJson` pretty-prints with a trailing newline by default and accepts `{ trailingNewline: false }` when the exact bytes matter.
|
|
117
|
+
|
|
118
|
+
### `json<T>(rel, options?)`
|
|
119
|
+
|
|
120
|
+
Returns a typed single-file JSON state helper for a file under this store. It
|
|
121
|
+
inherits the store's root, mode, max-size, and private-write policy, then adds
|
|
122
|
+
`readOr`, `readRequired`, `update`, `updateOr`, and optional sidecar locking:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const state = cache.json<State>("state/settings.json", { lock: true });
|
|
126
|
+
await state.updateOr(defaultState, (current) => ({ ...current, enabled: true }));
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Use this when one JSON file owns one piece of state. `jsonStore({ filePath })`
|
|
130
|
+
is the absolute-path convenience wrapper for the same primitive.
|
|
131
|
+
|
|
132
|
+
### `writeStream(rel, stream, options?)`
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { Readable } from "node:stream";
|
|
136
|
+
const path = await cache.writeStream("downloads/blob.bin", Readable.from(remoteFetch));
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Streams into a sibling temp with a running byte budget. Aborts the source stream with `too-large` if `maxBytes` is exceeded mid-stream — partial writes are cleaned up.
|
|
140
|
+
|
|
141
|
+
### `copyIn(rel, sourcePath, options?)`
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const path = await cache.copyIn("ingest/upload.bin", "/tmp/upload.bin");
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
One-shot ingest from an absolute source path. Source is checked for symlink/non-regular before copy. Same mode rules as `write`.
|
|
148
|
+
|
|
149
|
+
### `FileStoreWriteOptions`
|
|
150
|
+
|
|
151
|
+
Per-call overrides for the store-level defaults:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
type FileStoreWriteOptions = {
|
|
155
|
+
dirMode?: number;
|
|
156
|
+
mode?: number;
|
|
157
|
+
maxBytes?: number;
|
|
158
|
+
tempPrefix?: string; // override the default "." + basename
|
|
159
|
+
};
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Reads
|
|
163
|
+
|
|
164
|
+
`open`, `read`, `readBytes`, `readText`, and `readJson` delegate to a fresh `Root` with `hardlinks: "reject"` and the store's `maxBytes`. Same return shapes as `Root`.
|
|
165
|
+
Async and sync reads both report `not-file` when the key names a directory;
|
|
166
|
+
stable hardlinks and symlinks retain `hardlink` and `symlink`. The `IfExists`
|
|
167
|
+
methods return their nullish result only for `not-found`. Operational filesystem
|
|
168
|
+
read failures use `read-failed` with the Node error retained in `cause`.
|
|
169
|
+
|
|
170
|
+
## `remove(rel)` / `exists(rel)`
|
|
171
|
+
|
|
172
|
+
Forward to the underlying `Root`. `remove` unlinks files and `rmdir`s empty directories; non-empty dirs throw `not-empty`.
|
|
173
|
+
|
|
174
|
+
## `pruneExpired(options)`
|
|
175
|
+
|
|
176
|
+
Walk the store and delete files older than `options.ttlMs`:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
await cache.pruneExpired({
|
|
180
|
+
ttlMs: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
181
|
+
recursive: true,
|
|
182
|
+
pruneEmptyDirs: true,
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Options:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
type FileStorePruneOptions = {
|
|
190
|
+
ttlMs: number;
|
|
191
|
+
recursive?: boolean; // default false (top-level only)
|
|
192
|
+
maxDepth?: number; // bound recursion explicitly
|
|
193
|
+
pruneEmptyDirs?: boolean; // also remove dirs that became empty (only with recursive/maxDepth)
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Symlinks are skipped. The walk is best-effort — failures on individual entries don't abort the whole prune. Compares against `mtimeMs`.
|
|
198
|
+
|
|
199
|
+
## Difference from `Root`
|
|
200
|
+
|
|
201
|
+
| `FileStore` | `Root` |
|
|
202
|
+
|---|---|
|
|
203
|
+
| Object-style with mode+dirMode baked in. | Method-style boundary; mode is per-call or per-default. |
|
|
204
|
+
| `writeStream` with built-in byte budget. | Manual via `openWritable()`. |
|
|
205
|
+
| `writeText` / `writeJson` return the final absolute path. | `Root.write` / `writeJson` return void. |
|
|
206
|
+
| `copyIn` returns the final absolute path. | `Root.copyIn` returns void. |
|
|
207
|
+
| `pruneExpired` walks by `mtime`. | No prune helper. |
|
|
208
|
+
| Reads delegate via `Root` internally. | The boundary itself. |
|
|
209
|
+
|
|
210
|
+
If you need richer ops (move, list, append, mkdir), call `store.root()` to get a `Root` and use that.
|
|
211
|
+
|
|
212
|
+
`FileStore` owns portable key identity; `Root` owns filesystem confinement.
|
|
213
|
+
Existing-object Root lookups intentionally retain broader confined path
|
|
214
|
+
compatibility, including in-root absolute paths and parent-segment spellings,
|
|
215
|
+
and literal backslashes on POSIX. FileStore rejects those spellings even when
|
|
216
|
+
Root could resolve them safely inside the directory. This key policy does not
|
|
217
|
+
change Root's containment checks or the absolute-path `jsonStore({ filePath })`
|
|
218
|
+
contract.
|
|
219
|
+
|
|
220
|
+
## Common patterns
|
|
221
|
+
|
|
222
|
+
### Cache with TTL prune
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
const cache = fileStore({ rootDir: "/var/cache/app", maxBytes: 16 * 1024 * 1024 });
|
|
226
|
+
|
|
227
|
+
await cache.writeStream(`${id}.bin`, fetchStream(id));
|
|
228
|
+
|
|
229
|
+
// Background prune every hour
|
|
230
|
+
setInterval(() => cache.pruneExpired({ ttlMs: 24 * 60 * 60 * 1000 }), 60 * 60 * 1000);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Ingest pipeline
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
const ingest = fileStore({ rootDir: "/srv/ingest", mode: 0o644 });
|
|
237
|
+
|
|
238
|
+
for (const upload of uploads) {
|
|
239
|
+
const dest = await ingest.copyIn(`raw/${upload.id}`, upload.tempPath, {
|
|
240
|
+
maxBytes: 200 * 1024 * 1024,
|
|
241
|
+
});
|
|
242
|
+
await enqueueProcess(dest);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Drop down to `Root` for moves
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
const root = await store.root();
|
|
250
|
+
await root.move(`pending/${id}`, `done/${id}`);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## See also
|
|
254
|
+
|
|
255
|
+
- [`root()`](root.md) — the boundary `FileStore` is built on; reach for it when you need move/list/append.
|
|
256
|
+
- [JSON store](json-store.md) — the JSON-state-file equivalent of this surface.
|
|
257
|
+
- [Atomic writes](atomic.md) — `writeSiblingTempFile` is what every write goes through.
|
|
258
|
+
- [Temp workspaces](temp.md) — private scratch directories backed by `FileStore`.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Filenames
|
|
2
|
+
|
|
3
|
+
`sanitizeUntrustedFileName(name, fallback)` reduces a filename string from an untrusted source to one traversal-free path segment. Use it as a thin first pass before storing user-supplied names; pair with [`safeDirName`](install-path.md#safedirname) when you need stricter directory-name handling.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { sanitizeUntrustedFileName } from "@openclaw/fs-safe/advanced";
|
|
7
|
+
|
|
8
|
+
const safe = sanitizeUntrustedFileName(req.body.fileName, "upload");
|
|
9
|
+
await fs.write(`uploads/${safe}`, body);
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Signature
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
function sanitizeUntrustedFileName(fileName: string, fallbackName: string): string;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## What it does
|
|
19
|
+
|
|
20
|
+
In order:
|
|
21
|
+
|
|
22
|
+
1. **Trim** whitespace. If the result is empty, return `fallbackName`.
|
|
23
|
+
2. **Strip path components.** Apply `path.posix.basename` then `path.win32.basename` so neither `foo/bar.txt` nor `foo\bar.txt` survives — only the final segment remains.
|
|
24
|
+
3. **Strip non-portable characters.** C0/C1 controls (`0x00`–`0x1f`, `0x7f`–`0x9f`) and the Windows-invalid set `< > : " / \\ | ? *` are removed on every platform.
|
|
25
|
+
4. **Trim again.**
|
|
26
|
+
5. If the result is empty, `"."`, or `".."`, return `fallbackName`.
|
|
27
|
+
6. **Suffix Windows reserved basenames.** Compare the part before the first `.` case-insensitively with the Windows device-name set, including `CON`, `PRN`, `AUX`, `NUL`, `CLOCK$`, `CONIN$`, `CONOUT$`, `COM1..9`, `LPT1..9`, and their superscript `¹`, `²`, and `³` variants. Windows-ignored spaces and dots at the end of that basename do not disguise a device name. A match gains `_` before its extension, preserving the original case and extension on every platform.
|
|
28
|
+
7. **Truncate.** If the cleaned segment is longer than 200 UTF-16 code units, take up to the first 200 without splitting a valid Unicode surrogate pair.
|
|
29
|
+
|
|
30
|
+
That's it. The function stays intentionally small: it removes traversal and
|
|
31
|
+
the most obvious cross-platform device and character hazards, but it is not a
|
|
32
|
+
complete portable-filename or uniqueness policy.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
sanitizeUntrustedFileName("notes.txt", "untitled"); // "notes.txt"
|
|
38
|
+
sanitizeUntrustedFileName("../../etc/passwd", "upload"); // "passwd"
|
|
39
|
+
sanitizeUntrustedFileName("foo\\bar.png", "upload"); // "bar.png"
|
|
40
|
+
sanitizeUntrustedFileName("a\u0000b\tc", "upload"); // "abc"
|
|
41
|
+
sanitizeUntrustedFileName(" ", "fallback"); // "fallback"
|
|
42
|
+
sanitizeUntrustedFileName(".", "fallback"); // "fallback"
|
|
43
|
+
sanitizeUntrustedFileName("..", "fallback"); // "fallback"
|
|
44
|
+
sanitizeUntrustedFileName("CON", "fallback"); // "CON_"
|
|
45
|
+
sanitizeUntrustedFileName("nul.txt", "fallback"); // "nul_.txt"
|
|
46
|
+
sanitizeUntrustedFileName("aux.c", "fallback"); // "aux_.c"
|
|
47
|
+
sanitizeUntrustedFileName("conin$", "fallback"); // "conin$_"
|
|
48
|
+
sanitizeUntrustedFileName("a".repeat(300), "x"); // 200-char "aaa..."
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## What it does **not** do
|
|
52
|
+
|
|
53
|
+
The function is deliberately narrow. It will not:
|
|
54
|
+
|
|
55
|
+
- Replace leading dots (so a name like `.config` stays hidden on POSIX systems).
|
|
56
|
+
- Trim trailing dots. Surrounding spaces are removed by the documented trim
|
|
57
|
+
steps, but Windows-normalized dot/space spellings can still alias; reject or
|
|
58
|
+
rewrite them when Windows portability or cross-platform migration matters.
|
|
59
|
+
- Add an extension or change case.
|
|
60
|
+
- Validate file *content*. To enforce an extension allow-list, check after sanitization.
|
|
61
|
+
- Deduplicate against existing files. Append a random suffix if you need uniqueness.
|
|
62
|
+
|
|
63
|
+
Windows reserved basenames are handled by the default portability pass; callers no longer need to layer a separate reserved-name recipe on top.
|
|
64
|
+
|
|
65
|
+
## Common patterns
|
|
66
|
+
|
|
67
|
+
### Make a unique filename
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { sanitizeUntrustedFileName } from "@openclaw/fs-safe/advanced";
|
|
71
|
+
import { randomUUID } from "node:crypto";
|
|
72
|
+
|
|
73
|
+
const base = sanitizeUntrustedFileName(req.body.fileName, "upload");
|
|
74
|
+
const unique = `${randomUUID()}-${base}`;
|
|
75
|
+
await fs.write(`uploads/${unique}`, body);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Restrict to a known set of extensions
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
const safe = sanitizeUntrustedFileName(req.body.fileName, "upload");
|
|
82
|
+
const ext = path.extname(safe).toLowerCase();
|
|
83
|
+
if (![".png", ".jpg", ".webp"].includes(ext)) return reply(400, "unsupported extension");
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Sanitize, then write through a `Root`
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const safe = sanitizeUntrustedFileName(req.body.fileName, "upload");
|
|
90
|
+
await fs.write(`uploads/${safe}`, body); // fs is a Root() handle; rejects traversal too
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## See also
|
|
94
|
+
|
|
95
|
+
- [Install path helpers](install-path.md) — `safeDirName`, `safePathSegmentHashed` for directory-segment sanitization.
|
|
96
|
+
- [`root()`](root.md) — the boundary you'll write into after sanitizing.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Overview
|
|
3
|
+
permalink: /
|
|
4
|
+
description: "Capability-style filesystem roots for Node.js apps that handle untrusted relative paths."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# fs-safe
|
|
8
|
+
|
|
9
|
+
Trusted Node.js code that has to touch caller-controlled paths inside a directory it owns gets one boundary it can rely on. `root()` returns a capability-style handle that resolves every relative path against a real directory, refuses anything that escapes it, pins the file you opened, and verifies the write landed where you intended.
|
|
10
|
+
|
|
11
|
+
Think Go's `os.Root` / `OpenInRoot` or Rust's [`cap-std`](https://github.com/bytecodealliance/cap-std), but for Node. `root()` is the product; everything else in this doc set — JSON stores, atomic writes, secret files, archive extraction, temp workspaces — is supporting cast for the same boundary.
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
`path.resolve(root, input).startsWith(root)` validates a string. It does not pin the file you opened, defend against a symlink retarget between check and use, reject hardlinked aliases, or verify that a write landed where you intended after a rename. `fs-safe` does those things, packaged so every call site picks up the same defense without re-implementing it.
|
|
16
|
+
|
|
17
|
+
This is a **library-level guardrail**, not OS-level isolation. It does not replace containers, seccomp, AppArmor, or filesystem permissions. It is for code that already runs with the privileges of its workspace and wants to stop trivial path tricks from escaping it. Typical fits: agent runtimes, plugin systems, upload extraction, local workspaces, CLIs — anywhere trusted code touches untrusted relative path names.
|
|
18
|
+
|
|
19
|
+
## Hello world
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { root } from "@openclaw/fs-safe";
|
|
23
|
+
|
|
24
|
+
const fs = await root("/safe/workspace", {
|
|
25
|
+
hardlinks: "reject",
|
|
26
|
+
symlinks: "reject",
|
|
27
|
+
mkdir: true,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await fs.write("notes/today.txt", "hello\n");
|
|
31
|
+
const text = await fs.readText("notes/today.txt");
|
|
32
|
+
const parsed = await fs.readJson<{ users: string[] }>("config.json");
|
|
33
|
+
await fs.copyIn("uploads/upload.png", "/tmp/upload.png");
|
|
34
|
+
await fs.move("notes/today.txt", "notes/archive/today.txt", { overwrite: true });
|
|
35
|
+
await fs.remove("notes/archive/today.txt");
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Pick your path
|
|
39
|
+
|
|
40
|
+
- **First time?** [Install](install.md), then walk through the [Quickstart](quickstart.md). Five minutes from `pnpm add` to a working root.
|
|
41
|
+
- **Upgrading from 0.4?** Follow [Migrating to 0.5](migrating-to-0.5.md) in order, including the archive clamp-default audit.
|
|
42
|
+
- **Upgrading from 0.5?** Follow [Migrating to 0.6](migrating-to-0.6.md) to adopt platform-native optional packages.
|
|
43
|
+
- **Designing a workspace feature.** Read the [Security model](security-model.md) before you trust the boundary, the [native helper policy](native-helper.md) before you pick deployment defaults, and the [Errors](errors.md) reference so you know what to catch.
|
|
44
|
+
- **Replacing ad-hoc atomic writes.** Jump to [Atomic writes](atomic.md) or, for keyed JSON state, [JSON files](json.md).
|
|
45
|
+
- **Extracting an upload.** Start at [Archive extraction](archive.md) — handles ZIP and TAR with traversal, link, count, and byte limits.
|
|
46
|
+
- **Running an agent in a sandbox.** [Private temp workspaces](temp.md) plus [secret files](secret-file.md) cover the common scratch-and-credentials shape.
|
|
47
|
+
- **Looking up a name.** Use the [reference](errors.md) section in the sidebar — every public function has a page.
|
|
48
|
+
|
|
49
|
+
## What you get
|
|
50
|
+
|
|
51
|
+
| Surface | Use it for |
|
|
52
|
+
|---|---|
|
|
53
|
+
| [`root()`](root.md) | One boundary for read/write/move/remove and bounded recursive walking inside a trusted directory. |
|
|
54
|
+
| [`@openclaw/fs-safe/config`](config.md) | Process-global native helper and lock-option defaults. |
|
|
55
|
+
| [Native helper policy](native-helper.md) | Choose `auto`, `off`, or `require` for platform-native primitives. |
|
|
56
|
+
| [Native architecture](native.md) | Understand the thin syscall layer, beneath model, platform mechanisms, and fallback boundary. |
|
|
57
|
+
| [`replaceFileAtomic`](atomic.md) | Sibling-temp + rename, fsync hooks, mode preservation, copy fallback. |
|
|
58
|
+
| [`@openclaw/fs-safe/durability`](durability.md) | Pinned directory identities, durable creation, exclusive publication, streaming SHA-256, provenance receipts, and sync-failure policy. |
|
|
59
|
+
| [`writeExternalFileWithinRoot`](output.md) | Stage external-library file output in private temp storage, then finalize under a root. |
|
|
60
|
+
| [`writeJson` / `readJson*`](json.md) | JSON state files with strict and lenient read variants. |
|
|
61
|
+
| [`@openclaw/fs-safe/store`](store.md) | Overview of `fileStore`, `fileStoreSync`, and `jsonStore`. |
|
|
62
|
+
| [`jsonStore`](json-store.md) | Single JSON state file with explicit fallback, atomic writes, and optional locking. |
|
|
63
|
+
| [`fileStore`](file-store.md) | Managed multi-file/blob store with modes, stream writes, copy-in, pruning, and private mode. |
|
|
64
|
+
| [Private file-store mode](private-file-store.md) | `fileStore({ private: true })` for private JSON/text state at 0600 under 0700 dirs. |
|
|
65
|
+
| [`tempWorkspace`](temp.md) | 0700 scratch dir with auto-cleanup. |
|
|
66
|
+
| [`readSecureFile`](secure-file.md) | Absolute file reads with fd pinning, permissions, owner, size, and timeout checks. |
|
|
67
|
+
| [`walkDirectory` / `Root.walk`](walk.md) | Standalone inventories plus root-bounded pruning, budgets, and partial-error reporting. |
|
|
68
|
+
| [`extractArchive`](archive.md) | Policy-driven ZIP/TAR extraction with clamp/filter, metadata/path-depth, link, count, and byte limits. |
|
|
69
|
+
| [Secret files](secret-file.md) | Mode-0600 credentials with size and TOCTOU defense. |
|
|
70
|
+
| [Permissions](permissions.md) | POSIX mode helpers plus Windows ACL inspection, raw owner/ACE facts, remediation, and private-directory creation. |
|
|
71
|
+
| [`acquireFileLock`](sidecar-lock.md) | Cross-process file lock with retry and fail-closed stale-lock handling. |
|
|
72
|
+
| [`FsSafeError`](errors.md) | Closed code union (with `policy` / `operational` category) you can branch on. |
|
|
73
|
+
| [Public API inventory](public-api.md) | Complete runtime/type export cross-check against the generated declarations. |
|
|
74
|
+
| [`pathScope()`](path-scope.md) | Lower-level absolute-path boundary helper; lives behind `@openclaw/fs-safe/advanced`. |
|
|
75
|
+
| [`@openclaw/fs-safe/advanced`](advanced.md) | Directory of lower-level composition helpers (path scopes, regular-file I/O, install paths, sibling-temp writes, …). |
|
|
76
|
+
| [`@openclaw/fs-safe/test-hooks`](test-hooks.md) | Test-only injection hooks for reproducing open/lstat races. |
|
|
77
|
+
| [Migrating to 0.5](migrating-to-0.5.md) | End-to-end checklist for Python removal and 0.4 API behavior changes. |
|
|
78
|
+
| [Migrating to 0.6](migrating-to-0.6.md) | Installer-policy checklist for the platform-native package split. |
|
|
79
|
+
|
|
80
|
+
## Status
|
|
81
|
+
|
|
82
|
+
Currently `0.x` — APIs are stable in shape but may be tightened before `1.0`. The [CHANGELOG](https://github.com/openclaw/fs-safe/blob/main/CHANGELOG.md) tracks visible changes. Issues and PRs at the [GitHub repo](https://github.com/openclaw/fs-safe).
|
|
83
|
+
|
|
84
|
+
Released under the [MIT license](https://github.com/openclaw/fs-safe/blob/main/LICENSE).
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Install paths
|
|
2
|
+
|
|
3
|
+
Helpers for code that creates per-name install directories under a trusted base — typical for plugins, packages, snapshots, anywhere you want `<base>/<safe-name>/`. The combination of [`resolveSafeInstallDir`](#resolvesafeinstalldir) and [`assertCanonicalPathWithinBase`](#assertcanonicalpathwithinbase) gives you "compute the install path safely, then re-verify after creation."
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import {
|
|
7
|
+
assertCanonicalPathWithinBase,
|
|
8
|
+
resolveSafeInstallDir,
|
|
9
|
+
safeDirName,
|
|
10
|
+
safePathSegmentHashed,
|
|
11
|
+
} from "@openclaw/fs-safe/advanced";
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## `resolveSafeInstallDir`
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
function resolveSafeInstallDir(params: {
|
|
18
|
+
baseDir: string;
|
|
19
|
+
id: string;
|
|
20
|
+
invalidNameMessage: string;
|
|
21
|
+
nameEncoder?: (id: string) => string; // default safeDirName
|
|
22
|
+
}): { ok: true; path: string } | { ok: false; error: string };
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Computes the absolute install directory for `id` under `baseDir`, after running `id` through `nameEncoder` (`safeDirName` by default). Verifies the result stays inside `baseDir` — anything that would escape returns `{ ok: false, error: invalidNameMessage }`.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
const r = resolveSafeInstallDir({
|
|
29
|
+
baseDir: "/srv/plugins",
|
|
30
|
+
id: "@scope/my-plugin",
|
|
31
|
+
invalidNameMessage: "invalid plugin name",
|
|
32
|
+
});
|
|
33
|
+
if (!r.ok) return reply(400, r.error);
|
|
34
|
+
|
|
35
|
+
await fs.mkdir(r.path, { recursive: true });
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For ids whose default-sanitized form might collide (e.g. `"foo/bar"` and `"foo\\bar"` both map to `"foo__bar"`), pass `nameEncoder: safePathSegmentHashed` to append a content hash:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
const r = resolveSafeInstallDir({
|
|
42
|
+
baseDir: "/srv/plugins",
|
|
43
|
+
id: untrustedId,
|
|
44
|
+
invalidNameMessage: "invalid plugin name",
|
|
45
|
+
nameEncoder: safePathSegmentHashed,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The helper does **not** create the directory — it returns the path. Pair with `fs.mkdir`, [`Root.mkdir`](root.md), or `assertCanonicalPathWithinBase` before/after creation as needed.
|
|
50
|
+
|
|
51
|
+
## `assertCanonicalPathWithinBase`
|
|
52
|
+
|
|
53
|
+
Async. Verifies that a candidate absolute path's canonical real path stays inside the base. Useful as a post-`mkdir` check, or when you have an existing path you didn't compute yourself.
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
function assertCanonicalPathWithinBase(params: {
|
|
57
|
+
baseDir: string;
|
|
58
|
+
candidatePath: string;
|
|
59
|
+
boundaryLabel: string;
|
|
60
|
+
}): Promise<void>;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Throws if the candidate resolves outside `baseDir` after `realpath`. The `boundaryLabel` is included in the error message ("Invalid path: must stay within {boundaryLabel}").
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
await assertCanonicalPathWithinBase({
|
|
67
|
+
baseDir: "/srv/plugins",
|
|
68
|
+
candidatePath: "/srv/plugins/my-plugin",
|
|
69
|
+
boundaryLabel: "plugin install dir",
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If the candidate does not exist, the helper validates the parent directory instead — useful for "the directory I'm about to create" semantics.
|
|
74
|
+
|
|
75
|
+
## Segment sanitizers
|
|
76
|
+
|
|
77
|
+
### `safeDirName`
|
|
78
|
+
|
|
79
|
+
Returns a directory-safe segment derived from `input` by replacing `/` and `\` with `__`. Trims whitespace; returns an empty string if the input was only whitespace.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
safeDirName("@scope/my-plugin"); // "@scope__my-plugin"
|
|
83
|
+
safeDirName("../../etc"); // "..__..__etc"
|
|
84
|
+
safeDirName("plugin-v1"); // "plugin-v1"
|
|
85
|
+
safeDirName(""); // ""
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`safeDirName` does *not* try to be exhaustive about Windows-reserved names or special characters. It is purely a separator-stripping pass — `resolveSafeInstallDir` adds the boundary check on top so an `"../../etc"` input cannot escape `baseDir`.
|
|
89
|
+
|
|
90
|
+
For stricter sanitization, use `safePathSegmentHashed`.
|
|
91
|
+
|
|
92
|
+
### `safePathSegmentHashed`
|
|
93
|
+
|
|
94
|
+
Returns a directory-safe segment **plus** a short content hash when sanitization changed the input or when the safe form is too long. Use this when input collisions matter:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
safePathSegmentHashed("plugin-v1"); // "plugin-v1" (unchanged short input)
|
|
98
|
+
safePathSegmentHashed("plugin/v1"); // "plugin-v1-d9ef8af2eb"
|
|
99
|
+
safePathSegmentHashed("plugin\\v1"); // "plugin-v1-bed33f465b"
|
|
100
|
+
safePathSegmentHashed("Über@"); // "ber-e392bba2b3"
|
|
101
|
+
safePathSegmentHashed(""); // "skill-e3b0c44298"
|
|
102
|
+
safePathSegmentHashed("."); // "skill-cdb4ee2aea"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The sanitization is more aggressive than `safeDirName`: any character not in `[A-Za-z0-9._-]` becomes `-`, runs of `-` collapse, leading and trailing `-` are stripped, the empty/`.`/`..` fallback is `"skill"`. Long results are truncated to 50 chars before the hash is appended.
|
|
106
|
+
|
|
107
|
+
The suffix is the first 10 hex characters of `sha256(trimmedInput)`. It makes
|
|
108
|
+
collisions between distinct trimmed inputs unlikely, but it is a 40-bit
|
|
109
|
+
identifier rather than a mathematical uniqueness guarantee. Inputs that differ
|
|
110
|
+
only by surrounding whitespace intentionally map to the same output.
|
|
111
|
+
|
|
112
|
+
## Common patterns
|
|
113
|
+
|
|
114
|
+
### Install a plugin
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { resolveSafeInstallDir, assertCanonicalPathWithinBase, safePathSegmentHashed } from "@openclaw/fs-safe/advanced";
|
|
118
|
+
import { extractArchive } from "@openclaw/fs-safe/archive";
|
|
119
|
+
import fs from "node:fs/promises";
|
|
120
|
+
|
|
121
|
+
const r = resolveSafeInstallDir({
|
|
122
|
+
baseDir: "/srv/plugins",
|
|
123
|
+
id: untrustedName,
|
|
124
|
+
invalidNameMessage: "invalid plugin name",
|
|
125
|
+
nameEncoder: safePathSegmentHashed,
|
|
126
|
+
});
|
|
127
|
+
if (!r.ok) return reply(400, r.error);
|
|
128
|
+
|
|
129
|
+
await fs.mkdir(r.path, { recursive: true, mode: 0o755 });
|
|
130
|
+
await assertCanonicalPathWithinBase({
|
|
131
|
+
baseDir: "/srv/plugins",
|
|
132
|
+
candidatePath: r.path,
|
|
133
|
+
boundaryLabel: "plugin install dir",
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await extractArchive({
|
|
137
|
+
archivePath: pluginZip,
|
|
138
|
+
destDir: r.path,
|
|
139
|
+
kind: "zip",
|
|
140
|
+
timeoutMs: 30_000,
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Per-version snapshot directories
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const snap = resolveSafeInstallDir({
|
|
148
|
+
baseDir: "/srv/snapshots",
|
|
149
|
+
id: `${runId}-${version}`,
|
|
150
|
+
invalidNameMessage: "invalid snapshot id",
|
|
151
|
+
});
|
|
152
|
+
if (!snap.ok) throw new Error(snap.error);
|
|
153
|
+
await fs.mkdir(snap.path, { recursive: true });
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Reject and log on bad input
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
const r = resolveSafeInstallDir({ baseDir, id, invalidNameMessage: "bad name" });
|
|
160
|
+
if (!r.ok) {
|
|
161
|
+
logger.warn({ id, base: baseDir, error: r.error }, "rejected install attempt");
|
|
162
|
+
return reply(400, r.error);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## See also
|
|
167
|
+
|
|
168
|
+
- [`root()`](root.md) — when the install dir becomes a root for further writes.
|
|
169
|
+
- [Filenames](filename.md) — `sanitizeUntrustedFileName` for file-name (not directory-name) sanitization.
|
|
170
|
+
- [Archive extraction](archive.md) — extract into the install dir computed by these helpers.
|