UNPKG

@beignet/core

Version:

Core framework primitives for Beignet

2,142 lines 57.7 kB
import type { StandardSchemaV1 } from "@standard-schema/spec";
import type {
  StorageMetadata,
  StorageObject,
  StorageObjectBody,
  StoragePort,
} from "../ports/index.js";
import type { ProviderInstrumentationTarget } from "../providers/index.js";
import { createProviderInstrumentation } from "../providers/index.js";

/**
 * Any Standard Schema compatible validator.
 */
export type StandardSchema = StandardSchemaV1<unknown, unknown>;

/**
 * Value or promise of that value.
 */
export type MaybePromise<T> = T | Promise<T>;

/**
 * Infer the parsed output type from a Standard Schema.
 */
export type InferSchemaOutput<T extends StandardSchemaV1> =
  StandardSchemaV1.InferOutput<T>;

/**
 * File metadata declared by a browser before an upload starts.
 */
export interface UploadFileIntent {
  /**
   * Original file name supplied by the client.
   */
  name: string;
  /**
   * MIME content type supplied by the client.
   */
  contentType: string;
  /**
   * File size in bytes.
   */
  size: number;
  /**
   * Optional expected checksum for this file. Direct uploads use this to
   * verify the object bytes during completion.
   */
  checksum?: UploadFileChecksum;
}

/**
 * Checksum algorithms supported by Beignet upload verification.
 */
export type UploadChecksumAlgorithm = "sha256";

/**
 * Expected or computed file checksum.
 */
export interface UploadFileChecksum {
  /**
   * Hash algorithm used for the checksum.
   */
  algorithm: UploadChecksumAlgorithm;
  /**
   * Lowercase hex digest.
   */
  value: string;
}

/**
 * Checksum verification requested by an upload definition.
 */
export interface UploadChecksumRequirement {
  /**
   * Hash algorithm to compute.
   */
  algorithm: UploadChecksumAlgorithm;
  /**
   * Whether direct upload preparation/completion must include a checksum.
   *
   * @default true
   */
  required?: boolean;
}

/**
 * Constraints for files accepted by an upload definition.
 */
export interface UploadFileConstraints {
  /**
   * Accepted MIME content types. Omit to accept any content type.
   */
  contentTypes?: readonly string[];
  /**
   * Maximum accepted file size in bytes.
   */
  maxSizeBytes?: number;
  /**
   * Maximum files accepted by one request.
   *
   * @default 1
   */
  maxFiles?: number;
  /**
   * Object visibility written to storage.
   *
   * @default "private"
   */
  visibility?: "private" | "public";
  /**
   * Cache-Control value written to storage.
   */
  cacheControl?: string;
  /**
   * Verify supported MIME types against file signatures instead of trusting
   * only the client-declared content type.
   *
   * @default "signature"
   */
  contentTypeVerification?: "signature" | false;
  /**
   * Request checksum verification for direct uploads and expose the requirement
   * through the upload manifest so browser clients can send expected digests.
   */
  checksum?: UploadChecksumRequirement;
}

/**
 * Parsed file intent with a generated upload id and storage key.
 */
export interface PreparedUploadFile extends UploadFileIntent {
  /**
   * Stable upload id used to correlate prepare, direct upload, and complete.
   */
  uploadId: string;
  /**
   * Storage key that should receive the file.
   */
  key: string;
}

/**
 * Direct upload instruction returned by an upload signer.
 */
export interface DirectUploadInstruction {
  method: "PUT";
  url: string;
  headers?: Record<string, string>;
  expiresAt: string;
}

/**
 * Arguments passed to an upload signer.
 */
export interface SignUploadArgs {
  uploadName: string;
  uploadId: string;
  key: string;
  file: UploadFileIntent;
  metadata: unknown;
  storage: {
    visibility: "private" | "public";
    cacheControl?: string;
    metadata: StorageMetadata;
  };
}

/**
 * Port for providers that can create direct-upload instructions.
 */
export interface UploadSignerPort {
  /**
   * Create direct upload instructions for one prepared file.
   */
  sign(args: SignUploadArgs): MaybePromise<DirectUploadInstruction>;
}

/**
 * Prepared upload file returned to clients.
 */
export interface PreparedUploadResultFile extends PreparedUploadFile {
  /**
   * Direct upload instruction when a signer is configured.
   */
  direct?: DirectUploadInstruction;
}

/**
 * Result returned by `prepare(...)`.
 */
export interface PrepareUploadResult {
  uploadName: string;
  mode: "direct" | "server";
  files: PreparedUploadResultFile[];
}

/**
 * File object completed by direct upload or server upload.
 */
export interface CompletedUploadFile extends PreparedUploadFile {
  object: StorageObject;
}

/**
 * Result returned by upload completion.
 */
export interface CompleteUploadResult<Result = unknown> {
  uploadName: string;
  files: CompletedUploadFile[];
  result: Result;
}

/**
 * Input for `prepare(...)`.
 */
export interface PrepareUploadInput {
  metadata: unknown;
  files: readonly UploadFileIntent[];
}

/**
 * Input for `complete(...)`.
 */
export interface CompleteUploadInput {
  metadata: unknown;
  files: readonly PreparedUploadFile[];
}

/**
 * Input for server-handled multipart uploads.
 */
export interface ServerUploadInput {
  formData: FormData;
}

/**
 * Authorization result accepted by upload definitions.
 */
export type UploadAuthorizeResult =
  | boolean
  | undefined
  | {
      allowed: boolean;
      reason?: string;
    };

/**
 * Upload access mode.
 *
 * Protected uploads require an `authorize(...)` hook. Public uploads are
 * intentionally reachable without that hook.
 */
export type UploadAccess = "protected" | "public";

/**
 * Arguments passed to upload definition hooks.
 */
export interface UploadHookArgs<Metadata, Ctx> {
  ctx: Ctx;
  metadata: Metadata;
}

/**
 * Arguments passed to file-specific upload hooks.
 */
export interface UploadFileHookArgs<Metadata, Ctx>
  extends UploadHookArgs<Metadata, Ctx> {
  file: UploadFileIntent;
  uploadId: string;
}

/**
 * Arguments passed to `onComplete(...)`.
 */
export interface UploadCompleteHookArgs<Metadata, Ctx>
  extends UploadHookArgs<Metadata, Ctx> {
  files: CompletedUploadFile[];
}

/**
 * Arguments passed to `verifyFile(...)` after a file exists in storage and
 * before `onComplete(...)` runs.
 */
export interface UploadVerifyFileHookArgs<Metadata, Ctx>
  extends UploadHookArgs<Metadata, Ctx> {
  file: CompletedUploadFile;
  storage: StoragePort;
}

/**
 * Verification result accepted by `verifyFile(...)`.
 */
export type UploadFileVerificationResult =
  | boolean
  | undefined
  | {
      valid: boolean;
      reason?: string;
      details?: unknown;
    };

/**
 * Upload definition options.
 */
export interface DefineUploadOptions<
  MetadataSchema extends StandardSchema,
  Ctx,
  Result,
