@prisma/composer-prisma-cloud 0.30.0-dev.2 → 0.30.0-dev.4
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/auth/pack.mjs +1 -1
- package/dist/auth/pack.mjs.map +1 -1
- package/dist/auth/testing.mjs +1 -1
- package/dist/auth/testing.mjs.map +1 -1
- package/dist/buckets-main.mjs +102 -82
- package/dist/buckets-main.mjs.map +1 -1
- package/dist/compute-main.mjs +243 -231
- package/dist/compute-main.mjs.map +1 -1
- package/dist/control.mjs +3 -3
- package/dist/control.mjs.map +1 -1
- package/dist/{segments-BW2SYdBf-CtmcRzwy.mjs → daemon-D9BV062Q-ZTmWho_N.mjs} +2 -11
- package/dist/daemon-D9BV062Q-ZTmWho_N.mjs.map +1 -0
- package/dist/local-target.mjs +726 -317
- package/dist/local-target.mjs.map +1 -1
- package/dist/postgres-main.mjs +325 -193
- package/dist/postgres-main.mjs.map +1 -1
- package/dist/{s3-credentials-resource-BZjtuopJ-D0fKtjEH.mjs → s3-credentials-resource-D4jcpAZp-6qCQY8BD.mjs} +50 -10
- package/dist/{s3-credentials-resource-BZjtuopJ-D0fKtjEH.mjs.map → s3-credentials-resource-D4jcpAZp-6qCQY8BD.mjs.map} +1 -1
- package/package.json +18 -18
- package/dist/segments-BW2SYdBf-CtmcRzwy.mjs.map +0 -1
package/dist/buckets-main.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as readOwnVersion, i as readJsonFile, n as StateFile } from "./daemon-D9BV062Q-ZTmWho_N.mjs";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as fs$1 from "node:fs/promises";
|
|
4
4
|
import * as path from "node:path";
|
|
5
|
-
import { createHash, createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
5
|
+
import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
6
6
|
import * as http from "node:http";
|
|
7
7
|
//#region ../../1-prisma-cloud/0-lowering/s3-protocol/dist/index.mjs
|
|
8
8
|
const DEFAULT_CONTENT_TYPE$1 = "application/octet-stream";
|
|
@@ -557,27 +557,37 @@ function createS3Handler(opts) {
|
|
|
557
557
|
/**
|
|
558
558
|
* The bucket emulator daemon (local-dev spec § 2 `buckets-main.ts`): the S3
|
|
559
559
|
* wire protocol (`@internal/s3-protocol`'s handler + `fsStore`) over
|
|
560
|
-
* registered
|
|
561
|
-
*
|
|
562
|
-
*
|
|
560
|
+
* registered bucket instances. Each instance is keyed by an id this daemon
|
|
561
|
+
* generates, which is also its bucket name on the S3 wire; its objects live
|
|
562
|
+
* in the data root its creator registers, a path stored verbatim and never
|
|
563
|
+
* interpreted, as are its labels. Credentials are registered per instance.
|
|
564
|
+
* Admin lives under `/_pcdev/` (the underscore can't collide with a valid
|
|
565
|
+
* bucket name). Plain `node:http`.
|
|
563
566
|
*
|
|
564
567
|
* Runs as its own OS process, started by `daemon.ts`'s `ensureDaemon` via
|
|
565
568
|
* `process.execPath <this file> --port <n> --state-dir <dir>`.
|
|
566
569
|
*/
|
|
567
570
|
const STATE_MODE = 384;
|
|
568
|
-
const PHYSICAL_BUCKET_NAME_RE = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;
|
|
569
571
|
const MULTIPART_MESSAGE = "multipart upload is not supported by the local dev bucket emulator yet";
|
|
570
|
-
|
|
571
|
-
|
|
572
|
+
/** Also the bucket's name on the S3 wire, so it uses only characters a bucket name allows. */
|
|
573
|
+
const INSTANCE_ID_RE = /^bkt-[0-9a-f]{16}$/;
|
|
574
|
+
function newInstanceId() {
|
|
575
|
+
return `bkt-${randomBytes(8).toString("hex")}`;
|
|
576
|
+
}
|
|
577
|
+
function isStringRecord(value) {
|
|
578
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((v) => typeof v === "string");
|
|
579
|
+
}
|
|
580
|
+
function isBucketRecord(value) {
|
|
581
|
+
return typeof value === "object" && value !== null && "id" in value && typeof value.id === "string" && "labels" in value && isStringRecord(value.labels) && "dir" in value && typeof value.dir === "string";
|
|
572
582
|
}
|
|
573
583
|
function isCredentialRecord(value) {
|
|
574
|
-
return typeof value === "object" && value !== null && "
|
|
584
|
+
return typeof value === "object" && value !== null && "instanceId" in value && typeof value.instanceId === "string" && "secretAccessKey" in value && typeof value.secretAccessKey === "string";
|
|
575
585
|
}
|
|
576
586
|
function isBucketsState(value) {
|
|
577
|
-
return typeof value === "object" && value !== null && "
|
|
587
|
+
return typeof value === "object" && value !== null && "instances" in value && typeof value.instances === "object" && value.instances !== null && Object.values(value.instances).every(isBucketRecord) && "credentials" in value && typeof value.credentials === "object" && value.credentials !== null && Object.values(value.credentials).every(isCredentialRecord);
|
|
578
588
|
}
|
|
579
|
-
function
|
|
580
|
-
return typeof value === "object" && value !== null && "dir" in value && typeof value.dir === "string";
|
|
589
|
+
function isCreateBody(value) {
|
|
590
|
+
return typeof value === "object" && value !== null && "labels" in value && isStringRecord(value.labels) && "dir" in value && typeof value.dir === "string";
|
|
581
591
|
}
|
|
582
592
|
function isCredentialsBody(value) {
|
|
583
593
|
return typeof value === "object" && value !== null && "accessKeyId" in value && typeof value.accessKeyId === "string" && "secretAccessKey" in value && typeof value.secretAccessKey === "string";
|
|
@@ -623,13 +633,13 @@ async function sendWebResponse(res, webRes) {
|
|
|
623
633
|
function main() {
|
|
624
634
|
const { port, stateDir } = parseArgs(process.argv.slice(2));
|
|
625
635
|
const ownVersion = readOwnVersion();
|
|
626
|
-
const
|
|
627
|
-
const stateFile = new StateFile(
|
|
636
|
+
const statePath = path.join(stateDir, "instances.json");
|
|
637
|
+
const stateFile = new StateFile(statePath, STATE_MODE);
|
|
628
638
|
let state = {
|
|
629
|
-
|
|
639
|
+
instances: {},
|
|
630
640
|
credentials: {}
|
|
631
641
|
};
|
|
632
|
-
const store = fsStore((
|
|
642
|
+
const store = fsStore((bucket) => state.instances[bucket]?.dir);
|
|
633
643
|
function json(res, status, body) {
|
|
634
644
|
res.writeHead(status, { "content-type": "application/json" });
|
|
635
645
|
res.end(JSON.stringify(body));
|
|
@@ -638,55 +648,57 @@ function main() {
|
|
|
638
648
|
res.writeHead(status, { "content-type": "text/plain; charset=utf-8" });
|
|
639
649
|
res.end(body);
|
|
640
650
|
}
|
|
641
|
-
function
|
|
642
|
-
|
|
651
|
+
function noContent(res) {
|
|
652
|
+
res.writeHead(204);
|
|
653
|
+
res.end();
|
|
643
654
|
}
|
|
644
|
-
async function
|
|
645
|
-
const physicalName = `${app}--${name}`;
|
|
646
|
-
if (!PHYSICAL_BUCKET_NAME_RE.test(physicalName)) return text(res, 400, `invalid bucket "${physicalName}" (app "${app}", name "${name}"): the physical bucket name must match /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/ and be at most 63 characters`);
|
|
655
|
+
async function readJsonBody(req) {
|
|
647
656
|
const raw = await readBody(req);
|
|
648
|
-
let parsed;
|
|
649
657
|
try {
|
|
650
|
-
|
|
658
|
+
return JSON.parse(raw.toString("utf8"));
|
|
651
659
|
} catch {
|
|
652
|
-
return
|
|
660
|
+
return;
|
|
653
661
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
dir:
|
|
662
|
+
}
|
|
663
|
+
function instanceView(bucket) {
|
|
664
|
+
return {
|
|
665
|
+
id: bucket.id,
|
|
666
|
+
labels: bucket.labels,
|
|
667
|
+
dir: bucket.dir
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
async function handleCreate(req, res) {
|
|
671
|
+
const body = await readJsonBody(req);
|
|
672
|
+
if (!isCreateBody(body)) return text(res, 400, "malformed body: expected { \"labels\": Record<string, string>, \"dir\": string }");
|
|
673
|
+
await fs.promises.mkdir(body.dir, { recursive: true });
|
|
674
|
+
const id = newInstanceId();
|
|
675
|
+
const bucket = {
|
|
676
|
+
id,
|
|
677
|
+
labels: { ...body.labels },
|
|
678
|
+
dir: body.dir
|
|
660
679
|
};
|
|
680
|
+
state.instances[id] = bucket;
|
|
661
681
|
await stateFile.write(state);
|
|
662
|
-
res
|
|
663
|
-
res.end();
|
|
682
|
+
return json(res, 201, instanceView(bucket));
|
|
664
683
|
}
|
|
665
|
-
async function handlePutCredentials(req, res,
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
if (!isCredentialsBody(parsed)) return text(res, 400, "malformed credentials body: expected { \"accessKeyId\", \"secretAccessKey\" }");
|
|
674
|
-
const existing = state.credentials[parsed.accessKeyId];
|
|
675
|
-
if (existing && existing.app !== app) return text(res, 409, `accessKeyId "${parsed.accessKeyId}" is already registered by a different app`);
|
|
676
|
-
state.credentials[parsed.accessKeyId] = {
|
|
677
|
-
app,
|
|
678
|
-
secretAccessKey: parsed.secretAccessKey
|
|
684
|
+
async function handlePutCredentials(req, res, bucket) {
|
|
685
|
+
const body = await readJsonBody(req);
|
|
686
|
+
if (!isCredentialsBody(body)) return text(res, 400, "malformed credentials body: expected { \"accessKeyId\", \"secretAccessKey\" }");
|
|
687
|
+
const existing = state.credentials[body.accessKeyId];
|
|
688
|
+
if (existing && existing.instanceId !== bucket.id) return text(res, 409, `accessKeyId "${body.accessKeyId}" is already registered for another bucket`);
|
|
689
|
+
state.credentials[body.accessKeyId] = {
|
|
690
|
+
instanceId: bucket.id,
|
|
691
|
+
secretAccessKey: body.secretAccessKey
|
|
679
692
|
};
|
|
680
693
|
await stateFile.write(state);
|
|
681
|
-
res
|
|
682
|
-
res.end();
|
|
694
|
+
noContent(res);
|
|
683
695
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
696
|
+
/** Removes the bucket's registration and credentials; its objects stay where its creator put them. */
|
|
697
|
+
async function handleDelete(res, id) {
|
|
698
|
+
delete state.instances[id];
|
|
699
|
+
for (const [key, cred] of Object.entries(state.credentials)) if (cred.instanceId === id) delete state.credentials[key];
|
|
687
700
|
await stateFile.write(state);
|
|
688
|
-
res
|
|
689
|
-
res.end();
|
|
701
|
+
noContent(res);
|
|
690
702
|
}
|
|
691
703
|
/** Path-style addressing: the bucket is the first non-empty path segment. Mirrors the handler's own `parseTarget`, which isn't exported. */
|
|
692
704
|
function bucketFromPath(pathname) {
|
|
@@ -694,19 +706,14 @@ function main() {
|
|
|
694
706
|
return first !== void 0 ? decodeURIComponent(first) : void 0;
|
|
695
707
|
}
|
|
696
708
|
/**
|
|
697
|
-
* Credentials accepted for THIS request's target bucket only
|
|
698
|
-
*
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
* the string). An unknown bucket or an app with no registered credentials
|
|
702
|
-
* yields no candidates, which still resolves through the real 403 path
|
|
703
|
-
* below — never a bespoke "unknown bucket" shortcut that would reveal
|
|
704
|
-
* anything.
|
|
709
|
+
* Credentials accepted for THIS request's target bucket only. An unknown
|
|
710
|
+
* bucket or one with no registered credentials yields no candidates, which
|
|
711
|
+
* still resolves through the real 403 path below — never a bespoke
|
|
712
|
+
* "unknown bucket" shortcut that would reveal anything.
|
|
705
713
|
*/
|
|
706
714
|
function credentialsForBucket(bucket) {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
return Object.entries(state.credentials).filter(([, rec]) => rec.app === owningApp).map(([accessKeyId, rec]) => ({
|
|
715
|
+
if (bucket === void 0 || state.instances[bucket] === void 0) return [];
|
|
716
|
+
return Object.entries(state.credentials).filter(([, rec]) => rec.instanceId === bucket).map(([accessKeyId, rec]) => ({
|
|
710
717
|
accessKeyId,
|
|
711
718
|
secretAccessKey: rec.secretAccessKey
|
|
712
719
|
}));
|
|
@@ -738,28 +745,32 @@ function main() {
|
|
|
738
745
|
}
|
|
739
746
|
if (last) await sendWebResponse(res, last);
|
|
740
747
|
}
|
|
741
|
-
async function
|
|
742
|
-
const url = new URL(req.url ?? "/", `http://127.0.0.1:${String(port)}`);
|
|
748
|
+
async function handleAdmin(req, res, segments) {
|
|
743
749
|
const method = req.method ?? "GET";
|
|
744
|
-
if (method === "GET" &&
|
|
745
|
-
if (
|
|
746
|
-
const segments = url.pathname.split("/").filter((s) => s.length > 0).map((s) => decodeURIComponent(s));
|
|
747
|
-
if (method === "GET" && segments.length === 2 && segments[1] === "health") return json(res, 200, { version: ownVersion });
|
|
748
|
-
if (segments[1] === "apps" && segments.length >= 3) {
|
|
749
|
-
const app = segments[2];
|
|
750
|
-
if (app === void 0 || !isValidSegment(app)) return badSegment(res, app ?? "");
|
|
751
|
-
if (method === "PUT" && segments.length === 5 && segments[3] === "buckets") {
|
|
752
|
-
const name = segments[4];
|
|
753
|
-
if (name === void 0 || !isValidSegment(name)) return badSegment(res, name ?? "");
|
|
754
|
-
return handlePutBucket(req, res, app, name);
|
|
755
|
-
}
|
|
756
|
-
if (method === "PUT" && segments.length === 4 && segments[3] === "credentials") return handlePutCredentials(req, res, app);
|
|
757
|
-
if (method === "DELETE" && segments.length === 3) return handleDeleteApp(res, app);
|
|
758
|
-
}
|
|
750
|
+
if (method === "GET" && segments.length === 2 && segments[1] === "health") return json(res, 200, { version: ownVersion });
|
|
751
|
+
if (segments[1] !== "instances") {
|
|
759
752
|
res.writeHead(404);
|
|
760
753
|
res.end();
|
|
761
754
|
return;
|
|
762
755
|
}
|
|
756
|
+
if (segments.length === 2) {
|
|
757
|
+
if (method === "GET") return json(res, 200, Object.values(state.instances).map(instanceView));
|
|
758
|
+
if (method === "POST") return handleCreate(req, res);
|
|
759
|
+
}
|
|
760
|
+
const id = segments[2];
|
|
761
|
+
if (id !== void 0 && !INSTANCE_ID_RE.test(id)) return text(res, 400, `invalid instance id "${id}"`);
|
|
762
|
+
if (method === "DELETE" && segments.length === 3 && id !== void 0) return handleDelete(res, id);
|
|
763
|
+
const bucket = id === void 0 ? void 0 : state.instances[id];
|
|
764
|
+
if (!bucket) return text(res, 404, `no such instance: "${id ?? ""}"`);
|
|
765
|
+
if (method === "GET" && segments.length === 3) return json(res, 200, instanceView(bucket));
|
|
766
|
+
if (method === "PUT" && segments.length === 4 && segments[3] === "credentials") return handlePutCredentials(req, res, bucket);
|
|
767
|
+
res.writeHead(404);
|
|
768
|
+
res.end();
|
|
769
|
+
}
|
|
770
|
+
async function handleRequest(req, res) {
|
|
771
|
+
const url = new URL(req.url ?? "/", `http://127.0.0.1:${String(port)}`);
|
|
772
|
+
if ((req.method ?? "GET") === "GET" && url.pathname === "/health") return json(res, 200, { version: ownVersion });
|
|
773
|
+
if (url.pathname.startsWith("/_pcdev/")) return handleAdmin(req, res, url.pathname.split("/").filter((s) => s.length > 0).map((s) => decodeURIComponent(s)));
|
|
763
774
|
return handleS3Wire(req, res, url);
|
|
764
775
|
}
|
|
765
776
|
const server = http.createServer((req, res) => {
|
|
@@ -775,7 +786,7 @@ function main() {
|
|
|
775
786
|
}
|
|
776
787
|
process.on("SIGTERM", () => void shutdown());
|
|
777
788
|
process.on("SIGINT", () => void shutdown());
|
|
778
|
-
readJsonFile(
|
|
789
|
+
discardStateFromEarlierVersions(stateDir, statePath).then(() => readJsonFile(statePath, isBucketsState)).then((loaded) => {
|
|
779
790
|
if (loaded) state = loaded;
|
|
780
791
|
server.listen(port, "127.0.0.1", () => {
|
|
781
792
|
console.log(`[dev-emulators] buckets-main listening on 127.0.0.1:${String(port)}`);
|
|
@@ -785,6 +796,15 @@ function main() {
|
|
|
785
796
|
process.exit(1);
|
|
786
797
|
});
|
|
787
798
|
}
|
|
799
|
+
/**
|
|
800
|
+
* Removes state files this version does not write. Local dev state is never
|
|
801
|
+
* migrated across versions; buckets registered by an earlier version are
|
|
802
|
+
* gone, and their objects stay where they were.
|
|
803
|
+
*/
|
|
804
|
+
async function discardStateFromEarlierVersions(stateDir, statePath) {
|
|
805
|
+
const files = await fs.promises.readdir(stateDir).catch(() => []);
|
|
806
|
+
await Promise.all(files.map((name) => path.join(stateDir, name)).filter((file) => file.endsWith(".json") && file !== statePath).map((file) => fs.promises.rm(file, { force: true })));
|
|
807
|
+
}
|
|
788
808
|
main();
|
|
789
809
|
//#endregion
|
|
790
810
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buckets-main.mjs","names":["fs"],"sources":["../../../1-prisma-cloud/0-lowering/s3-protocol/dist/index.mjs","../../../1-prisma-cloud/0-lowering/dev-emulators/dist/buckets-main.mjs"],"sourcesContent":["import { createHash, createHmac, randomUUID, timingSafeEqual } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nconst DEFAULT_CONTENT_TYPE$1 = \"application/octet-stream\";\nconst TMP_DIR_NAME = \".tmp\";\nconst META_DIR_NAME = \".meta\";\nconst RESERVED_SEGMENTS = /* @__PURE__ */ new Set([TMP_DIR_NAME, META_DIR_NAME]);\nconst BUCKET_NAME_RE = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;\nfunction etagOf$1(bytes) {\n\treturn `\"${createHash(\"sha256\").update(bytes).digest(\"hex\")}\"`;\n}\nfunction isErrnoException(err) {\n\treturn err instanceof Error && \"code\" in err;\n}\nfunction isEnoent(err) {\n\treturn isErrnoException(err) && err.code === \"ENOENT\";\n}\n/**\n* Splits a key into its `/` segments, rejecting anything that could escape\n* the bucket dir or collide with the reserved `.tmp`/`.meta` namespaces:\n* `..` segments, an empty segment (leading/trailing/doubled `/`, which also\n* catches a leading-slash \"absolute\" key), or a segment literally `.tmp` or\n* `.meta` at any depth.\n*/\nfunction keySegments(key) {\n\tconst segments = key.split(\"/\");\n\tfor (const segment of segments) if (segment === \"\" || segment === \".\" || segment === \"..\" || RESERVED_SEGMENTS.has(segment)) throw new Error(`invalid object key: \"${key}\"`);\n\treturn segments;\n}\n/** `<bucketDir>/<key's segments>`, double-checked to still resolve inside `bucketDir`. */\nfunction objectPath(bucketDir, key) {\n\tconst target = path.join(bucketDir, ...keySegments(key));\n\tconst resolvedRoot = path.resolve(bucketDir) + path.sep;\n\tif (!(path.resolve(target) + path.sep).startsWith(resolvedRoot)) throw new Error(`invalid object key: \"${key}\"`);\n\treturn target;\n}\n/** `<bucketDir>/.meta/<key's segments>.json` — mirrors `objectPath`'s tree under `.meta`. */\nfunction sidecarPath(bucketDir, key) {\n\tconst segments = keySegments(key);\n\tconst last = segments[segments.length - 1];\n\tconst dirs = segments.slice(0, -1);\n\treturn path.join(bucketDir, META_DIR_NAME, ...dirs, `${last}.json`);\n}\n/** Write-temp-then-rename: never leaves a reader observing a partial file. */\nasync function writeAtomic(finalPath, tmpRoot, bytes) {\n\tawait fs.mkdir(tmpRoot, { recursive: true });\n\tconst tmpPath = path.join(tmpRoot, randomUUID());\n\tawait fs.writeFile(tmpPath, bytes);\n\tawait fs.mkdir(path.dirname(finalPath), { recursive: true });\n\tawait fs.rename(tmpPath, finalPath);\n}\nfunction isSidecar(value) {\n\treturn typeof value === \"object\" && value !== null && \"contentType\" in value && typeof value.contentType === \"string\" && \"etag\" in value && typeof value.etag === \"string\";\n}\nasync function readSidecar(sidecar) {\n\tlet raw;\n\ttry {\n\t\traw = await fs.readFile(sidecar, \"utf8\");\n\t} catch (err) {\n\t\tif (isEnoent(err)) return null;\n\t\tthrow err;\n\t}\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\tif (isSidecar(parsed)) return parsed;\n\t} catch {}\n\treturn null;\n}\n/** Read the object's bytes plus its metadata — adopting a sidecar-less file (dropped in by a developer) by computing and lazily persisting one. `null` when the object is missing. */\nasync function readObject(bucketDir, key) {\n\tconst target = objectPath(bucketDir, key);\n\tlet bytes;\n\ttry {\n\t\tbytes = await fs.readFile(target);\n\t} catch (err) {\n\t\tif (isEnoent(err)) return null;\n\t\tthrow err;\n\t}\n\tconst existing = await readSidecar(sidecarPath(bucketDir, key));\n\tif (existing) return {\n\t\tbytes,\n\t\tmeta: existing\n\t};\n\tconst meta = {\n\t\tcontentType: DEFAULT_CONTENT_TYPE$1,\n\t\tetag: etagOf$1(bytes)\n\t};\n\tawait writeAtomic(sidecarPath(bucketDir, key), path.join(bucketDir, TMP_DIR_NAME), Buffer.from(JSON.stringify(meta)));\n\treturn {\n\t\tbytes,\n\t\tmeta\n\t};\n}\n/** Remove now-empty directories from `startDir` up to (never including) `root`. */\nasync function pruneEmptyDirs(root, startDir) {\n\tconst resolvedRoot = path.resolve(root);\n\tlet dir = path.resolve(startDir);\n\twhile (dir !== resolvedRoot && dir.startsWith(resolvedRoot + path.sep)) {\n\t\tlet entries;\n\t\ttry {\n\t\t\tentries = await fs.readdir(dir);\n\t\t} catch (err) {\n\t\t\tif (isEnoent(err)) {\n\t\t\t\tdir = path.dirname(dir);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t\tif (entries.length > 0) break;\n\t\ttry {\n\t\t\tawait fs.rmdir(dir);\n\t\t} catch (err) {\n\t\t\tif (!isEnoent(err)) throw err;\n\t\t}\n\t\tdir = path.dirname(dir);\n\t}\n}\n/** Recursively lists every object key under `dir`, skipping `.tmp`/`.meta` at any depth. */\nasync function walkKeys(dir) {\n\tconst keys = [];\n\tasync function walk(current, prefix) {\n\t\tlet entries;\n\t\ttry {\n\t\t\tentries = await fs.readdir(current, { withFileTypes: true });\n\t\t} catch (err) {\n\t\t\tif (isEnoent(err)) return;\n\t\t\tthrow err;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (RESERVED_SEGMENTS.has(entry.name)) continue;\n\t\t\tconst rel = prefix === \"\" ? entry.name : `${prefix}/${entry.name}`;\n\t\t\tif (entry.isDirectory()) await walk(path.join(current, entry.name), rel);\n\t\t\telse if (entry.isFile()) keys.push(rel);\n\t\t}\n\t}\n\tawait walk(dir, \"\");\n\treturn keys;\n}\n/**\n* A disk-backed `ObjectStore`: object bytes and a metadata sidecar under a\n* per-bucket directory the caller resolves. See the module doc for the\n* unknown-bucket / invalid-key failure shapes.\n*/\nfunction fsStore(resolveBucketDir) {\n\tfunction resolveDir(bucket) {\n\t\tif (!BUCKET_NAME_RE.test(bucket)) return void 0;\n\t\treturn resolveBucketDir(bucket);\n\t}\n\treturn {\n\t\tasync put(bucket, key, bytes, opts = {}) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) throw new Error(`no such bucket: \"${bucket}\"`);\n\t\t\tconst target = objectPath(dir, key);\n\t\t\tconst tmpRoot = path.join(dir, TMP_DIR_NAME);\n\t\t\tconst etag = etagOf$1(bytes);\n\t\t\tconst contentType = opts.contentType ?? DEFAULT_CONTENT_TYPE$1;\n\t\t\tawait writeAtomic(target, tmpRoot, bytes);\n\t\t\tawait writeAtomic(sidecarPath(dir, key), tmpRoot, Buffer.from(JSON.stringify({\n\t\t\t\tcontentType,\n\t\t\t\tetag\n\t\t\t})));\n\t\t\treturn { etag };\n\t\t},\n\t\tasync get(bucket, key, opts = {}) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return null;\n\t\t\tconst found = await readObject(dir, key);\n\t\t\tif (!found) return null;\n\t\t\tconst { bytes, meta } = found;\n\t\t\tconst size = bytes.byteLength;\n\t\t\tif (opts.range) {\n\t\t\t\tconst start = opts.range.start;\n\t\t\t\tconst end = opts.range.end === void 0 ? size - 1 : Math.min(opts.range.end, size - 1);\n\t\t\t\treturn {\n\t\t\t\t\tbytes: start > end ? /* @__PURE__ */ new Uint8Array(0) : bytes.subarray(start, end + 1),\n\t\t\t\t\tetag: meta.etag,\n\t\t\t\t\tcontentType: meta.contentType,\n\t\t\t\t\tsize\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbytes: new Uint8Array(bytes),\n\t\t\t\tetag: meta.etag,\n\t\t\t\tcontentType: meta.contentType,\n\t\t\t\tsize\n\t\t\t};\n\t\t},\n\t\tasync head(bucket, key) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return null;\n\t\t\tconst found = await readObject(dir, key);\n\t\t\tif (!found) return null;\n\t\t\treturn {\n\t\t\t\tetag: found.meta.etag,\n\t\t\t\tsize: found.bytes.byteLength,\n\t\t\t\tcontentType: found.meta.contentType\n\t\t\t};\n\t\t},\n\t\tasync delete(bucket, key) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return;\n\t\t\tconst target = objectPath(dir, key);\n\t\t\tconst sidecar = sidecarPath(dir, key);\n\t\t\ttry {\n\t\t\t\tawait fs.unlink(target);\n\t\t\t} catch (err) {\n\t\t\t\tif (!isEnoent(err)) throw err;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait fs.unlink(sidecar);\n\t\t\t} catch (err) {\n\t\t\t\tif (!isEnoent(err)) throw err;\n\t\t\t}\n\t\t\tawait pruneEmptyDirs(dir, path.dirname(target));\n\t\t\tawait pruneEmptyDirs(path.join(dir, META_DIR_NAME), path.dirname(sidecar));\n\t\t},\n\t\tasync list(bucket, opts = {}) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return {\n\t\t\t\tkeys: [],\n\t\t\t\tisTruncated: false\n\t\t\t};\n\t\t\tconst prefix = opts.prefix ?? \"\";\n\t\t\tconst maxKeys = opts.maxKeys ?? 1e3;\n\t\t\tconst token = opts.continuationToken;\n\t\t\tconst matching = (await walkKeys(dir)).filter((key) => key.startsWith(prefix)).sort().filter((key) => token === void 0 ? true : key > token);\n\t\t\tconst page = matching.slice(0, maxKeys);\n\t\t\tconst isTruncated = matching.length > maxKeys;\n\t\t\tconst last = page.at(-1);\n\t\t\treturn {\n\t\t\t\tkeys: page,\n\t\t\t\tisTruncated,\n\t\t\t\t...isTruncated && last !== void 0 ? { nextContinuationToken: last } : {}\n\t\t\t};\n\t\t}\n\t};\n}\n//#endregion\n//#region src/sigv4.ts\n/**\n* AWS SigV4 verification for the S3 wire protocol (spec § 2 auth). The payload\n* hash comes from the client — `x-amz-content-sha256` (a real hash or\n* `UNSIGNED-PAYLOAD`) for header auth, `UNSIGNED-PAYLOAD` for presign — and is\n* never re-hashed; the verifier trusts what was signed, like a real S3 endpoint.\n* Runtime engine code (`node:crypto`); not re-exported from the authoring barrel.\n*\n* Also owns `mintKeyPair` (local-dev spec § 1) — the one key-pair generator\n* both the deploy-time `S3Credentials` resource and the local dev bucket\n* emulator's credential provisioning use.\n*/\nfunction randomBytes(n) {\n\treturn crypto.getRandomValues(new Uint8Array(n));\n}\nfunction toHexUpper(bytes) {\n\treturn Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\").toUpperCase();\n}\n/** A fresh SigV4 key pair: an AKIA-prefixed id and a 40-char base64 secret. */\nfunction mintKeyPair() {\n\treturn {\n\t\taccessKeyId: `AKIA${toHexUpper(randomBytes(8))}`,\n\t\tsecretAccessKey: btoa(String.fromCharCode(...randomBytes(30)))\n\t};\n}\nconst ALGORITHM = \"AWS4-HMAC-SHA256\";\nconst UNSIGNED_PAYLOAD = \"UNSIGNED-PAYLOAD\";\nfunction sha256Hex(data) {\n\treturn createHash(\"sha256\").update(data).digest(\"hex\");\n}\nfunction hmac(key, data) {\n\treturn createHmac(\"sha256\", key).update(data).digest();\n}\n/** AWS canonical URI encoding: every byte except the unreserved set is %XX. */\nfunction awsUriEncode(value) {\n\treturn encodeURIComponent(value).replace(/[!'()*]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%7E/g, \"~\");\n}\nfunction parseCredential(credential) {\n\tconst parts = credential.split(\"/\");\n\tif (parts.length !== 5 || parts[4] !== \"aws4_request\") return null;\n\tconst [accessKeyId, date, region, service] = parts;\n\tif (!accessKeyId || !date || !region || !service) return null;\n\treturn {\n\t\taccessKeyId,\n\t\tdate,\n\t\tregion,\n\t\tservice\n\t};\n}\nfunction signingKey(secret, scope) {\n\treturn hmac(hmac(hmac(hmac(`AWS4${secret}`, scope.date), scope.region), scope.service), \"aws4_request\");\n}\nfunction canonicalHeaders(url, req, signedHeaders) {\n\treturn signedHeaders.map((name) => {\n\t\treturn `${name}:${(name === \"host\" ? url.host : req.headers.get(name) ?? \"\").trim().replace(/\\s+/g, \" \")}\\n`;\n\t}).join(\"\");\n}\nfunction canonicalQuery(url, exclude) {\n\tconst entries = [];\n\tfor (const [key, value] of url.searchParams.entries()) {\n\t\tif (exclude !== void 0 && key === exclude) continue;\n\t\tentries.push([awsUriEncode(key), awsUriEncode(value)]);\n\t}\n\tconst cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n\tentries.sort(([ak, av], [bk, bv]) => cmp(ak, bk) || cmp(av, bv));\n\treturn entries.map(([k, v]) => `${k}=${v}`).join(\"&\");\n}\nfunction stringToSign(amzDate, scope, canonicalRequest) {\n\tconst scopeString = `${scope.date}/${scope.region}/${scope.service}/aws4_request`;\n\treturn [\n\t\tALGORITHM,\n\t\tamzDate,\n\t\tscopeString,\n\t\tsha256Hex(canonicalRequest)\n\t].join(\"\\n\");\n}\nfunction signatureMatches(expected, provided) {\n\tconst a = Buffer.from(expected, \"hex\");\n\tconst b = Buffer.from(provided, \"hex\");\n\treturn a.length === b.length && a.length > 0 && timingSafeEqual(a, b);\n}\n/** `YYYYMMDDTHHMMSSZ` → epoch ms, or null when malformed. */\nfunction parseAmzDate(amzDate) {\n\tconst match = /^(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})Z$/.exec(amzDate);\n\tif (!match) return null;\n\tconst [, y, mo, d, h, mi, s] = match;\n\treturn Date.UTC(Number(y), Number(mo) - 1, Number(d), Number(h), Number(mi), Number(s));\n}\nfunction parseAuthorizationHeader(header) {\n\tif (!header.startsWith(`${ALGORITHM} `)) return null;\n\tconst rest = header.slice(17);\n\tconst fields = /* @__PURE__ */ new Map();\n\tfor (const part of rest.split(\",\")) {\n\t\tconst eq = part.indexOf(\"=\");\n\t\tif (eq === -1) continue;\n\t\tfields.set(part.slice(0, eq).trim(), part.slice(eq + 1).trim());\n\t}\n\tconst credential = fields.get(\"Credential\");\n\tconst signedHeaders = fields.get(\"SignedHeaders\");\n\tconst signature = fields.get(\"Signature\");\n\tif (!credential || !signedHeaders || !signature) return null;\n\treturn {\n\t\tcredential,\n\t\tsignedHeaders: signedHeaders.split(\";\"),\n\t\tsignature\n\t};\n}\n/** The one signing core both auth forms share: check the access key, rebuild the canonical request, derive the key, compare in constant time. */\nfunction verifySignature(req, url, credentials, params) {\n\tif (params.scope.accessKeyId !== credentials.accessKeyId) return {\n\t\tok: false,\n\t\treason: \"unknown access key\"\n\t};\n\tconst canonicalRequest = [\n\t\treq.method,\n\t\turl.pathname,\n\t\tcanonicalQuery(url, params.excludeQuery),\n\t\tcanonicalHeaders(url, req, params.signedHeaders),\n\t\tparams.signedHeaders.join(\";\"),\n\t\tparams.payloadHash\n\t].join(\"\\n\");\n\treturn signatureMatches(hmac(signingKey(credentials.secretAccessKey, params.scope), stringToSign(params.amzDate, params.scope, canonicalRequest)).toString(\"hex\"), params.signature) ? { ok: true } : {\n\t\tok: false,\n\t\treason: \"signature mismatch\"\n\t};\n}\nfunction verifyHeader(req, url, credentials) {\n\tconst auth = parseAuthorizationHeader(req.headers.get(\"authorization\") ?? \"\");\n\tif (!auth) return {\n\t\tok: false,\n\t\treason: \"malformed Authorization header\"\n\t};\n\tconst scope = parseCredential(auth.credential);\n\tif (!scope) return {\n\t\tok: false,\n\t\treason: \"malformed credential scope\"\n\t};\n\tconst amzDate = req.headers.get(\"x-amz-date\");\n\tif (!amzDate) return {\n\t\tok: false,\n\t\treason: \"missing x-amz-date\"\n\t};\n\tconst payloadHash = req.headers.get(\"x-amz-content-sha256\");\n\tif (!payloadHash) return {\n\t\tok: false,\n\t\treason: \"missing x-amz-content-sha256\"\n\t};\n\treturn verifySignature(req, url, credentials, {\n\t\tscope,\n\t\tamzDate,\n\t\tsignedHeaders: auth.signedHeaders,\n\t\tpayloadHash,\n\t\tsignature: auth.signature\n\t});\n}\nfunction verifyPresigned(req, url, credentials, now) {\n\tconst q = url.searchParams;\n\tif (q.get(\"X-Amz-Algorithm\") !== ALGORITHM) return {\n\t\tok: false,\n\t\treason: \"unsupported presign algorithm\"\n\t};\n\tconst credentialRaw = q.get(\"X-Amz-Credential\");\n\tconst amzDate = q.get(\"X-Amz-Date\");\n\tconst expiresRaw = q.get(\"X-Amz-Expires\");\n\tconst signedHeadersRaw = q.get(\"X-Amz-SignedHeaders\");\n\tconst signature = q.get(\"X-Amz-Signature\");\n\tif (!credentialRaw || !amzDate || !expiresRaw || !signedHeadersRaw || !signature) return {\n\t\tok: false,\n\t\treason: \"incomplete presign parameters\"\n\t};\n\tconst scope = parseCredential(credentialRaw);\n\tif (!scope) return {\n\t\tok: false,\n\t\treason: \"malformed credential scope\"\n\t};\n\tconst signedAt = parseAmzDate(amzDate);\n\tconst expires = Number(expiresRaw);\n\tif (signedAt === null || !Number.isFinite(expires)) return {\n\t\tok: false,\n\t\treason: \"malformed presign date\"\n\t};\n\tif (now.getTime() > signedAt + expires * 1e3) return {\n\t\tok: false,\n\t\treason: \"presign expired\"\n\t};\n\treturn verifySignature(req, url, credentials, {\n\t\tscope,\n\t\tamzDate,\n\t\tsignedHeaders: signedHeadersRaw.split(\";\"),\n\t\tpayloadHash: UNSIGNED_PAYLOAD,\n\t\tsignature,\n\t\texcludeQuery: \"X-Amz-Signature\"\n\t});\n}\n/**\n* Verify a request's SigV4 signature against a single credential pair. Picks\n* the presigned form when `X-Amz-Signature` is present, otherwise the\n* `Authorization`-header form. `now` is injectable for deterministic\n* expiry tests.\n*/\nfunction verifyRequest(req, credentials, now = /* @__PURE__ */ new Date()) {\n\tconst url = new URL(req.url);\n\tif (url.searchParams.has(\"X-Amz-Signature\")) return verifyPresigned(req, url, credentials, now);\n\tif (req.headers.has(\"authorization\")) return verifyHeader(req, url, credentials);\n\treturn {\n\t\tok: false,\n\t\treason: \"unsigned request\"\n\t};\n}\n//#endregion\n//#region src/handler.ts\nconst DEFAULT_CONTENT_TYPE = \"application/octet-stream\";\n/** Path-style: `/{bucket}/{key…}`. Each segment is percent-decoded. */\nfunction parseTarget(url) {\n\tconst segments = url.pathname.split(\"/\").filter((s) => s.length > 0);\n\tif (segments.length === 0) return null;\n\tconst [bucket, ...keyParts] = segments;\n\treturn {\n\t\tbucket: decodeURIComponent(bucket ?? \"\"),\n\t\tkey: keyParts.map(decodeURIComponent).join(\"/\")\n\t};\n}\n/** `bytes=a-b` (inclusive) or `bytes=a-` (open-ended). Null when absent/malformed. */\nfunction parseRange(header) {\n\tif (!header) return null;\n\tconst match = /^bytes=(\\d+)-(\\d*)$/.exec(header.trim());\n\tif (!match) return null;\n\tconst start = Number(match[1]);\n\treturn match[2] ? {\n\t\tstart,\n\t\tend: Number(match[2])\n\t} : { start };\n}\nfunction xmlEscape(value) {\n\treturn value.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\").replace(/'/g, \"'\");\n}\nfunction listXml(bucket, prefix, maxKeys, result) {\n\tconst contents = result.keys.map((k) => `<Contents><Key>${xmlEscape(k)}</Key></Contents>`).join(\"\");\n\tconst next = result.isTruncated && result.nextContinuationToken !== void 0 ? `<NextContinuationToken>${xmlEscape(result.nextContinuationToken)}</NextContinuationToken>` : \"\";\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?><ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>${xmlEscape(bucket)}</Name><Prefix>${xmlEscape(prefix)}</Prefix><KeyCount>${result.keys.length}</KeyCount><MaxKeys>${maxKeys}</MaxKeys><IsTruncated>${result.isTruncated}</IsTruncated>` + contents + next + \"</ListBucketResult>\";\n}\nconst DEFAULT_MAX_KEYS$1 = 1e3;\nasync function handleList(store, bucket, url) {\n\tconst prefix = url.searchParams.get(\"prefix\") ?? \"\";\n\tconst continuationToken = url.searchParams.get(\"continuation-token\");\n\tconst maxKeysRaw = url.searchParams.get(\"max-keys\");\n\tconst maxKeys = maxKeysRaw !== null && Number.isFinite(Number(maxKeysRaw)) ? Number(maxKeysRaw) : DEFAULT_MAX_KEYS$1;\n\tconst result = await store.list(bucket, {\n\t\tprefix,\n\t\tmaxKeys,\n\t\t...continuationToken !== null ? { continuationToken } : {}\n\t});\n\treturn new Response(listXml(bucket, prefix, maxKeys, result), {\n\t\tstatus: 200,\n\t\theaders: { \"content-type\": \"application/xml\" }\n\t});\n}\n/** aws-chunked / flexible-checksum PUTs frame the body as chunks + a trailer (signalled by `x-amz-content-sha256: STREAMING-…` or `content-encoding: aws-chunked`); the seed signature still verifies, so reject them (501) rather than store the raw framing as the object bytes. Decoding is out of scope. */\nfunction isStreamingPut(req) {\n\tconst contentSha = req.headers.get(\"x-amz-content-sha256\") ?? \"\";\n\tconst contentEncoding = req.headers.get(\"content-encoding\") ?? \"\";\n\treturn contentSha.startsWith(\"STREAMING-\") || contentEncoding.split(\",\").some((e) => e.trim() === \"aws-chunked\");\n}\nasync function handlePut(store, t, req) {\n\tif (isStreamingPut(req)) return new Response(\"aws-chunked / flexible checksums not supported; set requestChecksumCalculation: 'WHEN_REQUIRED'\", { status: 501 });\n\tconst body = new Uint8Array(await req.arrayBuffer());\n\tconst contentType = req.headers.get(\"content-type\") ?? DEFAULT_CONTENT_TYPE;\n\tconst { etag } = await store.put(t.bucket, t.key, body, { contentType });\n\treturn new Response(null, {\n\t\tstatus: 200,\n\t\theaders: { etag }\n\t});\n}\n/** The etag/content-type/content-length/accept-ranges headers GET and HEAD share — `contentLength` is the slice length for GET, the total object size for HEAD. */\nfunction metaHeaders(meta) {\n\treturn new Headers({\n\t\tetag: meta.etag,\n\t\t\"content-type\": meta.contentType,\n\t\t\"content-length\": String(meta.contentLength),\n\t\t\"accept-ranges\": \"bytes\"\n\t});\n}\nasync function handleGet(store, t, req) {\n\tconst range = parseRange(req.headers.get(\"range\"));\n\tconst object = await store.get(t.bucket, t.key, range ? { range } : void 0);\n\tif (!object) return new Response(null, { status: 404 });\n\tconst headers = metaHeaders({\n\t\tetag: object.etag,\n\t\tcontentType: object.contentType,\n\t\tcontentLength: object.bytes.byteLength\n\t});\n\tif (!range) return new Response(object.bytes, {\n\t\tstatus: 200,\n\t\theaders\n\t});\n\tif (range.start >= object.size && object.size > 0) return new Response(null, {\n\t\tstatus: 416,\n\t\theaders: { \"content-range\": `bytes */${object.size}` }\n\t});\n\tconst end = range.end === void 0 ? object.size - 1 : Math.min(range.end, object.size - 1);\n\theaders.set(\"content-range\", `bytes ${range.start}-${end}/${object.size}`);\n\treturn new Response(object.bytes, {\n\t\tstatus: 206,\n\t\theaders\n\t});\n}\nasync function handleHead(store, t) {\n\tconst meta = await store.head(t.bucket, t.key);\n\tif (!meta) return new Response(null, { status: 404 });\n\treturn new Response(null, {\n\t\tstatus: 200,\n\t\theaders: metaHeaders({\n\t\t\tetag: meta.etag,\n\t\t\tcontentType: meta.contentType,\n\t\t\tcontentLength: meta.size\n\t\t})\n\t});\n}\nasync function handleDelete(store, t) {\n\tawait store.delete(t.bucket, t.key);\n\treturn new Response(null, { status: 204 });\n}\nfunction createS3Handler(opts) {\n\tconst { store, credentials } = opts;\n\treturn async (req) => {\n\t\tif (!verifyRequest(req, credentials).ok) return new Response(null, { status: 403 });\n\t\tconst url = new URL(req.url);\n\t\tconst target = parseTarget(url);\n\t\tif (!target) return new Response(null, { status: 400 });\n\t\tif (req.method === \"GET\" && url.searchParams.get(\"list-type\") === \"2\" && target.key === \"\") return handleList(store, target.bucket, url);\n\t\tif (target.key === \"\") return new Response(null, { status: 400 });\n\t\tswitch (req.method) {\n\t\t\tcase \"PUT\": return handlePut(store, target, req);\n\t\t\tcase \"GET\": return handleGet(store, target, req);\n\t\t\tcase \"HEAD\": return handleHead(store, target);\n\t\t\tcase \"DELETE\": return handleDelete(store, target);\n\t\t\tdefault: return new Response(null, { status: 405 });\n\t\t}\n\t};\n}\n//#endregion\n//#region src/memory-store.ts\n/**\n* An in-memory `ObjectStore` for the protocol tests — the same contract the\n* Postgres store (D3) implements. Test-only; never wired into a deployed\n* service. Not re-exported from the authoring barrel.\n*/\nconst DEFAULT_MAX_KEYS = 1e3;\nfunction etagOf(bytes) {\n\treturn `\"${createHash(\"sha256\").update(bytes).digest(\"hex\")}\"`;\n}\nvar MemoryObjectStore = class {\n\tentries = /* @__PURE__ */ new Map();\n\tid(bucket, key) {\n\t\treturn `${bucket}\\x00${key}`;\n\t}\n\tasync put(bucket, key, bytes, opts = {}) {\n\t\tconst copy = bytes.slice();\n\t\tconst etag = etagOf(copy);\n\t\tthis.entries.set(this.id(bucket, key), {\n\t\t\tbytes: copy,\n\t\t\tetag,\n\t\t\tcontentType: opts.contentType ?? \"application/octet-stream\"\n\t\t});\n\t\treturn { etag };\n\t}\n\tasync get(bucket, key, opts = {}) {\n\t\tconst entry = this.entries.get(this.id(bucket, key));\n\t\tif (!entry) return null;\n\t\tconst size = entry.bytes.byteLength;\n\t\tif (opts.range) {\n\t\t\tconst start = opts.range.start;\n\t\t\tconst end = opts.range.end === void 0 ? size - 1 : Math.min(opts.range.end, size - 1);\n\t\t\treturn {\n\t\t\t\tbytes: start > end ? /* @__PURE__ */ new Uint8Array(0) : entry.bytes.slice(start, end + 1),\n\t\t\t\tetag: entry.etag,\n\t\t\t\tcontentType: entry.contentType,\n\t\t\t\tsize\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tbytes: entry.bytes.slice(),\n\t\t\tetag: entry.etag,\n\t\t\tcontentType: entry.contentType,\n\t\t\tsize\n\t\t};\n\t}\n\tasync head(bucket, key) {\n\t\tconst entry = this.entries.get(this.id(bucket, key));\n\t\tif (!entry) return null;\n\t\treturn {\n\t\t\tetag: entry.etag,\n\t\t\tsize: entry.bytes.byteLength,\n\t\t\tcontentType: entry.contentType\n\t\t};\n\t}\n\tasync delete(bucket, key) {\n\t\tthis.entries.delete(this.id(bucket, key));\n\t}\n\tasync list(bucket, opts = {}) {\n\t\tconst prefix = opts.prefix ?? \"\";\n\t\tconst maxKeys = opts.maxKeys ?? DEFAULT_MAX_KEYS;\n\t\tconst token = opts.continuationToken;\n\t\tconst prefixHit = `${bucket}\\x00${prefix}`;\n\t\tconst matching = [...this.entries.keys()].filter((id) => id.startsWith(prefixHit)).map((id) => id.slice(bucket.length + 1)).sort().filter((key) => token === void 0 ? true : key > token);\n\t\tconst page = matching.slice(0, maxKeys);\n\t\tconst isTruncated = matching.length > maxKeys;\n\t\tconst last = page.at(-1);\n\t\treturn {\n\t\t\tkeys: page,\n\t\t\tisTruncated,\n\t\t\t...isTruncated && last !== void 0 ? { nextContinuationToken: last } : {}\n\t\t};\n\t}\n};\n//#endregion\nexport { MemoryObjectStore, createS3Handler, fsStore, mintKeyPair, verifyRequest };\n\n//# sourceMappingURL=index.mjs.map","import { h as readJsonFile, m as StateFile, t as isValidSegment, u as readOwnVersion } from \"./segments-BW2SYdBf.mjs\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as http from \"node:http\";\nimport { createS3Handler, fsStore } from \"@internal/s3-protocol\";\n//#region src/buckets-main.ts\n/**\n* The bucket emulator daemon (local-dev spec § 2 `buckets-main.ts`): the S3\n* wire protocol (`@internal/s3-protocol`'s handler + `fsStore`) over\n* registered per-app, per-bucket directories, multi-tenant via physical\n* names `<app>--<name>`. Admin lives under `/_pcdev/` (the underscore can't\n* collide with a valid bucket name). Plain `node:http`.\n*\n* Runs as its own OS process, started by `daemon.ts`'s `ensureDaemon` via\n* `process.execPath <this file> --port <n> --state-dir <dir>`.\n*/\nconst STATE_MODE = 384;\nconst PHYSICAL_BUCKET_NAME_RE = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;\nconst MULTIPART_MESSAGE = \"multipart upload is not supported by the local dev bucket emulator yet\";\nfunction isBucketRegistration(value) {\n\treturn typeof value === \"object\" && value !== null && \"app\" in value && typeof value.app === \"string\" && \"name\" in value && typeof value.name === \"string\" && \"dir\" in value && typeof value.dir === \"string\";\n}\nfunction isCredentialRecord(value) {\n\treturn typeof value === \"object\" && value !== null && \"app\" in value && typeof value.app === \"string\" && \"secretAccessKey\" in value && typeof value.secretAccessKey === \"string\";\n}\nfunction isBucketsState(value) {\n\treturn typeof value === \"object\" && value !== null && \"buckets\" in value && typeof value.buckets === \"object\" && value.buckets !== null && Object.values(value.buckets).every(isBucketRegistration) && \"credentials\" in value && typeof value.credentials === \"object\" && value.credentials !== null && Object.values(value.credentials).every(isCredentialRecord);\n}\nfunction isBucketBody(value) {\n\treturn typeof value === \"object\" && value !== null && \"dir\" in value && typeof value.dir === \"string\";\n}\nfunction isCredentialsBody(value) {\n\treturn typeof value === \"object\" && value !== null && \"accessKeyId\" in value && typeof value.accessKeyId === \"string\" && \"secretAccessKey\" in value && typeof value.secretAccessKey === \"string\";\n}\nfunction parseArgs(argv) {\n\tlet port;\n\tlet stateDir;\n\tfor (let i = 0; i < argv.length; i++) if (argv[i] === \"--port\") port = Number(argv[i + 1]);\n\telse if (argv[i] === \"--state-dir\") stateDir = argv[i + 1];\n\tif (port === void 0 || Number.isNaN(port)) throw new Error(\"buckets-main: --port <n> is required\");\n\tif (stateDir === void 0) throw new Error(\"buckets-main: --state-dir <dir> is required\");\n\treturn {\n\t\tport,\n\t\tstateDir\n\t};\n}\nfunction readBody(req) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst chunks = [];\n\t\treq.on(\"data\", (chunk) => chunks.push(chunk));\n\t\treq.on(\"end\", () => resolve(Buffer.concat(chunks)));\n\t\treq.on(\"error\", reject);\n\t});\n}\nfunction toWebHeaders(nodeHeaders) {\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(nodeHeaders)) {\n\t\tif (value === void 0) continue;\n\t\tif (Array.isArray(value)) for (const v of value) headers.append(key, v);\n\t\telse headers.set(key, value);\n\t}\n\treturn headers;\n}\nasync function sendWebResponse(res, webRes) {\n\tconst headers = {};\n\twebRes.headers.forEach((value, key) => {\n\t\theaders[key] = value;\n\t});\n\tconst buf = Buffer.from(await webRes.arrayBuffer());\n\tres.writeHead(webRes.status, headers);\n\tres.end(buf);\n}\nfunction main() {\n\tconst { port, stateDir } = parseArgs(process.argv.slice(2));\n\tconst ownVersion = readOwnVersion();\n\tconst stateJsonPath = path.join(stateDir, \"state.json\");\n\tconst stateFile = new StateFile(stateJsonPath, STATE_MODE);\n\tlet state = {\n\t\tbuckets: {},\n\t\tcredentials: {}\n\t};\n\tconst store = fsStore((physicalName) => state.buckets[physicalName]?.dir);\n\tfunction json(res, status, body) {\n\t\tres.writeHead(status, { \"content-type\": \"application/json\" });\n\t\tres.end(JSON.stringify(body));\n\t}\n\tfunction text(res, status, body) {\n\t\tres.writeHead(status, { \"content-type\": \"text/plain; charset=utf-8\" });\n\t\tres.end(body);\n\t}\n\tfunction badSegment(res, segment) {\n\t\ttext(res, 400, `invalid path segment \"${segment}\": must match /^[a-z0-9][a-z0-9-]*$/ and be at most 63 characters`);\n\t}\n\tasync function handlePutBucket(req, res, app, name) {\n\t\tconst physicalName = `${app}--${name}`;\n\t\tif (!PHYSICAL_BUCKET_NAME_RE.test(physicalName)) return text(res, 400, `invalid bucket \"${physicalName}\" (app \"${app}\", name \"${name}\"): the physical bucket name must match /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/ and be at most 63 characters`);\n\t\tconst raw = await readBody(req);\n\t\tlet parsed;\n\t\ttry {\n\t\t\tparsed = JSON.parse(raw.toString(\"utf8\"));\n\t\t} catch {\n\t\t\treturn text(res, 400, \"malformed JSON body\");\n\t\t}\n\t\tif (!isBucketBody(parsed)) return text(res, 400, \"malformed bucket body: expected { \\\"dir\\\": string }\");\n\t\tawait fs.promises.mkdir(parsed.dir, { recursive: true });\n\t\tstate.buckets[physicalName] = {\n\t\t\tapp,\n\t\t\tname,\n\t\t\tdir: parsed.dir\n\t\t};\n\t\tawait stateFile.write(state);\n\t\tres.writeHead(204);\n\t\tres.end();\n\t}\n\tasync function handlePutCredentials(req, res, app) {\n\t\tconst raw = await readBody(req);\n\t\tlet parsed;\n\t\ttry {\n\t\t\tparsed = JSON.parse(raw.toString(\"utf8\"));\n\t\t} catch {\n\t\t\treturn text(res, 400, \"malformed JSON body\");\n\t\t}\n\t\tif (!isCredentialsBody(parsed)) return text(res, 400, \"malformed credentials body: expected { \\\"accessKeyId\\\", \\\"secretAccessKey\\\" }\");\n\t\tconst existing = state.credentials[parsed.accessKeyId];\n\t\tif (existing && existing.app !== app) return text(res, 409, `accessKeyId \"${parsed.accessKeyId}\" is already registered by a different app`);\n\t\tstate.credentials[parsed.accessKeyId] = {\n\t\t\tapp,\n\t\t\tsecretAccessKey: parsed.secretAccessKey\n\t\t};\n\t\tawait stateFile.write(state);\n\t\tres.writeHead(204);\n\t\tres.end();\n\t}\n\tasync function handleDeleteApp(res, app) {\n\t\tfor (const [key, reg] of Object.entries(state.buckets)) if (reg.app === app) delete state.buckets[key];\n\t\tfor (const [key, cred] of Object.entries(state.credentials)) if (cred.app === app) delete state.credentials[key];\n\t\tawait stateFile.write(state);\n\t\tres.writeHead(204);\n\t\tres.end();\n\t}\n\t/** Path-style addressing: the bucket is the first non-empty path segment. Mirrors the handler's own `parseTarget`, which isn't exported. */\n\tfunction bucketFromPath(pathname) {\n\t\tconst first = pathname.split(\"/\").find((s) => s.length > 0);\n\t\treturn first !== void 0 ? decodeURIComponent(first) : void 0;\n\t}\n\t/**\n\t* Credentials accepted for THIS request's target bucket only — its\n\t* owning app, derived from the bucket's registration (the authoritative\n\t* source for the `<app>--<name>` split; unregistered apps/names may\n\t* themselves contain `--`, so the registration is trusted over re-parsing\n\t* the string). An unknown bucket or an app with no registered credentials\n\t* yields no candidates, which still resolves through the real 403 path\n\t* below — never a bespoke \"unknown bucket\" shortcut that would reveal\n\t* anything.\n\t*/\n\tfunction credentialsForBucket(bucket) {\n\t\tconst owningApp = bucket !== void 0 ? state.buckets[bucket]?.app : void 0;\n\t\tif (owningApp === void 0) return [];\n\t\treturn Object.entries(state.credentials).filter(([, rec]) => rec.app === owningApp).map(([accessKeyId, rec]) => ({\n\t\t\taccessKeyId,\n\t\t\tsecretAccessKey: rec.secretAccessKey\n\t\t}));\n\t}\n\tasync function handleS3Wire(req, res, url) {\n\t\tif (url.searchParams.has(\"uploads\") || url.searchParams.has(\"uploadId\") || url.searchParams.has(\"partNumber\")) return text(res, 501, MULTIPART_MESSAGE);\n\t\tconst method = req.method ?? \"GET\";\n\t\tconst bodyBuf = method !== \"GET\" && method !== \"HEAD\" ? await readBody(req) : void 0;\n\t\tconst fullUrl = `http://${req.headers.host ?? `127.0.0.1:${String(port)}`}${req.url ?? \"/\"}`;\n\t\tconst headers = toWebHeaders(req.headers);\n\t\tconst candidates = credentialsForBucket(bucketFromPath(url.pathname));\n\t\tif (candidates.length === 0) candidates.push({\n\t\t\taccessKeyId: \"\",\n\t\t\tsecretAccessKey: \"\"\n\t\t});\n\t\tlet last;\n\t\tfor (const credentials of candidates) {\n\t\t\tconst webReq = new Request(fullUrl, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\t...bodyBuf && bodyBuf.length > 0 ? { body: bodyBuf } : {}\n\t\t\t});\n\t\t\tconst webRes = await createS3Handler({\n\t\t\t\tstore,\n\t\t\t\tcredentials\n\t\t\t})(webReq);\n\t\t\tif (webRes.status !== 403) return sendWebResponse(res, webRes);\n\t\t\tlast = webRes;\n\t\t}\n\t\tif (last) await sendWebResponse(res, last);\n\t}\n\tasync function handleRequest(req, res) {\n\t\tconst url = new URL(req.url ?? \"/\", `http://127.0.0.1:${String(port)}`);\n\t\tconst method = req.method ?? \"GET\";\n\t\tif (method === \"GET\" && url.pathname === \"/health\") return json(res, 200, { version: ownVersion });\n\t\tif (url.pathname === \"/_pcdev/health\" || url.pathname.startsWith(\"/_pcdev/\")) {\n\t\t\tconst segments = url.pathname.split(\"/\").filter((s) => s.length > 0).map((s) => decodeURIComponent(s));\n\t\t\tif (method === \"GET\" && segments.length === 2 && segments[1] === \"health\") return json(res, 200, { version: ownVersion });\n\t\t\tif (segments[1] === \"apps\" && segments.length >= 3) {\n\t\t\t\tconst app = segments[2];\n\t\t\t\tif (app === void 0 || !isValidSegment(app)) return badSegment(res, app ?? \"\");\n\t\t\t\tif (method === \"PUT\" && segments.length === 5 && segments[3] === \"buckets\") {\n\t\t\t\t\tconst name = segments[4];\n\t\t\t\t\tif (name === void 0 || !isValidSegment(name)) return badSegment(res, name ?? \"\");\n\t\t\t\t\treturn handlePutBucket(req, res, app, name);\n\t\t\t\t}\n\t\t\t\tif (method === \"PUT\" && segments.length === 4 && segments[3] === \"credentials\") return handlePutCredentials(req, res, app);\n\t\t\t\tif (method === \"DELETE\" && segments.length === 3) return handleDeleteApp(res, app);\n\t\t\t}\n\t\t\tres.writeHead(404);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\treturn handleS3Wire(req, res, url);\n\t}\n\tconst server = http.createServer((req, res) => {\n\t\thandleRequest(req, res).catch((err) => {\n\t\t\tif (!res.headersSent) res.writeHead(500, { \"content-type\": \"text/plain\" });\n\t\t\tres.end(err instanceof Error ? err.message : String(err));\n\t\t});\n\t});\n\tasync function shutdown() {\n\t\tawait stateFile.flush();\n\t\tserver.close();\n\t\tprocess.exit(0);\n\t}\n\tprocess.on(\"SIGTERM\", () => void shutdown());\n\tprocess.on(\"SIGINT\", () => void shutdown());\n\treadJsonFile(stateJsonPath, isBucketsState).then((loaded) => {\n\t\tif (loaded) state = loaded;\n\t\tserver.listen(port, \"127.0.0.1\", () => {\n\t\t\tconsole.log(`[dev-emulators] buckets-main listening on 127.0.0.1:${String(port)}`);\n\t\t});\n\t}).catch((err) => {\n\t\tconsole.error(\"buckets-main: failed to load state\", err);\n\t\tprocess.exit(1);\n\t});\n}\nmain();\n//#endregion\nexport {};\n\n//# sourceMappingURL=buckets-main.mjs.map"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"buckets-main.mjs","names":["fs"],"sources":["../../../1-prisma-cloud/0-lowering/s3-protocol/dist/index.mjs","../../../1-prisma-cloud/0-lowering/dev-emulators/dist/buckets-main.mjs"],"sourcesContent":["import { createHash, createHmac, randomUUID, timingSafeEqual } from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nconst DEFAULT_CONTENT_TYPE$1 = \"application/octet-stream\";\nconst TMP_DIR_NAME = \".tmp\";\nconst META_DIR_NAME = \".meta\";\nconst RESERVED_SEGMENTS = /* @__PURE__ */ new Set([TMP_DIR_NAME, META_DIR_NAME]);\nconst BUCKET_NAME_RE = /^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$/;\nfunction etagOf$1(bytes) {\n\treturn `\"${createHash(\"sha256\").update(bytes).digest(\"hex\")}\"`;\n}\nfunction isErrnoException(err) {\n\treturn err instanceof Error && \"code\" in err;\n}\nfunction isEnoent(err) {\n\treturn isErrnoException(err) && err.code === \"ENOENT\";\n}\n/**\n* Splits a key into its `/` segments, rejecting anything that could escape\n* the bucket dir or collide with the reserved `.tmp`/`.meta` namespaces:\n* `..` segments, an empty segment (leading/trailing/doubled `/`, which also\n* catches a leading-slash \"absolute\" key), or a segment literally `.tmp` or\n* `.meta` at any depth.\n*/\nfunction keySegments(key) {\n\tconst segments = key.split(\"/\");\n\tfor (const segment of segments) if (segment === \"\" || segment === \".\" || segment === \"..\" || RESERVED_SEGMENTS.has(segment)) throw new Error(`invalid object key: \"${key}\"`);\n\treturn segments;\n}\n/** `<bucketDir>/<key's segments>`, double-checked to still resolve inside `bucketDir`. */\nfunction objectPath(bucketDir, key) {\n\tconst target = path.join(bucketDir, ...keySegments(key));\n\tconst resolvedRoot = path.resolve(bucketDir) + path.sep;\n\tif (!(path.resolve(target) + path.sep).startsWith(resolvedRoot)) throw new Error(`invalid object key: \"${key}\"`);\n\treturn target;\n}\n/** `<bucketDir>/.meta/<key's segments>.json` — mirrors `objectPath`'s tree under `.meta`. */\nfunction sidecarPath(bucketDir, key) {\n\tconst segments = keySegments(key);\n\tconst last = segments[segments.length - 1];\n\tconst dirs = segments.slice(0, -1);\n\treturn path.join(bucketDir, META_DIR_NAME, ...dirs, `${last}.json`);\n}\n/** Write-temp-then-rename: never leaves a reader observing a partial file. */\nasync function writeAtomic(finalPath, tmpRoot, bytes) {\n\tawait fs.mkdir(tmpRoot, { recursive: true });\n\tconst tmpPath = path.join(tmpRoot, randomUUID());\n\tawait fs.writeFile(tmpPath, bytes);\n\tawait fs.mkdir(path.dirname(finalPath), { recursive: true });\n\tawait fs.rename(tmpPath, finalPath);\n}\nfunction isSidecar(value) {\n\treturn typeof value === \"object\" && value !== null && \"contentType\" in value && typeof value.contentType === \"string\" && \"etag\" in value && typeof value.etag === \"string\";\n}\nasync function readSidecar(sidecar) {\n\tlet raw;\n\ttry {\n\t\traw = await fs.readFile(sidecar, \"utf8\");\n\t} catch (err) {\n\t\tif (isEnoent(err)) return null;\n\t\tthrow err;\n\t}\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\tif (isSidecar(parsed)) return parsed;\n\t} catch {}\n\treturn null;\n}\n/** Read the object's bytes plus its metadata — adopting a sidecar-less file (dropped in by a developer) by computing and lazily persisting one. `null` when the object is missing. */\nasync function readObject(bucketDir, key) {\n\tconst target = objectPath(bucketDir, key);\n\tlet bytes;\n\ttry {\n\t\tbytes = await fs.readFile(target);\n\t} catch (err) {\n\t\tif (isEnoent(err)) return null;\n\t\tthrow err;\n\t}\n\tconst existing = await readSidecar(sidecarPath(bucketDir, key));\n\tif (existing) return {\n\t\tbytes,\n\t\tmeta: existing\n\t};\n\tconst meta = {\n\t\tcontentType: DEFAULT_CONTENT_TYPE$1,\n\t\tetag: etagOf$1(bytes)\n\t};\n\tawait writeAtomic(sidecarPath(bucketDir, key), path.join(bucketDir, TMP_DIR_NAME), Buffer.from(JSON.stringify(meta)));\n\treturn {\n\t\tbytes,\n\t\tmeta\n\t};\n}\n/** Remove now-empty directories from `startDir` up to (never including) `root`. */\nasync function pruneEmptyDirs(root, startDir) {\n\tconst resolvedRoot = path.resolve(root);\n\tlet dir = path.resolve(startDir);\n\twhile (dir !== resolvedRoot && dir.startsWith(resolvedRoot + path.sep)) {\n\t\tlet entries;\n\t\ttry {\n\t\t\tentries = await fs.readdir(dir);\n\t\t} catch (err) {\n\t\t\tif (isEnoent(err)) {\n\t\t\t\tdir = path.dirname(dir);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t\tif (entries.length > 0) break;\n\t\ttry {\n\t\t\tawait fs.rmdir(dir);\n\t\t} catch (err) {\n\t\t\tif (!isEnoent(err)) throw err;\n\t\t}\n\t\tdir = path.dirname(dir);\n\t}\n}\n/** Recursively lists every object key under `dir`, skipping `.tmp`/`.meta` at any depth. */\nasync function walkKeys(dir) {\n\tconst keys = [];\n\tasync function walk(current, prefix) {\n\t\tlet entries;\n\t\ttry {\n\t\t\tentries = await fs.readdir(current, { withFileTypes: true });\n\t\t} catch (err) {\n\t\t\tif (isEnoent(err)) return;\n\t\t\tthrow err;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (RESERVED_SEGMENTS.has(entry.name)) continue;\n\t\t\tconst rel = prefix === \"\" ? entry.name : `${prefix}/${entry.name}`;\n\t\t\tif (entry.isDirectory()) await walk(path.join(current, entry.name), rel);\n\t\t\telse if (entry.isFile()) keys.push(rel);\n\t\t}\n\t}\n\tawait walk(dir, \"\");\n\treturn keys;\n}\n/**\n* A disk-backed `ObjectStore`: object bytes and a metadata sidecar under a\n* per-bucket directory the caller resolves. See the module doc for the\n* unknown-bucket / invalid-key failure shapes.\n*/\nfunction fsStore(resolveBucketDir) {\n\tfunction resolveDir(bucket) {\n\t\tif (!BUCKET_NAME_RE.test(bucket)) return void 0;\n\t\treturn resolveBucketDir(bucket);\n\t}\n\treturn {\n\t\tasync put(bucket, key, bytes, opts = {}) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) throw new Error(`no such bucket: \"${bucket}\"`);\n\t\t\tconst target = objectPath(dir, key);\n\t\t\tconst tmpRoot = path.join(dir, TMP_DIR_NAME);\n\t\t\tconst etag = etagOf$1(bytes);\n\t\t\tconst contentType = opts.contentType ?? DEFAULT_CONTENT_TYPE$1;\n\t\t\tawait writeAtomic(target, tmpRoot, bytes);\n\t\t\tawait writeAtomic(sidecarPath(dir, key), tmpRoot, Buffer.from(JSON.stringify({\n\t\t\t\tcontentType,\n\t\t\t\tetag\n\t\t\t})));\n\t\t\treturn { etag };\n\t\t},\n\t\tasync get(bucket, key, opts = {}) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return null;\n\t\t\tconst found = await readObject(dir, key);\n\t\t\tif (!found) return null;\n\t\t\tconst { bytes, meta } = found;\n\t\t\tconst size = bytes.byteLength;\n\t\t\tif (opts.range) {\n\t\t\t\tconst start = opts.range.start;\n\t\t\t\tconst end = opts.range.end === void 0 ? size - 1 : Math.min(opts.range.end, size - 1);\n\t\t\t\treturn {\n\t\t\t\t\tbytes: start > end ? /* @__PURE__ */ new Uint8Array(0) : bytes.subarray(start, end + 1),\n\t\t\t\t\tetag: meta.etag,\n\t\t\t\t\tcontentType: meta.contentType,\n\t\t\t\t\tsize\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbytes: new Uint8Array(bytes),\n\t\t\t\tetag: meta.etag,\n\t\t\t\tcontentType: meta.contentType,\n\t\t\t\tsize\n\t\t\t};\n\t\t},\n\t\tasync head(bucket, key) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return null;\n\t\t\tconst found = await readObject(dir, key);\n\t\t\tif (!found) return null;\n\t\t\treturn {\n\t\t\t\tetag: found.meta.etag,\n\t\t\t\tsize: found.bytes.byteLength,\n\t\t\t\tcontentType: found.meta.contentType\n\t\t\t};\n\t\t},\n\t\tasync delete(bucket, key) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return;\n\t\t\tconst target = objectPath(dir, key);\n\t\t\tconst sidecar = sidecarPath(dir, key);\n\t\t\ttry {\n\t\t\t\tawait fs.unlink(target);\n\t\t\t} catch (err) {\n\t\t\t\tif (!isEnoent(err)) throw err;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait fs.unlink(sidecar);\n\t\t\t} catch (err) {\n\t\t\t\tif (!isEnoent(err)) throw err;\n\t\t\t}\n\t\t\tawait pruneEmptyDirs(dir, path.dirname(target));\n\t\t\tawait pruneEmptyDirs(path.join(dir, META_DIR_NAME), path.dirname(sidecar));\n\t\t},\n\t\tasync list(bucket, opts = {}) {\n\t\t\tconst dir = resolveDir(bucket);\n\t\t\tif (dir === void 0) return {\n\t\t\t\tkeys: [],\n\t\t\t\tisTruncated: false\n\t\t\t};\n\t\t\tconst prefix = opts.prefix ?? \"\";\n\t\t\tconst maxKeys = opts.maxKeys ?? 1e3;\n\t\t\tconst token = opts.continuationToken;\n\t\t\tconst matching = (await walkKeys(dir)).filter((key) => key.startsWith(prefix)).sort().filter((key) => token === void 0 ? true : key > token);\n\t\t\tconst page = matching.slice(0, maxKeys);\n\t\t\tconst isTruncated = matching.length > maxKeys;\n\t\t\tconst last = page.at(-1);\n\t\t\treturn {\n\t\t\t\tkeys: page,\n\t\t\t\tisTruncated,\n\t\t\t\t...isTruncated && last !== void 0 ? { nextContinuationToken: last } : {}\n\t\t\t};\n\t\t}\n\t};\n}\n//#endregion\n//#region src/sigv4.ts\n/**\n* AWS SigV4 verification for the S3 wire protocol (spec § 2 auth). The payload\n* hash comes from the client — `x-amz-content-sha256` (a real hash or\n* `UNSIGNED-PAYLOAD`) for header auth, `UNSIGNED-PAYLOAD` for presign — and is\n* never re-hashed; the verifier trusts what was signed, like a real S3 endpoint.\n* Runtime engine code (`node:crypto`); not re-exported from the authoring barrel.\n*\n* Also owns `mintKeyPair` (local-dev spec § 1) — the one key-pair generator\n* both the deploy-time `S3Credentials` resource and the local dev bucket\n* emulator's credential provisioning use.\n*/\nfunction randomBytes(n) {\n\treturn crypto.getRandomValues(new Uint8Array(n));\n}\nfunction toHexUpper(bytes) {\n\treturn Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\").toUpperCase();\n}\n/** A fresh SigV4 key pair: an AKIA-prefixed id and a 40-char base64 secret. */\nfunction mintKeyPair() {\n\treturn {\n\t\taccessKeyId: `AKIA${toHexUpper(randomBytes(8))}`,\n\t\tsecretAccessKey: btoa(String.fromCharCode(...randomBytes(30)))\n\t};\n}\nconst ALGORITHM = \"AWS4-HMAC-SHA256\";\nconst UNSIGNED_PAYLOAD = \"UNSIGNED-PAYLOAD\";\nfunction sha256Hex(data) {\n\treturn createHash(\"sha256\").update(data).digest(\"hex\");\n}\nfunction hmac(key, data) {\n\treturn createHmac(\"sha256\", key).update(data).digest();\n}\n/** AWS canonical URI encoding: every byte except the unreserved set is %XX. */\nfunction awsUriEncode(value) {\n\treturn encodeURIComponent(value).replace(/[!'()*]/g, (ch) => `%${ch.charCodeAt(0).toString(16).toUpperCase()}`).replace(/%7E/g, \"~\");\n}\nfunction parseCredential(credential) {\n\tconst parts = credential.split(\"/\");\n\tif (parts.length !== 5 || parts[4] !== \"aws4_request\") return null;\n\tconst [accessKeyId, date, region, service] = parts;\n\tif (!accessKeyId || !date || !region || !service) return null;\n\treturn {\n\t\taccessKeyId,\n\t\tdate,\n\t\tregion,\n\t\tservice\n\t};\n}\nfunction signingKey(secret, scope) {\n\treturn hmac(hmac(hmac(hmac(`AWS4${secret}`, scope.date), scope.region), scope.service), \"aws4_request\");\n}\nfunction canonicalHeaders(url, req, signedHeaders) {\n\treturn signedHeaders.map((name) => {\n\t\treturn `${name}:${(name === \"host\" ? url.host : req.headers.get(name) ?? \"\").trim().replace(/\\s+/g, \" \")}\\n`;\n\t}).join(\"\");\n}\nfunction canonicalQuery(url, exclude) {\n\tconst entries = [];\n\tfor (const [key, value] of url.searchParams.entries()) {\n\t\tif (exclude !== void 0 && key === exclude) continue;\n\t\tentries.push([awsUriEncode(key), awsUriEncode(value)]);\n\t}\n\tconst cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n\tentries.sort(([ak, av], [bk, bv]) => cmp(ak, bk) || cmp(av, bv));\n\treturn entries.map(([k, v]) => `${k}=${v}`).join(\"&\");\n}\nfunction stringToSign(amzDate, scope, canonicalRequest) {\n\tconst scopeString = `${scope.date}/${scope.region}/${scope.service}/aws4_request`;\n\treturn [\n\t\tALGORITHM,\n\t\tamzDate,\n\t\tscopeString,\n\t\tsha256Hex(canonicalRequest)\n\t].join(\"\\n\");\n}\nfunction signatureMatches(expected, provided) {\n\tconst a = Buffer.from(expected, \"hex\");\n\tconst b = Buffer.from(provided, \"hex\");\n\treturn a.length === b.length && a.length > 0 && timingSafeEqual(a, b);\n}\n/** `YYYYMMDDTHHMMSSZ` → epoch ms, or null when malformed. */\nfunction parseAmzDate(amzDate) {\n\tconst match = /^(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})Z$/.exec(amzDate);\n\tif (!match) return null;\n\tconst [, y, mo, d, h, mi, s] = match;\n\treturn Date.UTC(Number(y), Number(mo) - 1, Number(d), Number(h), Number(mi), Number(s));\n}\nfunction parseAuthorizationHeader(header) {\n\tif (!header.startsWith(`${ALGORITHM} `)) return null;\n\tconst rest = header.slice(17);\n\tconst fields = /* @__PURE__ */ new Map();\n\tfor (const part of rest.split(\",\")) {\n\t\tconst eq = part.indexOf(\"=\");\n\t\tif (eq === -1) continue;\n\t\tfields.set(part.slice(0, eq).trim(), part.slice(eq + 1).trim());\n\t}\n\tconst credential = fields.get(\"Credential\");\n\tconst signedHeaders = fields.get(\"SignedHeaders\");\n\tconst signature = fields.get(\"Signature\");\n\tif (!credential || !signedHeaders || !signature) return null;\n\treturn {\n\t\tcredential,\n\t\tsignedHeaders: signedHeaders.split(\";\"),\n\t\tsignature\n\t};\n}\n/** The one signing core both auth forms share: check the access key, rebuild the canonical request, derive the key, compare in constant time. */\nfunction verifySignature(req, url, credentials, params) {\n\tif (params.scope.accessKeyId !== credentials.accessKeyId) return {\n\t\tok: false,\n\t\treason: \"unknown access key\"\n\t};\n\tconst canonicalRequest = [\n\t\treq.method,\n\t\turl.pathname,\n\t\tcanonicalQuery(url, params.excludeQuery),\n\t\tcanonicalHeaders(url, req, params.signedHeaders),\n\t\tparams.signedHeaders.join(\";\"),\n\t\tparams.payloadHash\n\t].join(\"\\n\");\n\treturn signatureMatches(hmac(signingKey(credentials.secretAccessKey, params.scope), stringToSign(params.amzDate, params.scope, canonicalRequest)).toString(\"hex\"), params.signature) ? { ok: true } : {\n\t\tok: false,\n\t\treason: \"signature mismatch\"\n\t};\n}\nfunction verifyHeader(req, url, credentials) {\n\tconst auth = parseAuthorizationHeader(req.headers.get(\"authorization\") ?? \"\");\n\tif (!auth) return {\n\t\tok: false,\n\t\treason: \"malformed Authorization header\"\n\t};\n\tconst scope = parseCredential(auth.credential);\n\tif (!scope) return {\n\t\tok: false,\n\t\treason: \"malformed credential scope\"\n\t};\n\tconst amzDate = req.headers.get(\"x-amz-date\");\n\tif (!amzDate) return {\n\t\tok: false,\n\t\treason: \"missing x-amz-date\"\n\t};\n\tconst payloadHash = req.headers.get(\"x-amz-content-sha256\");\n\tif (!payloadHash) return {\n\t\tok: false,\n\t\treason: \"missing x-amz-content-sha256\"\n\t};\n\treturn verifySignature(req, url, credentials, {\n\t\tscope,\n\t\tamzDate,\n\t\tsignedHeaders: auth.signedHeaders,\n\t\tpayloadHash,\n\t\tsignature: auth.signature\n\t});\n}\nfunction verifyPresigned(req, url, credentials, now) {\n\tconst q = url.searchParams;\n\tif (q.get(\"X-Amz-Algorithm\") !== ALGORITHM) return {\n\t\tok: false,\n\t\treason: \"unsupported presign algorithm\"\n\t};\n\tconst credentialRaw = q.get(\"X-Amz-Credential\");\n\tconst amzDate = q.get(\"X-Amz-Date\");\n\tconst expiresRaw = q.get(\"X-Amz-Expires\");\n\tconst signedHeadersRaw = q.get(\"X-Amz-SignedHeaders\");\n\tconst signature = q.get(\"X-Amz-Signature\");\n\tif (!credentialRaw || !amzDate || !expiresRaw || !signedHeadersRaw || !signature) return {\n\t\tok: false,\n\t\treason: \"incomplete presign parameters\"\n\t};\n\tconst scope = parseCredential(credentialRaw);\n\tif (!scope) return {\n\t\tok: false,\n\t\treason: \"malformed credential scope\"\n\t};\n\tconst signedAt = parseAmzDate(amzDate);\n\tconst expires = Number(expiresRaw);\n\tif (signedAt === null || !Number.isFinite(expires)) return {\n\t\tok: false,\n\t\treason: \"malformed presign date\"\n\t};\n\tif (now.getTime() > signedAt + expires * 1e3) return {\n\t\tok: false,\n\t\treason: \"presign expired\"\n\t};\n\treturn verifySignature(req, url, credentials, {\n\t\tscope,\n\t\tamzDate,\n\t\tsignedHeaders: signedHeadersRaw.split(\";\"),\n\t\tpayloadHash: UNSIGNED_PAYLOAD,\n\t\tsignature,\n\t\texcludeQuery: \"X-Amz-Signature\"\n\t});\n}\n/**\n* Verify a request's SigV4 signature against a single credential pair. Picks\n* the presigned form when `X-Amz-Signature` is present, otherwise the\n* `Authorization`-header form. `now` is injectable for deterministic\n* expiry tests.\n*/\nfunction verifyRequest(req, credentials, now = /* @__PURE__ */ new Date()) {\n\tconst url = new URL(req.url);\n\tif (url.searchParams.has(\"X-Amz-Signature\")) return verifyPresigned(req, url, credentials, now);\n\tif (req.headers.has(\"authorization\")) return verifyHeader(req, url, credentials);\n\treturn {\n\t\tok: false,\n\t\treason: \"unsigned request\"\n\t};\n}\n//#endregion\n//#region src/handler.ts\nconst DEFAULT_CONTENT_TYPE = \"application/octet-stream\";\n/** Path-style: `/{bucket}/{key…}`. Each segment is percent-decoded. */\nfunction parseTarget(url) {\n\tconst segments = url.pathname.split(\"/\").filter((s) => s.length > 0);\n\tif (segments.length === 0) return null;\n\tconst [bucket, ...keyParts] = segments;\n\treturn {\n\t\tbucket: decodeURIComponent(bucket ?? \"\"),\n\t\tkey: keyParts.map(decodeURIComponent).join(\"/\")\n\t};\n}\n/** `bytes=a-b` (inclusive) or `bytes=a-` (open-ended). Null when absent/malformed. */\nfunction parseRange(header) {\n\tif (!header) return null;\n\tconst match = /^bytes=(\\d+)-(\\d*)$/.exec(header.trim());\n\tif (!match) return null;\n\tconst start = Number(match[1]);\n\treturn match[2] ? {\n\t\tstart,\n\t\tend: Number(match[2])\n\t} : { start };\n}\nfunction xmlEscape(value) {\n\treturn value.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\").replace(/'/g, \"'\");\n}\nfunction listXml(bucket, prefix, maxKeys, result) {\n\tconst contents = result.keys.map((k) => `<Contents><Key>${xmlEscape(k)}</Key></Contents>`).join(\"\");\n\tconst next = result.isTruncated && result.nextContinuationToken !== void 0 ? `<NextContinuationToken>${xmlEscape(result.nextContinuationToken)}</NextContinuationToken>` : \"\";\n\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?><ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>${xmlEscape(bucket)}</Name><Prefix>${xmlEscape(prefix)}</Prefix><KeyCount>${result.keys.length}</KeyCount><MaxKeys>${maxKeys}</MaxKeys><IsTruncated>${result.isTruncated}</IsTruncated>` + contents + next + \"</ListBucketResult>\";\n}\nconst DEFAULT_MAX_KEYS$1 = 1e3;\nasync function handleList(store, bucket, url) {\n\tconst prefix = url.searchParams.get(\"prefix\") ?? \"\";\n\tconst continuationToken = url.searchParams.get(\"continuation-token\");\n\tconst maxKeysRaw = url.searchParams.get(\"max-keys\");\n\tconst maxKeys = maxKeysRaw !== null && Number.isFinite(Number(maxKeysRaw)) ? Number(maxKeysRaw) : DEFAULT_MAX_KEYS$1;\n\tconst result = await store.list(bucket, {\n\t\tprefix,\n\t\tmaxKeys,\n\t\t...continuationToken !== null ? { continuationToken } : {}\n\t});\n\treturn new Response(listXml(bucket, prefix, maxKeys, result), {\n\t\tstatus: 200,\n\t\theaders: { \"content-type\": \"application/xml\" }\n\t});\n}\n/** aws-chunked / flexible-checksum PUTs frame the body as chunks + a trailer (signalled by `x-amz-content-sha256: STREAMING-…` or `content-encoding: aws-chunked`); the seed signature still verifies, so reject them (501) rather than store the raw framing as the object bytes. Decoding is out of scope. */\nfunction isStreamingPut(req) {\n\tconst contentSha = req.headers.get(\"x-amz-content-sha256\") ?? \"\";\n\tconst contentEncoding = req.headers.get(\"content-encoding\") ?? \"\";\n\treturn contentSha.startsWith(\"STREAMING-\") || contentEncoding.split(\",\").some((e) => e.trim() === \"aws-chunked\");\n}\nasync function handlePut(store, t, req) {\n\tif (isStreamingPut(req)) return new Response(\"aws-chunked / flexible checksums not supported; set requestChecksumCalculation: 'WHEN_REQUIRED'\", { status: 501 });\n\tconst body = new Uint8Array(await req.arrayBuffer());\n\tconst contentType = req.headers.get(\"content-type\") ?? DEFAULT_CONTENT_TYPE;\n\tconst { etag } = await store.put(t.bucket, t.key, body, { contentType });\n\treturn new Response(null, {\n\t\tstatus: 200,\n\t\theaders: { etag }\n\t});\n}\n/** The etag/content-type/content-length/accept-ranges headers GET and HEAD share — `contentLength` is the slice length for GET, the total object size for HEAD. */\nfunction metaHeaders(meta) {\n\treturn new Headers({\n\t\tetag: meta.etag,\n\t\t\"content-type\": meta.contentType,\n\t\t\"content-length\": String(meta.contentLength),\n\t\t\"accept-ranges\": \"bytes\"\n\t});\n}\nasync function handleGet(store, t, req) {\n\tconst range = parseRange(req.headers.get(\"range\"));\n\tconst object = await store.get(t.bucket, t.key, range ? { range } : void 0);\n\tif (!object) return new Response(null, { status: 404 });\n\tconst headers = metaHeaders({\n\t\tetag: object.etag,\n\t\tcontentType: object.contentType,\n\t\tcontentLength: object.bytes.byteLength\n\t});\n\tif (!range) return new Response(object.bytes, {\n\t\tstatus: 200,\n\t\theaders\n\t});\n\tif (range.start >= object.size && object.size > 0) return new Response(null, {\n\t\tstatus: 416,\n\t\theaders: { \"content-range\": `bytes */${object.size}` }\n\t});\n\tconst end = range.end === void 0 ? object.size - 1 : Math.min(range.end, object.size - 1);\n\theaders.set(\"content-range\", `bytes ${range.start}-${end}/${object.size}`);\n\treturn new Response(object.bytes, {\n\t\tstatus: 206,\n\t\theaders\n\t});\n}\nasync function handleHead(store, t) {\n\tconst meta = await store.head(t.bucket, t.key);\n\tif (!meta) return new Response(null, { status: 404 });\n\treturn new Response(null, {\n\t\tstatus: 200,\n\t\theaders: metaHeaders({\n\t\t\tetag: meta.etag,\n\t\t\tcontentType: meta.contentType,\n\t\t\tcontentLength: meta.size\n\t\t})\n\t});\n}\nasync function handleDelete(store, t) {\n\tawait store.delete(t.bucket, t.key);\n\treturn new Response(null, { status: 204 });\n}\nfunction createS3Handler(opts) {\n\tconst { store, credentials } = opts;\n\treturn async (req) => {\n\t\tif (!verifyRequest(req, credentials).ok) return new Response(null, { status: 403 });\n\t\tconst url = new URL(req.url);\n\t\tconst target = parseTarget(url);\n\t\tif (!target) return new Response(null, { status: 400 });\n\t\tif (req.method === \"GET\" && url.searchParams.get(\"list-type\") === \"2\" && target.key === \"\") return handleList(store, target.bucket, url);\n\t\tif (target.key === \"\") return new Response(null, { status: 400 });\n\t\tswitch (req.method) {\n\t\t\tcase \"PUT\": return handlePut(store, target, req);\n\t\t\tcase \"GET\": return handleGet(store, target, req);\n\t\t\tcase \"HEAD\": return handleHead(store, target);\n\t\t\tcase \"DELETE\": return handleDelete(store, target);\n\t\t\tdefault: return new Response(null, { status: 405 });\n\t\t}\n\t};\n}\n//#endregion\n//#region src/memory-store.ts\n/**\n* An in-memory `ObjectStore` for the protocol tests — the same contract the\n* Postgres store (D3) implements. Test-only; never wired into a deployed\n* service. Not re-exported from the authoring barrel.\n*/\nconst DEFAULT_MAX_KEYS = 1e3;\nfunction etagOf(bytes) {\n\treturn `\"${createHash(\"sha256\").update(bytes).digest(\"hex\")}\"`;\n}\nvar MemoryObjectStore = class {\n\tentries = /* @__PURE__ */ new Map();\n\tid(bucket, key) {\n\t\treturn `${bucket}\\x00${key}`;\n\t}\n\tasync put(bucket, key, bytes, opts = {}) {\n\t\tconst copy = bytes.slice();\n\t\tconst etag = etagOf(copy);\n\t\tthis.entries.set(this.id(bucket, key), {\n\t\t\tbytes: copy,\n\t\t\tetag,\n\t\t\tcontentType: opts.contentType ?? \"application/octet-stream\"\n\t\t});\n\t\treturn { etag };\n\t}\n\tasync get(bucket, key, opts = {}) {\n\t\tconst entry = this.entries.get(this.id(bucket, key));\n\t\tif (!entry) return null;\n\t\tconst size = entry.bytes.byteLength;\n\t\tif (opts.range) {\n\t\t\tconst start = opts.range.start;\n\t\t\tconst end = opts.range.end === void 0 ? size - 1 : Math.min(opts.range.end, size - 1);\n\t\t\treturn {\n\t\t\t\tbytes: start > end ? /* @__PURE__ */ new Uint8Array(0) : entry.bytes.slice(start, end + 1),\n\t\t\t\tetag: entry.etag,\n\t\t\t\tcontentType: entry.contentType,\n\t\t\t\tsize\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tbytes: entry.bytes.slice(),\n\t\t\tetag: entry.etag,\n\t\t\tcontentType: entry.contentType,\n\t\t\tsize\n\t\t};\n\t}\n\tasync head(bucket, key) {\n\t\tconst entry = this.entries.get(this.id(bucket, key));\n\t\tif (!entry) return null;\n\t\treturn {\n\t\t\tetag: entry.etag,\n\t\t\tsize: entry.bytes.byteLength,\n\t\t\tcontentType: entry.contentType\n\t\t};\n\t}\n\tasync delete(bucket, key) {\n\t\tthis.entries.delete(this.id(bucket, key));\n\t}\n\tasync list(bucket, opts = {}) {\n\t\tconst prefix = opts.prefix ?? \"\";\n\t\tconst maxKeys = opts.maxKeys ?? DEFAULT_MAX_KEYS;\n\t\tconst token = opts.continuationToken;\n\t\tconst prefixHit = `${bucket}\\x00${prefix}`;\n\t\tconst matching = [...this.entries.keys()].filter((id) => id.startsWith(prefixHit)).map((id) => id.slice(bucket.length + 1)).sort().filter((key) => token === void 0 ? true : key > token);\n\t\tconst page = matching.slice(0, maxKeys);\n\t\tconst isTruncated = matching.length > maxKeys;\n\t\tconst last = page.at(-1);\n\t\treturn {\n\t\t\tkeys: page,\n\t\t\tisTruncated,\n\t\t\t...isTruncated && last !== void 0 ? { nextContinuationToken: last } : {}\n\t\t};\n\t}\n};\n//#endregion\nexport { MemoryObjectStore, createS3Handler, fsStore, mintKeyPair, verifyRequest };\n\n//# sourceMappingURL=index.mjs.map","import { l as readOwnVersion, m as readJsonFile, p as StateFile } from \"./daemon-D9BV062Q.mjs\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport * as http from \"node:http\";\nimport { createS3Handler, fsStore } from \"@internal/s3-protocol\";\n//#region src/buckets-main.ts\n/**\n* The bucket emulator daemon (local-dev spec § 2 `buckets-main.ts`): the S3\n* wire protocol (`@internal/s3-protocol`'s handler + `fsStore`) over\n* registered bucket instances. Each instance is keyed by an id this daemon\n* generates, which is also its bucket name on the S3 wire; its objects live\n* in the data root its creator registers, a path stored verbatim and never\n* interpreted, as are its labels. Credentials are registered per instance.\n* Admin lives under `/_pcdev/` (the underscore can't collide with a valid\n* bucket name). Plain `node:http`.\n*\n* Runs as its own OS process, started by `daemon.ts`'s `ensureDaemon` via\n* `process.execPath <this file> --port <n> --state-dir <dir>`.\n*/\nconst STATE_MODE = 384;\nconst MULTIPART_MESSAGE = \"multipart upload is not supported by the local dev bucket emulator yet\";\n/** Also the bucket's name on the S3 wire, so it uses only characters a bucket name allows. */\nconst INSTANCE_ID_RE = /^bkt-[0-9a-f]{16}$/;\nfunction newInstanceId() {\n\treturn `bkt-${randomBytes(8).toString(\"hex\")}`;\n}\nfunction isStringRecord(value) {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value) && Object.values(value).every((v) => typeof v === \"string\");\n}\nfunction isBucketRecord(value) {\n\treturn typeof value === \"object\" && value !== null && \"id\" in value && typeof value.id === \"string\" && \"labels\" in value && isStringRecord(value.labels) && \"dir\" in value && typeof value.dir === \"string\";\n}\nfunction isCredentialRecord(value) {\n\treturn typeof value === \"object\" && value !== null && \"instanceId\" in value && typeof value.instanceId === \"string\" && \"secretAccessKey\" in value && typeof value.secretAccessKey === \"string\";\n}\nfunction isBucketsState(value) {\n\treturn typeof value === \"object\" && value !== null && \"instances\" in value && typeof value.instances === \"object\" && value.instances !== null && Object.values(value.instances).every(isBucketRecord) && \"credentials\" in value && typeof value.credentials === \"object\" && value.credentials !== null && Object.values(value.credentials).every(isCredentialRecord);\n}\nfunction isCreateBody(value) {\n\treturn typeof value === \"object\" && value !== null && \"labels\" in value && isStringRecord(value.labels) && \"dir\" in value && typeof value.dir === \"string\";\n}\nfunction isCredentialsBody(value) {\n\treturn typeof value === \"object\" && value !== null && \"accessKeyId\" in value && typeof value.accessKeyId === \"string\" && \"secretAccessKey\" in value && typeof value.secretAccessKey === \"string\";\n}\nfunction parseArgs(argv) {\n\tlet port;\n\tlet stateDir;\n\tfor (let i = 0; i < argv.length; i++) if (argv[i] === \"--port\") port = Number(argv[i + 1]);\n\telse if (argv[i] === \"--state-dir\") stateDir = argv[i + 1];\n\tif (port === void 0 || Number.isNaN(port)) throw new Error(\"buckets-main: --port <n> is required\");\n\tif (stateDir === void 0) throw new Error(\"buckets-main: --state-dir <dir> is required\");\n\treturn {\n\t\tport,\n\t\tstateDir\n\t};\n}\nfunction readBody(req) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst chunks = [];\n\t\treq.on(\"data\", (chunk) => chunks.push(chunk));\n\t\treq.on(\"end\", () => resolve(Buffer.concat(chunks)));\n\t\treq.on(\"error\", reject);\n\t});\n}\nfunction toWebHeaders(nodeHeaders) {\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(nodeHeaders)) {\n\t\tif (value === void 0) continue;\n\t\tif (Array.isArray(value)) for (const v of value) headers.append(key, v);\n\t\telse headers.set(key, value);\n\t}\n\treturn headers;\n}\nasync function sendWebResponse(res, webRes) {\n\tconst headers = {};\n\twebRes.headers.forEach((value, key) => {\n\t\theaders[key] = value;\n\t});\n\tconst buf = Buffer.from(await webRes.arrayBuffer());\n\tres.writeHead(webRes.status, headers);\n\tres.end(buf);\n}\nfunction main() {\n\tconst { port, stateDir } = parseArgs(process.argv.slice(2));\n\tconst ownVersion = readOwnVersion();\n\tconst statePath = path.join(stateDir, \"instances.json\");\n\tconst stateFile = new StateFile(statePath, STATE_MODE);\n\tlet state = {\n\t\tinstances: {},\n\t\tcredentials: {}\n\t};\n\tconst store = fsStore((bucket) => state.instances[bucket]?.dir);\n\tfunction json(res, status, body) {\n\t\tres.writeHead(status, { \"content-type\": \"application/json\" });\n\t\tres.end(JSON.stringify(body));\n\t}\n\tfunction text(res, status, body) {\n\t\tres.writeHead(status, { \"content-type\": \"text/plain; charset=utf-8\" });\n\t\tres.end(body);\n\t}\n\tfunction noContent(res) {\n\t\tres.writeHead(204);\n\t\tres.end();\n\t}\n\tasync function readJsonBody(req) {\n\t\tconst raw = await readBody(req);\n\t\ttry {\n\t\t\treturn JSON.parse(raw.toString(\"utf8\"));\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n\tfunction instanceView(bucket) {\n\t\treturn {\n\t\t\tid: bucket.id,\n\t\t\tlabels: bucket.labels,\n\t\t\tdir: bucket.dir\n\t\t};\n\t}\n\tasync function handleCreate(req, res) {\n\t\tconst body = await readJsonBody(req);\n\t\tif (!isCreateBody(body)) return text(res, 400, \"malformed body: expected { \\\"labels\\\": Record<string, string>, \\\"dir\\\": string }\");\n\t\tawait fs.promises.mkdir(body.dir, { recursive: true });\n\t\tconst id = newInstanceId();\n\t\tconst bucket = {\n\t\t\tid,\n\t\t\tlabels: { ...body.labels },\n\t\t\tdir: body.dir\n\t\t};\n\t\tstate.instances[id] = bucket;\n\t\tawait stateFile.write(state);\n\t\treturn json(res, 201, instanceView(bucket));\n\t}\n\tasync function handlePutCredentials(req, res, bucket) {\n\t\tconst body = await readJsonBody(req);\n\t\tif (!isCredentialsBody(body)) return text(res, 400, \"malformed credentials body: expected { \\\"accessKeyId\\\", \\\"secretAccessKey\\\" }\");\n\t\tconst existing = state.credentials[body.accessKeyId];\n\t\tif (existing && existing.instanceId !== bucket.id) return text(res, 409, `accessKeyId \"${body.accessKeyId}\" is already registered for another bucket`);\n\t\tstate.credentials[body.accessKeyId] = {\n\t\t\tinstanceId: bucket.id,\n\t\t\tsecretAccessKey: body.secretAccessKey\n\t\t};\n\t\tawait stateFile.write(state);\n\t\tnoContent(res);\n\t}\n\t/** Removes the bucket's registration and credentials; its objects stay where its creator put them. */\n\tasync function handleDelete(res, id) {\n\t\tdelete state.instances[id];\n\t\tfor (const [key, cred] of Object.entries(state.credentials)) if (cred.instanceId === id) delete state.credentials[key];\n\t\tawait stateFile.write(state);\n\t\tnoContent(res);\n\t}\n\t/** Path-style addressing: the bucket is the first non-empty path segment. Mirrors the handler's own `parseTarget`, which isn't exported. */\n\tfunction bucketFromPath(pathname) {\n\t\tconst first = pathname.split(\"/\").find((s) => s.length > 0);\n\t\treturn first !== void 0 ? decodeURIComponent(first) : void 0;\n\t}\n\t/**\n\t* Credentials accepted for THIS request's target bucket only. An unknown\n\t* bucket or one with no registered credentials yields no candidates, which\n\t* still resolves through the real 403 path below — never a bespoke\n\t* \"unknown bucket\" shortcut that would reveal anything.\n\t*/\n\tfunction credentialsForBucket(bucket) {\n\t\tif (bucket === void 0 || state.instances[bucket] === void 0) return [];\n\t\treturn Object.entries(state.credentials).filter(([, rec]) => rec.instanceId === bucket).map(([accessKeyId, rec]) => ({\n\t\t\taccessKeyId,\n\t\t\tsecretAccessKey: rec.secretAccessKey\n\t\t}));\n\t}\n\tasync function handleS3Wire(req, res, url) {\n\t\tif (url.searchParams.has(\"uploads\") || url.searchParams.has(\"uploadId\") || url.searchParams.has(\"partNumber\")) return text(res, 501, MULTIPART_MESSAGE);\n\t\tconst method = req.method ?? \"GET\";\n\t\tconst bodyBuf = method !== \"GET\" && method !== \"HEAD\" ? await readBody(req) : void 0;\n\t\tconst fullUrl = `http://${req.headers.host ?? `127.0.0.1:${String(port)}`}${req.url ?? \"/\"}`;\n\t\tconst headers = toWebHeaders(req.headers);\n\t\tconst candidates = credentialsForBucket(bucketFromPath(url.pathname));\n\t\tif (candidates.length === 0) candidates.push({\n\t\t\taccessKeyId: \"\",\n\t\t\tsecretAccessKey: \"\"\n\t\t});\n\t\tlet last;\n\t\tfor (const credentials of candidates) {\n\t\t\tconst webReq = new Request(fullUrl, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\t...bodyBuf && bodyBuf.length > 0 ? { body: bodyBuf } : {}\n\t\t\t});\n\t\t\tconst webRes = await createS3Handler({\n\t\t\t\tstore,\n\t\t\t\tcredentials\n\t\t\t})(webReq);\n\t\t\tif (webRes.status !== 403) return sendWebResponse(res, webRes);\n\t\t\tlast = webRes;\n\t\t}\n\t\tif (last) await sendWebResponse(res, last);\n\t}\n\tasync function handleAdmin(req, res, segments) {\n\t\tconst method = req.method ?? \"GET\";\n\t\tif (method === \"GET\" && segments.length === 2 && segments[1] === \"health\") return json(res, 200, { version: ownVersion });\n\t\tif (segments[1] !== \"instances\") {\n\t\t\tres.writeHead(404);\n\t\t\tres.end();\n\t\t\treturn;\n\t\t}\n\t\tif (segments.length === 2) {\n\t\t\tif (method === \"GET\") return json(res, 200, Object.values(state.instances).map(instanceView));\n\t\t\tif (method === \"POST\") return handleCreate(req, res);\n\t\t}\n\t\tconst id = segments[2];\n\t\tif (id !== void 0 && !INSTANCE_ID_RE.test(id)) return text(res, 400, `invalid instance id \"${id}\"`);\n\t\tif (method === \"DELETE\" && segments.length === 3 && id !== void 0) return handleDelete(res, id);\n\t\tconst bucket = id === void 0 ? void 0 : state.instances[id];\n\t\tif (!bucket) return text(res, 404, `no such instance: \"${id ?? \"\"}\"`);\n\t\tif (method === \"GET\" && segments.length === 3) return json(res, 200, instanceView(bucket));\n\t\tif (method === \"PUT\" && segments.length === 4 && segments[3] === \"credentials\") return handlePutCredentials(req, res, bucket);\n\t\tres.writeHead(404);\n\t\tres.end();\n\t}\n\tasync function handleRequest(req, res) {\n\t\tconst url = new URL(req.url ?? \"/\", `http://127.0.0.1:${String(port)}`);\n\t\tif ((req.method ?? \"GET\") === \"GET\" && url.pathname === \"/health\") return json(res, 200, { version: ownVersion });\n\t\tif (url.pathname.startsWith(\"/_pcdev/\")) return handleAdmin(req, res, url.pathname.split(\"/\").filter((s) => s.length > 0).map((s) => decodeURIComponent(s)));\n\t\treturn handleS3Wire(req, res, url);\n\t}\n\tconst server = http.createServer((req, res) => {\n\t\thandleRequest(req, res).catch((err) => {\n\t\t\tif (!res.headersSent) res.writeHead(500, { \"content-type\": \"text/plain\" });\n\t\t\tres.end(err instanceof Error ? err.message : String(err));\n\t\t});\n\t});\n\tasync function shutdown() {\n\t\tawait stateFile.flush();\n\t\tserver.close();\n\t\tprocess.exit(0);\n\t}\n\tprocess.on(\"SIGTERM\", () => void shutdown());\n\tprocess.on(\"SIGINT\", () => void shutdown());\n\tdiscardStateFromEarlierVersions(stateDir, statePath).then(() => readJsonFile(statePath, isBucketsState)).then((loaded) => {\n\t\tif (loaded) state = loaded;\n\t\tserver.listen(port, \"127.0.0.1\", () => {\n\t\t\tconsole.log(`[dev-emulators] buckets-main listening on 127.0.0.1:${String(port)}`);\n\t\t});\n\t}).catch((err) => {\n\t\tconsole.error(\"buckets-main: failed to load state\", err);\n\t\tprocess.exit(1);\n\t});\n}\n/**\n* Removes state files this version does not write. Local dev state is never\n* migrated across versions; buckets registered by an earlier version are\n* gone, and their objects stay where they were.\n*/\nasync function discardStateFromEarlierVersions(stateDir, statePath) {\n\tconst files = await fs.promises.readdir(stateDir).catch(() => []);\n\tawait Promise.all(files.map((name) => path.join(stateDir, name)).filter((file) => file.endsWith(\".json\") && file !== statePath).map((file) => fs.promises.rm(file, { force: true })));\n}\nmain();\n//#endregion\nexport {};\n\n//# sourceMappingURL=buckets-main.mjs.map"],"mappings":"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"}
|