@cloudflare/sandbox 1.0.0-rc.2 → 1.0.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/dist/index.d.mts +7 -4
- package/dist/index.mjs +22 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -41,7 +41,7 @@ interface DirectoryBackupOptions {
|
|
|
41
41
|
interface DirectoryRestoreOptions {
|
|
42
42
|
/** Absolute path to restore into instead of the record's `dir`. */
|
|
43
43
|
dir?: string;
|
|
44
|
-
/** Cancels the
|
|
44
|
+
/** Cancels the restore until the download is verified, without imposing a timeout. */
|
|
45
45
|
signal?: AbortSignal;
|
|
46
46
|
}
|
|
47
47
|
interface DirectoryBackupDeleteOptions {
|
|
@@ -145,9 +145,12 @@ declare class DirectoryBackup {
|
|
|
145
145
|
backup(options: DirectoryBackupOptions): Promise<DirectoryBackupRecord>;
|
|
146
146
|
/**
|
|
147
147
|
* Replaces `options.dir`, or the record's `dir`, with the backup's contents. The directory is
|
|
148
|
-
* extracted beside the target and swapped in only after the download is verified
|
|
149
|
-
* or
|
|
150
|
-
*
|
|
148
|
+
* extracted beside the target and swapped in only after the download is verified. A
|
|
149
|
+
* `SandboxFileError` or `SandboxBackupError` means the target was not replaced, and so does
|
|
150
|
+
* an abort before the download is verified; after that, aborting no longer ends the call. If the
|
|
151
|
+
* connection to the Container is lost, as when the Durable Object restarts, the target may or
|
|
152
|
+
* may not have been replaced, and restoring again settles it. The target's parent must exist;
|
|
153
|
+
* the target need not.
|
|
151
154
|
*
|
|
152
155
|
* @throws {SandboxFileError} The target's parent is missing (`ENOENT`), the target isn't a
|
|
153
156
|
* directory (`ENOTDIR`), is a mount point or has one inside it (`EBUSY`), the swap fails (for
|
package/dist/index.mjs
CHANGED
|
@@ -367,6 +367,10 @@ var ShimSession = class ShimSession {
|
|
|
367
367
|
waitFor(operation) {
|
|
368
368
|
return this.#abort.waitFor(operation);
|
|
369
369
|
}
|
|
370
|
+
/** Stops following the caller's signal: later waits no longer reject when it aborts. */
|
|
371
|
+
stopFollowingSignal() {
|
|
372
|
+
this.#abort.dispose();
|
|
373
|
+
}
|
|
370
374
|
finish() {
|
|
371
375
|
if (this.#settled) return;
|
|
372
376
|
this.#settled = true;
|
|
@@ -490,6 +494,7 @@ const errorSchema = z.object({
|
|
|
490
494
|
detail: z.string()
|
|
491
495
|
});
|
|
492
496
|
const lockedSchema = z.strictObject({ kind: z.literal("locked") });
|
|
497
|
+
const verifiedSchema = z.strictObject({ kind: z.literal("verified") });
|
|
493
498
|
/**
|
|
494
499
|
* Runs one `directory-backup` shim exchange: wait for the lock, register the grant, acknowledge,
|
|
495
500
|
* wait for the result, then deny and close stdin, in that order on every path. The shim holds
|
|
@@ -497,7 +502,10 @@ const lockedSchema = z.strictObject({ kind: z.literal("locked") });
|
|
|
497
502
|
* operation's deny.
|
|
498
503
|
*
|
|
499
504
|
* An abort closes stdin rather than killing the shim, which then removes whatever it had
|
|
500
|
-
* partly written, and rejects
|
|
505
|
+
* partly written, and rejects with the signal's reason without waiting for the shim. A restore
|
|
506
|
+
* reports `verified` before it swaps and swaps only once acknowledged, so the exchange
|
|
507
|
+
* acknowledges it only while the signal hasn't aborted, and from then on reports the swap's
|
|
508
|
+
* outcome instead of the abort.
|
|
501
509
|
*/
|
|
502
510
|
async function runShimExchange(container, exchange) {
|
|
503
511
|
const { signal } = exchange;
|
|
@@ -535,6 +543,13 @@ async function runShimExchange(container, exchange) {
|
|
|
535
543
|
granting = exchange.grant();
|
|
536
544
|
await session.waitFor(granting);
|
|
537
545
|
await session.waitFor(input.write(ACKNOWLEDGEMENT));
|
|
546
|
+
if (exchange.command === "restore") {
|
|
547
|
+
const verified = await readMessage(control, operation, exchange.path);
|
|
548
|
+
if (!verifiedSchema.safeParse(verified).success) throw protocolError("sandbox-shim did not report a verified restore");
|
|
549
|
+
signal?.throwIfAborted();
|
|
550
|
+
session.stopFollowingSignal();
|
|
551
|
+
await input.write(ACKNOWLEDGEMENT);
|
|
552
|
+
}
|
|
538
553
|
const result = await readMessage(control, operation, exchange.path);
|
|
539
554
|
const done = exchange.done.safeParse(result);
|
|
540
555
|
if (!done.success) throw protocolError("sandbox-shim returned an invalid backup result");
|
|
@@ -704,9 +719,12 @@ var DirectoryBackup = class {
|
|
|
704
719
|
}
|
|
705
720
|
/**
|
|
706
721
|
* Replaces `options.dir`, or the record's `dir`, with the backup's contents. The directory is
|
|
707
|
-
* extracted beside the target and swapped in only after the download is verified
|
|
708
|
-
* or
|
|
709
|
-
*
|
|
722
|
+
* extracted beside the target and swapped in only after the download is verified. A
|
|
723
|
+
* `SandboxFileError` or `SandboxBackupError` means the target was not replaced, and so does
|
|
724
|
+
* an abort before the download is verified; after that, aborting no longer ends the call. If the
|
|
725
|
+
* connection to the Container is lost, as when the Durable Object restarts, the target may or
|
|
726
|
+
* may not have been replaced, and restoring again settles it. The target's parent must exist;
|
|
727
|
+
* the target need not.
|
|
710
728
|
*
|
|
711
729
|
* @throws {SandboxFileError} The target's parent is missing (`ENOENT`), the target isn't a
|
|
712
730
|
* directory (`ENOTDIR`), is a mount point or has one inside it (`EBUSY`), the swap fails (for
|