> {
  /**
   * Metadata schema submitted with prepare, server upload, and complete calls.
   */
  metadata: MetadataSchema;
  /**
   * File constraints for this upload workflow.
   */
  file: UploadFileConstraints;
  /**
   * Whether this upload may be prepared without an authorize hook.
   *
   * @default "protected"
   */
  access?: UploadAccess;
  /**
   * Optional human-readable description for docs and tooling.
   */
  description?: string;
  /**
   * Check whether the current actor may start this upload.
   */
  authorize?(
    args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<UploadAuthorizeResult>;
  /**
   * Build the storage key for one file.
   */
  key(
    args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<string>;
  /**
   * Add storage metadata for one file.
   */
  storageMetadata?(
    args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<StorageMetadata>;
  /**
   * Run after a file exists in storage and before `onComplete(...)`. Use this
   * for app-owned scanning, moderation, or quarantine decisions.
   */
  verifyFile?(
    args: UploadVerifyFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<UploadFileVerificationResult>;
  /**
   * Run after files exist in storage.
   */
  onComplete?(
    args: UploadCompleteHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<Result>;
}

/**
 * Upload definition created by `defineUpload(...)`.
 */
export interface UploadDef<
  Name extends string = string,
  MetadataSchema extends StandardSchema = StandardSchema,
  Ctx = unknown,
  Result = unknown,
> {
  readonly kind: "upload";
  readonly name: Name;
  readonly metadata: MetadataSchema;
  readonly file: UploadFileConstraints;
  readonly access?: UploadAccess;
  readonly description?: string;
  authorize?(
    args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<UploadAuthorizeResult>;
  key(
    args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<string>;
  storageMetadata?(
    args: UploadFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<StorageMetadata>;
  verifyFile?(
    args: UploadVerifyFileHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<UploadFileVerificationResult>;
  onComplete?(
    args: UploadCompleteHookArgs<InferSchemaOutput<MetadataSchema>, Ctx>,
  ): MaybePromise<Result>;
}

/**
 * Infer the parsed metadata type for an upload definition.
 */
export type InferUploadMetadata<U extends UploadDef> =
  U["metadata"] extends StandardSchemaV1<unknown, infer Output>
    ? Output
    : never;

/**
 * Infer the result returned by an upload definition's completion hook.
 */
export type InferUploadResult<U extends UploadDef> =
  U extends UploadDef<string, StandardSchema, unknown, infer Result>
    ? Result
    : unknown;

/**
 * Nested upload registry shape used by server registration and typed clients.
 */
export interface UploadRegistry {
  /**
   * Upload definition or nested upload registry.
   */
  readonly [key: string]: UploadDef | UploadRegistry;
}

/**
 * Infer every upload definition contained in a nested upload registry.
 */
export type UploadFromRegistry<Registry> = Registry extends UploadDef
  ? Registry
  : Registry extends readonly (infer Upload)[]
    ? Upload extends UploadDef
      ? Upload
      : never
    : Registry extends object
      ? {
          [Key in keyof Registry]: UploadFromRegistry<Registry[Key]>;
        }[keyof Registry]
      : never;

/**
 * Client-safe upload metadata generated from server upload definitions.
 */
export interface UploadManifestEntry {
  /**
   * Upload route name.
   */
  name: string;
  /**
   * Optional human-readable upload description.
   */
  description?: string;
  /**
   * File constraints safe to expose to browser UI code.
   */
  file: UploadFileConstraints;
}

/**
 * Request body limits for upload route actions.
 */
export interface UploadRequestLimits {
  /**
   * Maximum JSON body size for prepare and complete actions.
   *
   * @default 262144
   */
  jsonMaxBytes?: number;
  /**
   * Maximum multipart body size for server-handled upload actions when
   * Content-Length is present. File constraints still enforce per-file limits.
   *
   * @default 26214400
   */
  multipartMaxBytes?: number;
}

/**
 * Options for `createUploadRouter(...)`.
 */
export interface CreateUploadRouterOptions<Ctx> {
  /**
   * Upload definitions registered with this router.
   */
  uploads: readonly UploadDef<string, StandardSchema, Ctx, unknown>[];
  /**
   * Request context value or lazy context factory.
   */
  ctx: Ctx | (() => MaybePromise<Ctx>);
  /**
   * Storage port used for server uploads and direct upload completion checks.
   */
  storage: StoragePort;
  /**
   * Optional signer used to prepare direct upload instructions.
   */
  signer?: UploadSignerPort;
  /**
   * Request body limits for upload actions.
   */
  limits?: UploadRequestLimits;
  /**
   * Optional instrumentation target used by devtools/provider watchers.
   */
  instrumentation?: ProviderInstrumentationTarget;
  /**
   * Optional upload id generator for tests or custom id policies.
   */
  id?: () => string;
}

/**
 * Framework-neutral upload router.
 */
export interface UploadRouter {
  prepare(
    uploadName: string,
    input: PrepareUploadInput,
  ): Promise<PrepareUploadResult>;
  complete(
    uploadName: string,
    input: CompleteUploadInput,
  ): Promise<CompleteUploadResult>;
  upload(
    uploadName: string,
    input: ServerUploadInput,
  ): Promise<CompleteUploadResult>;
  handleRequest(
    request: Request,
    options: { uploadName: string; action: "prepare" | "complete" | "upload" },
  ): Promise<Response>;
}

/**
 * Machine-readable upload error codes.
 */
export type UploadErrorCode =
  | "UPLOAD_NOT_FOUND"
  | "INVALID_UPLOAD_ACTION"
  | "INVALID_UPLOAD_METADATA"
  | "INVALID_UPLOAD_FILE"
  | "UNAUTHORIZED_UPLOAD"
  | "UPLOAD_OBJECT_NOT_FOUND"
  | "UPLOAD_BODY_TOO_LARGE"
  | "INVALID_UPLOAD_BODY";

/**
 * Base error for expected upload failures.
 *
 * Upload workflows throw one of the specific subclasses, such as
 * {@link UploadNotFoundError} or {@link UnauthorizedUploadError}. Catch this
 * base class to handle any expected upload failure; the upload router maps it
 * to an HTTP response using `code`, `status`, and `details`.
 */
export class UploadError extends Error {
  readonly code: UploadErrorCode;
  readonly status: number;
  readonly details?: unknown;

  protected constructor(args: {
    code: UploadErrorCode;
    message: string;
    status?: number;
    details?: unknown;
  }) {
    super(args.message);
    this.name = "UploadError";
    this.code = args.code;
    this.status = args.status ?? 400;
    this.details = args.details;
  }
}

/**
 * Error thrown when an upload name is not registered on the router.
 */
export class UploadNotFoundError extends UploadError {
  declare readonly code: "UPLOAD_NOT_FOUND";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "UPLOAD_NOT_FOUND", status: 404, ...args });
    this.name = "UploadNotFoundError";
  }
}

/**
 * Error thrown when an upload request targets an unknown upload action.
 */
export class InvalidUploadActionError extends UploadError {
  declare readonly code: "INVALID_UPLOAD_ACTION";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "INVALID_UPLOAD_ACTION", status: 400, ...args });
    this.name = "InvalidUploadActionError";
  }
}

/**
 * Error thrown when upload metadata fails schema validation.
 */
export class InvalidUploadMetadataError extends UploadError {
  declare readonly code: "INVALID_UPLOAD_METADATA";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "INVALID_UPLOAD_METADATA", status: 422, ...args });
    this.name = "InvalidUploadMetadataError";
  }
}

