@openclaw/fs-safe 0.11.0 → 0.12.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 +58 -0
- package/README.md +4 -2
- package/dist/advanced.d.ts +1 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +1 -1
- package/dist/archive-entry.d.ts.map +1 -1
- package/dist/archive-entry.js +4 -3
- package/dist/archive-gzip-tail.d.ts.map +1 -1
- package/dist/archive-gzip-tail.js +13 -9
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +37 -33
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +17 -5
- package/dist/bounded-read.js +2 -2
- package/dist/device-path.d.ts.map +1 -1
- package/dist/device-path.js +5 -3
- package/dist/file-hash.d.ts.map +1 -1
- package/dist/file-hash.js +9 -2
- package/dist/file-store-prune.d.ts.map +1 -1
- package/dist/file-store-prune.js +9 -1
- package/dist/filename.d.ts +1 -0
- package/dist/filename.d.ts.map +1 -1
- package/dist/filename.js +30 -13
- package/dist/guarded-mkdir.d.ts +2 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +50 -15
- package/dist/guest.d.ts.map +1 -1
- package/dist/guest.js +12 -4
- package/dist/install-path.d.ts +6 -0
- package/dist/install-path.d.ts.map +1 -1
- package/dist/install-path.js +13 -0
- package/dist/json-durable-queue-ownership.d.ts +2 -0
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +47 -3
- package/dist/json-durable-queue-read.d.ts +6 -0
- package/dist/json-durable-queue-read.d.ts.map +1 -0
- package/dist/json-durable-queue-read.js +59 -0
- package/dist/json-durable-queue.d.ts +1 -1
- package/dist/json-durable-queue.d.ts.map +1 -1
- package/dist/json-durable-queue.js +37 -80
- package/dist/native-binding.d.ts +7 -0
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/path-scope-lexical.d.ts +14 -0
- package/dist/path-scope-lexical.d.ts.map +1 -0
- package/dist/path-scope-lexical.js +27 -0
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +20 -2
- package/dist/pinned-write.js +1 -0
- package/dist/root-boundary.d.ts +25 -0
- package/dist/root-boundary.d.ts.map +1 -0
- package/dist/root-boundary.js +177 -0
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +32 -5
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +10 -2
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +53 -34
- package/dist/root-move-preflight.d.ts +8 -0
- package/dist/root-move-preflight.d.ts.map +1 -0
- package/dist/root-move-preflight.js +16 -0
- package/dist/root-path-existing.d.ts +2 -0
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +10 -2
- package/dist/root-path.d.ts +2 -0
- package/dist/root-path.d.ts.map +1 -1
- package/dist/root-path.js +54 -26
- package/dist/root-paths.d.ts +2 -6
- package/dist/root-paths.d.ts.map +1 -1
- package/dist/root-paths.js +14 -26
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +2 -1
- package/dist/root-write-mode.d.ts +2 -0
- package/dist/root-write-mode.d.ts.map +1 -1
- package/dist/root-write-mode.js +20 -7
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +12 -3
- package/dist/safe-path-segment.d.ts.map +1 -1
- package/dist/safe-path-segment.js +3 -1
- package/dist/secure-file-windows.d.ts +10 -0
- package/dist/secure-file-windows.d.ts.map +1 -0
- package/dist/secure-file-windows.js +186 -0
- package/dist/secure-file.d.ts.map +1 -1
- package/dist/secure-file.js +6 -3
- package/dist/sibling-staged-file.d.ts +1 -0
- package/dist/sibling-staged-file.d.ts.map +1 -1
- package/dist/sibling-staged-file.js +7 -0
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +2 -1
- package/dist/sidecar-lock-acquire.js +1 -1
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +2 -3
- package/dist/temp-target.d.ts.map +1 -1
- package/dist/temp-target.js +3 -1
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +11 -10
- package/docs/advanced.md +3 -1
- package/docs/archive.md +6 -0
- package/docs/contributing.md +4 -1
- package/docs/copy.md +1 -1
- package/docs/durability.md +4 -2
- package/docs/file-store.md +6 -0
- package/docs/filename.md +9 -2
- package/docs/guest.md +5 -0
- package/docs/install-path.md +59 -13
- package/docs/install.md +4 -1
- package/docs/native-helper.md +4 -2
- package/docs/native.md +14 -2
- package/docs/path.md +1 -1
- package/docs/permissions.md +26 -1
- package/docs/public-api.md +5 -0
- package/docs/root.md +3 -1
- package/docs/secure-file.md +15 -14
- package/docs/security-model.md +1 -1
- package/docs/store.md +22 -1
- package/docs/temp.md +4 -0
- package/package.json +8 -8
package/dist/guarded-mkdir.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import fsSync from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard } from "./directory-guard.js";
|
|
4
|
+
import { assertAsyncDirectoryGuard, createAsyncDirectoryGuard, } from "./directory-guard.js";
|
|
5
5
|
import { FsSafeError } from "./errors.js";
|
|
6
6
|
import { isNotFoundPathError, isPathRelativeEscape } from "./path.js";
|
|
7
|
-
import { directoryComponentNotDirectoryError } from "./root-errors.js";
|
|
7
|
+
import { directoryComponentNotDirectoryError, rootPathChangedError } from "./root-errors.js";
|
|
8
8
|
import { realpathSync } from "./realpath.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return
|
|
9
|
+
import { admitPathInsideRoot } from "./root-boundary.js";
|
|
10
|
+
function suppliedExactRootIdentity(identity) {
|
|
11
|
+
return typeof identity?.dev === "bigint" && typeof identity.ino === "bigint"
|
|
12
|
+
? { dev: identity.dev, ino: identity.ino }
|
|
13
|
+
: undefined;
|
|
14
|
+
}
|
|
15
|
+
function assertGuardMatchesRootIdentity(guard, expected) {
|
|
16
|
+
if (guard.stat.dev !== expected.dev || guard.stat.ino !== expected.ino) {
|
|
17
|
+
throw rootPathChangedError();
|
|
18
|
+
}
|
|
12
19
|
}
|
|
13
20
|
async function realpathOrThrowNotFile(target) {
|
|
14
21
|
try {
|
|
@@ -31,16 +38,38 @@ async function realpathOrThrowNotFile(target) {
|
|
|
31
38
|
*/
|
|
32
39
|
export async function mkdirPathComponentsWithGuards(params) {
|
|
33
40
|
const root = path.resolve(params.rootReal);
|
|
34
|
-
const
|
|
41
|
+
const configuredRootGuard = await createAsyncDirectoryGuard(root, { bigint: true });
|
|
42
|
+
const suppliedIdentity = suppliedExactRootIdentity(params.rootIdentity);
|
|
43
|
+
const checkedRootIdentity = suppliedIdentity ?? {
|
|
44
|
+
dev: configuredRootGuard.stat.dev,
|
|
45
|
+
ino: configuredRootGuard.stat.ino,
|
|
46
|
+
};
|
|
47
|
+
assertGuardMatchesRootIdentity(configuredRootGuard, checkedRootIdentity);
|
|
48
|
+
const rootCanonical = path.resolve(configuredRootGuard.realPath);
|
|
49
|
+
const rootGuard = rootCanonical === root
|
|
50
|
+
? configuredRootGuard
|
|
51
|
+
: await createAsyncDirectoryGuard(rootCanonical, { bigint: true });
|
|
52
|
+
assertGuardMatchesRootIdentity(rootGuard, checkedRootIdentity);
|
|
35
53
|
const target = path.resolve(params.targetPath);
|
|
36
|
-
const
|
|
37
|
-
|
|
54
|
+
const admissionParams = {
|
|
55
|
+
candidatePath: target,
|
|
56
|
+
rootIdentity: checkedRootIdentity,
|
|
57
|
+
};
|
|
58
|
+
// Derive the suffix from the caller's trusted root spelling first. The
|
|
59
|
+
// canonical spelling is also accepted after both names have been bound to
|
|
60
|
+
// the same exact root object above.
|
|
61
|
+
const admittedTarget = admitPathInsideRoot({ rootPath: root, ...admissionParams }) ??
|
|
62
|
+
(rootCanonical === root
|
|
63
|
+
? undefined
|
|
64
|
+
: admitPathInsideRoot({ rootPath: rootCanonical, ...admissionParams }));
|
|
65
|
+
if (!admittedTarget || isPathRelativeEscape(admittedTarget.relativePath)) {
|
|
38
66
|
throw new FsSafeError("outside-workspace", "directory is outside workspace root");
|
|
39
67
|
}
|
|
40
|
-
let current =
|
|
41
|
-
|
|
68
|
+
let current = rootCanonical;
|
|
69
|
+
let currentGuard = rootGuard;
|
|
70
|
+
for (const part of admittedTarget.relativePath.split(path.sep).filter(Boolean)) {
|
|
42
71
|
const next = path.join(current, part);
|
|
43
|
-
const parentGuard =
|
|
72
|
+
const parentGuard = currentGuard;
|
|
44
73
|
await assertAsyncDirectoryGuard(parentGuard);
|
|
45
74
|
await params.beforeComponent?.(next);
|
|
46
75
|
params.assertBeforeMutation?.();
|
|
@@ -58,10 +87,16 @@ export async function mkdirPathComponentsWithGuards(params) {
|
|
|
58
87
|
}
|
|
59
88
|
// Node's recursive mkdir follows symlinks in missing components. Build one
|
|
60
89
|
// segment at a time and realpath-check each segment before descending.
|
|
61
|
-
const
|
|
62
|
-
|
|
90
|
+
const observedNextReal = await realpathOrThrowNotFile(next);
|
|
91
|
+
const admittedNextReal = admitPathInsideRoot({
|
|
92
|
+
rootPath: rootCanonical,
|
|
93
|
+
candidatePath: observedNextReal,
|
|
94
|
+
rootIdentity: checkedRootIdentity,
|
|
95
|
+
});
|
|
96
|
+
if (!admittedNextReal) {
|
|
63
97
|
throw new FsSafeError("outside-workspace", "directory escaped workspace root");
|
|
64
98
|
}
|
|
99
|
+
const nextReal = admittedNextReal.path;
|
|
65
100
|
if (stat.isSymbolicLink()) {
|
|
66
101
|
// An existing path component may legitimately be a symlink to a real
|
|
67
102
|
// directory inside the root (e.g. a skill-bank layout). We already
|
|
@@ -76,12 +111,12 @@ export async function mkdirPathComponentsWithGuards(params) {
|
|
|
76
111
|
if (!targetStat.isDirectory()) {
|
|
77
112
|
throw directoryComponentNotDirectoryError();
|
|
78
113
|
}
|
|
79
|
-
await createAsyncDirectoryGuard(nextReal);
|
|
114
|
+
currentGuard = await createAsyncDirectoryGuard(nextReal);
|
|
80
115
|
await assertAsyncDirectoryGuard(parentGuard);
|
|
81
116
|
current = nextReal;
|
|
82
117
|
continue;
|
|
83
118
|
}
|
|
84
|
-
await createAsyncDirectoryGuard(next);
|
|
119
|
+
currentGuard = await createAsyncDirectoryGuard(next);
|
|
85
120
|
await assertAsyncDirectoryGuard(parentGuard);
|
|
86
121
|
current = next;
|
|
87
122
|
}
|
package/dist/guest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guest.d.ts","sourceRoot":"","sources":["../src/guest.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,yCAAyC,EAC1C,MAAM,0BAA0B,CAAC;AAElC,yFAAyF;AACzF,eAAO,MAAM,wCAAwC,KAAK,CAAC;AAC3D,8EAA8E;AAC9E,eAAO,MAAM,yCAAyC,IAAI,CAAC;AAE3D,gGAAgG;AAChG,eAAO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"guest.d.ts","sourceRoot":"","sources":["../src/guest.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,yCAAyC,EAC1C,MAAM,0BAA0B,CAAC;AAElC,yFAAyF;AACzF,eAAO,MAAM,wCAAwC,KAAK,CAAC;AAC3D,8EAA8E;AAC9E,eAAO,MAAM,yCAAyC,IAAI,CAAC;AAE3D,gGAAgG;AAChG,eAAO,MAAM,uBAAuB,QA2ZxB,CAAC;AAEb,OAAO,EAAE,yCAAyC,EAAE,CAAC"}
|
package/dist/guest.js
CHANGED
|
@@ -356,11 +356,19 @@ export const GUEST_FILESYSTEM_PYTHON = [
|
|
|
356
356
|
" return",
|
|
357
357
|
" if stat.S_ISLNK(src_stat.st_mode):",
|
|
358
358
|
" link_target = os.readlink(src_basename, dir_fd=src_parent_fd)",
|
|
359
|
+
" temp_dir_name, temp_dir_fd = create_staging_dir(dst_parent_fd)",
|
|
359
360
|
" try:",
|
|
360
|
-
" os.
|
|
361
|
-
"
|
|
362
|
-
"
|
|
363
|
-
"
|
|
361
|
+
" os.symlink(link_target, 'link', dir_fd=temp_dir_fd)",
|
|
362
|
+
" os.replace('link', dst_basename, src_dir_fd=temp_dir_fd, dst_dir_fd=dst_parent_fd)",
|
|
363
|
+
" finally:",
|
|
364
|
+
" try:",
|
|
365
|
+
" try:",
|
|
366
|
+
" os.unlink('link', dir_fd=temp_dir_fd)",
|
|
367
|
+
" except FileNotFoundError:",
|
|
368
|
+
" pass",
|
|
369
|
+
" finally:",
|
|
370
|
+
" os.close(temp_dir_fd)",
|
|
371
|
+
" os.rmdir(temp_dir_name, dir_fd=dst_parent_fd)",
|
|
364
372
|
" os.unlink(src_basename, dir_fd=src_parent_fd)",
|
|
365
373
|
" os.fsync(dst_parent_fd)",
|
|
366
374
|
" os.fsync(src_parent_fd)",
|
package/dist/install-path.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export declare function safeDirName(input: string): string;
|
|
2
|
+
/** Legacy readable encoding; distinct IDs can share a result. Use V2 for untrusted IDs. */
|
|
2
3
|
export declare function safePathSegmentHashed(input: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Versioned install-ID encoding: every trimmed ID receives a domain-separated
|
|
6
|
+
* SHA-256 digest. Only surrounding whitespace is intentionally equivalent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function safePathSegmentHashedV2(input: string): string;
|
|
3
9
|
export declare function resolveSafeInstallDir(params: {
|
|
4
10
|
baseDir: string;
|
|
5
11
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-path.d.ts","sourceRoot":"","sources":["../src/install-path.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB3D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAe5D;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDhB"}
|
|
1
|
+
{"version":3,"file":"install-path.d.ts","sourceRoot":"","sources":["../src/install-path.ts"],"names":[],"mappings":"AAMA,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB3D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO7D;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;CACtC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAe5D;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDhB"}
|
package/dist/install-path.js
CHANGED
|
@@ -10,6 +10,7 @@ export function safeDirName(input) {
|
|
|
10
10
|
}
|
|
11
11
|
return trimmed.replaceAll("/", "__").replaceAll("\\", "__");
|
|
12
12
|
}
|
|
13
|
+
/** Legacy readable encoding; distinct IDs can share a result. Use V2 for untrusted IDs. */
|
|
13
14
|
export function safePathSegmentHashed(input) {
|
|
14
15
|
const trimmed = input.trim();
|
|
15
16
|
const base = trimmed
|
|
@@ -26,6 +27,18 @@ export function safePathSegmentHashed(input) {
|
|
|
26
27
|
}
|
|
27
28
|
return safe;
|
|
28
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Versioned install-ID encoding: every trimmed ID receives a domain-separated
|
|
32
|
+
* SHA-256 digest. Only surrounding whitespace is intentionally equivalent.
|
|
33
|
+
*/
|
|
34
|
+
export function safePathSegmentHashedV2(input) {
|
|
35
|
+
const hash = createHash("sha256")
|
|
36
|
+
.update("@openclaw/fs-safe:install-path:v2\0", "utf8")
|
|
37
|
+
// UTF-16LE preserves every JavaScript code unit, including lone surrogates.
|
|
38
|
+
.update(input.trim(), "utf16le")
|
|
39
|
+
.digest("hex");
|
|
40
|
+
return `id-v2-${hash}`;
|
|
41
|
+
}
|
|
29
42
|
export function resolveSafeInstallDir(params) {
|
|
30
43
|
const encodedName = (params.nameEncoder ?? safeDirName)(params.id);
|
|
31
44
|
const targetDir = path.join(params.baseDir, encodedName);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type BigIntStats } from "node:fs";
|
|
1
2
|
export type DurableQueueEntryPathsLike = {
|
|
2
3
|
jsonPath: string;
|
|
3
4
|
deliveredPath: string;
|
|
@@ -7,6 +8,7 @@ export declare function durableQueueProcessingPath(paths: DurableQueueEntryPaths
|
|
|
7
8
|
export declare function claimDurableQueueEntry(paths: DurableQueueEntryPathsLike, options?: {
|
|
8
9
|
skipUnowned?: boolean;
|
|
9
10
|
}): Promise<string | null>;
|
|
11
|
+
export declare function migrateDurableQueueEntry<T>(paths: DurableQueueEntryPathsLike, expected: BigIntStats, releaseReadPin: () => Promise<void>, run: (filePath: string, beforePublish: () => Promise<void>) => Promise<T>): Promise<T>;
|
|
10
12
|
export declare function completeDeliveredQueueEntry(paths: DurableQueueEntryPathsLike): Promise<boolean>;
|
|
11
13
|
export declare function acknowledgeDurableQueueEntry(paths: DurableQueueEntryPathsLike): Promise<void>;
|
|
12
14
|
export declare function moveDurableQueueEntryToFailed(params: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-durable-queue-ownership.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-ownership.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-durable-queue-ownership.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-ownership.ts"],"names":[],"mappings":"AAEA,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AASnD,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CAKpF;AAwED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,0BAA0B,EACjC,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAGD,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,KAAK,EAAE,0BAA0B,EACjC,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACnC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACxE,OAAO,CAAC,CAAC,CAAC,CAkCZ;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,OAAO,CAAC,CAalB;AAED,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDhB;AAKD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI1D"}
|
|
@@ -6,6 +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 { inspectFileIdentity } from "./strict-file-identity.js";
|
|
9
10
|
import { serializePathWrite } from "./write-queue.js";
|
|
10
11
|
export function durableQueueProcessingPath(paths) {
|
|
11
12
|
if (paths.processingPath)
|
|
@@ -32,10 +33,17 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
|
32
33
|
const existingProcessing = await regularQueueFileIdentity(processingPath);
|
|
33
34
|
if (existingProcessing) {
|
|
34
35
|
const pending = await lstatOrNull(paths.jsonPath);
|
|
35
|
-
|
|
36
|
+
const retiresPending = pending !== null &&
|
|
36
37
|
!pending.isSymbolicLink() &&
|
|
37
38
|
pending.isFile() &&
|
|
38
|
-
sameFileIdentityForCleanup(pending, existingProcessing)
|
|
39
|
+
sameFileIdentityForCleanup(pending, existingProcessing);
|
|
40
|
+
if (!retiresPending ||
|
|
41
|
+
path.resolve(path.dirname(processingPath)) !== path.resolve(path.dirname(paths.jsonPath))) {
|
|
42
|
+
// An existing claim can contain a migration whose publication sync failed.
|
|
43
|
+
// Retirement already syncs this edge when both names share a parent.
|
|
44
|
+
await syncDirectory(path.dirname(processingPath));
|
|
45
|
+
}
|
|
46
|
+
if (retiresPending) {
|
|
39
47
|
await retireDurableQueueSource({ jsonPath: paths.jsonPath, processingPath });
|
|
40
48
|
}
|
|
41
49
|
return processingPath;
|
|
@@ -54,7 +62,10 @@ async function claimDurableQueueEntryUnlocked(paths, options = {}) {
|
|
|
54
62
|
}
|
|
55
63
|
catch (error) {
|
|
56
64
|
if (getErrorCode(error) === "EEXIST") {
|
|
57
|
-
|
|
65
|
+
if (!(await regularQueueFileIdentity(processingPath)))
|
|
66
|
+
return null;
|
|
67
|
+
await syncDirectory(path.dirname(processingPath));
|
|
68
|
+
return processingPath;
|
|
58
69
|
}
|
|
59
70
|
if (getErrorCode(error) === "ENOENT")
|
|
60
71
|
return null;
|
|
@@ -73,6 +84,39 @@ export async function claimDurableQueueEntry(paths, options = {}) {
|
|
|
73
84
|
return null;
|
|
74
85
|
return await withQueueEntryLock(paths, async () => await claimDurableQueueEntryUnlocked(paths, options));
|
|
75
86
|
}
|
|
87
|
+
// The caller retains its read pin until this owner releases it or migration settles.
|
|
88
|
+
export async function migrateDurableQueueEntry(paths, expected, releaseReadPin, run) {
|
|
89
|
+
return await withQueueEntryLock(paths, async () => {
|
|
90
|
+
const processingPath = durableQueueProcessingPath(paths);
|
|
91
|
+
const assertCurrent = async () => {
|
|
92
|
+
try {
|
|
93
|
+
await inspectFileIdentity(() => {
|
|
94
|
+
const current = fsSync.lstatSync(processingPath, { bigint: true });
|
|
95
|
+
if (current.isSymbolicLink() || !current.isFile() || current.nlink !== 1n) {
|
|
96
|
+
throw new FsSafeError("path-mismatch", "queue migration requires its original processing claim");
|
|
97
|
+
}
|
|
98
|
+
return current;
|
|
99
|
+
}, expected);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (getErrorCode(error) === "ENOENT") {
|
|
103
|
+
throw new FsSafeError("path-mismatch", "queue processing claim disappeared before migration", { cause: error });
|
|
104
|
+
}
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
await assertCurrent();
|
|
109
|
+
return await run(processingPath, async () => {
|
|
110
|
+
await assertCurrent();
|
|
111
|
+
if (process.platform === "win32") {
|
|
112
|
+
// Windows cannot replace our still-open target. Keep the transfer lock
|
|
113
|
+
// across release and reject changes made while the async close settles.
|
|
114
|
+
await releaseReadPin();
|
|
115
|
+
await assertCurrent();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
76
120
|
export async function completeDeliveredQueueEntry(paths) {
|
|
77
121
|
if (!(await lstatOrNull(path.dirname(paths.deliveredPath))))
|
|
78
122
|
return false;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type BigIntStats } from "node:fs";
|
|
2
|
+
export declare const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES: number;
|
|
3
|
+
export declare function withJsonDurableQueueEntry<T, R>(filePath: string, options: {
|
|
4
|
+
maxBytes?: number;
|
|
5
|
+
}, run: (entry: T, identity: BigIntStats, releaseReadPin: () => Promise<void>) => Promise<R>): Promise<R>;
|
|
6
|
+
//# sourceMappingURL=json-durable-queue-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-durable-queue-read.d.ts","sourceRoot":"","sources":["../src/json-durable-queue-read.ts"],"names":[],"mappings":"AAAA,OAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAM/C,eAAO,MAAM,0CAA0C,QAAmB,CAAC;AA8B3E,wBAAsB,yBAAyB,CAAC,CAAC,EAAE,CAAC,EAClD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EAC9B,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GACxF,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fs, {} from "node:fs";
|
|
2
|
+
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
3
|
+
import { readBoundedAsync } from "./bounded-read.js";
|
|
4
|
+
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
5
|
+
import { inspectFileIdentity } from "./strict-file-identity.js";
|
|
6
|
+
export const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES = 16 * 1024 * 1024;
|
|
7
|
+
async function inspectQueueEntry(inspect, maxBytes, expected) {
|
|
8
|
+
let inspectionFailed = false;
|
|
9
|
+
try {
|
|
10
|
+
return await inspectFileIdentity(async () => {
|
|
11
|
+
try {
|
|
12
|
+
const stat = inspect();
|
|
13
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
14
|
+
throw new Error("queue entry is not a regular file");
|
|
15
|
+
}
|
|
16
|
+
if (stat.nlink > 1n)
|
|
17
|
+
throw new Error("queue entry hardlinks are not allowed");
|
|
18
|
+
if (stat.size > maxBytes)
|
|
19
|
+
throw new Error(`queue entry exceeds ${maxBytes} bytes`);
|
|
20
|
+
return stat;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
inspectionFailed = true;
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}, expected);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// Translate only the identity helper's rejection, never inspection errors.
|
|
30
|
+
if (inspectionFailed)
|
|
31
|
+
throw error;
|
|
32
|
+
throw new Error("queue entry changed during read", { cause: error });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function withJsonDurableQueueEntry(filePath, options, run) {
|
|
36
|
+
const maxBytes = normalizeMaxBytes(options.maxBytes, {
|
|
37
|
+
defaultValue: DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES,
|
|
38
|
+
});
|
|
39
|
+
const inspectPath = () => fs.lstatSync(filePath, { bigint: true });
|
|
40
|
+
const initialStat = await inspectQueueEntry(inspectPath, maxBytes);
|
|
41
|
+
const handle = await fs.promises.open(filePath, resolveReadOpenFlags());
|
|
42
|
+
let closePromise;
|
|
43
|
+
const releaseReadPin = () => closePromise ??= (async () => { await handle.close(); })();
|
|
44
|
+
try {
|
|
45
|
+
const openedStat = await inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), maxBytes, initialStat);
|
|
46
|
+
await inspectQueueEntry(inspectPath, maxBytes, openedStat);
|
|
47
|
+
const bytes = await readBoundedAsync(maxBytes, async (buffer, length) => (await handle.read(buffer, 0, length, null)).bytesRead, {
|
|
48
|
+
initialSize: openedStat.size >= 0n && Number.isSafeInteger(Number(openedStat.size))
|
|
49
|
+
? Number(openedStat.size) : undefined,
|
|
50
|
+
createLimitError: () => new Error(`queue entry exceeds ${maxBytes} bytes`),
|
|
51
|
+
});
|
|
52
|
+
// The migration owner may release this pin only at the verified publication
|
|
53
|
+
// boundary; until then an unlinked inode cannot be recycled into a new claim.
|
|
54
|
+
return await run(JSON.parse(bytes.toString("utf8")), openedStat, releaseReadPin);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
await releaseReadPin();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES } from "./json-durable-queue-read.js";
|
|
1
2
|
export type JsonDurableQueueEntryPaths = {
|
|
2
3
|
jsonPath: string;
|
|
3
4
|
deliveredPath: string;
|
|
@@ -14,7 +15,6 @@ export type JsonDurableQueueLoadOptions<T> = {
|
|
|
14
15
|
cleanupTmpMaxAgeMs?: number;
|
|
15
16
|
maxBytes?: number;
|
|
16
17
|
};
|
|
17
|
-
export declare const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES: number;
|
|
18
18
|
export declare function unlinkBestEffort(filePath: string): Promise<void>;
|
|
19
19
|
export declare function jsonDurableQueueEntryExists(filePath: string): Promise<boolean>;
|
|
20
20
|
export declare function resolveJsonDurableQueueEntryPaths(queueDir: string, id: string): JsonDurableQueueEntryPaths;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-durable-queue.d.ts","sourceRoot":"","sources":["../src/json-durable-queue.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"json-durable-queue.d.ts","sourceRoot":"","sources":["../src/json-durable-queue.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,0CAA0C,EAAE,MAAM,8BAA8B,CAAC;AAE1F,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC1C,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAWF,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUpF;AAmBD,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,GACT,0BAA0B,CAO5B;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhB;AAiLD,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhB;AAgBD,wBAAsB,yBAAyB,CAAC,CAAC,EAC/C,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,OAAO,CAAC,CAAC,CAAC,CAEZ;AAgBD,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/F;AAED,wBAAsB,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE;IACzD,KAAK,EAAE,0BAA0B,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAqBpB;AAED,wBAAsB,kCAAkC,CAAC,CAAC,EACxD,OAAO,EAAE,2BAA2B,CAAC,CAAC,CAAC,GACtC,OAAO,CAAC,CAAC,EAAE,CAAC,CAqEd;AAED,wBAAsB,iCAAiC,CAAC,MAAM,EAAE;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CAShB"}
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import fs, {} from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { normalizeMaxBytes } from "./byte-budget.js";
|
|
4
|
-
import { readBoundedAsync } from "./bounded-read.js";
|
|
5
3
|
import { syncDirectory } from "./directory-durability.js";
|
|
6
4
|
import { syncQueueDirectoryCreation } from "./json-durable-queue-directory.js";
|
|
7
|
-
import { getErrorCode, acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, moveDurableQueueEntryToFailed, } from "./json-durable-queue-ownership.js";
|
|
5
|
+
import { getErrorCode, acknowledgeDurableQueueEntry, claimDurableQueueEntry, completeDeliveredQueueEntry, migrateDurableQueueEntry, moveDurableQueueEntryToFailed, } from "./json-durable-queue-ownership.js";
|
|
6
|
+
import { withJsonDurableQueueEntry } from "./json-durable-queue-read.js";
|
|
8
7
|
import { stringifyJsonDocument } from "./json-stringify.js";
|
|
9
|
-
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
10
8
|
import { realpathSync } from "./realpath.js";
|
|
11
9
|
import { recursiveMkdirPath } from "./recursive-mkdir-path.js";
|
|
12
10
|
import { replaceFileAtomicWithDirectorySync } from "./replace-file.js";
|
|
13
11
|
import { assertSafePathSegment } from "./safe-path-segment.js";
|
|
14
|
-
|
|
15
|
-
export const DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES = 16 * 1024 * 1024;
|
|
12
|
+
export { DEFAULT_JSON_DURABLE_QUEUE_ENTRY_MAX_BYTES } from "./json-durable-queue-read.js";
|
|
16
13
|
function assertSafeQueueEntryId(id) {
|
|
17
14
|
assertSafePathSegment(id, { label: "queue entry id" });
|
|
18
15
|
}
|
|
@@ -213,67 +210,25 @@ async function chmodQueueDirectory(dir) {
|
|
|
213
210
|
}
|
|
214
211
|
}
|
|
215
212
|
export async function writeJsonDurableQueueEntry(params) {
|
|
213
|
+
await writeQueueEntry(params);
|
|
214
|
+
}
|
|
215
|
+
async function writeQueueEntry(params, beforeRename) {
|
|
216
216
|
await replaceFileAtomicWithDirectorySync({
|
|
217
217
|
filePath: params.filePath,
|
|
218
218
|
content: stringifyJsonDocument(params.entry, null, 2),
|
|
219
219
|
mode: 0o600,
|
|
220
220
|
tempPrefix: params.tempPrefix,
|
|
221
221
|
syncTempFile: true,
|
|
222
|
+
beforeRename,
|
|
222
223
|
}, syncDirectory);
|
|
223
224
|
}
|
|
224
|
-
async function inspectQueueEntry(inspect, maxBytes, expected) {
|
|
225
|
-
let inspectionFailed = false;
|
|
226
|
-
try {
|
|
227
|
-
return await inspectFileIdentity(async () => {
|
|
228
|
-
try {
|
|
229
|
-
const stat = inspect();
|
|
230
|
-
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
231
|
-
throw new Error("queue entry is not a regular file");
|
|
232
|
-
}
|
|
233
|
-
if (stat.nlink > 1n)
|
|
234
|
-
throw new Error("queue entry hardlinks are not allowed");
|
|
235
|
-
if (stat.size > maxBytes)
|
|
236
|
-
throw new Error(`queue entry exceeds ${maxBytes} bytes`);
|
|
237
|
-
return stat;
|
|
238
|
-
}
|
|
239
|
-
catch (error) {
|
|
240
|
-
inspectionFailed = true;
|
|
241
|
-
throw error;
|
|
242
|
-
}
|
|
243
|
-
}, expected);
|
|
244
|
-
}
|
|
245
|
-
catch (error) {
|
|
246
|
-
// Translate only the identity helper's rejection, never inspection errors.
|
|
247
|
-
if (inspectionFailed)
|
|
248
|
-
throw error;
|
|
249
|
-
throw new Error("queue entry changed during read", { cause: error });
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
async function readBoundedUtf8File(params) {
|
|
253
|
-
const inspectPath = () => fs.lstatSync(params.filePath, { bigint: true });
|
|
254
|
-
const initialStat = await inspectQueueEntry(inspectPath, params.maxBytes);
|
|
255
|
-
const handle = await fs.promises.open(params.filePath, resolveReadOpenFlags());
|
|
256
|
-
try {
|
|
257
|
-
const openedStat = await inspectQueueEntry(() => fs.fstatSync(handle.fd, { bigint: true }), params.maxBytes, initialStat);
|
|
258
|
-
await inspectQueueEntry(inspectPath, params.maxBytes, openedStat);
|
|
259
|
-
const bytes = await readBoundedAsync(params.maxBytes, async (buffer, length) => (await handle.read(buffer, 0, length, null)).bytesRead, {
|
|
260
|
-
initialSize: openedStat.size >= 0n && Number.isSafeInteger(Number(openedStat.size))
|
|
261
|
-
? Number(openedStat.size) : undefined,
|
|
262
|
-
createLimitError: () => new Error(`queue entry exceeds ${params.maxBytes} bytes`),
|
|
263
|
-
});
|
|
264
|
-
return bytes.toString("utf8");
|
|
265
|
-
}
|
|
266
|
-
finally {
|
|
267
|
-
await handle.close();
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
225
|
export async function readJsonDurableQueueEntry(filePath, options = {}) {
|
|
271
|
-
return
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
})
|
|
276
|
-
})
|
|
226
|
+
return await withJsonDurableQueueEntry(filePath, options, async (entry) => entry);
|
|
227
|
+
}
|
|
228
|
+
async function migrateClaimedQueueEntry(params) {
|
|
229
|
+
await migrateDurableQueueEntry(params.paths, params.identity, params.releaseReadPin, async (filePath, beforePublish) => {
|
|
230
|
+
await writeQueueEntry({ filePath, entry: params.entry, tempPrefix: params.tempPrefix }, beforePublish);
|
|
231
|
+
});
|
|
277
232
|
}
|
|
278
233
|
export async function ackJsonDurableQueueEntry(paths) {
|
|
279
234
|
await acknowledgeDurableQueueEntry(paths);
|
|
@@ -283,18 +238,17 @@ export async function loadJsonDurableQueueEntry(params) {
|
|
|
283
238
|
const claimedPath = await claimDurableQueueEntry(params.paths);
|
|
284
239
|
if (!claimedPath)
|
|
285
240
|
return null;
|
|
286
|
-
|
|
241
|
+
return await withJsonDurableQueueEntry(claimedPath, {
|
|
287
242
|
maxBytes: params.maxBytes,
|
|
243
|
+
}, async (raw, identity, releaseReadPin) => {
|
|
244
|
+
const result = params.read ? await params.read(raw, params.paths.jsonPath) : { entry: raw };
|
|
245
|
+
if (result.migrated) {
|
|
246
|
+
await migrateClaimedQueueEntry({
|
|
247
|
+
paths: params.paths, identity, releaseReadPin, entry: result.entry, tempPrefix: params.tempPrefix,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return result.entry;
|
|
288
251
|
});
|
|
289
|
-
const result = params.read ? await params.read(raw, params.paths.jsonPath) : { entry: raw };
|
|
290
|
-
if (result.migrated) {
|
|
291
|
-
await writeJsonDurableQueueEntry({
|
|
292
|
-
filePath: claimedPath,
|
|
293
|
-
entry: result.entry,
|
|
294
|
-
tempPrefix: params.tempPrefix,
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
return result.entry;
|
|
298
252
|
}
|
|
299
253
|
catch (error) {
|
|
300
254
|
if (getErrorCode(error) === "ENOENT") {
|
|
@@ -358,22 +312,25 @@ export async function loadPendingJsonDurableQueueEntries(options) {
|
|
|
358
312
|
const claimedPath = await claimDurableQueueEntry(paths, { skipUnowned: true });
|
|
359
313
|
if (!claimedPath)
|
|
360
314
|
continue;
|
|
361
|
-
let
|
|
315
|
+
let migrationStarted = false;
|
|
362
316
|
try {
|
|
363
|
-
const
|
|
364
|
-
|
|
317
|
+
const entry = await withJsonDurableQueueEntry(claimedPath, { maxBytes: options.maxBytes }, async (raw, identity, releaseReadPin) => {
|
|
318
|
+
const result = options.read ? await options.read(raw, paths.jsonPath) : { entry: raw };
|
|
319
|
+
if (result.migrated) {
|
|
320
|
+
migrationStarted = true;
|
|
321
|
+
await migrateClaimedQueueEntry({
|
|
322
|
+
paths, identity, releaseReadPin, entry: result.entry, tempPrefix: options.tempPrefix,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
return result.entry;
|
|
326
|
+
});
|
|
327
|
+
entries.push(entry);
|
|
365
328
|
}
|
|
366
|
-
catch {
|
|
329
|
+
catch (error) {
|
|
330
|
+
if (migrationStarted)
|
|
331
|
+
throw error;
|
|
367
332
|
continue;
|
|
368
333
|
}
|
|
369
|
-
if (result.migrated) {
|
|
370
|
-
await writeJsonDurableQueueEntry({
|
|
371
|
-
filePath: claimedPath,
|
|
372
|
-
entry: result.entry,
|
|
373
|
-
tempPrefix: options.tempPrefix,
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
entries.push(result.entry);
|
|
377
334
|
}
|
|
378
335
|
return entries;
|
|
379
336
|
}
|
package/dist/native-binding.d.ts
CHANGED
|
@@ -75,6 +75,11 @@ export interface NativeWindowsSecurityFacts {
|
|
|
75
75
|
unsupportedAceTypes: number[];
|
|
76
76
|
aces: NativeWindowsAccessControlEntry[];
|
|
77
77
|
}
|
|
78
|
+
export interface NativeWindowsDescriptorSecurityFacts {
|
|
79
|
+
/** Canonical lowercase 32-bit volume serial and 64-bit file-index projection used by Node. */
|
|
80
|
+
identity: string;
|
|
81
|
+
security: NativeWindowsSecurityFacts;
|
|
82
|
+
}
|
|
78
83
|
export interface NativeBinding {
|
|
79
84
|
/** POSIX system canonicalization; confinement and identity policy stay with callers. */
|
|
80
85
|
canonicalizePath?(path: string, ordinary: boolean): {
|
|
@@ -111,6 +116,8 @@ export interface NativeBinding {
|
|
|
111
116
|
openBeneath(rootFd: number, relPath: string, flags: number): NativeOpenBeneathResult;
|
|
112
117
|
readArchiveEntryNative(path: string, kind: string, requested: string, maxBytes: number, limits: TarMeterLimits, signal: AbortSignal): Promise<Buffer>;
|
|
113
118
|
readOwnerAndDacl(path: string): NativeWindowsSecurityFacts;
|
|
119
|
+
/** Internal Windows-only inspection of the exact borrowed Node descriptor. */
|
|
120
|
+
inspectWindowsSecureFileHandle?(fd: number): NativeWindowsDescriptorSecurityFacts;
|
|
114
121
|
ownedTreeRemovalAvailable?(parentFd: number): boolean;
|
|
115
122
|
removeOwnedTree?(parentFd: number, basename: string, directoryFd: number): Promise<NativeOwnedTreeRemovalResult>;
|
|
116
123
|
removeOwnedTreeSync?(parentFd: number, basename: string, directoryFd: number): NativeOwnedTreeRemovalResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-binding.d.ts","sourceRoot":"","sources":["../src/native-binding.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"native-binding.d.ts","sourceRoot":"","sources":["../src/native-binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ResolvePathWithinRootParams = {
|
|
2
|
+
rootDir: string;
|
|
3
|
+
requestedPath: string;
|
|
4
|
+
scopeLabel: string;
|
|
5
|
+
defaultFileName?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function resolvePathWithinNormalizedRoot(params: ResolvePathWithinRootParams, root: string): {
|
|
8
|
+
ok: true;
|
|
9
|
+
path: string;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=path-scope-lexical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-scope-lexical.d.ts","sourceRoot":"","sources":["../src/path-scope-lexical.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAUF,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,2BAA2B,EACnC,IAAI,EAAE,MAAM,GACX;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiB3D"}
|