everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
194 lines (192 loc) • 8.16 kB
JavaScript
let effect = require("effect");
let zod = require("zod");
let every_plugin_version_manifest = require("every-plugin/version-manifest");
//#region ../../apps/upload/src/client.ts
const BundleFileSchema = zod.z.object({
path: zod.z.string().min(1).max(512),
contentBase64: zod.z.string().min(1)
});
const UploadRequestSchema = zod.z.object({
account: zod.z.string().min(1),
gateway: zod.z.string().min(1),
workspace: zod.z.string().min(1),
files: zod.z.array(BundleFileSchema).min(1).max(1e4)
});
const UploadResponseSchema = zod.z.object({
stored: zod.z.number().int(),
/** files recognized as byte-identical to what the store already holds (SRI metadata match) and skipped */
unchanged: zod.z.number().int().optional(),
totalBytes: zod.z.number().int(),
integrity: zod.z.record(zod.z.string(), zod.z.string()),
storage: zod.z.enum(["s3", "memory"]).optional().describe("Resolved bundle-storage backend: `s3` (R2/MinIO, persistent) or `memory` (ephemeral — bytes are lost on restart)")
});
const NamespaceQuerySchema = zod.z.object({
account: zod.z.string().min(1),
gateway: zod.z.string().min(1)
});
const ListBundlesQuerySchema = NamespaceQuerySchema.extend({ workspace: zod.z.string().min(1).optional() });
const BundleObjectSummarySchema = zod.z.object({
key: zod.z.string(),
size: zod.z.number().int(),
lastModified: zod.z.string().nullable().optional()
});
const ListBundlesResultSchema = zod.z.object({
storage: zod.z.enum(["s3", "memory"]),
prefix: zod.z.string(),
objects: zod.z.array(BundleObjectSummarySchema),
truncated: zod.z.boolean()
});
const ListVersionsQuerySchema = NamespaceQuerySchema.extend({ workspace: zod.z.string().min(1) });
const VersionSummarySchema = zod.z.object({
version: zod.z.string().regex(/^[0-9a-f]{16}$/),
entry: zod.z.string(),
entryIntegrity: zod.z.string(),
gitSha: zod.z.string().optional(),
builtAt: zod.z.string().optional(),
fileCount: zod.z.number().int().optional(),
lastModified: zod.z.string().nullable().optional()
});
const ListVersionsResultSchema = zod.z.object({
storage: zod.z.enum(["s3", "memory"]),
versions: zod.z.array(VersionSummarySchema),
truncated: zod.z.boolean()
});
const IntegrityReportQuerySchema = NamespaceQuerySchema.extend({
workspace: zod.z.string().min(1),
version: zod.z.string().regex(/^[0-9a-f]{16}$/)
});
const IntegrityReportResultSchema = zod.z.object({
storage: zod.z.enum(["s3", "memory"]),
manifest: every_plugin_version_manifest.WorkspaceVersionManifestSchema,
/** SRI recompute of the manifest's entry object against `entryIntegrity`;
* null when the entry object is missing from the store. */
entryVerified: zod.z.boolean().nullable()
});
const STATUS_ATTEMPTS = 3;
const TRANSPORT_ATTEMPTS = 5;
/** 522/524 are Cloudflare's "connection timed out"/"origin exceeded the proxy
* timeout" codes — the origin may still have applied the upload, and the
* server-side SRI dedupe makes a retry idempotent. */
const RETRYABLE_STATUSES = /* @__PURE__ */ new Set([
408,
429,
500,
502,
503,
504,
522,
524
]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const backoffMs = (attempt) => 1e3 * attempt + Math.floor(Math.random() * 500);
var UploadTransferError = class UploadTransferError extends effect.Data.TaggedError("UploadTransferError") {
constructor(status, detail, note) {
super({
status,
detail,
note
});
}
get message() {
return `${this.detail}${this.note ?? ""}`;
}
withNote(note) {
return new UploadTransferError(this.status, this.detail, `${this.note ?? ""}${note}`);
}
};
function describeTransferFailure(status, detail) {
const trimmed = detail.slice(0, 300);
if (status === 408 || /request timeout|bundle upload timed out/i.test(trimmed)) return `${trimmed} — the serving host timed out the upload; raise BOS_STORAGE_UPLOAD_TIMEOUT_MS there or upload smaller batches (BOS_MAX_BUNDLE_UPLOAD_BYTES)`;
if (status === 524) return `Cloudflare gave up waiting for the upload service (proxy timeout) — the upload may still have been applied (server-side SRI dedupe makes retries idempotent). Upload smaller batches (BOS_MAX_BUNDLE_UPLOAD_BYTES)`;
try {
const parsed = JSON.parse(detail);
if (parsed?.code === "INTERNAL_SERVER_ERROR" && parsed?.message === "Internal Server Error") return `${trimmed} — the host hid the underlying error; check the host logs for the cause`;
} catch {}
return trimmed;
}
async function requestJson(config, label, path, parse, init) {
const fetchImpl = config.fetchImpl ?? fetch;
const headers = { ...init?.headers };
if (config.apiKey) headers["x-api-key"] = config.apiKey;
if (init?.body && !headers["content-type"]) headers["content-type"] = "application/json";
let lastError;
let transportFailures = 0;
let statusFailures = 0;
for (let attempt = 1; attempt <= TRANSPORT_ATTEMPTS; attempt++) {
try {
const response = await fetchImpl(`${config.origin.replace(/\/$/, "")}${path}`, {
...init,
headers: transportFailures > 0 ? {
...headers,
connection: "close"
} : headers
});
if (response.ok) return parse(await response.json());
const detail = await response.text().catch(() => "");
lastError = new UploadTransferError(response.status, `[upload] ${label} failed: ${response.status} ${describeTransferFailure(response.status, detail)}`);
if (!RETRYABLE_STATUSES.has(response.status)) break;
statusFailures += 1;
if (statusFailures >= STATUS_ATTEMPTS) break;
} catch (error) {
transportFailures += 1;
lastError = new UploadTransferError(0, `[upload] ${label} failed: ${error instanceof Error ? error.message : String(error)}`);
}
if (attempt < TRANSPORT_ATTEMPTS) await sleep(backoffMs(attempt));
}
if (lastError instanceof UploadTransferError && lastError.status === 0) lastError = lastError.withNote(" (Bun fetch note: re-run with fetch verbose diagnostics for detail)");
throw lastError ?? /* @__PURE__ */ new Error(`[upload] ${label} failed`);
}
const parseJsonBody = (label, schema) => {
return (response) => {
try {
return schema.parse(response);
} catch (error) {
throw new UploadTransferError(0, `[upload] ${label} returned an unexpected payload: ${error instanceof Error ? error.message : String(error)}`);
}
};
};
function createUploadClient(config) {
return {
uploadBundle(input) {
const payload = UploadRequestSchema.parse(input);
return requestJson(config, `bundle upload for ${payload.workspace}`, "/api/storage/bundles", parseJsonBody("bundle upload", UploadResponseSchema), {
method: "POST",
body: JSON.stringify(payload)
});
},
listBundles(input) {
const query = new URLSearchParams({
account: input.account,
gateway: input.gateway
});
if (input.workspace) query.set("workspace", input.workspace);
return requestJson(config, "bundle listing", `/api/storage/bundles?${query.toString()}`, parseJsonBody("bundle listing", ListBundlesResultSchema), { method: "GET" });
},
listVersions(input) {
return requestJson(config, "version listing", `/api/storage/versions?${new URLSearchParams({
account: input.account,
gateway: input.gateway,
workspace: input.workspace
}).toString()}`, parseJsonBody("version listing", ListVersionsResultSchema), { method: "GET" });
},
integrityReport(input) {
return requestJson(config, "integrity report", `/api/storage/integrity?${new URLSearchParams({
account: input.account,
gateway: input.gateway,
workspace: input.workspace,
version: input.version
}).toString()}`, parseJsonBody("integrity report", IntegrityReportResultSchema), { method: "GET" });
}
};
}
//#endregion
exports.BundleFileSchema = BundleFileSchema;
exports.BundleObjectSummarySchema = BundleObjectSummarySchema;
exports.IntegrityReportResultSchema = IntegrityReportResultSchema;
exports.ListBundlesResultSchema = ListBundlesResultSchema;
exports.ListVersionsResultSchema = ListVersionsResultSchema;
exports.UploadRequestSchema = UploadRequestSchema;
exports.UploadResponseSchema = UploadResponseSchema;
exports.VersionSummarySchema = VersionSummarySchema;
exports.createUploadClient = createUploadClient;
//# sourceMappingURL=client.cjs.map