/**
 * Error thrown when a file fails upload validation, such as file count,
 * content type (415), size limits (413), or prepared-file mismatches.
 */
export class InvalidUploadFileError extends UploadError {
  declare readonly code: "INVALID_UPLOAD_FILE";

  constructor(args: { message: string; details?: unknown; status?: number }) {
    super({
      code: "INVALID_UPLOAD_FILE",
      message: args.message,
      status: args.status ?? 422,
      details: args.details,
    });
    this.name = "InvalidUploadFileError";
  }
}

/**
 * Error thrown when an upload is denied by authorize(...) or lacks
 * authorization configuration.
 */
export class UnauthorizedUploadError extends UploadError {
  declare readonly code: "UNAUTHORIZED_UPLOAD";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "UNAUTHORIZED_UPLOAD", status: 403, ...args });
    this.name = "UnauthorizedUploadError";
  }
}

/**
 * Error thrown when a completed upload references a stored object that does
 * not exist.
 */
export class UploadObjectNotFoundError extends UploadError {
  declare readonly code: "UPLOAD_OBJECT_NOT_FOUND";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "UPLOAD_OBJECT_NOT_FOUND", status: 404, ...args });
    this.name = "UploadObjectNotFoundError";
  }
}

/**
 * Error thrown when an upload request body exceeds the configured size limit.
 */
export class UploadBodyTooLargeError extends UploadError {
  declare readonly code: "UPLOAD_BODY_TOO_LARGE";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "UPLOAD_BODY_TOO_LARGE", status: 413, ...args });
    this.name = "UploadBodyTooLargeError";
  }
}

/**
 * Error thrown when an upload request body cannot be parsed or has an
 * invalid shape.
 */
export class InvalidUploadBodyError extends UploadError {
  declare readonly code: "INVALID_UPLOAD_BODY";

  constructor(args: { message: string; details?: unknown }) {
    super({ code: "INVALID_UPLOAD_BODY", status: 400, ...args });
    this.name = "InvalidUploadBodyError";
  }
}

/**
 * Define a typed upload workflow.
 */
export function defineUpload<
  const Name extends string,
  MetadataSchema extends StandardSchema,
  Ctx = unknown,
  Result = unknown,
>(
  name: Name,
  options: DefineUploadOptions<MetadataSchema, Ctx, Result>,
): UploadDef<Name, MetadataSchema, Ctx, Result> {
  return {
    kind: "upload",
    name,
    metadata: options.metadata,
    file: {
      ...options.file,
      maxFiles: options.file.maxFiles ?? 1,
      visibility: options.file.visibility ?? "private",
    },
    access: options.access ?? "protected",
    ...(options.description !== undefined
      ? { description: options.description }
      : {}),
    ...(options.authorize ? { authorize: options.authorize } : {}),
    key: options.key,
    ...(options.storageMetadata
      ? { storageMetadata: options.storageMetadata }
      : {}),
    ...(options.verifyFile ? { verifyFile: options.verifyFile } : {}),
    ...(options.onComplete ? { onComplete: options.onComplete } : {}),
  };
}

/**
 * Context-bound upload helper factory.
 */
export interface Uploads<Ctx> {
  /**
   * Define an upload workflow with the bound context type.
   */
  defineUpload<
    const Name extends string,
    MetadataSchema extends StandardSchema,
    Result = unknown,
  >(
    name: Name,
    options: DefineUploadOptions<MetadataSchema, Ctx, Result>,
  ): UploadDef<Name, MetadataSchema, Ctx, Result>;
}

/**
 * Create upload helper methods bound to an application context type.
 *
 * Call it once in `lib/uploads.ts`:
 *
 * ```ts
 * export const { defineUpload } = createUploads<AppContext>();
 * ```
 */
export function createUploads<Ctx>(): Uploads<Ctx> {
  return {
    defineUpload<
      const Name extends string,
      MetadataSchema extends StandardSchema,
      Result = unknown,
    >(
      name: Name,
      options: DefineUploadOptions<MetadataSchema, Ctx, Result>,
    ): UploadDef<Name, MetadataSchema, Ctx, Result> {
      return defineUpload(name, options);
    },
  };
}

/**
 * Define a nested upload registry while preserving upload names and metadata
 * types for client code.
 */
export function defineUploads<const Uploads extends UploadRegistry>(
  uploads: Uploads,
): Uploads {
  return uploads;
}

/**
 * Flatten a nested upload registry into the list expected by
 * `createUploadRouter(...)`.
 */
export function uploadsFromRegistry(
  uploads: UploadRegistry | readonly UploadDef[],
): UploadDef[] {
  if (Array.isArray(uploads)) return [...uploads];

  const result: UploadDef[] = [];
  for (const value of Object.values(uploads)) {
    if (isUploadDef(value)) {
      result.push(value);
    } else {
      result.push(...uploadsFromRegistry(value));
    }
  }
  return result;
}

/**
 * Create client-safe upload metadata for browser helpers.
 */
export function createUploadManifest(
  uploads: UploadRegistry | readonly UploadDef[],
): UploadManifestEntry[] {
  return uploadsFromRegistry(uploads).map((upload) => ({
    name: upload.name,
    ...(upload.description !== undefined
      ? { description: upload.description }
      : {}),
    file: upload.file,
  }));
}

/**
 * Create deterministic direct upload instructions for tests.
 */
export function createMemoryUploadSigner(
  options: { baseUrl?: string; expiresAt?: string } = {},
): UploadSignerPort {
  const baseUrl = options.baseUrl ?? "https://uploads.beignet.test";
  const expiresAt = options.expiresAt ?? "2100-01-01T00:00:00.000Z";

  return {
    sign(args) {
      return {
        method: "PUT",
        url: `${baseUrl}/${encodeURIComponent(args.key)}`,
        headers: {
          "content-type": args.file.contentType,
        },
        expiresAt,
      };
    },
  };
}

/**
 * Create a framework-neutral upload router.
 */
export function createUploadRouter<Ctx>(
  options: CreateUploadRouterOptions<Ctx>,
): UploadRouter {
  const uploads = new Map<string, UploadDef<string, StandardSchema, Ctx>>();
  for (const upload of options.uploads) {
    if (uploads.has(upload.name)) {
      throw new Error(
        `createUploadRouter received duplicate upload name "${upload.name}". Each defineUpload(...) name must be unique.`,
      );
    }
    uploads.set(upload.name, upload);
  }
  const id = options.id ?? randomUploadId;
  const instrumentation = createProviderInstrumentation(
    options.instrumentation,
    {
      providerName: "uploads",
      watcher: "uploads",
    },
  );
  const requestLimits = uploadRequestLimits(options.limits);

  async function resolveCtx(): Promise<Ctx> {
    return typeof options.ctx === "function"
      ? (options.ctx as () => MaybePromise<Ctx>)()
      : options.ctx;
  }

  function findUpload(name: string) {
    const upload = uploads.get(name);
    if (!upload) {
      const registered = [...uploads.keys()]
        .map((registeredName) => `"${registeredName}"`)
        .join(", ");
      throw new UploadNotFoundError({
        message: `Upload "${name}" is not registered. Registered uploads: ${registered || "none"}. Upload routes resolve the defineUpload(...) name, not the defineUploads({...}) registry key.`,
      });
    }
    return upload;
  }

  async function prepare(uploadName: string, input: PrepareUploadInput) {
    const startedAt = Date.now();
    instrumentation.custom({
      name: "upload.prepare.started",
      label: "Upload prepare started",
      summary: uploadName,
    });

    try {
      const upload = findUpload(uploadName);
      const parsed = parsePrepareInput(uploadName, input);
      const ctx = await resolveCtx();
      const metadata = await parseMetadata(upload, parsed.metadata);
      assertFiles(upload, parsed.files, {
        requireChecksum: Boolean(options.signer),
      });

      const files: PreparedUploadResultFile[] = [];
      for (const file of parsed.files) {
        const uploadId = id();
        await assertAuthorized(upload, { ctx, metadata, file, uploadId });
        const key = await upload.key({ ctx, metadata, file, uploadId });
        const storageMetadata =
          (await upload.storageMetadata?.({ ctx, metadata, file, uploadId })) ??
          {};
        const prepared: PreparedUploadResultFile = {
          ...file,
          uploadId,
          key,
        };

        if (options.signer) {
          prepared.direct = await options.signer.sign({
            uploadName,
            uploadId,
            key,
            file,
            metadata,
            storage: {
              visibility: upload.file.visibility ?? "private",
              ...(upload.file.cacheControl !== undefined
                ? { cacheControl: upload.file.cacheControl }
                : {}),
              metadata: storageMetadata,
            },
          });
        }

        files.push(prepared);
      }

      instrumentation.custom({
        name: "upload.prepare.completed",
        label: "Upload prepare completed",
        summary: `${uploadName} (${files.length} file${files.length === 1 ? "" : "s"})`,
        details: {
          uploadName,
          mode: options.signer ? "direct" : "server",
          fileCount: files.length,
          durationMs: Date.now() - startedAt,
        },
      });

      return {
        uploadName,
        mode: options.signer ? "direct" : "server",
        files,
      } satisfies PrepareUploadResult;
    } catch (error) {
      recordFailure("upload.prepare.failed", uploadName, startedAt, error);
      throw error;
    }
  }

  async function complete(uploadName: string, input: CompleteUploadInput) {
    const startedAt = Date.now();
    instrumentation.custom({
      name: "upload.complete.started",
      label: "Upload complete started",
      summary: uploadName,
    });

    try {
      const upload = findUpload(uploadName);
      const parsed = parseCompleteInput(uploadName, input);
      const ctx = await resolveCtx();
      const metadata = await parseMetadata(upload, parsed.metadata);
      assertFiles(upload, parsed.files, { requireChecksum: true });

      const files: CompletedUploadFile[] = [];
      for (const file of parsed.files) {
        await assertAuthorized(upload, {
          ctx,
          metadata,
          file,
          uploadId: file.uploadId,
        });
        const expectedKey = await upload.key({
          ctx,
          metadata,
          file,
          uploadId: file.uploadId,
        });
        if (file.key !== expectedKey) {
          throw new InvalidUploadFileError({
            message: `Uploaded object key does not match upload "${upload.name}".`,
            details: {
              expectedKey,
              actualKey: file.key,
            },
          });
        }
        const object = needsUploadBodyVerification(upload, file)
          ? await options.storage.get(file.key)
          : await options.storage.stat(file.key);
        if (!object) {
          throw new UploadObjectNotFoundError({
            message: `Uploaded object "${file.key}" was not found.`,
          });
        }
        assertStoredObject(upload, file, object);
        const verified = await verifyStoredUploadFile(upload, file, object);
        const completedObject = storageObjectMetadata(object);
        const completedFile = {
          ...file,
          ...(verified.checksum ? { checksum: verified.checksum } : {}),
          object: completedObject,
        };
        await assertVerifiedFile(upload, {
          ctx,
          metadata,
          file: completedFile,
          storage: options.storage,
        });
        files.push(completedFile);
      }

      const result = await upload.onComplete?.({ ctx, metadata, files });
      instrumentation.custom({
        name: "upload.complete.completed",
        label: "Upload complete completed",
        summary: `${uploadName} (${files.length} file${files.length === 1 ? "" : "s"})`,
        details: {
          uploadName,
          fileCount: files.length,
          durationMs: Date.now() - startedAt,
        },
      });

      return {
        uploadName,
        files,
        result,
      } satisfies CompleteUploadResult;
    } catch (error) {
      recordFailure("upload.complete.failed", uploadName, startedAt, error);
      throw error;
    }
  }

  async function upload(uploadName: string, input: ServerUploadInput) {
    const startedAt = Date.now();
    instrumentation.custom({
      name: "upload.server.started",
      label: "Server upload started",
      summary: uploadName,
    });

    try {
      const definition = findUpload(uploadName);
      const ctx = await resolveCtx();
      const metadata = await parseMetadata(
        definition,
        metadataFromFormData(input.formData),
      );
      const webFiles = filesFromFormData(input.formData);
      const intents = webFiles.map(fileIntentFromFile);
      assertFiles(definition, intents, { requireChecksum: false });

      const completed: CompletedUploadFile[] = [];
      const storedKeys: string[] = [];
      try {
        for (const [index, file] of webFiles.entries()) {
          const intent = intents[index];
          if (!intent) continue;
          const uploadId = id();
          await assertAuthorized(definition, {
            ctx,
            metadata,
            file: intent,
            uploadId,
          });
          const verified = await verifyBlobUploadFile(definition, intent, file);
          const verifiedIntent = {
            ...intent,
            ...(verified.checksum ? { checksum: verified.checksum } : {}),
          };
          const key = await definition.key({
            ctx,
            metadata,
            file: verifiedIntent,
            uploadId,
          });
          const storageMetadata =
            (await definition.storageMetadata?.({
              ctx,
              metadata,
              file: verifiedIntent,
              uploadId,
            })) ?? {};
          const object = await options.storage.put(key, file, {
            contentType: verifiedIntent.contentType,
            ...(definition.file.cacheControl !== undefined
              ? { cacheControl: definition.file.cacheControl }
              : {}),
            metadata: storageMetadata,
            visibility: definition.file.visibility ?? "private",
          });
          storedKeys.push(key);
          const completedFile = {
            ...verifiedIntent,
            uploadId,
            key,
            object,
          };
          await assertVerifiedFile(definition, {
            ctx,
            metadata,
            file: completedFile,
            storage: options.storage,
          });
          completed.push(completedFile);
        }
      } catch (error) {
        if (storedKeys.length > 0) {
          await cleanupRejectedServerUpload(uploadName, storedKeys);
        }
        throw error;
      }

      // Once app-owned completion begins, the app may persist durable references
      // to these objects. The framework can no longer delete them safely if a
      // later completion step fails; transaction or compensation belongs to the
      // app from this point forward.
      const result = await definition.onComplete?.({
        ctx,
        metadata,
        files: completed,
      });
      instrumentation.custom({
        name: "upload.server.completed",
        label: "Server upload completed",
        summary: `${uploadName} (${completed.length} file${completed.length === 1 ? "" : "s"})`,
        details: {
          uploadName,
          fileCount: completed.length,
          durationMs: Date.now() - startedAt,
        },
      });

      return {
        uploadName,
        files: completed,
        result,
      } satisfies CompleteUploadResult;
    } catch (error) {
      recordFailure("upload.server.failed", uploadName, startedAt, error);
      throw error;
    }
  }

  async function cleanupRejectedServerUpload(
    uploadName: string,
    keys: readonly string[],
  ): Promise<void> {
    const failures: Array<{ key: string; error: string }> = [];

    await Promise.all(
      keys.map(async (key) => {
        try {
          await options.storage.delete(key);
        } catch (error) {
          failures.push({
            key,
            error: error instanceof Error ? error.message : String(error),
          });
        }
      }),
    );

    if (failures.length === 0) return;
    instrumentation.custom({
      name: "upload.server.cleanup.failed",
      label: "Rejected upload cleanup failed",
      summary: uploadName,
      details: {
        uploadName,
        failures,
      },
    });
  }

  function recordFailure(
    name: string,
    uploadName: string,
    startedAt: number,
    error: unknown,
  ) {
    instrumentation.custom({
      name,
      label: "Upload failed",
      summary: uploadName,
      details: {
        uploadName,
        durationMs: Date.now() - startedAt,
        error: error instanceof Error ? error.message : String(error),
      },
    });
  }

  return {
    prepare,
    complete,
    upload,
    async handleRequest(request, requestOptions) {
      try {
        if (requestOptions.action === "prepare") {
          const input = await readJsonBody(request, {
            uploadName: requestOptions.uploadName,
            action: "prepare",
            maxBytes: requestLimits.jsonMaxBytes,
          });
          return jsonResponse(
            await prepare(
              requestOptions.uploadName,
              input as PrepareUploadInput,
            ),
          );
        }

        if (requestOptions.action === "complete") {
          const input = await readJsonBody(request, {
            uploadName: requestOptions.uploadName,
            action: "complete",
            maxBytes: requestLimits.jsonMaxBytes,
          });
          return jsonResponse(
            await complete(
              requestOptions.uploadName,
              input as CompleteUploadInput,
            ),
          );
        }

        const multipartContext = {
          uploadName: requestOptions.uploadName,
          action: "upload",
          maxBytes: requestLimits.multipartMaxBytes,
        } as const;
        const multipartBody = await readLimitedRequestBytes(
          request,
          multipartContext,
        );
        const multipartHeaders = new Headers(request.headers);
        multipartHeaders.delete("content-length");
        const formData = await new Request(request.url, {
          method: request.method,
          headers: multipartHeaders,
          body: multipartBody,
          signal: request.signal,
        }).formData();
        return jsonResponse(
          await upload(requestOptions.uploadName, {
            formData,
          }),
        );
      } catch (error) {
        return uploadErrorResponse(error);
      }
    },
  };
}

const DEFAULT_UPLOAD_JSON_MAX_BYTES = 256 * 1024;
const DEFAULT_UPLOAD_MULTIPART_MAX_BYTES = 25 * 1024 * 1024;

function uploadRequestLimits(
  limits: UploadRequestLimits | undefined,
): Required<UploadRequestLimits> {
  return {
    jsonMaxBytes: positiveLimit(
      limits?.jsonMaxBytes,
      DEFAULT_UPLOAD_JSON_MAX_BYTES,
      "limits.jsonMaxBytes",
    ),
    multipartMaxBytes: positiveLimit(
      limits?.multipartMaxBytes,
      DEFAULT_UPLOAD_MULTIPART_MAX_BYTES,
      "limits.multipartMaxBytes",
    ),
  };
}

function positiveLimit(
  value: number | undefined,
  fallback: number,
  name: string,
): number {
  const limit = value ?? fallback;
  if (!Number.isFinite(limit) || limit <= 0) {
    throw new Error(`createUploadRouter ${name} must be a positive number.`);
  }
  return limit;
}

function assertUploadContentLengthWithinLimit(
  headers: Headers,
  context: {
    uploadName: string;
    action: "prepare" | "complete" | "upload";
    maxBytes: number;
  },
): void {
  const contentLength = headers.get("content-length");
  if (contentLength === null) return;

  const actualBytes = Number(contentLength);
  if (!Number.isFinite(actualBytes) || actualBytes < 0) return;
  if (actualBytes > context.maxBytes) {
    throw new UploadBodyTooLargeError({
      message: `Upload "${context.uploadName}" ${context.action} body is too large.`,
      details: {
        maxBytes: context.maxBytes,
        actualBytes,
      },
    });
  }
}

async function readLimitedRequestBytes(
  request: Request,
  context: {
    uploadName: string;
    action: "upload";
    maxBytes: number;
  },
): Promise<ArrayBuffer> {
  assertUploadContentLengthWithinLimit(request.headers, context);

  if (!request.body) return new ArrayBuffer(0);

  const reader = request.body.getReader();
  const chunks: Uint8Array[] = [];
  let actualBytes = 0;

  try {
    while (true) {
      const result = await reader.read();
      if (result.done) break;
      actualBytes += result.value.byteLength;
      if (actualBytes > context.maxBytes) {
        try {
          await reader.cancel();
        } catch {
          // Preserve the size-limit error when the request source rejects cancellation.
        }
        throw new UploadBodyTooLargeError({
          message: `Upload "${context.uploadName}" ${context.action} body is too large.`,
          details: {
            maxBytes: context.maxBytes,
            actualBytes,
          },
        });
      }
      chunks.push(result.value);
    }
  } finally {
    reader.releaseLock();
  }

  const body = new ArrayBuffer(actualBytes);
  const bytes = new Uint8Array(body);
  let offset = 0;
  for (const chunk of chunks) {
    bytes.set(chunk, offset);
    offset += chunk.byteLength;
  }
  return body;
}

async function readLimitedRequestText(
  request: Request,
  context: {
    uploadName: string;
    action: "prepare" | "complete";
    maxBytes: number;
  },
): Promise<string> {
  assertUploadContentLengthWithinLimit(request.headers, context);

  if (!request.body) {
    const text = await request.text();
    const actualBytes = new TextEncoder().encode(text).byteLength;
    if (actualBytes > context.maxBytes) {
      throw new UploadBodyTooLargeError({
        message: `Upload "${context.uploadName}" ${context.action} body is too large.`,
        details: {
          maxBytes: context.maxBytes,
          actualBytes,
        },
      });
    }
    return text;
  }

  const reader = request.body.getReader();
  const decoder = new TextDecoder();
  let actualBytes = 0;
  let text = "";

  try {
    while (true) {
      const result = await reader.read();
      if (result.done) break;
      actualBytes += result.value.byteLength;
      if (actualBytes > context.maxBytes) {
        throw new UploadBodyTooLargeError({
          message: `Upload "${context.uploadName}" ${context.action} body is too large.`,
          details: {
            maxBytes: context.maxBytes,
            actualBytes,
          },
        });
      }
      text += decoder.decode(result.value, { stream: true });
    }
    text += decoder.decode();
  } finally {
    reader.releaseLock();
  }

  return text;
}

async function readJsonBody(
  request: Request,
  context: {
    uploadName: string;
    action: "prepare" | "complete";
    maxBytes: number;
  },
): Promise<unknown> {
  try {
    return JSON.parse(await readLimitedRequestText(request, context));
  } catch (error) {
    if (error instanceof UploadError) throw error;
    throw new InvalidUploadBodyError({
      message: `Upload "${context.uploadName}" ${context.action} body must be valid JSON.`,
    });
  }
}

interface UploadBodyIssue {
  message: string;
  path: (string | number)[];
}

function collectBodyIssues(
  body: unknown,
  options: { requireCompletedFileFields: boolean },
): UploadBodyIssue[] {
  if (typeof body !== "object" || body === null || Array.isArray(body)) {
    return [{ message: "Body must be a JSON object.", path: [] }];
  }

  const files = (body as { files?: unknown }).files;
  if (!Array.isArray(files)) {
    return [{ message: 'Body must include a "files" array.', path: ["files"] }];
  }

  const issues: UploadBodyIssue[] = [];
  for (const [index, file] of files.entries()) {
    if (typeof file !== "object" || file === null || Array.isArray(file)) {
      issues.push({
        message: "Each file must be an object.",
        path: ["files", index],
      });
      continue;
    }

    if (!options.requireCompletedFileFields) continue;

    const completed = file as { uploadId?: unknown; key?: unknown };
    if (typeof completed.uploadId !== "string") {
      issues.push({
        message: 'Each completed file must include a string "uploadId".',
        path: ["files", index, "uploadId"],
      });
    }
    if (typeof completed.key !== "string") {
      issues.push({
        message: 'Each completed file must include a string "key".',
        path: ["files", index, "key"],
      });
    }
  }
  return issues;
}

function parsePrepareInput(
  uploadName: string,
  body: unknown,
): PrepareUploadInput {
  const issues = collectBodyIssues(body, {
    requireCompletedFileFields: false,
  });
  if (issues.length > 0) {
    throw new InvalidUploadBodyError({
      message: `Upload "${uploadName}" prepare body is invalid.`,
      details: { issues },
    });
  }
  return body as PrepareUploadInput;
}

function parseCompleteInput(
  uploadName: string,
  body: unknown,
): CompleteUploadInput {
  const issues = collectBodyIssues(body, {
    requireCompletedFileFields: true,
  });
  if (issues.length > 0) {
    throw new InvalidUploadBodyError({
      message: `Upload "${uploadName}" complete body is invalid.`,
      details: { issues },
    });
  }
  return body as CompleteUploadInput;
}

async function parseMetadata<U extends UploadDef>(
  upload: U,
  input: unknown,
): Promise<InferUploadMetadata<U>> {
  const result = await upload.metadata["~standard"].validate(input);

  if (result.issues?.length) {
    throw new InvalidUploadMetadataError({
      message: `Invalid metadata for upload "${upload.name}".`,
      details: { issues: result.issues },
    });
  }

  if ("value" in result) {
    return result.value as InferUploadMetadata<U>;
  }

  throw new Error("Invalid Standard Schema result: missing value");
}

function assertFiles(
  upload: UploadDef,
  files: readonly UploadFileIntent[],
  options: { requireChecksum?: boolean } = {},
): void {
  const maxFiles = upload.file.maxFiles ?? 1;
  if (files.length === 0 || files.length > maxFiles) {
    throw new InvalidUploadFileError({
      message: `Upload "${upload.name}" requires between 1 and ${maxFiles} file${maxFiles === 1 ? "" : "s"}.`,
      details: { fileCount: files.length, maxFiles },
    });
  }

  for (const file of files) {
    if (!file.name || !file.contentType || !Number.isFinite(file.size)) {
      throw new InvalidUploadFileError({
        message: `Upload "${upload.name}" received invalid file metadata.`,
        details: { file },
      });
    }

    assertFileChecksum(upload, file, options);

    if (
      upload.file.contentTypes?.length &&
      !upload.file.contentTypes
        .map(normalizeContentType)
        .includes(normalizeContentType(file.contentType))
    ) {
      throw new InvalidUploadFileError({
        status: 415,
        message: `Upload "${upload.name}" does not accept "${file.contentType}".`,
        details: {
          contentType: file.contentType,
          acceptedContentTypes: upload.file.contentTypes,
        },
      });
    }

    if (
      upload.file.maxSizeBytes !== undefined &&
      file.size > upload.file.maxSizeBytes
    ) {
      throw new InvalidUploadFileError({
        status: 413,
        message: `Upload "${upload.name}" exceeds the maximum file size.`,
        details: {
          size: file.size,
          maxSizeBytes: upload.file.maxSizeBytes,
        },
      });
    }
  }
}

function assertFileChecksum(
  upload: UploadDef,
  file: UploadFileIntent,
  options: { requireChecksum?: boolean },
): void {
  const requirement = upload.file.checksum;
  if (!requirement && !file.checksum) return;

  const configuredAlgorithm = requirement?.algorithm as string | undefined;
  if (configuredAlgorithm && configuredAlgorithm !== "sha256") {
    throw new InvalidUploadFileError({
      message: `Upload "${upload.name}" uses an unsupported checksum algorithm.`,
      details: {
        algorithm: configuredAlgorithm,
      },
    });
  }

  const required = requirement
    ? requirement.required !== false && options.requireChecksum === true
    : false;
  if (!file.checksum) {
    if (!required) return;
    throw new InvalidUploadFileError({
      message: `Upload "${upload.name}" requires a sha256 checksum for "${file.name}".`,
      details: {
        fileName: file.name,
        algorithm: "sha256",
      },
    });
  }

  if (
    file.checksum.algorithm !== "sha256" ||
    !isSha256Hex(file.checksum.value)
  ) {
    throw new InvalidUploadFileError({
      message: `Upload "${upload.name}" received an invalid checksum for "${file.name}".`,
      details: {
        fileName: file.name,
        checksum: file.checksum,
      },
    });
  }
}

const UPLOAD_SIGNATURE_MAX_BYTES = 512;

type UploadFileBodyVerification = {
  checksum?: UploadFileChecksum;
};

function needsUploadBodyVerification(
  upload: UploadDef,
  file: UploadFileIntent,
): boolean {
  return (
    needsUploadChecksumVerification(upload, file) ||
    needsUploadContentTypeVerification(upload, file)
  );
}

function needsUploadChecksumVerification(
  upload: UploadDef,
  file: UploadFileIntent,
): boolean {
  return Boolean(
    file.checksum ||
      (upload.file.checksum && upload.file.checksum.required !== false),
  );
}

function needsUploadContentTypeVerification(
  upload: UploadDef,
  file: UploadFileIntent,
): boolean {
  if (upload.file.contentTypeVerification === false) return false;

  if (hasContentTypeSignature(file.contentType)) return true;
  return Boolean(
    upload.file.contentTypes?.some((contentType) =>
      hasContentTypeSignature(contentType),
    ),
  );
}

async function verifyBlobUploadFile(
  upload: UploadDef,
  file: UploadFileIntent,
  blob: Blob,
): Promise<UploadFileBodyVerification> {
  if (!needsUploadBodyVerification(upload, file)) return {};

  const needsChecksum = needsUploadChecksumVerification(upload, file);
  const bytes = needsChecksum
    ? new Uint8Array(await blob.arrayBuffer())
    : new Uint8Array(
        await blob.slice(0, UPLOAD_SIGNATURE_MAX_BYTES).arrayBuffer(),
      );

  assertUploadContentTypeSignature(upload, file, bytes);

  if (!needsChecksum) return {};
  const checksum = await createUploadChecksum(bytes);
  assertUploadChecksum(upload, file, checksum);
  return { checksum };
}

async function verifyStoredUploadFile(
  upload: UploadDef,
  file: UploadFileIntent,
  object: StorageObject | StorageObjectBody,
): Promise<UploadFileBodyVerification> {
  if (!needsUploadBodyVerification(upload, file)) return {};

  if (!("bytes" in object)) {
    throw new InvalidUploadFileError({
      message: `Uploaded object "${object.key}" must be readable for verification.`,
      details: {
        key: object.key,
      },
    });
  }

  const needsChecksum = needsUploadChecksumVerification(upload, file);
  const bytes = needsChecksum
    ? await object.bytes()
    : await readObjectPrefix(object, UPLOAD_SIGNATURE_MAX_BYTES);

  assertUploadContentTypeSignature(upload, file, bytes);

  if (!needsChecksum) return {};
  const checksum = await createUploadChecksum(bytes);
  assertUploadChecksum(upload, file, checksum);
  return { checksum };
}

function storageObjectMetadata(object: StorageObject): StorageObject {
  return {
    key: object.key,
    size: object.size,
    ...(object.contentType !== undefined
      ? { contentType: object.contentType }
      : {}),
    ...(object.cacheControl !== undefined
      ? { cacheControl: object.cacheControl }
      : {}),
    metadata: object.metadata,
    visibility: object.visibility,
    lastModified: object.lastModified,
  };
}

function assertUploadContentTypeSignature(
  upload: UploadDef,
  file: UploadFileIntent,
  bytes: Uint8Array,
): void {
  if (upload.file.contentTypeVerification === false) return;

  const declaredContentType = normalizeContentType(file.contentType);
  const acceptedContentTypes =
    upload.file.contentTypes?.map(normalizeContentType) ?? [];
  const detectedContentType = detectSupportedContentType(bytes);

  if (
    detectedContentType &&
    acceptedContentTypes.length > 0 &&
    !acceptedContentTypes.includes(detectedContentType)
  ) {
    throw new InvalidUploadFileError({
      status: 415,
      message: `Upload "${upload.name}" does not accept detected content type "${detectedContentType}".`,
      details: {
        fileName: file.name,
        declaredContentType,
        detectedContentType,
        acceptedContentTypes,
      },
    });
  }

  if (
    hasContentTypeSignature(declaredContentType) &&
    !matchesContentTypeSignature(declaredContentType, bytes)
  ) {
    throw new InvalidUploadFileError({
      status: 415,
      message: `Upload "${upload.name}" content type "${declaredContentType}" does not match the file bytes.`,
      details: {
        fileName: file.name,
        expectedContentType: declaredContentType,
        detectedContentType: detectedContentType ?? "unknown",
      },
    });
  }
}

function assertUploadChecksum(
  upload: UploadDef,
  file: UploadFileIntent,
  actual: UploadFileChecksum,
): void {
  if (!file.checksum) return;

  if (file.checksum.value.toLowerCase() === actual.value) return;

  throw new InvalidUploadFileError({
    message: `Upload "${upload.name}" checksum does not match "${file.name}".`,
    details: {
      fileName: file.name,
      algorithm: "sha256",
      expected: file.checksum.value.toLowerCase(),
      actual: actual.value,
    },
  });
}

async function assertVerifiedFile<Metadata, Ctx>(
  upload: UploadDef<string, StandardSchema, Ctx>,
  args: UploadVerifyFileHookArgs<Metadata, Ctx>,
): Promise<void> {
  if (!upload.verifyFile) return;

  const result = await upload.verifyFile(
    args as UploadVerifyFileHookArgs<InferUploadMetadata<typeof upload>, Ctx>,
  );
  const invalid =
    result === false ||
    (typeof result === "object" &&
      result !== null &&
      "valid" in result &&
      result.valid === false);
  if (!invalid) return;

  throw new InvalidUploadFileError({
    message:
      typeof result === "object" && result?.reason
        ? result.reason
        : `Upload "${upload.name}" file "${args.file.name}" did not pass verification.`,
    details:
      typeof result === "object" && "details" in result
        ? result.details
        : {
            fileName: args.file.name,
            key: args.file.key,
          },
  });
}

async function readObjectPrefix(
  object: StorageObjectBody,
  maxBytes: number,
): Promise<Uint8Array> {
  const reader = object.stream().getReader();
  const chunks: Uint8Array[] = [];
  let total = 0;

  try {
    while (total < maxBytes) {
      const result = await reader.read();
      if (result.done) break;
      const remaining = maxBytes - total;
      const chunk =
        result.value.byteLength > remaining
          ? result.value.slice(0, remaining)
          : result.value;
      chunks.push(chunk);
      total += chunk.byteLength;
      if (result.value.byteLength > remaining) break;
    }
  } finally {
    await reader.cancel().catch(() => undefined);
    reader.releaseLock();
  }

  const bytes = new Uint8Array(total);
  let offset = 0;
  for (const chunk of chunks) {
    bytes.set(chunk, offset);
    offset += chunk.byteLength;
  }
  return bytes;
}

async function createUploadChecksum(
  bytes: Uint8Array,
): Promise<UploadFileChecksum> {
  if (!globalThis.crypto?.subtle) {
    throw new InvalidUploadFileError({
      message: "Upload checksum verification requires Web Crypto.",
    });
  }

  const buffer = new ArrayBuffer(bytes.byteLength);
  new Uint8Array(buffer).set(bytes);
  const digest = await globalThis.crypto.subtle.digest("SHA-256", buffer);
  return {
    algorithm: "sha256",
    value: bytesToHex(new Uint8Array(digest)),
  };
}

function bytesToHex(bytes: Uint8Array): string {
  return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

function isSha256Hex(value: string): boolean {
  return /^[a-f0-9]{64}$/i.test(value);
}

function normalizeContentType(contentType: string): string {
  return contentType.split(";")[0]?.trim().toLowerCase() ?? "";
}

function hasContentTypeSignature(contentType: string): boolean {
  return SIGNATURE_CONTENT_TYPES.has(normalizeContentType(contentType));
}

function matchesContentTypeSignature(
  contentType: string,
  bytes: Uint8Array,
): boolean {
  const normalized = normalizeContentType(contentType);
  switch (normalized) {
    case "application/pdf":
      return startsWithBytes(bytes, [0x25, 0x50, 0x44, 0x46, 0x2d]);
    case "application/zip":
      return (
        startsWithBytes(bytes, [0x50, 0x4b, 0x03, 0x04]) ||
        startsWithBytes(bytes, [0x50, 0x4b, 0x05, 0x06]) ||
        startsWithBytes(bytes, [0x50, 0x4b, 0x07, 0x08])
      );
    case "image/gif":
      return (
        startsWithAscii(bytes, "GIF87a") || startsWithAscii(bytes, "GIF89a")
      );
    case "image/jpeg":
      return startsWithBytes(bytes, [0xff, 0xd8, 0xff]);
    case "image/png":
      return startsWithBytes(
        bytes,
        [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
      );
    case "image/svg+xml":
      return looksLikeSvg(bytes);
    case "image/webp":
      return (
        startsWithAscii(bytes, "RIFF") &&
        bytes.length >= 12 &&
        asciiAt(bytes, 8, 4) === "WEBP"
      );
    default:
      return false;
  }
}

function detectSupportedContentType(bytes: Uint8Array): string | undefined {
  for (const contentType of SIGNATURE_CONTENT_TYPES) {
    if (matchesContentTypeSignature(contentType, bytes)) return contentType;
  }
  return undefined;
}

const SIGNATURE_CONTENT_TYPES = new Set([
  "application/pdf",
  "application/zip",
  "image/gif",
  "image/jpeg",
  "image/png",
  "image/svg+xml",
  "image/webp",
]);

function startsWithBytes(
  bytes: Uint8Array,
  prefix: readonly number[],
): boolean {
  if (bytes.length < prefix.length) return false;
  return prefix.every((byte, index) => bytes[index] === byte);
}

function startsWithAscii(bytes: Uint8Array, prefix: string): boolean {
  return asciiAt(bytes, 0, prefix.length) === prefix;
}

function asciiAt(bytes: Uint8Array, offset: number, length: number): string {
  return String.fromCharCode(...bytes.slice(offset, offset + length));
}

function looksLikeSvg(bytes: Uint8Array): boolean {
  const text = new TextDecoder()
    .decode(bytes)
    .replace(/^\uFEFF/, "")
    .trimStart()
    .toLowerCase();
  return (
    text.startsWith("<svg") ||
    (text.startsWith("<?xml") && text.includes("<svg"))
  );
}

async function assertAuthorized<Metadata, Ctx>(
  upload: UploadDef<string, StandardSchema, Ctx>,
  args: UploadFileHookArgs<Metadata, Ctx>,
): Promise<void> {
  if (!upload.authorize) {
    if ((upload.access ?? "protected") === "public") return;

    throw new UnauthorizedUploadError({
      message: `Upload "${upload.name}" must declare authorize(...) or set access: "public".`,
    });
  }

  const result = await upload.authorize?.(
    args as UploadFileHookArgs<InferUploadMetadata<typeof upload>, Ctx>,
  );
  const denied =
    result === false ||
    (typeof result === "object" &&
      result !== null &&
      "allowed" in result &&
      result.allowed === false);
  if (!denied) return;

  throw new UnauthorizedUploadError({
    message:
      typeof result === "object" && result?.reason
        ? result.reason
        : `Upload "${upload.name}" is not authorized.`,
  });
}

function assertStoredObject(
  upload: UploadDef,
  file: UploadFileIntent,
  object: StorageObject,
): void {
  assertFiles(upload, [file]);

  if (
    upload.file.maxSizeBytes !== undefined &&
    object.size > upload.file.maxSizeBytes
  ) {
    throw new InvalidUploadFileError({
      status: 413,
      message: `Uploaded object "${object.key}" exceeds the maximum file size.`,
      details: {
        size: object.size,
        maxSizeBytes: upload.file.maxSizeBytes,
      },
    });
  }

  if (object.size !== file.size) {
    throw new InvalidUploadFileError({
      message: `Uploaded object "${object.key}" size does not match the prepared file.`,
      details: {
        expected: file.size,
        actual: object.size,
      },
    });
  }

  if (
    object.contentType &&
    file.contentType &&
    normalizeContentType(object.contentType) !==
      normalizeContentType(file.contentType)
  ) {
    throw new InvalidUploadFileError({
      message: `Uploaded object "${object.key}" content type does not match the prepared file.`,
      details: {
        expected: file.contentType,
        actual: object.contentType,
      },
    });
  }
}

function metadataFromFormData(formData: FormData): unknown {
  const metadata = formData.get("metadata");
  if (typeof metadata !== "string") return {};

  try {
    return JSON.parse(metadata);
  } catch {
    throw new InvalidUploadBodyError({
      message: "Upload metadata must be valid JSON.",
    });
  }
}

function filesFromFormData(formData: FormData): File[] {
  const values = [...formData.getAll("file"), ...formData.getAll("files")];
  const files = values.filter((value): value is File => value instanceof File);
  if (files.length === 0) {
    throw new InvalidUploadBodyError({
      message: 'Multipart upload must include at least one "file" field.',
    });
  }
  return files;
}

function fileIntentFromFile(file: File): UploadFileIntent {
  const contentType =
    normalizeContentType(file.type) || "application/octet-stream";
  return {
    name: file.name,
    contentType,
    size: file.size,
  };
}

function jsonResponse(body: unknown, init?: ResponseInit): Response {
  const headers: Record<string, string> = {
    "content-type": "application/json",
  };
  if (init?.headers) {
    new Headers(init.headers).forEach((value, key) => {
      headers[key] = value;
    });
  }

  return new Response(JSON.stringify(body), {
    status: init?.status ?? 200,
    headers,
  });
}

function uploadErrorResponse(error: unknown): Response {
  if (error instanceof UploadError) {
    return jsonResponse(
      {
        code: error.code,
        message: error.message,
        ...(error.details !== undefined ? { details: error.details } : {}),
      },
      { status: error.status },
    );
  }

  return jsonResponse(
    {
      code: "INTERNAL_SERVER_ERROR",
      message: "Internal server error",
    },
    { status: 500 },
  );
}

function randomUploadId(): string {
  if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
    return crypto.randomUUID();
  }

  return `upload_${Math.random().toString(36).slice(2)}`;
}

function isUploadDef(value: UploadDef | UploadRegistry): value is UploadDef {
  return (
    typeof value === "object" &&
    value !== null &&
    "kind" in value &&
    value.kind === "upload"
  );
}