@vryzel/file-next 0.4.1 → 0.4.2
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/{filesystem-D1Jjx3md.d.ts → filesystem-B0bJh8bW.d.ts} +11 -0
- package/dist/{filesystem-BbZJLy4A.d.cts → filesystem-CewcaWEl.d.cts} +11 -0
- package/dist/index.cjs +137 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +137 -2
- package/dist/index.js.map +1 -1
- package/dist/server/index.cjs +14 -0
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +3 -2
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +14 -0
- package/dist/server/index.js.map +1 -1
- package/dist/sync/index.cjs +20 -0
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -1
- package/dist/sync/index.d.ts +5 -1
- package/dist/sync/index.js +20 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/{with-auth-BueIpNZ7.d.cts → with-auth-DDTngJoQ.d.cts} +1 -1
- package/dist/{with-auth-yfezt7YS.d.ts → with-auth-f82V2WB6.d.ts} +1 -1
- package/package.json +1 -1
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types/result.ts","../../src/errors/mappers.ts","../../src/errors/index.ts","../../src/types/branded.ts","../../src/server/actions.ts","../../src/server/route-handlers/upload.ts","../../src/server/route-handlers/download.ts"],"names":["err","MAX_EXPIRES_IN_SECONDS","DEFAULT_EXPIRES_IN_SECONDS","assertExpiresIn"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Discriminated `Result<T, E>` for typed error returns.\n *\n * Why Result over throw at boundaries:\n * - No `any` at the call site (vs try/catch which loses the type).\n * - `switch (r.ok)` narrows the type in consumer code.\n * - The wire shape `{ ok, value | error }` is JSON-serializable,\n * so it survives the RSC boundary without an extra DTO.\n * - Helpers (`map`, `andThen`, `unwrap`) make the common shapes\n * (chain, bail-out, recover) terse and exhaustive.\n *\n * The default error type is `FileSystemError` (see `@/errors`).\n * Consumers can specialize: `Result<User, ZodError>`.\n *\n * All helpers are pure functions; they do NOT allocate closures in\n * hot paths beyond what the spec demands (no `try`/`catch` wrapping).\n */\n\nimport { FileSystemError } from \"@/errors\";\n\nexport type Result<T, E = FileSystemError> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\n\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport const map = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => U,\n): Result<U, E> => (r.ok ? ok(f(r.value)) : r);\n\nexport const mapErr = <T, E, F>(\n r: Result<T, E>,\n f: (e: E) => F,\n): Result<T, F> => (r.ok ? r : err(f(r.error)));\n\nexport const andThen = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => Result<U, E>,\n): Result<U, E> => (r.ok ? f(r.value) : r);\n\nexport const unwrap = <T, E>(r: Result<T, E>): T => {\n if (r.ok) return r.value;\n throw r.error;\n};\n\nexport const unwrapOr = <T, E>(r: Result<T, E>, fallback: T): T =>\n r.ok ? r.value : fallback;\n","/**\n * Upstream error mappers for FileSystemError.\n *\n * Each mapper is a pure function `(*unknown) -> FileSystemError`.\n * The class re-exposes them as static methods (FileSystemError.fromAws\n * etc.) so callers can pick the import style that fits.\n *\n * Mapping strategy:\n * 1. If the input is already a FileSystemError, return it as-is\n * (we never re-wrap our own errors).\n * 2. Try the most specific signal first: S3 `name`, Postgres\n * SQLSTATE, SQLite extended code.\n * 3. Fall back to the HTTP status code (AWS SDK v3 exposes\n * `$metadata.httpStatusCode`).\n * 4. Last resort: InternalError, retryable, with the original\n * payload in `cause`.\n *\n * Provider-specific codes are preserved on `cause.code` (e.g. S3\n * \"NoSuchKey\", Postgres \"23505\") so callers can still branch on\n * them while the top-level `code` stays in the 11-code spec catalog.\n *\n * Mapping notes (post-C' merge, see\n * `sdd/file-next/decisions/error-codes-deviation`):\n * - S3 `SlowDown` -> QuotaExceeded (broader than RateLimited;\n * SlowDown means reduce request rate, which\n * is conceptually quota pressure, not\n * throttling of a single call).\n * - S3 `BadDigest` -> ChecksumMismatch (checksum verified by\n * S3 on upload did not match the client).\n * - HTTP 429 -> RateLimited (was QuotaExceeded in the\n * pre-C' catalog; RateLimited is the more\n * specific code for throttling responses).\n * - HTTP 408 -> NetworkError (transient transport error).\n * - HTTP 400 / Postgres 23514 / S3 InvalidRequest\n * -> fall through to the 4xx branch (no\n * top-level 400 code in the C' catalog;\n * these inputs are usually caught by the\n * name/SQLSTATE mapping first anyway).\n */\n\nimport { FileSystemError, type FileSystemErrorCode } from \"./index\";\n\n/* ---------------------------------------------------------------- *\n * Mapping tables (private) *\n * ---------------------------------------------------------------- */\n\ninterface CodeMapping {\n code: FileSystemErrorCode;\n retryable: boolean;\n}\n\nconst HTTP_STATUS_TO_CODE: Readonly<Record<number, CodeMapping>> = {\n 401: { code: \"Unauthorized\", retryable: false },\n 403: { code: \"Forbidden\", retryable: false },\n 404: { code: \"NotFound\", retryable: false },\n 408: { code: \"NetworkError\", retryable: true },\n 409: { code: \"Conflict\", retryable: false },\n 413: { code: \"PayloadTooLarge\", retryable: false },\n 415: { code: \"UnsupportedMediaType\", retryable: false },\n 429: { code: \"RateLimited\", retryable: true },\n};\n\nconst AWS_NAME_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n NoSuchKey: { code: \"NotFound\", retryable: false },\n NoSuchBucket: { code: \"NotFound\", retryable: false },\n // v0.2 multipart: unknown/aborted/expired uploadId.\n NoSuchUpload: { code: \"NotFound\", retryable: false },\n AccessDenied: { code: \"Forbidden\", retryable: false },\n SlowDown: { code: \"QuotaExceeded\", retryable: true },\n BadDigest: { code: \"ChecksumMismatch\", retryable: true },\n XAmzContentSHA256Mismatch: { code: \"ChecksumMismatch\", retryable: true },\n NetworkingError: { code: \"NetworkError\", retryable: true },\n TimeoutError: { code: \"NetworkError\", retryable: true },\n};\n\nconst PG_SQLSTATE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n \"23505\": { code: \"Conflict\", retryable: false },\n};\n\nconst SQLITE_CODE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n SQLITE_CONSTRAINT_UNIQUE: { code: \"Conflict\", retryable: false },\n SQLITE_CONSTRAINT_PRIMARYKEY: { code: \"Conflict\", retryable: false },\n};\n\n/* ---------------------------------------------------------------- *\n * Public mappers *\n * ---------------------------------------------------------------- */\n\nconst toCause = (code: string, message: string, extra?: Record<string, unknown>) => ({\n code,\n message,\n ...(extra ?? {}),\n});\n\nconst fallback = (err: unknown): FileSystemError =>\n new FileSystemError({\n code: \"InternalError\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n cause: toCause(\n \"Unknown\",\n err instanceof Error ? err.message : String(err),\n ),\n });\n\nexport const fromAws = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const awsErr = err as {\n name?: unknown;\n message?: unknown;\n $metadata?: { httpStatusCode?: unknown };\n };\n const name = typeof awsErr.name === \"string\" ? awsErr.name : undefined;\n const message =\n typeof awsErr.message === \"string\" ? awsErr.message : `AWS error: ${name ?? \"unknown\"}`;\n const status =\n typeof awsErr.$metadata?.httpStatusCode === \"number\"\n ? awsErr.$metadata.httpStatusCode\n : undefined;\n\n const cause = toCause(\n name ?? (status !== undefined ? String(status) : \"Unknown\"),\n message,\n status !== undefined ? { httpStatusCode: status } : undefined,\n );\n\n // 1) name-based mapping wins (more specific than HTTP status)\n if (name && name in AWS_NAME_TO_CODE) {\n const m = AWS_NAME_TO_CODE[name]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 2) HTTP status mapping\n if (status !== undefined && status in HTTP_STATUS_TO_CODE) {\n const m = HTTP_STATUS_TO_CODE[status]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 3) 5xx bucket\n if (status !== undefined && status >= 500 && status < 600) {\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n }\n\n // 4) anything else 4xx-shaped\n if (status !== undefined && status >= 400 && status < 500) {\n return new FileSystemError({ code: \"Forbidden\", message, retryable: false, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromPg = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const pgErr = err as { code?: unknown; message?: unknown };\n const sqlstate = typeof pgErr.code === \"string\" ? pgErr.code : undefined;\n const message =\n typeof pgErr.message === \"string\" ? pgErr.message : `Postgres error: ${sqlstate ?? \"unknown\"}`;\n const cause = toCause(sqlstate ?? \"Unknown\", message);\n\n if (sqlstate && sqlstate in PG_SQLSTATE_TO_CODE) {\n const m = PG_SQLSTATE_TO_CODE[sqlstate]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromSqlite = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const sqlErr = err as { code?: unknown; message?: unknown };\n const code = typeof sqlErr.code === \"string\" ? sqlErr.code : undefined;\n const message =\n typeof sqlErr.message === \"string\" ? sqlErr.message : `SQLite error: ${code ?? \"unknown\"}`;\n const cause = toCause(code ?? \"Unknown\", message);\n\n if (code && code in SQLITE_CODE_TO_CODE) {\n const m = SQLITE_CODE_TO_CODE[code]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n","/**\n * FileSystemError — the single error class every adapter, store,\n * server action, and route handler in `file-next` returns or throws.\n *\n * Spec reference: requirement \"FileSystemError discriminated union\"\n * in `sdd/file-next/spec`. The 11 codes are the CLOSED set; any\n * provider-specific code (e.g. S3 `NoSuchKey`, Postgres `23505`) is\n * preserved on `cause.code` so callers can still distinguish upstream\n * reasons while the top-level `code` stays in the catalog.\n *\n * The catalog is a merge of spec + impl: the 6 fixed codes\n * (NotFound, Forbidden, Conflict, QuotaExceeded, NetworkError,\n * InternalError) are non-negotiable; the remaining 5 keep the wire\n * aligned with both the HTTP boundary (route handlers map the\n * top-level `code` to a status directly) and the storage boundary\n * (`RateLimited` and `ChecksumMismatch` carry semantics that have\n * no natural HTTP equivalent). See\n * `sdd/file-next/decisions/error-codes-deviation` for the\n * deviation log and rationale.\n *\n * Retryability table is the design's `error-mapping` excerpt; see\n * `sdd/file-next/design` §C. Any future code MUST add an entry in\n * `RETRYABLE_BY_CODE` (the catalog test enforces this).\n *\n * The placeholder from T-006 is replaced by this file in T-007a.\n * The upstream mappers (fromAws / fromPg / fromSqlite) land in T-007b\n * in `mappers.ts`.\n */\n\nexport const FILE_SYSTEM_ERROR_CODES = [\n \"NotFound\",\n \"Forbidden\",\n \"Conflict\",\n \"QuotaExceeded\",\n \"NetworkError\",\n \"InternalError\",\n \"Unauthorized\",\n \"PayloadTooLarge\",\n \"UnsupportedMediaType\",\n \"RateLimited\",\n \"ChecksumMismatch\",\n] as const satisfies readonly string[];\n\nexport type FileSystemErrorCode = (typeof FILE_SYSTEM_ERROR_CODES)[number];\n\nexport const RETRYABLE_BY_CODE: Readonly<Record<FileSystemErrorCode, boolean>> = {\n NotFound: false,\n Forbidden: false,\n Conflict: false,\n QuotaExceeded: true,\n NetworkError: true,\n InternalError: true,\n Unauthorized: false,\n PayloadTooLarge: false,\n UnsupportedMediaType: false,\n RateLimited: true,\n ChecksumMismatch: true,\n};\n\nexport interface FileSystemErrorOptions {\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport interface FileSystemErrorJson {\n name: string;\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport class FileSystemError extends Error {\n readonly code: FileSystemErrorCode;\n readonly retryable: boolean;\n override readonly cause?: { code: string; message: string; [k: string]: unknown };\n\n constructor(opts: FileSystemErrorOptions) {\n super(opts.message);\n this.name = \"FileSystemError\";\n this.code = opts.code;\n this.retryable = opts.retryable;\n if (opts.cause !== undefined) {\n this.cause = opts.cause;\n }\n }\n\n /**\n * Stable JSON shape for RSC pass-through. Error.prototype.message\n * is non-enumerable, so plain `JSON.stringify(err)` would emit `{}`\n * and lose the message + code + retryable flag. `cause` is omitted\n * entirely (not set to undefined) when absent so the shape stays\n * stable for hash-based caches.\n */\n toJSON(): FileSystemErrorJson {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n ...(this.cause !== undefined ? { cause: this.cause } : {}),\n };\n }\n\n /**\n * Mappers from upstream error shapes (AWS SDK v3, node-postgres,\n * better-sqlite3) to FileSystemError. See `./mappers.ts` for the\n * mapping tables. Re-exposed as static methods so callers can pick\n * the import style that fits; the free functions are the canonical\n * implementation.\n */\n static fromAws(err: unknown): FileSystemError {\n // Lazy import via the runtime binding avoids the static-field\n // circular-dep trap in ESM. The mapper file imports this class\n // for instanceof checks; we look up the function at call time.\n return _fromAws(err);\n }\n\n static fromPg(err: unknown): FileSystemError {\n return _fromPg(err);\n }\n\n static fromSqlite(err: unknown): FileSystemError {\n return _fromSqlite(err);\n }\n}\n\n// Imported here as bindings (not values) so the static methods above\n// can resolve them lazily. The actual implementation lives in mappers.ts.\nimport { fromAws as _fromAws, fromPg as _fromPg, fromSqlite as _fromSqlite } from \"./mappers\";\nexport { fromAws, fromPg, fromSqlite } from \"./mappers\";\n","/**\n * Branded string types and their constructors/guards.\n *\n * Brands are TypeScript-only fictions: a `Path` and an `S3Key` are\n * both strings at runtime, but the type system treats them as\n * distinct nominal types so the compiler catches accidental\n * cross-assignment (e.g. passing an S3Key where a TenantId is\n * expected).\n *\n * Conventions:\n * - `as*` is a zero-cost cast: trust the caller, brand the value.\n * Use it at trust boundaries you have already validated.\n * - `assert*` is a runtime guard: throws TypeError on invalid\n * input. Use it at the edge (parsing user/env input).\n *\n * Validation rules are intentionally minimal in v0.1 and can be\n * tightened as the spec evolves. None of them touch the network or\n * allocate; they are safe in hot paths.\n */\n\nexport type Path = string & { readonly __brand: \"Path\" };\nexport type Prefix = string & { readonly __brand: \"Prefix\" };\nexport type S3Key = string & { readonly __brand: \"S3Key\" };\nexport type TenantId = string & { readonly __brand: \"TenantId\" };\nexport type UserId = string & { readonly __brand: \"UserId\" };\n\n/**\n * POSIX file path. Non-empty, '/' is allowed as the root.\n */\nexport const asPath = (s: string): Path => s as Path;\nexport const assertPath = (s: string): Path => {\n if (s.length === 0) {\n throw new TypeError(\"Path must be a non-empty string\");\n }\n return s as Path;\n};\n\n/**\n * S3 prefix. Empty string is the root prefix. Non-empty prefixes\n * MUST end with '/' so concatenation with a key never produces\n * 'usersfile.jpg' by accident.\n */\nexport const asPrefix = (s: string): Prefix => s as Prefix;\nexport const assertPrefix = (s: string): Prefix => {\n if (s.length > 0 && !s.endsWith(\"/\")) {\n throw new TypeError(\n `Prefix must end with \"/\" or be empty: ${JSON.stringify(s)}`,\n );\n }\n return s as Prefix;\n};\n\n/**\n * S3 object key. No leading slash, no empty segments, no '..' hops.\n */\nexport const asS3Key = (s: string): S3Key => s as S3Key;\nexport const assertS3Key = (s: string): S3Key => {\n if (s.length === 0) {\n throw new TypeError(\"S3Key must be a non-empty string\");\n }\n if (s.startsWith(\"/\")) {\n throw new TypeError(\n `S3Key must not start with a slash: ${JSON.stringify(s)}`,\n );\n }\n if (s.includes(\"..\")) {\n throw new TypeError(\n `S3Key must not contain '..' segments: ${JSON.stringify(s)}`,\n );\n }\n return s as S3Key;\n};\n\n/**\n * Tenant identifier. Alphanumerics, dashes, underscores only.\n */\nexport const asTenantId = (s: string): TenantId => s as TenantId;\nexport const assertTenantId = (s: string): TenantId => {\n if (s.length === 0 || !/^[a-zA-Z0-9_-]+$/.test(s)) {\n throw new TypeError(`Invalid TenantId: ${JSON.stringify(s)}`);\n }\n return s as TenantId;\n};\n\n/**\n * Opaque user identifier. Non-empty; the format is provider-defined.\n */\nexport const asUserId = (s: string): UserId => s as UserId;\nexport const assertUserId = (s: string): UserId => {\n if (s.length === 0) {\n throw new TypeError(\"UserId must be a non-empty string\");\n }\n return s as UserId;\n};\n","/**\n * Server actions — tenant comes from getAuth(), never from the client.\n */\nimport { z } from \"zod\";\nimport { ok, err, type Result } from \"@/types/result\";\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key, asTenantId, type TenantId } from \"@/types/branded\";\nimport type { AuthContext } from \"../auth/with-auth\";\nimport type { MetadataStore, FileNode } from \"../metadata/store\";\nimport type { FileSystem } from \"../storage/filesystem\";\nimport type { createWriteThrough } from \"../sync/write-through\";\n\ntype CreateWriteThrough = ReturnType<typeof createWriteThrough>;\n\nconst NodeIdSchema = z.string().min(1, \"id is required\");\nconst PathSchema = z.string().nullable();\n\nexport const ListFilesInputSchema = z.object({\n parentId: PathSchema,\n limit: z.number().int().positive().optional(),\n cursor: z.string().optional(),\n});\n\nexport const DeleteFileInputSchema = z.object({\n id: NodeIdSchema,\n recursive: z.boolean().optional(),\n});\n\nexport const MoveFileInputSchema = z.object({\n id: NodeIdSchema,\n newParentId: PathSchema,\n newName: z.string().min(1).max(255).optional(),\n});\n\nexport const CopyFileInputSchema = z.object({\n id: NodeIdSchema,\n newParentId: PathSchema,\n newName: z.string().min(1).max(255).optional(),\n});\n\nexport const SetMetadataInputSchema = z.object({\n id: NodeIdSchema,\n metadata: z.record(z.string()),\n replace: z.boolean().optional(),\n});\n\nexport const CreateFolderInputSchema = z.object({\n parentId: PathSchema,\n name: z.string().min(1).max(255),\n});\n\nexport const PrepareUploadInputSchema = z.object({\n parentId: PathSchema,\n name: z.string().min(1).max(255),\n contentType: z.string().min(1),\n contentLength: z.number().int().nonnegative(),\n});\n\nexport const ConfirmUploadInputSchema = z.object({\n id: NodeIdSchema,\n parentId: PathSchema,\n name: z.string().min(1).max(255),\n contentType: z.string().optional(),\n size: z.number().int().nonnegative().optional(),\n});\n\nexport const SearchFilesInputSchema = z.object({\n query: z.string(),\n parentId: z.string().optional(),\n limit: z.number().int().positive().optional(),\n});\n\nexport const RestoreNodeInputSchema = z.object({\n id: NodeIdSchema,\n});\n\nexport const CreateShareInputSchema = z.object({\n id: NodeIdSchema,\n});\n\nexport const ResolveShareInputSchema = z.object({\n token: z.string().min(1),\n});\n\nexport const RevokeShareInputSchema = z.object({\n token: z.string().min(1),\n});\n\nconst zodErr = (message: string, parsed: z.SafeParseError<unknown>) =>\n err(\n new FileSystemError({\n code: \"InternalError\",\n message,\n retryable: false,\n cause: { code: \"ZodError\", message: parsed.error.message, issues: parsed.error.issues },\n }),\n );\n\nexport interface ServerActionsDeps {\n readonly store: MetadataStore;\n readonly writeThrough: CreateWriteThrough;\n readonly fs: FileSystem;\n readonly getAuth: () => AuthContext | Promise<AuthContext>;\n}\n\nexport const createServerActions = (deps: ServerActionsDeps) => {\n const { store, writeThrough, fs, getAuth } = deps;\n\n const wrap = (e: unknown, code: FileSystemError[\"code\"], message: string): FileSystemError => {\n if (e instanceof FileSystemError) return e;\n return new FileSystemError({\n code,\n message: `${message}: ${e instanceof Error ? e.message : String(e)}`,\n retryable: true,\n });\n };\n\n const authTenant = async (): Promise<AuthContext> => getAuth();\n\n const listFiles = async (\n input: z.infer<typeof ListFilesInputSchema>,\n ): Promise<Result<ListFilesOutput, FileSystemError>> => {\n const parsed = ListFilesInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid listFiles input\", parsed);\n try {\n const auth = await authTenant();\n return store.listChildren({\n tenantId: asTenantId(auth.tenantId),\n parentId: parsed.data.parentId,\n limit: parsed.data.limit,\n cursor: parsed.data.cursor,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"listFiles failed\"));\n }\n };\n\n const deleteFile = async (\n input: z.infer<typeof DeleteFileInputSchema>,\n ): Promise<Result<void, FileSystemError>> => {\n const parsed = DeleteFileInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid deleteFile input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.deleteThroughFile({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n recursive: parsed.data.recursive,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"deleteFile failed\"));\n }\n };\n\n const moveFile = async (\n input: z.infer<typeof MoveFileInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = MoveFileInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid moveFile input\", parsed);\n try {\n const auth = await authTenant();\n return store.moveNode({\n tenantId: asTenantId(auth.tenantId),\n id: parsed.data.id,\n newParentId: parsed.data.newParentId,\n newName: parsed.data.newName,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"moveFile failed\"));\n }\n };\n\n const copyFile = async (\n input: z.infer<typeof CopyFileInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = CopyFileInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid copyFile input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.copyThroughFile({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n newParentId: parsed.data.newParentId,\n newName: parsed.data.newName,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"copyFile failed\"));\n }\n };\n\n const setMetadata = async (\n input: z.infer<typeof SetMetadataInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = SetMetadataInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid setMetadata input\", parsed);\n try {\n const auth = await authTenant();\n return store.updateMetadata({\n tenantId: asTenantId(auth.tenantId),\n id: parsed.data.id,\n metadata: parsed.data.metadata,\n replace: parsed.data.replace,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"setMetadata failed\"));\n }\n };\n\n const createFolder = async (\n input: z.infer<typeof CreateFolderInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = CreateFolderInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid createFolder input\", parsed);\n try {\n const auth = await authTenant();\n return store.createNode({\n tenantId: asTenantId(auth.tenantId),\n parentId: parsed.data.parentId,\n name: parsed.data.name,\n kind: \"folder\",\n size: 0,\n mimeType: \"\",\n s3Key: \"\",\n ownerId: auth.userId,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"createFolder failed\"));\n }\n };\n\n const prepareUpload = async (\n input: z.infer<typeof PrepareUploadInputSchema>,\n ): Promise<Result<PrepareUploadOutput, FileSystemError>> => {\n const parsed = PrepareUploadInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid prepareUpload input\", parsed);\n try {\n const auth = await authTenant();\n const id =\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : `upl-${Date.now()}`;\n const signed = await fs.forTenant(auth.tenantId).adapter.createPresignedUploadUrl({\n key: asS3Key(id),\n contentType: parsed.data.contentType,\n expiresIn: 900,\n });\n if (!signed.ok) return signed;\n return ok({\n id,\n key: id,\n url: signed.value.url,\n method: signed.value.method,\n headers: signed.value.requiredHeaders ?? {},\n expiresAt: new Date(Date.now() + 900_000).toISOString(),\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"prepareUpload failed\"));\n }\n };\n\n const confirmUpload = async (\n input: z.infer<typeof ConfirmUploadInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = ConfirmUploadInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid confirmUpload input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.confirmUpload({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n parentId: parsed.data.parentId,\n name: parsed.data.name,\n contentType: parsed.data.contentType,\n size: parsed.data.size,\n ownerId: auth.userId,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"confirmUpload failed\"));\n }\n };\n\n const searchFiles = async (\n input: z.infer<typeof SearchFilesInputSchema>,\n ): Promise<Result<ListFilesOutput, FileSystemError>> => {\n const parsed = SearchFilesInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid searchFiles input\", parsed);\n try {\n const auth = await authTenant();\n return store.search({\n tenantId: asTenantId(auth.tenantId),\n query: parsed.data.query,\n parentId: parsed.data.parentId,\n limit: parsed.data.limit,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"searchFiles failed\"));\n }\n };\n\n const listTrash = async (\n input: { limit?: number; cursor?: string } = {},\n ): Promise<Result<ListFilesOutput, FileSystemError>> => {\n try {\n const auth = await authTenant();\n return store.listTrash({\n tenantId: asTenantId(auth.tenantId),\n limit: input.limit,\n cursor: input.cursor,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"listTrash failed\"));\n }\n };\n\n const restoreNode = async (\n input: z.infer<typeof RestoreNodeInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = RestoreNodeInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid restoreNode input\", parsed);\n try {\n const auth = await authTenant();\n return store.restoreNode({\n tenantId: asTenantId(auth.tenantId),\n id: parsed.data.id,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"restoreNode failed\"));\n }\n };\n\n const createShare = async (\n input: z.infer<typeof CreateShareInputSchema>,\n ): Promise<Result<{ token: string }, FileSystemError>> => {\n const parsed = CreateShareInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid createShare input\", parsed);\n try {\n const auth = await authTenant();\n return store.createShare({\n tenantId: asTenantId(auth.tenantId),\n nodeId: parsed.data.id,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"createShare failed\"));\n }\n };\n\n const resolveShare = async (\n input: z.infer<typeof ResolveShareInputSchema>,\n ): Promise<Result<FileNode | null, FileSystemError>> => {\n const parsed = ResolveShareInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid resolveShare input\", parsed);\n try {\n return store.resolveShare({ token: parsed.data.token });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"resolveShare failed\"));\n }\n };\n\n const revokeShare = async (\n input: z.infer<typeof RevokeShareInputSchema>,\n ): Promise<Result<void, FileSystemError>> => {\n const parsed = RevokeShareInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid revokeShare input\", parsed);\n try {\n const auth = await authTenant();\n return store.revokeShare({\n tenantId: asTenantId(auth.tenantId),\n token: parsed.data.token,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"revokeShare failed\"));\n }\n };\n\n return {\n listFiles,\n deleteFile,\n moveFile,\n copyFile,\n setMetadata,\n createFolder,\n prepareUpload,\n confirmUpload,\n searchFiles,\n listTrash,\n restoreNode,\n createShare,\n resolveShare,\n revokeShare,\n };\n};\n\nexport interface ListFilesOutput {\n readonly items: ReadonlyArray<FileNode>;\n readonly nextCursor?: string;\n}\n\nexport interface PrepareUploadOutput {\n readonly id: string;\n readonly key: string;\n readonly url: string;\n readonly method: \"PUT\" | \"POST\";\n readonly headers: Record<string, string>;\n readonly expiresAt: string;\n}\n\nexport type { TenantId };\n","/**\n * `createUploadRouteHandler` — the Next.js Route Handler factory\n * for the presigned-URL upload flow.\n *\n * The client flow:\n * 1. Client POSTs `{ key, contentType, contentLength }` to this\n * route (typically `/api/files/upload`).\n * 2. Route validates `contentLength` against `maxBytes` (413) and\n * `contentType` against `allowedContentTypes` (415). No URL\n * is signed on a rejected request.\n * 3. Route calls `fs.adapter.createPresignedUploadUrl({ key,\n * contentType, expiresIn })` and returns `{ url, key,\n * expiresAt }`.\n * 4. Client PUTs the file body to the signed URL (bypassing the\n * Next.js server entirely).\n *\n * Spec scenarios: `route-handlers#1` (maxBytes), `route-handlers#2`\n * (allowedContentTypes).\n *\n * Construction-time validation: `expiresIn` is validated when the\n * factory is called (synchronous throw), per decision\n * `sdd/file-next/design/decision/expiresin-cap-timing`. A handler\n * built with `expiresIn: 30 * 86400` should never reach runtime —\n * the developer should see the error at server startup, not on\n * the first user request.\n */\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key } from \"@/types/branded\";\nimport type { FileSystem } from \"@/storage/filesystem\";\nimport type { AuthContext } from \"../../auth/with-auth\";\n\n/** S3 SigV4 presign hard cap. The SDK itself rejects anything longer. */\nconst MAX_EXPIRES_IN_SECONDS = 7 * 24 * 60 * 60;\n/** Default 15 minutes — matches the adapter default and the AWS SDK default. */\nconst DEFAULT_EXPIRES_IN_SECONDS = 900;\n\n/**\n * Convert a glob pattern (`image/*`) to a regex; convert a literal\n * (`image/png`) to an exact match. Both forms are common in\n * `allowedContentTypes` arrays.\n */\nconst matchesContentType = (pattern: string, actual: string): boolean => {\n if (pattern === actual) return true;\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -1); // \"image/*\" → \"image/\"\n return actual.startsWith(prefix);\n }\n return false;\n};\n\nexport interface CreateUploadRouteHandlerOptions {\n readonly fs: FileSystem;\n /** Resolve the caller. 401 when it returns null. */\n readonly getAuth?: (req: Request) => Promise<AuthContext | null>;\n /** Reject requests whose `contentLength` exceeds this. Omit for no cap. */\n readonly maxBytes?: number;\n /**\n * Reject requests whose `contentType` is not in this list.\n * Each entry is a literal (`image/png`) or a wildcard (`image/*`).\n * Omit for no restriction.\n */\n readonly allowedContentTypes?: ReadonlyArray<string>;\n /** Presigned URL lifetime in seconds. Default 900, max 7d (S3 SigV4). */\n readonly expiresIn?: number;\n}\n\nexport interface UploadRouteHandlerRequest {\n key: string;\n contentType: string;\n contentLength: number;\n}\n\nexport interface UploadRouteHandlerResult {\n url: string;\n key: string;\n expiresAt: string;\n}\n\n/**\n * Validate `expiresIn` against the S3 SigV4 hard cap. Throws\n * `FileSystemError(InternalError)` with `cause.code: \"InvalidArgument\"`\n * if the value is out of range. The top-level code stays in the\n * closed 11-code catalog; the specific reason lives on `cause`.\n */\nconst assertExpiresIn = (expiresIn: number): void => {\n if (!Number.isFinite(expiresIn) || expiresIn < 1 || expiresIn > MAX_EXPIRES_IN_SECONDS) {\n throw new FileSystemError({\n code: \"InternalError\",\n message: `expiresIn must be between 1 and ${MAX_EXPIRES_IN_SECONDS} seconds (S3 SigV4 limit)`,\n retryable: false,\n cause: { code: \"InvalidArgument\", message: `expiresIn=${expiresIn}` },\n });\n }\n};\n\n/**\n * Build a Next.js Route Handler `(req) => Response` that signs a\n * presigned upload URL after validating the request.\n */\nexport const createUploadRouteHandler = (\n opts: CreateUploadRouteHandlerOptions,\n): ((req: Request) => Promise<Response>) => {\n const expiresIn = opts.expiresIn ?? DEFAULT_EXPIRES_IN_SECONDS;\n // Construction-time validation: fail-fast on misconfiguration.\n assertExpiresIn(expiresIn);\n\n return async (req: Request): Promise<Response> => {\n let body: UploadRouteHandlerRequest;\n try {\n body = (await req.json()) as UploadRouteHandlerRequest;\n } catch {\n return Response.json(\n { ok: false, error: { code: \"InternalError\", message: \"Request body must be valid JSON\" } },\n { status: 400 },\n );\n }\n\n // 1. maxBytes — reject BEFORE signing\n if (typeof opts.maxBytes === \"number\" && body.contentLength > opts.maxBytes) {\n return Response.json(\n {\n ok: false,\n error: {\n code: \"PayloadTooLarge\",\n message: `contentLength ${body.contentLength} exceeds maxBytes ${opts.maxBytes}`,\n },\n },\n { status: 413 },\n );\n }\n\n // 2. allowedContentTypes — reject BEFORE signing\n if (opts.allowedContentTypes && opts.allowedContentTypes.length > 0) {\n const allowed = opts.allowedContentTypes.some((p) => matchesContentType(p, body.contentType));\n if (!allowed) {\n return Response.json(\n {\n ok: false,\n error: {\n code: \"UnsupportedMediaType\",\n message: `contentType \"${body.contentType}\" is not in the allowed list`,\n },\n },\n { status: 415 },\n );\n }\n }\n\n let fs = opts.fs;\n if (opts.getAuth) {\n const auth = await opts.getAuth(req);\n if (!auth) {\n return Response.json(\n { ok: false, error: { code: \"Unauthorized\", message: \"Not authenticated\" } },\n { status: 401 },\n );\n }\n fs = opts.fs.forTenant(auth.tenantId);\n }\n\n const id =\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : `upl-${Date.now()}`;\n const r = await fs.adapter.createPresignedUploadUrl({\n key: asS3Key(id),\n contentType: body.contentType,\n expiresIn,\n });\n if (!r.ok) {\n return Response.json(\n { ok: false, error: { code: r.error.code, message: r.error.message } },\n { status: 500 },\n );\n }\n\n const expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n return Response.json({\n ok: true,\n value: {\n url: r.value.url,\n key: id,\n id,\n method: r.value.method,\n headers: r.value.requiredHeaders ?? {},\n expiresAt,\n },\n });\n };\n};\n","/**\n * `createDownloadRouteHandler` — the Next.js Route Handler factory\n * for the presigned-URL download flow.\n *\n * The client flow:\n * 1. Client GETs `/api/files/download?key=uploads/report.pdf`.\n * 2. Route calls `fs.adapter.createPresignedDownloadUrl({ key,\n * expiresIn })` and returns `{ url, expiresAt }`.\n * 3. Client GETs the signed URL (bypassing the Next.js server).\n *\n * Spec scenario: `route-handlers#3` — `X-Amz-Expires=900` is present\n * in the signed URL and `expiresAt` is `now + 900s`.\n *\n * Construction-time validation: same `expiresIn` policy as the\n * upload handler (see `expiresin-cap-timing` decision). The cap\n * lives at the factory level, not the adapter, so a misconfigured\n * handler fails fast at server startup.\n */\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key } from \"@/types/branded\";\nimport type { FileSystem } from \"@/storage/filesystem\";\nimport type { AuthContext } from \"../../auth/with-auth\";\n\n/** S3 SigV4 presign hard cap. The SDK itself rejects anything longer. */\nconst MAX_EXPIRES_IN_SECONDS = 7 * 24 * 60 * 60;\n/** Default 15 minutes — matches the adapter default and the AWS SDK default. */\nconst DEFAULT_EXPIRES_IN_SECONDS = 900;\n\nexport interface CreateDownloadRouteHandlerOptions {\n readonly fs: FileSystem;\n readonly getAuth?: (req: Request) => Promise<AuthContext | null>;\n /** Presigned URL lifetime in seconds. Default 900, max 7d (S3 SigV4). */\n readonly expiresIn?: number;\n}\n\nexport interface DownloadRouteHandlerResult {\n url: string;\n expiresAt: string;\n}\n\n/**\n * Validate `expiresIn` against the S3 SigV4 hard cap. Throws\n * `FileSystemError(InternalError)` with `cause.code: \"InvalidArgument\"`\n * if the value is out of range.\n */\nconst assertExpiresIn = (expiresIn: number): void => {\n if (!Number.isFinite(expiresIn) || expiresIn < 1 || expiresIn > MAX_EXPIRES_IN_SECONDS) {\n throw new FileSystemError({\n code: \"InternalError\",\n message: `expiresIn must be between 1 and ${MAX_EXPIRES_IN_SECONDS} seconds (S3 SigV4 limit)`,\n retryable: false,\n cause: { code: \"InvalidArgument\", message: `expiresIn=${expiresIn}` },\n });\n }\n};\n\n/**\n * Build a Next.js Route Handler `(req) => Response` that signs a\n * presigned GET URL.\n *\n * The `key` is read from the `?key=` query param. The handler does\n * NOT do any body / content-type / size validation (downloads\n * don't have those concerns); the only chokepoint is the\n * construction-time `expiresIn` cap.\n */\nexport const createDownloadRouteHandler = (\n opts: CreateDownloadRouteHandlerOptions,\n): ((req: Request) => Promise<Response>) => {\n const expiresIn = opts.expiresIn ?? DEFAULT_EXPIRES_IN_SECONDS;\n assertExpiresIn(expiresIn);\n\n return async (req: Request): Promise<Response> => {\n const url = new URL(req.url);\n const key = url.searchParams.get(\"key\");\n if (!key) {\n return Response.json(\n { ok: false, error: { code: \"InternalError\", message: \"Missing required query param: key\" } },\n { status: 400 },\n );\n }\n\n let fs = opts.fs;\n if (opts.getAuth) {\n const auth = await opts.getAuth(req);\n if (!auth) {\n return Response.json(\n { ok: false, error: { code: \"Unauthorized\", message: \"Not authenticated\" } },\n { status: 401 },\n );\n }\n fs = opts.fs.forTenant(auth.tenantId);\n }\n\n const r = await fs.adapter.createPresignedDownloadUrl({\n key: asS3Key(key),\n expiresIn,\n });\n if (!r.ok) {\n return Response.json(\n { ok: false, error: { code: r.error.code, message: r.error.message } },\n { status: 500 },\n );\n }\n\n const expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n return Response.json({\n ok: true,\n value: { url: r.value.url, expiresAt },\n });\n };\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/types/result.ts","../../src/errors/mappers.ts","../../src/errors/index.ts","../../src/types/branded.ts","../../src/server/actions.ts","../../src/server/route-handlers/upload.ts","../../src/server/route-handlers/download.ts"],"names":["err","MAX_EXPIRES_IN_SECONDS","DEFAULT_EXPIRES_IN_SECONDS","assertExpiresIn"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Discriminated `Result<T, E>` for typed error returns.\n *\n * Why Result over throw at boundaries:\n * - No `any` at the call site (vs try/catch which loses the type).\n * - `switch (r.ok)` narrows the type in consumer code.\n * - The wire shape `{ ok, value | error }` is JSON-serializable,\n * so it survives the RSC boundary without an extra DTO.\n * - Helpers (`map`, `andThen`, `unwrap`) make the common shapes\n * (chain, bail-out, recover) terse and exhaustive.\n *\n * The default error type is `FileSystemError` (see `@/errors`).\n * Consumers can specialize: `Result<User, ZodError>`.\n *\n * All helpers are pure functions; they do NOT allocate closures in\n * hot paths beyond what the spec demands (no `try`/`catch` wrapping).\n */\n\nimport { FileSystemError } from \"@/errors\";\n\nexport type Result<T, E = FileSystemError> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\n\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport const map = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => U,\n): Result<U, E> => (r.ok ? ok(f(r.value)) : r);\n\nexport const mapErr = <T, E, F>(\n r: Result<T, E>,\n f: (e: E) => F,\n): Result<T, F> => (r.ok ? r : err(f(r.error)));\n\nexport const andThen = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => Result<U, E>,\n): Result<U, E> => (r.ok ? f(r.value) : r);\n\nexport const unwrap = <T, E>(r: Result<T, E>): T => {\n if (r.ok) return r.value;\n throw r.error;\n};\n\nexport const unwrapOr = <T, E>(r: Result<T, E>, fallback: T): T =>\n r.ok ? r.value : fallback;\n","/**\n * Upstream error mappers for FileSystemError.\n *\n * Each mapper is a pure function `(*unknown) -> FileSystemError`.\n * The class re-exposes them as static methods (FileSystemError.fromAws\n * etc.) so callers can pick the import style that fits.\n *\n * Mapping strategy:\n * 1. If the input is already a FileSystemError, return it as-is\n * (we never re-wrap our own errors).\n * 2. Try the most specific signal first: S3 `name`, Postgres\n * SQLSTATE, SQLite extended code.\n * 3. Fall back to the HTTP status code (AWS SDK v3 exposes\n * `$metadata.httpStatusCode`).\n * 4. Last resort: InternalError, retryable, with the original\n * payload in `cause`.\n *\n * Provider-specific codes are preserved on `cause.code` (e.g. S3\n * \"NoSuchKey\", Postgres \"23505\") so callers can still branch on\n * them while the top-level `code` stays in the 11-code spec catalog.\n *\n * Mapping notes (post-C' merge, see\n * `sdd/file-next/decisions/error-codes-deviation`):\n * - S3 `SlowDown` -> QuotaExceeded (broader than RateLimited;\n * SlowDown means reduce request rate, which\n * is conceptually quota pressure, not\n * throttling of a single call).\n * - S3 `BadDigest` -> ChecksumMismatch (checksum verified by\n * S3 on upload did not match the client).\n * - HTTP 429 -> RateLimited (was QuotaExceeded in the\n * pre-C' catalog; RateLimited is the more\n * specific code for throttling responses).\n * - HTTP 408 -> NetworkError (transient transport error).\n * - HTTP 400 / Postgres 23514 / S3 InvalidRequest\n * -> fall through to the 4xx branch (no\n * top-level 400 code in the C' catalog;\n * these inputs are usually caught by the\n * name/SQLSTATE mapping first anyway).\n */\n\nimport { FileSystemError, type FileSystemErrorCode } from \"./index\";\n\n/* ---------------------------------------------------------------- *\n * Mapping tables (private) *\n * ---------------------------------------------------------------- */\n\ninterface CodeMapping {\n code: FileSystemErrorCode;\n retryable: boolean;\n}\n\nconst HTTP_STATUS_TO_CODE: Readonly<Record<number, CodeMapping>> = {\n 401: { code: \"Unauthorized\", retryable: false },\n 403: { code: \"Forbidden\", retryable: false },\n 404: { code: \"NotFound\", retryable: false },\n 408: { code: \"NetworkError\", retryable: true },\n 409: { code: \"Conflict\", retryable: false },\n 413: { code: \"PayloadTooLarge\", retryable: false },\n 415: { code: \"UnsupportedMediaType\", retryable: false },\n 429: { code: \"RateLimited\", retryable: true },\n};\n\nconst AWS_NAME_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n NoSuchKey: { code: \"NotFound\", retryable: false },\n NoSuchBucket: { code: \"NotFound\", retryable: false },\n // v0.2 multipart: unknown/aborted/expired uploadId.\n NoSuchUpload: { code: \"NotFound\", retryable: false },\n AccessDenied: { code: \"Forbidden\", retryable: false },\n SlowDown: { code: \"QuotaExceeded\", retryable: true },\n BadDigest: { code: \"ChecksumMismatch\", retryable: true },\n XAmzContentSHA256Mismatch: { code: \"ChecksumMismatch\", retryable: true },\n NetworkingError: { code: \"NetworkError\", retryable: true },\n TimeoutError: { code: \"NetworkError\", retryable: true },\n};\n\nconst PG_SQLSTATE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n \"23505\": { code: \"Conflict\", retryable: false },\n};\n\nconst SQLITE_CODE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n SQLITE_CONSTRAINT_UNIQUE: { code: \"Conflict\", retryable: false },\n SQLITE_CONSTRAINT_PRIMARYKEY: { code: \"Conflict\", retryable: false },\n};\n\n/* ---------------------------------------------------------------- *\n * Public mappers *\n * ---------------------------------------------------------------- */\n\nconst toCause = (code: string, message: string, extra?: Record<string, unknown>) => ({\n code,\n message,\n ...(extra ?? {}),\n});\n\nconst fallback = (err: unknown): FileSystemError =>\n new FileSystemError({\n code: \"InternalError\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n cause: toCause(\n \"Unknown\",\n err instanceof Error ? err.message : String(err),\n ),\n });\n\nexport const fromAws = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const awsErr = err as {\n name?: unknown;\n message?: unknown;\n $metadata?: { httpStatusCode?: unknown };\n };\n const name = typeof awsErr.name === \"string\" ? awsErr.name : undefined;\n const message =\n typeof awsErr.message === \"string\" ? awsErr.message : `AWS error: ${name ?? \"unknown\"}`;\n const status =\n typeof awsErr.$metadata?.httpStatusCode === \"number\"\n ? awsErr.$metadata.httpStatusCode\n : undefined;\n\n const cause = toCause(\n name ?? (status !== undefined ? String(status) : \"Unknown\"),\n message,\n status !== undefined ? { httpStatusCode: status } : undefined,\n );\n\n // 1) name-based mapping wins (more specific than HTTP status)\n if (name && name in AWS_NAME_TO_CODE) {\n const m = AWS_NAME_TO_CODE[name]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 2) HTTP status mapping\n if (status !== undefined && status in HTTP_STATUS_TO_CODE) {\n const m = HTTP_STATUS_TO_CODE[status]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 3) 5xx bucket\n if (status !== undefined && status >= 500 && status < 600) {\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n }\n\n // 4) anything else 4xx-shaped\n if (status !== undefined && status >= 400 && status < 500) {\n return new FileSystemError({ code: \"Forbidden\", message, retryable: false, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromPg = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const pgErr = err as { code?: unknown; message?: unknown };\n const sqlstate = typeof pgErr.code === \"string\" ? pgErr.code : undefined;\n const message =\n typeof pgErr.message === \"string\" ? pgErr.message : `Postgres error: ${sqlstate ?? \"unknown\"}`;\n const cause = toCause(sqlstate ?? \"Unknown\", message);\n\n if (sqlstate && sqlstate in PG_SQLSTATE_TO_CODE) {\n const m = PG_SQLSTATE_TO_CODE[sqlstate]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromSqlite = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const sqlErr = err as { code?: unknown; message?: unknown };\n const code = typeof sqlErr.code === \"string\" ? sqlErr.code : undefined;\n const message =\n typeof sqlErr.message === \"string\" ? sqlErr.message : `SQLite error: ${code ?? \"unknown\"}`;\n const cause = toCause(code ?? \"Unknown\", message);\n\n if (code && code in SQLITE_CODE_TO_CODE) {\n const m = SQLITE_CODE_TO_CODE[code]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n","/**\n * FileSystemError — the single error class every adapter, store,\n * server action, and route handler in `file-next` returns or throws.\n *\n * Spec reference: requirement \"FileSystemError discriminated union\"\n * in `sdd/file-next/spec`. The 11 codes are the CLOSED set; any\n * provider-specific code (e.g. S3 `NoSuchKey`, Postgres `23505`) is\n * preserved on `cause.code` so callers can still distinguish upstream\n * reasons while the top-level `code` stays in the catalog.\n *\n * The catalog is a merge of spec + impl: the 6 fixed codes\n * (NotFound, Forbidden, Conflict, QuotaExceeded, NetworkError,\n * InternalError) are non-negotiable; the remaining 5 keep the wire\n * aligned with both the HTTP boundary (route handlers map the\n * top-level `code` to a status directly) and the storage boundary\n * (`RateLimited` and `ChecksumMismatch` carry semantics that have\n * no natural HTTP equivalent). See\n * `sdd/file-next/decisions/error-codes-deviation` for the\n * deviation log and rationale.\n *\n * Retryability table is the design's `error-mapping` excerpt; see\n * `sdd/file-next/design` §C. Any future code MUST add an entry in\n * `RETRYABLE_BY_CODE` (the catalog test enforces this).\n *\n * The placeholder from T-006 is replaced by this file in T-007a.\n * The upstream mappers (fromAws / fromPg / fromSqlite) land in T-007b\n * in `mappers.ts`.\n */\n\nexport const FILE_SYSTEM_ERROR_CODES = [\n \"NotFound\",\n \"Forbidden\",\n \"Conflict\",\n \"QuotaExceeded\",\n \"NetworkError\",\n \"InternalError\",\n \"Unauthorized\",\n \"PayloadTooLarge\",\n \"UnsupportedMediaType\",\n \"RateLimited\",\n \"ChecksumMismatch\",\n] as const satisfies readonly string[];\n\nexport type FileSystemErrorCode = (typeof FILE_SYSTEM_ERROR_CODES)[number];\n\nexport const RETRYABLE_BY_CODE: Readonly<Record<FileSystemErrorCode, boolean>> = {\n NotFound: false,\n Forbidden: false,\n Conflict: false,\n QuotaExceeded: true,\n NetworkError: true,\n InternalError: true,\n Unauthorized: false,\n PayloadTooLarge: false,\n UnsupportedMediaType: false,\n RateLimited: true,\n ChecksumMismatch: true,\n};\n\nexport interface FileSystemErrorOptions {\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport interface FileSystemErrorJson {\n name: string;\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport class FileSystemError extends Error {\n readonly code: FileSystemErrorCode;\n readonly retryable: boolean;\n override readonly cause?: { code: string; message: string; [k: string]: unknown };\n\n constructor(opts: FileSystemErrorOptions) {\n super(opts.message);\n this.name = \"FileSystemError\";\n this.code = opts.code;\n this.retryable = opts.retryable;\n if (opts.cause !== undefined) {\n this.cause = opts.cause;\n }\n }\n\n /**\n * Stable JSON shape for RSC pass-through. Error.prototype.message\n * is non-enumerable, so plain `JSON.stringify(err)` would emit `{}`\n * and lose the message + code + retryable flag. `cause` is omitted\n * entirely (not set to undefined) when absent so the shape stays\n * stable for hash-based caches.\n */\n toJSON(): FileSystemErrorJson {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n ...(this.cause !== undefined ? { cause: this.cause } : {}),\n };\n }\n\n /**\n * Mappers from upstream error shapes (AWS SDK v3, node-postgres,\n * better-sqlite3) to FileSystemError. See `./mappers.ts` for the\n * mapping tables. Re-exposed as static methods so callers can pick\n * the import style that fits; the free functions are the canonical\n * implementation.\n */\n static fromAws(err: unknown): FileSystemError {\n // Lazy import via the runtime binding avoids the static-field\n // circular-dep trap in ESM. The mapper file imports this class\n // for instanceof checks; we look up the function at call time.\n return _fromAws(err);\n }\n\n static fromPg(err: unknown): FileSystemError {\n return _fromPg(err);\n }\n\n static fromSqlite(err: unknown): FileSystemError {\n return _fromSqlite(err);\n }\n}\n\n// Imported here as bindings (not values) so the static methods above\n// can resolve them lazily. The actual implementation lives in mappers.ts.\nimport { fromAws as _fromAws, fromPg as _fromPg, fromSqlite as _fromSqlite } from \"./mappers\";\nexport { fromAws, fromPg, fromSqlite } from \"./mappers\";\n","/**\n * Branded string types and their constructors/guards.\n *\n * Brands are TypeScript-only fictions: a `Path` and an `S3Key` are\n * both strings at runtime, but the type system treats them as\n * distinct nominal types so the compiler catches accidental\n * cross-assignment (e.g. passing an S3Key where a TenantId is\n * expected).\n *\n * Conventions:\n * - `as*` is a zero-cost cast: trust the caller, brand the value.\n * Use it at trust boundaries you have already validated.\n * - `assert*` is a runtime guard: throws TypeError on invalid\n * input. Use it at the edge (parsing user/env input).\n *\n * Validation rules are intentionally minimal in v0.1 and can be\n * tightened as the spec evolves. None of them touch the network or\n * allocate; they are safe in hot paths.\n */\n\nexport type Path = string & { readonly __brand: \"Path\" };\nexport type Prefix = string & { readonly __brand: \"Prefix\" };\nexport type S3Key = string & { readonly __brand: \"S3Key\" };\nexport type TenantId = string & { readonly __brand: \"TenantId\" };\nexport type UserId = string & { readonly __brand: \"UserId\" };\n\n/**\n * POSIX file path. Non-empty, '/' is allowed as the root.\n */\nexport const asPath = (s: string): Path => s as Path;\nexport const assertPath = (s: string): Path => {\n if (s.length === 0) {\n throw new TypeError(\"Path must be a non-empty string\");\n }\n return s as Path;\n};\n\n/**\n * S3 prefix. Empty string is the root prefix. Non-empty prefixes\n * MUST end with '/' so concatenation with a key never produces\n * 'usersfile.jpg' by accident.\n */\nexport const asPrefix = (s: string): Prefix => s as Prefix;\nexport const assertPrefix = (s: string): Prefix => {\n if (s.length > 0 && !s.endsWith(\"/\")) {\n throw new TypeError(\n `Prefix must end with \"/\" or be empty: ${JSON.stringify(s)}`,\n );\n }\n return s as Prefix;\n};\n\n/**\n * S3 object key. No leading slash, no empty segments, no '..' hops.\n */\nexport const asS3Key = (s: string): S3Key => s as S3Key;\nexport const assertS3Key = (s: string): S3Key => {\n if (s.length === 0) {\n throw new TypeError(\"S3Key must be a non-empty string\");\n }\n if (s.startsWith(\"/\")) {\n throw new TypeError(\n `S3Key must not start with a slash: ${JSON.stringify(s)}`,\n );\n }\n if (s.includes(\"..\")) {\n throw new TypeError(\n `S3Key must not contain '..' segments: ${JSON.stringify(s)}`,\n );\n }\n return s as S3Key;\n};\n\n/**\n * Tenant identifier. Alphanumerics, dashes, underscores only.\n */\nexport const asTenantId = (s: string): TenantId => s as TenantId;\nexport const assertTenantId = (s: string): TenantId => {\n if (s.length === 0 || !/^[a-zA-Z0-9_-]+$/.test(s)) {\n throw new TypeError(`Invalid TenantId: ${JSON.stringify(s)}`);\n }\n return s as TenantId;\n};\n\n/**\n * Opaque user identifier. Non-empty; the format is provider-defined.\n */\nexport const asUserId = (s: string): UserId => s as UserId;\nexport const assertUserId = (s: string): UserId => {\n if (s.length === 0) {\n throw new TypeError(\"UserId must be a non-empty string\");\n }\n return s as UserId;\n};\n","/**\n * Server actions — tenant comes from getAuth(), never from the client.\n */\nimport { z } from \"zod\";\nimport { ok, err, type Result } from \"@/types/result\";\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key, asTenantId, type TenantId } from \"@/types/branded\";\nimport type { AuthContext } from \"../auth/with-auth\";\nimport type { MetadataStore, FileNode } from \"../metadata/store\";\nimport type { FileSystem } from \"../storage/filesystem\";\nimport type { createWriteThrough } from \"../sync/write-through\";\n\ntype CreateWriteThrough = ReturnType<typeof createWriteThrough>;\n\nconst NodeIdSchema = z.string().min(1, \"id is required\");\nconst PathSchema = z.string().nullable();\n\nexport const ListFilesInputSchema = z.object({\n parentId: PathSchema,\n limit: z.number().int().positive().optional(),\n cursor: z.string().optional(),\n});\n\nexport const DeleteFileInputSchema = z.object({\n id: NodeIdSchema,\n recursive: z.boolean().optional(),\n});\n\nexport const MoveFileInputSchema = z.object({\n id: NodeIdSchema,\n newParentId: PathSchema,\n newName: z.string().min(1).max(255).optional(),\n});\n\nexport const CopyFileInputSchema = z.object({\n id: NodeIdSchema,\n newParentId: PathSchema,\n newName: z.string().min(1).max(255).optional(),\n});\n\nexport const SetMetadataInputSchema = z.object({\n id: NodeIdSchema,\n metadata: z.record(z.string()),\n replace: z.boolean().optional(),\n});\n\nexport const CreateFolderInputSchema = z.object({\n parentId: PathSchema,\n name: z.string().min(1).max(255),\n});\n\nexport const PrepareUploadInputSchema = z.object({\n parentId: PathSchema,\n name: z.string().min(1).max(255),\n contentType: z.string().min(1),\n contentLength: z.number().int().nonnegative(),\n});\n\nexport const ConfirmUploadInputSchema = z.object({\n id: NodeIdSchema,\n parentId: PathSchema,\n name: z.string().min(1).max(255),\n contentType: z.string().optional(),\n size: z.number().int().nonnegative().optional(),\n});\n\nexport const SearchFilesInputSchema = z.object({\n query: z.string(),\n parentId: z.string().optional(),\n limit: z.number().int().positive().optional(),\n});\n\nexport const RestoreNodeInputSchema = z.object({\n id: NodeIdSchema,\n});\n\nexport const CreateShareInputSchema = z.object({\n id: NodeIdSchema,\n});\n\nexport const ResolveShareInputSchema = z.object({\n token: z.string().min(1),\n});\n\nexport const RevokeShareInputSchema = z.object({\n token: z.string().min(1),\n});\n\nconst zodErr = (message: string, parsed: z.SafeParseError<unknown>) =>\n err(\n new FileSystemError({\n code: \"InternalError\",\n message,\n retryable: false,\n cause: { code: \"ZodError\", message: parsed.error.message, issues: parsed.error.issues },\n }),\n );\n\nexport interface ServerActionsDeps {\n readonly store: MetadataStore;\n readonly writeThrough: CreateWriteThrough;\n readonly fs: FileSystem;\n readonly getAuth: () => AuthContext | Promise<AuthContext>;\n}\n\nexport const createServerActions = (deps: ServerActionsDeps) => {\n const { store, writeThrough, fs, getAuth } = deps;\n\n const wrap = (e: unknown, code: FileSystemError[\"code\"], message: string): FileSystemError => {\n if (e instanceof FileSystemError) return e;\n return new FileSystemError({\n code,\n message: `${message}: ${e instanceof Error ? e.message : String(e)}`,\n retryable: true,\n });\n };\n\n const authTenant = async (): Promise<AuthContext> => getAuth();\n\n const listFiles = async (\n input: z.infer<typeof ListFilesInputSchema>,\n ): Promise<Result<ListFilesOutput, FileSystemError>> => {\n const parsed = ListFilesInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid listFiles input\", parsed);\n try {\n const auth = await authTenant();\n return store.listChildren({\n tenantId: asTenantId(auth.tenantId),\n parentId: parsed.data.parentId,\n limit: parsed.data.limit,\n cursor: parsed.data.cursor,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"listFiles failed\"));\n }\n };\n\n const deleteFile = async (\n input: z.infer<typeof DeleteFileInputSchema>,\n ): Promise<Result<void, FileSystemError>> => {\n const parsed = DeleteFileInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid deleteFile input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.deleteThroughFile({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n recursive: parsed.data.recursive,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"deleteFile failed\"));\n }\n };\n\n const moveFile = async (\n input: z.infer<typeof MoveFileInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = MoveFileInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid moveFile input\", parsed);\n try {\n const auth = await authTenant();\n return store.moveNode({\n tenantId: asTenantId(auth.tenantId),\n id: parsed.data.id,\n newParentId: parsed.data.newParentId,\n newName: parsed.data.newName,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"moveFile failed\"));\n }\n };\n\n const copyFile = async (\n input: z.infer<typeof CopyFileInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = CopyFileInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid copyFile input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.copyThroughFile({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n newParentId: parsed.data.newParentId,\n newName: parsed.data.newName,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"copyFile failed\"));\n }\n };\n\n const setMetadata = async (\n input: z.infer<typeof SetMetadataInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = SetMetadataInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid setMetadata input\", parsed);\n try {\n const auth = await authTenant();\n return store.updateMetadata({\n tenantId: asTenantId(auth.tenantId),\n id: parsed.data.id,\n metadata: parsed.data.metadata,\n replace: parsed.data.replace,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"setMetadata failed\"));\n }\n };\n\n const createFolder = async (\n input: z.infer<typeof CreateFolderInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = CreateFolderInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid createFolder input\", parsed);\n try {\n const auth = await authTenant();\n return store.createNode({\n tenantId: asTenantId(auth.tenantId),\n parentId: parsed.data.parentId,\n name: parsed.data.name,\n kind: \"folder\",\n size: 0,\n mimeType: \"\",\n s3Key: \"\",\n ownerId: auth.userId,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"createFolder failed\"));\n }\n };\n\n const prepareUpload = async (\n input: z.infer<typeof PrepareUploadInputSchema>,\n ): Promise<Result<PrepareUploadOutput, FileSystemError>> => {\n const parsed = PrepareUploadInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid prepareUpload input\", parsed);\n try {\n const auth = await authTenant();\n const id =\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : `upl-${Date.now()}`;\n const signed = await fs.forTenant(auth.tenantId).adapter.createPresignedUploadUrl({\n key: asS3Key(id),\n contentType: parsed.data.contentType,\n expiresIn: 900,\n });\n if (!signed.ok) return signed;\n return ok({\n id,\n key: id,\n url: signed.value.url,\n method: signed.value.method,\n headers: signed.value.requiredHeaders ?? {},\n expiresAt: new Date(Date.now() + 900_000).toISOString(),\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"prepareUpload failed\"));\n }\n };\n\n const confirmUpload = async (\n input: z.infer<typeof ConfirmUploadInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = ConfirmUploadInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid confirmUpload input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.confirmUpload({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n parentId: parsed.data.parentId,\n name: parsed.data.name,\n contentType: parsed.data.contentType,\n size: parsed.data.size,\n ownerId: auth.userId,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"confirmUpload failed\"));\n }\n };\n\n const searchFiles = async (\n input: z.infer<typeof SearchFilesInputSchema>,\n ): Promise<Result<ListFilesOutput, FileSystemError>> => {\n const parsed = SearchFilesInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid searchFiles input\", parsed);\n try {\n const auth = await authTenant();\n return store.search({\n tenantId: asTenantId(auth.tenantId),\n query: parsed.data.query,\n parentId: parsed.data.parentId,\n limit: parsed.data.limit,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"searchFiles failed\"));\n }\n };\n\n const listTrash = async (\n input: { limit?: number; cursor?: string } = {},\n ): Promise<Result<ListFilesOutput, FileSystemError>> => {\n try {\n const auth = await authTenant();\n return store.listTrash({\n tenantId: asTenantId(auth.tenantId),\n limit: input.limit,\n cursor: input.cursor,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"listTrash failed\"));\n }\n };\n\n const restoreNode = async (\n input: z.infer<typeof RestoreNodeInputSchema>,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const parsed = RestoreNodeInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid restoreNode input\", parsed);\n try {\n const auth = await authTenant();\n return store.restoreNode({\n tenantId: asTenantId(auth.tenantId),\n id: parsed.data.id,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"restoreNode failed\"));\n }\n };\n\n const purgeNode = async (\n input: z.infer<typeof RestoreNodeInputSchema>,\n ): Promise<Result<void, FileSystemError>> => {\n const parsed = RestoreNodeInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid purgeNode input\", parsed);\n try {\n const auth = await authTenant();\n return writeThrough.purgeThroughFile({\n tenantId: auth.tenantId,\n id: parsed.data.id,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"purgeNode failed\"));\n }\n };\n\n const createShare = async (\n input: z.infer<typeof CreateShareInputSchema>,\n ): Promise<Result<{ token: string }, FileSystemError>> => {\n const parsed = CreateShareInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid createShare input\", parsed);\n try {\n const auth = await authTenant();\n return store.createShare({\n tenantId: asTenantId(auth.tenantId),\n nodeId: parsed.data.id,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"createShare failed\"));\n }\n };\n\n const resolveShare = async (\n input: z.infer<typeof ResolveShareInputSchema>,\n ): Promise<Result<FileNode | null, FileSystemError>> => {\n const parsed = ResolveShareInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid resolveShare input\", parsed);\n try {\n return store.resolveShare({ token: parsed.data.token });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"resolveShare failed\"));\n }\n };\n\n const revokeShare = async (\n input: z.infer<typeof RevokeShareInputSchema>,\n ): Promise<Result<void, FileSystemError>> => {\n const parsed = RevokeShareInputSchema.safeParse(input);\n if (!parsed.success) return zodErr(\"Invalid revokeShare input\", parsed);\n try {\n const auth = await authTenant();\n return store.revokeShare({\n tenantId: asTenantId(auth.tenantId),\n token: parsed.data.token,\n });\n } catch (e) {\n return err(wrap(e, \"InternalError\", \"revokeShare failed\"));\n }\n };\n\n return {\n listFiles,\n deleteFile,\n moveFile,\n copyFile,\n setMetadata,\n createFolder,\n prepareUpload,\n confirmUpload,\n searchFiles,\n listTrash,\n restoreNode,\n purgeNode,\n createShare,\n resolveShare,\n revokeShare,\n };\n};\n\nexport interface ListFilesOutput {\n readonly items: ReadonlyArray<FileNode>;\n readonly nextCursor?: string;\n}\n\nexport interface PrepareUploadOutput {\n readonly id: string;\n readonly key: string;\n readonly url: string;\n readonly method: \"PUT\" | \"POST\";\n readonly headers: Record<string, string>;\n readonly expiresAt: string;\n}\n\nexport type { TenantId };\n","/**\n * `createUploadRouteHandler` — the Next.js Route Handler factory\n * for the presigned-URL upload flow.\n *\n * The client flow:\n * 1. Client POSTs `{ key, contentType, contentLength }` to this\n * route (typically `/api/files/upload`).\n * 2. Route validates `contentLength` against `maxBytes` (413) and\n * `contentType` against `allowedContentTypes` (415). No URL\n * is signed on a rejected request.\n * 3. Route calls `fs.adapter.createPresignedUploadUrl({ key,\n * contentType, expiresIn })` and returns `{ url, key,\n * expiresAt }`.\n * 4. Client PUTs the file body to the signed URL (bypassing the\n * Next.js server entirely).\n *\n * Spec scenarios: `route-handlers#1` (maxBytes), `route-handlers#2`\n * (allowedContentTypes).\n *\n * Construction-time validation: `expiresIn` is validated when the\n * factory is called (synchronous throw), per decision\n * `sdd/file-next/design/decision/expiresin-cap-timing`. A handler\n * built with `expiresIn: 30 * 86400` should never reach runtime —\n * the developer should see the error at server startup, not on\n * the first user request.\n */\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key } from \"@/types/branded\";\nimport type { FileSystem } from \"@/storage/filesystem\";\nimport type { AuthContext } from \"../../auth/with-auth\";\n\n/** S3 SigV4 presign hard cap. The SDK itself rejects anything longer. */\nconst MAX_EXPIRES_IN_SECONDS = 7 * 24 * 60 * 60;\n/** Default 15 minutes — matches the adapter default and the AWS SDK default. */\nconst DEFAULT_EXPIRES_IN_SECONDS = 900;\n\n/**\n * Convert a glob pattern (`image/*`) to a regex; convert a literal\n * (`image/png`) to an exact match. Both forms are common in\n * `allowedContentTypes` arrays.\n */\nconst matchesContentType = (pattern: string, actual: string): boolean => {\n if (pattern === actual) return true;\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -1); // \"image/*\" → \"image/\"\n return actual.startsWith(prefix);\n }\n return false;\n};\n\nexport interface CreateUploadRouteHandlerOptions {\n readonly fs: FileSystem;\n /** Resolve the caller. 401 when it returns null. */\n readonly getAuth?: (req: Request) => Promise<AuthContext | null>;\n /** Reject requests whose `contentLength` exceeds this. Omit for no cap. */\n readonly maxBytes?: number;\n /**\n * Reject requests whose `contentType` is not in this list.\n * Each entry is a literal (`image/png`) or a wildcard (`image/*`).\n * Omit for no restriction.\n */\n readonly allowedContentTypes?: ReadonlyArray<string>;\n /** Presigned URL lifetime in seconds. Default 900, max 7d (S3 SigV4). */\n readonly expiresIn?: number;\n}\n\nexport interface UploadRouteHandlerRequest {\n key: string;\n contentType: string;\n contentLength: number;\n}\n\nexport interface UploadRouteHandlerResult {\n url: string;\n key: string;\n expiresAt: string;\n}\n\n/**\n * Validate `expiresIn` against the S3 SigV4 hard cap. Throws\n * `FileSystemError(InternalError)` with `cause.code: \"InvalidArgument\"`\n * if the value is out of range. The top-level code stays in the\n * closed 11-code catalog; the specific reason lives on `cause`.\n */\nconst assertExpiresIn = (expiresIn: number): void => {\n if (!Number.isFinite(expiresIn) || expiresIn < 1 || expiresIn > MAX_EXPIRES_IN_SECONDS) {\n throw new FileSystemError({\n code: \"InternalError\",\n message: `expiresIn must be between 1 and ${MAX_EXPIRES_IN_SECONDS} seconds (S3 SigV4 limit)`,\n retryable: false,\n cause: { code: \"InvalidArgument\", message: `expiresIn=${expiresIn}` },\n });\n }\n};\n\n/**\n * Build a Next.js Route Handler `(req) => Response` that signs a\n * presigned upload URL after validating the request.\n */\nexport const createUploadRouteHandler = (\n opts: CreateUploadRouteHandlerOptions,\n): ((req: Request) => Promise<Response>) => {\n const expiresIn = opts.expiresIn ?? DEFAULT_EXPIRES_IN_SECONDS;\n // Construction-time validation: fail-fast on misconfiguration.\n assertExpiresIn(expiresIn);\n\n return async (req: Request): Promise<Response> => {\n let body: UploadRouteHandlerRequest;\n try {\n body = (await req.json()) as UploadRouteHandlerRequest;\n } catch {\n return Response.json(\n { ok: false, error: { code: \"InternalError\", message: \"Request body must be valid JSON\" } },\n { status: 400 },\n );\n }\n\n // 1. maxBytes — reject BEFORE signing\n if (typeof opts.maxBytes === \"number\" && body.contentLength > opts.maxBytes) {\n return Response.json(\n {\n ok: false,\n error: {\n code: \"PayloadTooLarge\",\n message: `contentLength ${body.contentLength} exceeds maxBytes ${opts.maxBytes}`,\n },\n },\n { status: 413 },\n );\n }\n\n // 2. allowedContentTypes — reject BEFORE signing\n if (opts.allowedContentTypes && opts.allowedContentTypes.length > 0) {\n const allowed = opts.allowedContentTypes.some((p) => matchesContentType(p, body.contentType));\n if (!allowed) {\n return Response.json(\n {\n ok: false,\n error: {\n code: \"UnsupportedMediaType\",\n message: `contentType \"${body.contentType}\" is not in the allowed list`,\n },\n },\n { status: 415 },\n );\n }\n }\n\n let fs = opts.fs;\n if (opts.getAuth) {\n const auth = await opts.getAuth(req);\n if (!auth) {\n return Response.json(\n { ok: false, error: { code: \"Unauthorized\", message: \"Not authenticated\" } },\n { status: 401 },\n );\n }\n fs = opts.fs.forTenant(auth.tenantId);\n }\n\n const id =\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : `upl-${Date.now()}`;\n const r = await fs.adapter.createPresignedUploadUrl({\n key: asS3Key(id),\n contentType: body.contentType,\n expiresIn,\n });\n if (!r.ok) {\n return Response.json(\n { ok: false, error: { code: r.error.code, message: r.error.message } },\n { status: 500 },\n );\n }\n\n const expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n return Response.json({\n ok: true,\n value: {\n url: r.value.url,\n key: id,\n id,\n method: r.value.method,\n headers: r.value.requiredHeaders ?? {},\n expiresAt,\n },\n });\n };\n};\n","/**\n * `createDownloadRouteHandler` — the Next.js Route Handler factory\n * for the presigned-URL download flow.\n *\n * The client flow:\n * 1. Client GETs `/api/files/download?key=uploads/report.pdf`.\n * 2. Route calls `fs.adapter.createPresignedDownloadUrl({ key,\n * expiresIn })` and returns `{ url, expiresAt }`.\n * 3. Client GETs the signed URL (bypassing the Next.js server).\n *\n * Spec scenario: `route-handlers#3` — `X-Amz-Expires=900` is present\n * in the signed URL and `expiresAt` is `now + 900s`.\n *\n * Construction-time validation: same `expiresIn` policy as the\n * upload handler (see `expiresin-cap-timing` decision). The cap\n * lives at the factory level, not the adapter, so a misconfigured\n * handler fails fast at server startup.\n */\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key } from \"@/types/branded\";\nimport type { FileSystem } from \"@/storage/filesystem\";\nimport type { AuthContext } from \"../../auth/with-auth\";\n\n/** S3 SigV4 presign hard cap. The SDK itself rejects anything longer. */\nconst MAX_EXPIRES_IN_SECONDS = 7 * 24 * 60 * 60;\n/** Default 15 minutes — matches the adapter default and the AWS SDK default. */\nconst DEFAULT_EXPIRES_IN_SECONDS = 900;\n\nexport interface CreateDownloadRouteHandlerOptions {\n readonly fs: FileSystem;\n readonly getAuth?: (req: Request) => Promise<AuthContext | null>;\n /** Presigned URL lifetime in seconds. Default 900, max 7d (S3 SigV4). */\n readonly expiresIn?: number;\n}\n\nexport interface DownloadRouteHandlerResult {\n url: string;\n expiresAt: string;\n}\n\n/**\n * Validate `expiresIn` against the S3 SigV4 hard cap. Throws\n * `FileSystemError(InternalError)` with `cause.code: \"InvalidArgument\"`\n * if the value is out of range.\n */\nconst assertExpiresIn = (expiresIn: number): void => {\n if (!Number.isFinite(expiresIn) || expiresIn < 1 || expiresIn > MAX_EXPIRES_IN_SECONDS) {\n throw new FileSystemError({\n code: \"InternalError\",\n message: `expiresIn must be between 1 and ${MAX_EXPIRES_IN_SECONDS} seconds (S3 SigV4 limit)`,\n retryable: false,\n cause: { code: \"InvalidArgument\", message: `expiresIn=${expiresIn}` },\n });\n }\n};\n\n/**\n * Build a Next.js Route Handler `(req) => Response` that signs a\n * presigned GET URL.\n *\n * The `key` is read from the `?key=` query param. The handler does\n * NOT do any body / content-type / size validation (downloads\n * don't have those concerns); the only chokepoint is the\n * construction-time `expiresIn` cap.\n */\nexport const createDownloadRouteHandler = (\n opts: CreateDownloadRouteHandlerOptions,\n): ((req: Request) => Promise<Response>) => {\n const expiresIn = opts.expiresIn ?? DEFAULT_EXPIRES_IN_SECONDS;\n assertExpiresIn(expiresIn);\n\n return async (req: Request): Promise<Response> => {\n const url = new URL(req.url);\n const key = url.searchParams.get(\"key\");\n if (!key) {\n return Response.json(\n { ok: false, error: { code: \"InternalError\", message: \"Missing required query param: key\" } },\n { status: 400 },\n );\n }\n\n let fs = opts.fs;\n if (opts.getAuth) {\n const auth = await opts.getAuth(req);\n if (!auth) {\n return Response.json(\n { ok: false, error: { code: \"Unauthorized\", message: \"Not authenticated\" } },\n { status: 401 },\n );\n }\n fs = opts.fs.forTenant(auth.tenantId);\n }\n\n const r = await fs.adapter.createPresignedDownloadUrl({\n key: asS3Key(key),\n expiresIn,\n });\n if (!r.ok) {\n return Response.json(\n { ok: false, error: { code: r.error.code, message: r.error.message } },\n { status: 500 },\n );\n }\n\n const expiresAt = new Date(Date.now() + expiresIn * 1000).toISOString();\n return Response.json({\n ok: true,\n value: { url: r.value.url, expiresAt },\n });\n };\n};\n"]}
|
package/dist/sync/index.cjs
CHANGED
|
@@ -299,6 +299,25 @@ var createWriteThrough = (fs, store) => {
|
|
|
299
299
|
}
|
|
300
300
|
return ok(void 0);
|
|
301
301
|
};
|
|
302
|
+
const purgeThroughFile = async (input) => {
|
|
303
|
+
const tenantId = asTenantId(input.tenantId);
|
|
304
|
+
await drainPendingOrphansFor(fs, store, tenantId);
|
|
305
|
+
const adapter = scopedFs(fs, tenantId).adapter;
|
|
306
|
+
const purged = await store.purgeNode({ tenantId, id: input.id });
|
|
307
|
+
if (!purged.ok) return purged;
|
|
308
|
+
for (const key of purged.value.s3Keys) {
|
|
309
|
+
const del = await adapter.delete({ key: asS3Key(key) });
|
|
310
|
+
if (!del.ok) {
|
|
311
|
+
await store.enqueueOrphan({
|
|
312
|
+
tenantId,
|
|
313
|
+
s3Key: asS3Key(key),
|
|
314
|
+
metadataId: input.id,
|
|
315
|
+
reason: del.error.message
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return ok(void 0);
|
|
320
|
+
};
|
|
302
321
|
const copyThroughFile = async (input) => {
|
|
303
322
|
const tenantId = asTenantId(input.tenantId);
|
|
304
323
|
await drainPendingOrphansFor(fs, store, tenantId);
|
|
@@ -429,6 +448,7 @@ var createWriteThrough = (fs, store) => {
|
|
|
429
448
|
return {
|
|
430
449
|
writeThroughFile,
|
|
431
450
|
deleteThroughFile,
|
|
451
|
+
purgeThroughFile,
|
|
432
452
|
copyThroughFile,
|
|
433
453
|
confirmUpload,
|
|
434
454
|
reconcile,
|
package/dist/sync/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/types/result.ts","../../src/errors/mappers.ts","../../src/errors/index.ts","../../src/types/branded.ts","../../src/sync/write-through.ts"],"names":["err"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Discriminated `Result<T, E>` for typed error returns.\n *\n * Why Result over throw at boundaries:\n * - No `any` at the call site (vs try/catch which loses the type).\n * - `switch (r.ok)` narrows the type in consumer code.\n * - The wire shape `{ ok, value | error }` is JSON-serializable,\n * so it survives the RSC boundary without an extra DTO.\n * - Helpers (`map`, `andThen`, `unwrap`) make the common shapes\n * (chain, bail-out, recover) terse and exhaustive.\n *\n * The default error type is `FileSystemError` (see `@/errors`).\n * Consumers can specialize: `Result<User, ZodError>`.\n *\n * All helpers are pure functions; they do NOT allocate closures in\n * hot paths beyond what the spec demands (no `try`/`catch` wrapping).\n */\n\nimport { FileSystemError } from \"@/errors\";\n\nexport type Result<T, E = FileSystemError> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\n\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport const map = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => U,\n): Result<U, E> => (r.ok ? ok(f(r.value)) : r);\n\nexport const mapErr = <T, E, F>(\n r: Result<T, E>,\n f: (e: E) => F,\n): Result<T, F> => (r.ok ? r : err(f(r.error)));\n\nexport const andThen = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => Result<U, E>,\n): Result<U, E> => (r.ok ? f(r.value) : r);\n\nexport const unwrap = <T, E>(r: Result<T, E>): T => {\n if (r.ok) return r.value;\n throw r.error;\n};\n\nexport const unwrapOr = <T, E>(r: Result<T, E>, fallback: T): T =>\n r.ok ? r.value : fallback;\n","/**\n * Upstream error mappers for FileSystemError.\n *\n * Each mapper is a pure function `(*unknown) -> FileSystemError`.\n * The class re-exposes them as static methods (FileSystemError.fromAws\n * etc.) so callers can pick the import style that fits.\n *\n * Mapping strategy:\n * 1. If the input is already a FileSystemError, return it as-is\n * (we never re-wrap our own errors).\n * 2. Try the most specific signal first: S3 `name`, Postgres\n * SQLSTATE, SQLite extended code.\n * 3. Fall back to the HTTP status code (AWS SDK v3 exposes\n * `$metadata.httpStatusCode`).\n * 4. Last resort: InternalError, retryable, with the original\n * payload in `cause`.\n *\n * Provider-specific codes are preserved on `cause.code` (e.g. S3\n * \"NoSuchKey\", Postgres \"23505\") so callers can still branch on\n * them while the top-level `code` stays in the 11-code spec catalog.\n *\n * Mapping notes (post-C' merge, see\n * `sdd/file-next/decisions/error-codes-deviation`):\n * - S3 `SlowDown` -> QuotaExceeded (broader than RateLimited;\n * SlowDown means reduce request rate, which\n * is conceptually quota pressure, not\n * throttling of a single call).\n * - S3 `BadDigest` -> ChecksumMismatch (checksum verified by\n * S3 on upload did not match the client).\n * - HTTP 429 -> RateLimited (was QuotaExceeded in the\n * pre-C' catalog; RateLimited is the more\n * specific code for throttling responses).\n * - HTTP 408 -> NetworkError (transient transport error).\n * - HTTP 400 / Postgres 23514 / S3 InvalidRequest\n * -> fall through to the 4xx branch (no\n * top-level 400 code in the C' catalog;\n * these inputs are usually caught by the\n * name/SQLSTATE mapping first anyway).\n */\n\nimport { FileSystemError, type FileSystemErrorCode } from \"./index\";\n\n/* ---------------------------------------------------------------- *\n * Mapping tables (private) *\n * ---------------------------------------------------------------- */\n\ninterface CodeMapping {\n code: FileSystemErrorCode;\n retryable: boolean;\n}\n\nconst HTTP_STATUS_TO_CODE: Readonly<Record<number, CodeMapping>> = {\n 401: { code: \"Unauthorized\", retryable: false },\n 403: { code: \"Forbidden\", retryable: false },\n 404: { code: \"NotFound\", retryable: false },\n 408: { code: \"NetworkError\", retryable: true },\n 409: { code: \"Conflict\", retryable: false },\n 413: { code: \"PayloadTooLarge\", retryable: false },\n 415: { code: \"UnsupportedMediaType\", retryable: false },\n 429: { code: \"RateLimited\", retryable: true },\n};\n\nconst AWS_NAME_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n NoSuchKey: { code: \"NotFound\", retryable: false },\n NoSuchBucket: { code: \"NotFound\", retryable: false },\n // v0.2 multipart: unknown/aborted/expired uploadId.\n NoSuchUpload: { code: \"NotFound\", retryable: false },\n AccessDenied: { code: \"Forbidden\", retryable: false },\n SlowDown: { code: \"QuotaExceeded\", retryable: true },\n BadDigest: { code: \"ChecksumMismatch\", retryable: true },\n XAmzContentSHA256Mismatch: { code: \"ChecksumMismatch\", retryable: true },\n NetworkingError: { code: \"NetworkError\", retryable: true },\n TimeoutError: { code: \"NetworkError\", retryable: true },\n};\n\nconst PG_SQLSTATE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n \"23505\": { code: \"Conflict\", retryable: false },\n};\n\nconst SQLITE_CODE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n SQLITE_CONSTRAINT_UNIQUE: { code: \"Conflict\", retryable: false },\n SQLITE_CONSTRAINT_PRIMARYKEY: { code: \"Conflict\", retryable: false },\n};\n\n/* ---------------------------------------------------------------- *\n * Public mappers *\n * ---------------------------------------------------------------- */\n\nconst toCause = (code: string, message: string, extra?: Record<string, unknown>) => ({\n code,\n message,\n ...(extra ?? {}),\n});\n\nconst fallback = (err: unknown): FileSystemError =>\n new FileSystemError({\n code: \"InternalError\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n cause: toCause(\n \"Unknown\",\n err instanceof Error ? err.message : String(err),\n ),\n });\n\nexport const fromAws = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const awsErr = err as {\n name?: unknown;\n message?: unknown;\n $metadata?: { httpStatusCode?: unknown };\n };\n const name = typeof awsErr.name === \"string\" ? awsErr.name : undefined;\n const message =\n typeof awsErr.message === \"string\" ? awsErr.message : `AWS error: ${name ?? \"unknown\"}`;\n const status =\n typeof awsErr.$metadata?.httpStatusCode === \"number\"\n ? awsErr.$metadata.httpStatusCode\n : undefined;\n\n const cause = toCause(\n name ?? (status !== undefined ? String(status) : \"Unknown\"),\n message,\n status !== undefined ? { httpStatusCode: status } : undefined,\n );\n\n // 1) name-based mapping wins (more specific than HTTP status)\n if (name && name in AWS_NAME_TO_CODE) {\n const m = AWS_NAME_TO_CODE[name]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 2) HTTP status mapping\n if (status !== undefined && status in HTTP_STATUS_TO_CODE) {\n const m = HTTP_STATUS_TO_CODE[status]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 3) 5xx bucket\n if (status !== undefined && status >= 500 && status < 600) {\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n }\n\n // 4) anything else 4xx-shaped\n if (status !== undefined && status >= 400 && status < 500) {\n return new FileSystemError({ code: \"Forbidden\", message, retryable: false, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromPg = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const pgErr = err as { code?: unknown; message?: unknown };\n const sqlstate = typeof pgErr.code === \"string\" ? pgErr.code : undefined;\n const message =\n typeof pgErr.message === \"string\" ? pgErr.message : `Postgres error: ${sqlstate ?? \"unknown\"}`;\n const cause = toCause(sqlstate ?? \"Unknown\", message);\n\n if (sqlstate && sqlstate in PG_SQLSTATE_TO_CODE) {\n const m = PG_SQLSTATE_TO_CODE[sqlstate]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromSqlite = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const sqlErr = err as { code?: unknown; message?: unknown };\n const code = typeof sqlErr.code === \"string\" ? sqlErr.code : undefined;\n const message =\n typeof sqlErr.message === \"string\" ? sqlErr.message : `SQLite error: ${code ?? \"unknown\"}`;\n const cause = toCause(code ?? \"Unknown\", message);\n\n if (code && code in SQLITE_CODE_TO_CODE) {\n const m = SQLITE_CODE_TO_CODE[code]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n","/**\n * FileSystemError — the single error class every adapter, store,\n * server action, and route handler in `file-next` returns or throws.\n *\n * Spec reference: requirement \"FileSystemError discriminated union\"\n * in `sdd/file-next/spec`. The 11 codes are the CLOSED set; any\n * provider-specific code (e.g. S3 `NoSuchKey`, Postgres `23505`) is\n * preserved on `cause.code` so callers can still distinguish upstream\n * reasons while the top-level `code` stays in the catalog.\n *\n * The catalog is a merge of spec + impl: the 6 fixed codes\n * (NotFound, Forbidden, Conflict, QuotaExceeded, NetworkError,\n * InternalError) are non-negotiable; the remaining 5 keep the wire\n * aligned with both the HTTP boundary (route handlers map the\n * top-level `code` to a status directly) and the storage boundary\n * (`RateLimited` and `ChecksumMismatch` carry semantics that have\n * no natural HTTP equivalent). See\n * `sdd/file-next/decisions/error-codes-deviation` for the\n * deviation log and rationale.\n *\n * Retryability table is the design's `error-mapping` excerpt; see\n * `sdd/file-next/design` §C. Any future code MUST add an entry in\n * `RETRYABLE_BY_CODE` (the catalog test enforces this).\n *\n * The placeholder from T-006 is replaced by this file in T-007a.\n * The upstream mappers (fromAws / fromPg / fromSqlite) land in T-007b\n * in `mappers.ts`.\n */\n\nexport const FILE_SYSTEM_ERROR_CODES = [\n \"NotFound\",\n \"Forbidden\",\n \"Conflict\",\n \"QuotaExceeded\",\n \"NetworkError\",\n \"InternalError\",\n \"Unauthorized\",\n \"PayloadTooLarge\",\n \"UnsupportedMediaType\",\n \"RateLimited\",\n \"ChecksumMismatch\",\n] as const satisfies readonly string[];\n\nexport type FileSystemErrorCode = (typeof FILE_SYSTEM_ERROR_CODES)[number];\n\nexport const RETRYABLE_BY_CODE: Readonly<Record<FileSystemErrorCode, boolean>> = {\n NotFound: false,\n Forbidden: false,\n Conflict: false,\n QuotaExceeded: true,\n NetworkError: true,\n InternalError: true,\n Unauthorized: false,\n PayloadTooLarge: false,\n UnsupportedMediaType: false,\n RateLimited: true,\n ChecksumMismatch: true,\n};\n\nexport interface FileSystemErrorOptions {\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport interface FileSystemErrorJson {\n name: string;\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport class FileSystemError extends Error {\n readonly code: FileSystemErrorCode;\n readonly retryable: boolean;\n override readonly cause?: { code: string; message: string; [k: string]: unknown };\n\n constructor(opts: FileSystemErrorOptions) {\n super(opts.message);\n this.name = \"FileSystemError\";\n this.code = opts.code;\n this.retryable = opts.retryable;\n if (opts.cause !== undefined) {\n this.cause = opts.cause;\n }\n }\n\n /**\n * Stable JSON shape for RSC pass-through. Error.prototype.message\n * is non-enumerable, so plain `JSON.stringify(err)` would emit `{}`\n * and lose the message + code + retryable flag. `cause` is omitted\n * entirely (not set to undefined) when absent so the shape stays\n * stable for hash-based caches.\n */\n toJSON(): FileSystemErrorJson {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n ...(this.cause !== undefined ? { cause: this.cause } : {}),\n };\n }\n\n /**\n * Mappers from upstream error shapes (AWS SDK v3, node-postgres,\n * better-sqlite3) to FileSystemError. See `./mappers.ts` for the\n * mapping tables. Re-exposed as static methods so callers can pick\n * the import style that fits; the free functions are the canonical\n * implementation.\n */\n static fromAws(err: unknown): FileSystemError {\n // Lazy import via the runtime binding avoids the static-field\n // circular-dep trap in ESM. The mapper file imports this class\n // for instanceof checks; we look up the function at call time.\n return _fromAws(err);\n }\n\n static fromPg(err: unknown): FileSystemError {\n return _fromPg(err);\n }\n\n static fromSqlite(err: unknown): FileSystemError {\n return _fromSqlite(err);\n }\n}\n\n// Imported here as bindings (not values) so the static methods above\n// can resolve them lazily. The actual implementation lives in mappers.ts.\nimport { fromAws as _fromAws, fromPg as _fromPg, fromSqlite as _fromSqlite } from \"./mappers\";\nexport { fromAws, fromPg, fromSqlite } from \"./mappers\";\n","/**\n * Branded string types and their constructors/guards.\n *\n * Brands are TypeScript-only fictions: a `Path` and an `S3Key` are\n * both strings at runtime, but the type system treats them as\n * distinct nominal types so the compiler catches accidental\n * cross-assignment (e.g. passing an S3Key where a TenantId is\n * expected).\n *\n * Conventions:\n * - `as*` is a zero-cost cast: trust the caller, brand the value.\n * Use it at trust boundaries you have already validated.\n * - `assert*` is a runtime guard: throws TypeError on invalid\n * input. Use it at the edge (parsing user/env input).\n *\n * Validation rules are intentionally minimal in v0.1 and can be\n * tightened as the spec evolves. None of them touch the network or\n * allocate; they are safe in hot paths.\n */\n\nexport type Path = string & { readonly __brand: \"Path\" };\nexport type Prefix = string & { readonly __brand: \"Prefix\" };\nexport type S3Key = string & { readonly __brand: \"S3Key\" };\nexport type TenantId = string & { readonly __brand: \"TenantId\" };\nexport type UserId = string & { readonly __brand: \"UserId\" };\n\n/**\n * POSIX file path. Non-empty, '/' is allowed as the root.\n */\nexport const asPath = (s: string): Path => s as Path;\nexport const assertPath = (s: string): Path => {\n if (s.length === 0) {\n throw new TypeError(\"Path must be a non-empty string\");\n }\n return s as Path;\n};\n\n/**\n * S3 prefix. Empty string is the root prefix. Non-empty prefixes\n * MUST end with '/' so concatenation with a key never produces\n * 'usersfile.jpg' by accident.\n */\nexport const asPrefix = (s: string): Prefix => s as Prefix;\nexport const assertPrefix = (s: string): Prefix => {\n if (s.length > 0 && !s.endsWith(\"/\")) {\n throw new TypeError(\n `Prefix must end with \"/\" or be empty: ${JSON.stringify(s)}`,\n );\n }\n return s as Prefix;\n};\n\n/**\n * S3 object key. No leading slash, no empty segments, no '..' hops.\n */\nexport const asS3Key = (s: string): S3Key => s as S3Key;\nexport const assertS3Key = (s: string): S3Key => {\n if (s.length === 0) {\n throw new TypeError(\"S3Key must be a non-empty string\");\n }\n if (s.startsWith(\"/\")) {\n throw new TypeError(\n `S3Key must not start with a slash: ${JSON.stringify(s)}`,\n );\n }\n if (s.includes(\"..\")) {\n throw new TypeError(\n `S3Key must not contain '..' segments: ${JSON.stringify(s)}`,\n );\n }\n return s as S3Key;\n};\n\n/**\n * Tenant identifier. Alphanumerics, dashes, underscores only.\n */\nexport const asTenantId = (s: string): TenantId => s as TenantId;\nexport const assertTenantId = (s: string): TenantId => {\n if (s.length === 0 || !/^[a-zA-Z0-9_-]+$/.test(s)) {\n throw new TypeError(`Invalid TenantId: ${JSON.stringify(s)}`);\n }\n return s as TenantId;\n};\n\n/**\n * Opaque user identifier. Non-empty; the format is provider-defined.\n */\nexport const asUserId = (s: string): UserId => s as UserId;\nexport const assertUserId = (s: string): UserId => {\n if (s.length === 0) {\n throw new TypeError(\"UserId must be a non-empty string\");\n }\n return s as UserId;\n};\n","/**\n * WriteThrough — keeps object storage and the metadata tree in lockstep.\n *\n * Object keys are the node UUID. Rename/move stay metadata-only.\n * Copy writes a new object under a new UUID.\n */\nimport { ok, err, type Result } from \"@/types/result\";\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key, asTenantId, asUserId, type S3Key, type TenantId } from \"@/types/branded\";\nimport type { FileSystem } from \"../storage/filesystem\";\nimport type { MetadataStore, FileNode, CreateNodeInput } from \"../metadata/store\";\n\nexport type OrphanOp = \"delete\" | \"restore\";\n\nexport interface PendingOrphan {\n readonly id: string;\n readonly tenantId: TenantId;\n readonly s3Key: S3Key;\n readonly op: OrphanOp;\n readonly createdAt: Date;\n readonly reason: string;\n readonly nodeId?: string;\n}\n\nexport interface WriteThroughFileInput {\n readonly tenantId: string;\n readonly parentId: string | null;\n readonly name: string;\n readonly body: Uint8Array | ReadableStream<Uint8Array>;\n readonly contentType: string;\n readonly metadata?: Readonly<Record<string, string>>;\n readonly ownerId?: string;\n readonly maxBytes?: number;\n readonly id?: string;\n}\n\nexport interface DeleteThroughFileInput {\n readonly tenantId: string;\n readonly id: string;\n readonly recursive?: boolean;\n}\n\nexport interface CopyThroughFileInput {\n readonly tenantId: string;\n readonly id: string;\n readonly newParentId: string | null;\n readonly newName?: string;\n}\n\nexport interface ConfirmUploadInput {\n readonly tenantId: string;\n readonly id: string;\n readonly parentId: string | null;\n readonly name: string;\n readonly contentType?: string;\n readonly size?: number;\n readonly ownerId?: string;\n readonly metadata?: Readonly<Record<string, string>>;\n}\n\nexport interface ReconcileReport {\n readonly orphans: ReadonlyArray<PendingOrphan>;\n readonly scanned: number;\n readonly missingInS3: ReadonlyArray<string>;\n readonly orphansInS3: ReadonlyArray<string>;\n readonly fixed: number;\n}\n\nconst bootedTenants = new Set<string>();\n\nexport const __resetDrainState = (): void => {\n bootedTenants.clear();\n};\n\nconst newId = (): string =>\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : `node-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n\nconst scopedFs = (fs: FileSystem, tenantId: string): FileSystem =>\n fs.tenantId === tenantId ? fs : fs.forTenant(tenantId);\n\nconst bodySize = (body: WriteThroughFileInput[\"body\"]): number => {\n const maybe = body as { byteLength?: number };\n return typeof maybe.byteLength === \"number\" ? maybe.byteLength : 0;\n};\n\nconst drainPendingOrphansFor = async (\n fs: FileSystem,\n store: MetadataStore,\n tenantId: TenantId,\n): Promise<void> => {\n if (bootedTenants.has(tenantId)) return;\n bootedTenants.add(tenantId);\n const result = await store.listPendingOrphans({ tenantId });\n if (!result.ok) return;\n const adapter = scopedFs(fs, tenantId).adapter;\n for (const orphan of result.value) {\n await adapter.delete({ key: asS3Key(orphan.s3Key) });\n await store.deleteOrphan({ tenantId, id: orphan.id });\n }\n};\n\nexport const createWriteThrough = (\n fs: FileSystem,\n store: MetadataStore,\n): {\n writeThroughFile: (\n input: WriteThroughFileInput,\n ) => Promise<Result<FileNode, FileSystemError>>;\n deleteThroughFile: (\n input: DeleteThroughFileInput,\n ) => Promise<Result<void, FileSystemError>>;\n copyThroughFile: (\n input: CopyThroughFileInput,\n ) => Promise<Result<FileNode, FileSystemError>>;\n confirmUpload: (\n input: ConfirmUploadInput,\n ) => Promise<Result<FileNode, FileSystemError>>;\n reconcile: (input?: {\n tenantId?: string;\n dryRun?: boolean;\n }) => Promise<Result<ReconcileReport, FileSystemError>>;\n getOrphans: () => ReadonlyArray<PendingOrphan>;\n} => {\n const writeThroughFile = async (\n input: WriteThroughFileInput,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const id = input.id ?? newId();\n const s3Key = asS3Key(id);\n const calcSize = bodySize(input.body);\n\n if (fs.quotaBytes != null) {\n const used = await store.sumSize({ tenantId });\n if (!used.ok) return used;\n if (used.value + calcSize > fs.quotaBytes) {\n return err(\n new FileSystemError({\n code: \"QuotaExceeded\",\n message: `Tenant quota of ${fs.quotaBytes} bytes exceeded`,\n retryable: false,\n }),\n );\n }\n }\n\n const w = await adapter.write({\n key: s3Key,\n body: input.body,\n contentType: input.contentType,\n metadata: input.metadata,\n });\n if (!w.ok) return w;\n\n const ownerId = input.ownerId ? asUserId(input.ownerId) : asUserId(\"system\");\n const createInput: CreateNodeInput = {\n id,\n tenantId,\n parentId: input.parentId,\n name: input.name,\n kind: \"file\",\n size: calcSize,\n mimeType: input.contentType,\n s3Key,\n ownerId,\n metadata: input.metadata,\n };\n const c = await store.createNode(createInput);\n if (!c.ok) {\n const enqueue = await store.enqueueOrphan({\n tenantId,\n s3Key,\n reason: c.error.message,\n });\n if (!enqueue.ok) {\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `S3 write succeeded, metadata insert failed, and orphan enqueue failed: ${enqueue.error.message}; original: ${c.error.message}`,\n retryable: false,\n }),\n );\n }\n await adapter.delete({ key: s3Key });\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `S3 write succeeded but metadata insert failed; orphan logged for reconcile. S3 cleanup attempted. Original: ${c.error.message}`,\n retryable: false,\n }),\n );\n }\n\n return ok(c.value);\n };\n\n const deleteThroughFile = async (\n input: DeleteThroughFileInput,\n ): Promise<Result<void, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n\n const g = await store.getNode({ tenantId, id: input.id });\n if (!g.ok) return g;\n if (!g.value) {\n return err(\n new FileSystemError({\n code: \"NotFound\",\n message: `Node ${input.id} not found`,\n retryable: false,\n }),\n );\n }\n const node = g.value;\n const d = await store.deleteNode({\n tenantId,\n id: input.id,\n recursive: input.recursive,\n });\n if (!d.ok) {\n await store.enqueueOrphan({\n tenantId,\n s3Key: asS3Key(node.s3Key || node.id),\n metadataId: input.id,\n reason: d.error.message,\n });\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `Metadata soft-delete failed; orphan logged. Original: ${d.error.message}`,\n retryable: false,\n }),\n );\n }\n\n if (node.kind === \"file\" && node.s3Key) {\n const del = await adapter.delete({ key: asS3Key(node.s3Key) });\n if (!del.ok) {\n await store.enqueueOrphan({\n tenantId,\n s3Key: asS3Key(node.s3Key),\n metadataId: input.id,\n reason: del.error.message,\n });\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `Metadata deleted but S3 delete failed; orphan logged. Original: ${del.error.message}`,\n retryable: false,\n }),\n );\n }\n }\n\n return ok(undefined);\n };\n\n const copyThroughFile = async (\n input: CopyThroughFileInput,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const g = await store.getNode({ tenantId, id: input.id });\n if (!g.ok) return g;\n if (!g.value) {\n return err(\n new FileSystemError({\n code: \"NotFound\",\n message: `Node ${input.id} not found`,\n retryable: false,\n }),\n );\n }\n const src = g.value;\n const id = newId();\n if (src.kind === \"file\" && src.s3Key) {\n const copied = await adapter.copy({\n sourceKey: asS3Key(src.s3Key),\n destinationKey: asS3Key(id),\n });\n if (!copied.ok) return copied;\n }\n return store.createNode({\n id,\n tenantId,\n parentId: input.newParentId,\n name: input.newName ?? src.name,\n kind: src.kind,\n size: src.size,\n mimeType: src.mimeType,\n s3Key: src.kind === \"file\" ? id : \"\",\n ownerId: src.ownerId,\n metadata: src.metadata,\n });\n };\n\n const confirmUpload = async (\n input: ConfirmUploadInput,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const existing = await store.findByS3Key({ tenantId, s3Key: input.id });\n if (existing.ok && existing.value) return ok(existing.value);\n\n const st = await adapter.stat({ key: asS3Key(input.id) });\n const size = st.ok ? st.value.size : (input.size ?? 0);\n const mimeType = input.contentType ?? (st.ok ? st.value.contentType : \"\");\n if (!st.ok && input.size === undefined) return st;\n\n if (fs.quotaBytes != null) {\n const used = await store.sumSize({ tenantId });\n if (!used.ok) return used;\n if (used.value + size > fs.quotaBytes) {\n return err(\n new FileSystemError({\n code: \"QuotaExceeded\",\n message: `Tenant quota of ${fs.quotaBytes} bytes exceeded`,\n retryable: false,\n }),\n );\n }\n }\n\n return store.createNode({\n id: input.id,\n tenantId,\n parentId: input.parentId,\n name: input.name,\n kind: \"file\",\n size,\n mimeType,\n s3Key: input.id,\n ownerId: input.ownerId ? asUserId(input.ownerId) : asUserId(\"system\"),\n metadata: input.metadata,\n });\n };\n\n const reconcile = async (input?: {\n tenantId?: string;\n dryRun?: boolean;\n }): Promise<Result<ReconcileReport, FileSystemError>> => {\n if (!input?.tenantId) {\n return ok({\n orphans: [],\n scanned: 0,\n missingInS3: [],\n orphansInS3: [],\n fixed: 0,\n });\n }\n const tenantId = asTenantId(input.tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const dryRun = input.dryRun === true;\n let fixed = 0;\n\n const pending = await store.listPendingOrphans({ tenantId });\n if (!pending.ok) return pending;\n if (!dryRun) {\n for (const orphan of pending.value) {\n await adapter.delete({ key: asS3Key(orphan.s3Key) });\n const del = await store.deleteOrphan({ tenantId, id: orphan.id });\n if (del.ok) fixed += 1;\n }\n }\n\n const keys = await store.scanFileKeys({ tenantId });\n if (!keys.ok) return keys;\n const missingInS3: string[] = [];\n for (const row of keys.value) {\n const exists = await adapter.exists({ key: asS3Key(row.s3Key) });\n if (exists.ok && !exists.value.exists) missingInS3.push(row.s3Key);\n }\n\n const listed = await adapter.list({ prefix: \"\" as never });\n const orphansInS3: string[] = [];\n if (listed.ok) {\n const known = new Set(keys.value.map((k) => k.s3Key));\n for (const item of listed.value.items) {\n if (!known.has(item.key)) orphansInS3.push(item.key);\n }\n }\n\n return ok({\n orphans: pending.value.map((orphan) => ({\n id: orphan.id,\n tenantId: orphan.tenantId,\n s3Key: orphan.s3Key,\n op: \"delete\" as const,\n createdAt: orphan.createdAt,\n reason: orphan.reason,\n nodeId: orphan.metadataId ?? undefined,\n })),\n scanned: keys.value.length,\n missingInS3,\n orphansInS3,\n fixed,\n });\n };\n\n return {\n writeThroughFile,\n deleteThroughFile,\n copyThroughFile,\n confirmUpload,\n reconcile,\n getOrphans: () => [],\n };\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/types/result.ts","../../src/errors/mappers.ts","../../src/errors/index.ts","../../src/types/branded.ts","../../src/sync/write-through.ts"],"names":["err"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Discriminated `Result<T, E>` for typed error returns.\n *\n * Why Result over throw at boundaries:\n * - No `any` at the call site (vs try/catch which loses the type).\n * - `switch (r.ok)` narrows the type in consumer code.\n * - The wire shape `{ ok, value | error }` is JSON-serializable,\n * so it survives the RSC boundary without an extra DTO.\n * - Helpers (`map`, `andThen`, `unwrap`) make the common shapes\n * (chain, bail-out, recover) terse and exhaustive.\n *\n * The default error type is `FileSystemError` (see `@/errors`).\n * Consumers can specialize: `Result<User, ZodError>`.\n *\n * All helpers are pure functions; they do NOT allocate closures in\n * hot paths beyond what the spec demands (no `try`/`catch` wrapping).\n */\n\nimport { FileSystemError } from \"@/errors\";\n\nexport type Result<T, E = FileSystemError> =\n | { readonly ok: true; readonly value: T }\n | { readonly ok: false; readonly error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\n\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport const map = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => U,\n): Result<U, E> => (r.ok ? ok(f(r.value)) : r);\n\nexport const mapErr = <T, E, F>(\n r: Result<T, E>,\n f: (e: E) => F,\n): Result<T, F> => (r.ok ? r : err(f(r.error)));\n\nexport const andThen = <T, U, E>(\n r: Result<T, E>,\n f: (t: T) => Result<U, E>,\n): Result<U, E> => (r.ok ? f(r.value) : r);\n\nexport const unwrap = <T, E>(r: Result<T, E>): T => {\n if (r.ok) return r.value;\n throw r.error;\n};\n\nexport const unwrapOr = <T, E>(r: Result<T, E>, fallback: T): T =>\n r.ok ? r.value : fallback;\n","/**\n * Upstream error mappers for FileSystemError.\n *\n * Each mapper is a pure function `(*unknown) -> FileSystemError`.\n * The class re-exposes them as static methods (FileSystemError.fromAws\n * etc.) so callers can pick the import style that fits.\n *\n * Mapping strategy:\n * 1. If the input is already a FileSystemError, return it as-is\n * (we never re-wrap our own errors).\n * 2. Try the most specific signal first: S3 `name`, Postgres\n * SQLSTATE, SQLite extended code.\n * 3. Fall back to the HTTP status code (AWS SDK v3 exposes\n * `$metadata.httpStatusCode`).\n * 4. Last resort: InternalError, retryable, with the original\n * payload in `cause`.\n *\n * Provider-specific codes are preserved on `cause.code` (e.g. S3\n * \"NoSuchKey\", Postgres \"23505\") so callers can still branch on\n * them while the top-level `code` stays in the 11-code spec catalog.\n *\n * Mapping notes (post-C' merge, see\n * `sdd/file-next/decisions/error-codes-deviation`):\n * - S3 `SlowDown` -> QuotaExceeded (broader than RateLimited;\n * SlowDown means reduce request rate, which\n * is conceptually quota pressure, not\n * throttling of a single call).\n * - S3 `BadDigest` -> ChecksumMismatch (checksum verified by\n * S3 on upload did not match the client).\n * - HTTP 429 -> RateLimited (was QuotaExceeded in the\n * pre-C' catalog; RateLimited is the more\n * specific code for throttling responses).\n * - HTTP 408 -> NetworkError (transient transport error).\n * - HTTP 400 / Postgres 23514 / S3 InvalidRequest\n * -> fall through to the 4xx branch (no\n * top-level 400 code in the C' catalog;\n * these inputs are usually caught by the\n * name/SQLSTATE mapping first anyway).\n */\n\nimport { FileSystemError, type FileSystemErrorCode } from \"./index\";\n\n/* ---------------------------------------------------------------- *\n * Mapping tables (private) *\n * ---------------------------------------------------------------- */\n\ninterface CodeMapping {\n code: FileSystemErrorCode;\n retryable: boolean;\n}\n\nconst HTTP_STATUS_TO_CODE: Readonly<Record<number, CodeMapping>> = {\n 401: { code: \"Unauthorized\", retryable: false },\n 403: { code: \"Forbidden\", retryable: false },\n 404: { code: \"NotFound\", retryable: false },\n 408: { code: \"NetworkError\", retryable: true },\n 409: { code: \"Conflict\", retryable: false },\n 413: { code: \"PayloadTooLarge\", retryable: false },\n 415: { code: \"UnsupportedMediaType\", retryable: false },\n 429: { code: \"RateLimited\", retryable: true },\n};\n\nconst AWS_NAME_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n NoSuchKey: { code: \"NotFound\", retryable: false },\n NoSuchBucket: { code: \"NotFound\", retryable: false },\n // v0.2 multipart: unknown/aborted/expired uploadId.\n NoSuchUpload: { code: \"NotFound\", retryable: false },\n AccessDenied: { code: \"Forbidden\", retryable: false },\n SlowDown: { code: \"QuotaExceeded\", retryable: true },\n BadDigest: { code: \"ChecksumMismatch\", retryable: true },\n XAmzContentSHA256Mismatch: { code: \"ChecksumMismatch\", retryable: true },\n NetworkingError: { code: \"NetworkError\", retryable: true },\n TimeoutError: { code: \"NetworkError\", retryable: true },\n};\n\nconst PG_SQLSTATE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n \"23505\": { code: \"Conflict\", retryable: false },\n};\n\nconst SQLITE_CODE_TO_CODE: Readonly<Record<string, CodeMapping>> = {\n SQLITE_CONSTRAINT_UNIQUE: { code: \"Conflict\", retryable: false },\n SQLITE_CONSTRAINT_PRIMARYKEY: { code: \"Conflict\", retryable: false },\n};\n\n/* ---------------------------------------------------------------- *\n * Public mappers *\n * ---------------------------------------------------------------- */\n\nconst toCause = (code: string, message: string, extra?: Record<string, unknown>) => ({\n code,\n message,\n ...(extra ?? {}),\n});\n\nconst fallback = (err: unknown): FileSystemError =>\n new FileSystemError({\n code: \"InternalError\",\n message: err instanceof Error ? err.message : String(err),\n retryable: true,\n cause: toCause(\n \"Unknown\",\n err instanceof Error ? err.message : String(err),\n ),\n });\n\nexport const fromAws = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const awsErr = err as {\n name?: unknown;\n message?: unknown;\n $metadata?: { httpStatusCode?: unknown };\n };\n const name = typeof awsErr.name === \"string\" ? awsErr.name : undefined;\n const message =\n typeof awsErr.message === \"string\" ? awsErr.message : `AWS error: ${name ?? \"unknown\"}`;\n const status =\n typeof awsErr.$metadata?.httpStatusCode === \"number\"\n ? awsErr.$metadata.httpStatusCode\n : undefined;\n\n const cause = toCause(\n name ?? (status !== undefined ? String(status) : \"Unknown\"),\n message,\n status !== undefined ? { httpStatusCode: status } : undefined,\n );\n\n // 1) name-based mapping wins (more specific than HTTP status)\n if (name && name in AWS_NAME_TO_CODE) {\n const m = AWS_NAME_TO_CODE[name]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 2) HTTP status mapping\n if (status !== undefined && status in HTTP_STATUS_TO_CODE) {\n const m = HTTP_STATUS_TO_CODE[status]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n // 3) 5xx bucket\n if (status !== undefined && status >= 500 && status < 600) {\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n }\n\n // 4) anything else 4xx-shaped\n if (status !== undefined && status >= 400 && status < 500) {\n return new FileSystemError({ code: \"Forbidden\", message, retryable: false, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromPg = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const pgErr = err as { code?: unknown; message?: unknown };\n const sqlstate = typeof pgErr.code === \"string\" ? pgErr.code : undefined;\n const message =\n typeof pgErr.message === \"string\" ? pgErr.message : `Postgres error: ${sqlstate ?? \"unknown\"}`;\n const cause = toCause(sqlstate ?? \"Unknown\", message);\n\n if (sqlstate && sqlstate in PG_SQLSTATE_TO_CODE) {\n const m = PG_SQLSTATE_TO_CODE[sqlstate]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n\nexport const fromSqlite = (err: unknown): FileSystemError => {\n if (err instanceof FileSystemError) return err;\n\n if (typeof err !== \"object\" || err === null) return fallback(err);\n\n const sqlErr = err as { code?: unknown; message?: unknown };\n const code = typeof sqlErr.code === \"string\" ? sqlErr.code : undefined;\n const message =\n typeof sqlErr.message === \"string\" ? sqlErr.message : `SQLite error: ${code ?? \"unknown\"}`;\n const cause = toCause(code ?? \"Unknown\", message);\n\n if (code && code in SQLITE_CODE_TO_CODE) {\n const m = SQLITE_CODE_TO_CODE[code]!;\n return new FileSystemError({ code: m.code, message, retryable: m.retryable, cause });\n }\n\n return new FileSystemError({ code: \"InternalError\", message, retryable: true, cause });\n};\n","/**\n * FileSystemError — the single error class every adapter, store,\n * server action, and route handler in `file-next` returns or throws.\n *\n * Spec reference: requirement \"FileSystemError discriminated union\"\n * in `sdd/file-next/spec`. The 11 codes are the CLOSED set; any\n * provider-specific code (e.g. S3 `NoSuchKey`, Postgres `23505`) is\n * preserved on `cause.code` so callers can still distinguish upstream\n * reasons while the top-level `code` stays in the catalog.\n *\n * The catalog is a merge of spec + impl: the 6 fixed codes\n * (NotFound, Forbidden, Conflict, QuotaExceeded, NetworkError,\n * InternalError) are non-negotiable; the remaining 5 keep the wire\n * aligned with both the HTTP boundary (route handlers map the\n * top-level `code` to a status directly) and the storage boundary\n * (`RateLimited` and `ChecksumMismatch` carry semantics that have\n * no natural HTTP equivalent). See\n * `sdd/file-next/decisions/error-codes-deviation` for the\n * deviation log and rationale.\n *\n * Retryability table is the design's `error-mapping` excerpt; see\n * `sdd/file-next/design` §C. Any future code MUST add an entry in\n * `RETRYABLE_BY_CODE` (the catalog test enforces this).\n *\n * The placeholder from T-006 is replaced by this file in T-007a.\n * The upstream mappers (fromAws / fromPg / fromSqlite) land in T-007b\n * in `mappers.ts`.\n */\n\nexport const FILE_SYSTEM_ERROR_CODES = [\n \"NotFound\",\n \"Forbidden\",\n \"Conflict\",\n \"QuotaExceeded\",\n \"NetworkError\",\n \"InternalError\",\n \"Unauthorized\",\n \"PayloadTooLarge\",\n \"UnsupportedMediaType\",\n \"RateLimited\",\n \"ChecksumMismatch\",\n] as const satisfies readonly string[];\n\nexport type FileSystemErrorCode = (typeof FILE_SYSTEM_ERROR_CODES)[number];\n\nexport const RETRYABLE_BY_CODE: Readonly<Record<FileSystemErrorCode, boolean>> = {\n NotFound: false,\n Forbidden: false,\n Conflict: false,\n QuotaExceeded: true,\n NetworkError: true,\n InternalError: true,\n Unauthorized: false,\n PayloadTooLarge: false,\n UnsupportedMediaType: false,\n RateLimited: true,\n ChecksumMismatch: true,\n};\n\nexport interface FileSystemErrorOptions {\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport interface FileSystemErrorJson {\n name: string;\n code: FileSystemErrorCode;\n message: string;\n retryable: boolean;\n cause?: { code: string; message: string; [k: string]: unknown };\n}\n\nexport class FileSystemError extends Error {\n readonly code: FileSystemErrorCode;\n readonly retryable: boolean;\n override readonly cause?: { code: string; message: string; [k: string]: unknown };\n\n constructor(opts: FileSystemErrorOptions) {\n super(opts.message);\n this.name = \"FileSystemError\";\n this.code = opts.code;\n this.retryable = opts.retryable;\n if (opts.cause !== undefined) {\n this.cause = opts.cause;\n }\n }\n\n /**\n * Stable JSON shape for RSC pass-through. Error.prototype.message\n * is non-enumerable, so plain `JSON.stringify(err)` would emit `{}`\n * and lose the message + code + retryable flag. `cause` is omitted\n * entirely (not set to undefined) when absent so the shape stays\n * stable for hash-based caches.\n */\n toJSON(): FileSystemErrorJson {\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n retryable: this.retryable,\n ...(this.cause !== undefined ? { cause: this.cause } : {}),\n };\n }\n\n /**\n * Mappers from upstream error shapes (AWS SDK v3, node-postgres,\n * better-sqlite3) to FileSystemError. See `./mappers.ts` for the\n * mapping tables. Re-exposed as static methods so callers can pick\n * the import style that fits; the free functions are the canonical\n * implementation.\n */\n static fromAws(err: unknown): FileSystemError {\n // Lazy import via the runtime binding avoids the static-field\n // circular-dep trap in ESM. The mapper file imports this class\n // for instanceof checks; we look up the function at call time.\n return _fromAws(err);\n }\n\n static fromPg(err: unknown): FileSystemError {\n return _fromPg(err);\n }\n\n static fromSqlite(err: unknown): FileSystemError {\n return _fromSqlite(err);\n }\n}\n\n// Imported here as bindings (not values) so the static methods above\n// can resolve them lazily. The actual implementation lives in mappers.ts.\nimport { fromAws as _fromAws, fromPg as _fromPg, fromSqlite as _fromSqlite } from \"./mappers\";\nexport { fromAws, fromPg, fromSqlite } from \"./mappers\";\n","/**\n * Branded string types and their constructors/guards.\n *\n * Brands are TypeScript-only fictions: a `Path` and an `S3Key` are\n * both strings at runtime, but the type system treats them as\n * distinct nominal types so the compiler catches accidental\n * cross-assignment (e.g. passing an S3Key where a TenantId is\n * expected).\n *\n * Conventions:\n * - `as*` is a zero-cost cast: trust the caller, brand the value.\n * Use it at trust boundaries you have already validated.\n * - `assert*` is a runtime guard: throws TypeError on invalid\n * input. Use it at the edge (parsing user/env input).\n *\n * Validation rules are intentionally minimal in v0.1 and can be\n * tightened as the spec evolves. None of them touch the network or\n * allocate; they are safe in hot paths.\n */\n\nexport type Path = string & { readonly __brand: \"Path\" };\nexport type Prefix = string & { readonly __brand: \"Prefix\" };\nexport type S3Key = string & { readonly __brand: \"S3Key\" };\nexport type TenantId = string & { readonly __brand: \"TenantId\" };\nexport type UserId = string & { readonly __brand: \"UserId\" };\n\n/**\n * POSIX file path. Non-empty, '/' is allowed as the root.\n */\nexport const asPath = (s: string): Path => s as Path;\nexport const assertPath = (s: string): Path => {\n if (s.length === 0) {\n throw new TypeError(\"Path must be a non-empty string\");\n }\n return s as Path;\n};\n\n/**\n * S3 prefix. Empty string is the root prefix. Non-empty prefixes\n * MUST end with '/' so concatenation with a key never produces\n * 'usersfile.jpg' by accident.\n */\nexport const asPrefix = (s: string): Prefix => s as Prefix;\nexport const assertPrefix = (s: string): Prefix => {\n if (s.length > 0 && !s.endsWith(\"/\")) {\n throw new TypeError(\n `Prefix must end with \"/\" or be empty: ${JSON.stringify(s)}`,\n );\n }\n return s as Prefix;\n};\n\n/**\n * S3 object key. No leading slash, no empty segments, no '..' hops.\n */\nexport const asS3Key = (s: string): S3Key => s as S3Key;\nexport const assertS3Key = (s: string): S3Key => {\n if (s.length === 0) {\n throw new TypeError(\"S3Key must be a non-empty string\");\n }\n if (s.startsWith(\"/\")) {\n throw new TypeError(\n `S3Key must not start with a slash: ${JSON.stringify(s)}`,\n );\n }\n if (s.includes(\"..\")) {\n throw new TypeError(\n `S3Key must not contain '..' segments: ${JSON.stringify(s)}`,\n );\n }\n return s as S3Key;\n};\n\n/**\n * Tenant identifier. Alphanumerics, dashes, underscores only.\n */\nexport const asTenantId = (s: string): TenantId => s as TenantId;\nexport const assertTenantId = (s: string): TenantId => {\n if (s.length === 0 || !/^[a-zA-Z0-9_-]+$/.test(s)) {\n throw new TypeError(`Invalid TenantId: ${JSON.stringify(s)}`);\n }\n return s as TenantId;\n};\n\n/**\n * Opaque user identifier. Non-empty; the format is provider-defined.\n */\nexport const asUserId = (s: string): UserId => s as UserId;\nexport const assertUserId = (s: string): UserId => {\n if (s.length === 0) {\n throw new TypeError(\"UserId must be a non-empty string\");\n }\n return s as UserId;\n};\n","/**\n * WriteThrough — keeps object storage and the metadata tree in lockstep.\n *\n * Object keys are the node UUID. Rename/move stay metadata-only.\n * Copy writes a new object under a new UUID.\n */\nimport { ok, err, type Result } from \"@/types/result\";\nimport { FileSystemError } from \"@/errors\";\nimport { asS3Key, asTenantId, asUserId, type S3Key, type TenantId } from \"@/types/branded\";\nimport type { FileSystem } from \"../storage/filesystem\";\nimport type { MetadataStore, FileNode, CreateNodeInput } from \"../metadata/store\";\n\nexport type OrphanOp = \"delete\" | \"restore\";\n\nexport interface PendingOrphan {\n readonly id: string;\n readonly tenantId: TenantId;\n readonly s3Key: S3Key;\n readonly op: OrphanOp;\n readonly createdAt: Date;\n readonly reason: string;\n readonly nodeId?: string;\n}\n\nexport interface WriteThroughFileInput {\n readonly tenantId: string;\n readonly parentId: string | null;\n readonly name: string;\n readonly body: Uint8Array | ReadableStream<Uint8Array>;\n readonly contentType: string;\n readonly metadata?: Readonly<Record<string, string>>;\n readonly ownerId?: string;\n readonly maxBytes?: number;\n readonly id?: string;\n}\n\nexport interface DeleteThroughFileInput {\n readonly tenantId: string;\n readonly id: string;\n readonly recursive?: boolean;\n}\n\nexport interface CopyThroughFileInput {\n readonly tenantId: string;\n readonly id: string;\n readonly newParentId: string | null;\n readonly newName?: string;\n}\n\nexport interface ConfirmUploadInput {\n readonly tenantId: string;\n readonly id: string;\n readonly parentId: string | null;\n readonly name: string;\n readonly contentType?: string;\n readonly size?: number;\n readonly ownerId?: string;\n readonly metadata?: Readonly<Record<string, string>>;\n}\n\nexport interface ReconcileReport {\n readonly orphans: ReadonlyArray<PendingOrphan>;\n readonly scanned: number;\n readonly missingInS3: ReadonlyArray<string>;\n readonly orphansInS3: ReadonlyArray<string>;\n readonly fixed: number;\n}\n\nconst bootedTenants = new Set<string>();\n\nexport const __resetDrainState = (): void => {\n bootedTenants.clear();\n};\n\nconst newId = (): string =>\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : `node-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n\nconst scopedFs = (fs: FileSystem, tenantId: string): FileSystem =>\n fs.tenantId === tenantId ? fs : fs.forTenant(tenantId);\n\nconst bodySize = (body: WriteThroughFileInput[\"body\"]): number => {\n const maybe = body as { byteLength?: number };\n return typeof maybe.byteLength === \"number\" ? maybe.byteLength : 0;\n};\n\nconst drainPendingOrphansFor = async (\n fs: FileSystem,\n store: MetadataStore,\n tenantId: TenantId,\n): Promise<void> => {\n if (bootedTenants.has(tenantId)) return;\n bootedTenants.add(tenantId);\n const result = await store.listPendingOrphans({ tenantId });\n if (!result.ok) return;\n const adapter = scopedFs(fs, tenantId).adapter;\n for (const orphan of result.value) {\n await adapter.delete({ key: asS3Key(orphan.s3Key) });\n await store.deleteOrphan({ tenantId, id: orphan.id });\n }\n};\n\nexport const createWriteThrough = (\n fs: FileSystem,\n store: MetadataStore,\n): {\n writeThroughFile: (\n input: WriteThroughFileInput,\n ) => Promise<Result<FileNode, FileSystemError>>;\n deleteThroughFile: (\n input: DeleteThroughFileInput,\n ) => Promise<Result<void, FileSystemError>>;\n purgeThroughFile: (\n input: { tenantId: string; id: string },\n ) => Promise<Result<void, FileSystemError>>;\n copyThroughFile: (\n input: CopyThroughFileInput,\n ) => Promise<Result<FileNode, FileSystemError>>;\n confirmUpload: (\n input: ConfirmUploadInput,\n ) => Promise<Result<FileNode, FileSystemError>>;\n reconcile: (input?: {\n tenantId?: string;\n dryRun?: boolean;\n }) => Promise<Result<ReconcileReport, FileSystemError>>;\n getOrphans: () => ReadonlyArray<PendingOrphan>;\n} => {\n const writeThroughFile = async (\n input: WriteThroughFileInput,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const id = input.id ?? newId();\n const s3Key = asS3Key(id);\n const calcSize = bodySize(input.body);\n\n if (fs.quotaBytes != null) {\n const used = await store.sumSize({ tenantId });\n if (!used.ok) return used;\n if (used.value + calcSize > fs.quotaBytes) {\n return err(\n new FileSystemError({\n code: \"QuotaExceeded\",\n message: `Tenant quota of ${fs.quotaBytes} bytes exceeded`,\n retryable: false,\n }),\n );\n }\n }\n\n const w = await adapter.write({\n key: s3Key,\n body: input.body,\n contentType: input.contentType,\n metadata: input.metadata,\n });\n if (!w.ok) return w;\n\n const ownerId = input.ownerId ? asUserId(input.ownerId) : asUserId(\"system\");\n const createInput: CreateNodeInput = {\n id,\n tenantId,\n parentId: input.parentId,\n name: input.name,\n kind: \"file\",\n size: calcSize,\n mimeType: input.contentType,\n s3Key,\n ownerId,\n metadata: input.metadata,\n };\n const c = await store.createNode(createInput);\n if (!c.ok) {\n const enqueue = await store.enqueueOrphan({\n tenantId,\n s3Key,\n reason: c.error.message,\n });\n if (!enqueue.ok) {\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `S3 write succeeded, metadata insert failed, and orphan enqueue failed: ${enqueue.error.message}; original: ${c.error.message}`,\n retryable: false,\n }),\n );\n }\n await adapter.delete({ key: s3Key });\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `S3 write succeeded but metadata insert failed; orphan logged for reconcile. S3 cleanup attempted. Original: ${c.error.message}`,\n retryable: false,\n }),\n );\n }\n\n return ok(c.value);\n };\n\n const deleteThroughFile = async (\n input: DeleteThroughFileInput,\n ): Promise<Result<void, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n\n const g = await store.getNode({ tenantId, id: input.id });\n if (!g.ok) return g;\n if (!g.value) {\n return err(\n new FileSystemError({\n code: \"NotFound\",\n message: `Node ${input.id} not found`,\n retryable: false,\n }),\n );\n }\n const node = g.value;\n const d = await store.deleteNode({\n tenantId,\n id: input.id,\n recursive: input.recursive,\n });\n if (!d.ok) {\n await store.enqueueOrphan({\n tenantId,\n s3Key: asS3Key(node.s3Key || node.id),\n metadataId: input.id,\n reason: d.error.message,\n });\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `Metadata soft-delete failed; orphan logged. Original: ${d.error.message}`,\n retryable: false,\n }),\n );\n }\n\n if (node.kind === \"file\" && node.s3Key) {\n const del = await adapter.delete({ key: asS3Key(node.s3Key) });\n if (!del.ok) {\n await store.enqueueOrphan({\n tenantId,\n s3Key: asS3Key(node.s3Key),\n metadataId: input.id,\n reason: del.error.message,\n });\n return err(\n new FileSystemError({\n code: \"InternalError\",\n message: `Metadata deleted but S3 delete failed; orphan logged. Original: ${del.error.message}`,\n retryable: false,\n }),\n );\n }\n }\n\n return ok(undefined);\n };\n\n const purgeThroughFile = async (input: {\n tenantId: string;\n id: string;\n }): Promise<Result<void, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const purged = await store.purgeNode({ tenantId, id: input.id });\n if (!purged.ok) return purged;\n for (const key of purged.value.s3Keys) {\n const del = await adapter.delete({ key: asS3Key(key) });\n if (!del.ok) {\n await store.enqueueOrphan({\n tenantId,\n s3Key: asS3Key(key),\n metadataId: input.id,\n reason: del.error.message,\n });\n }\n }\n return ok(undefined);\n };\n\n const copyThroughFile = async (\n input: CopyThroughFileInput,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const g = await store.getNode({ tenantId, id: input.id });\n if (!g.ok) return g;\n if (!g.value) {\n return err(\n new FileSystemError({\n code: \"NotFound\",\n message: `Node ${input.id} not found`,\n retryable: false,\n }),\n );\n }\n const src = g.value;\n const id = newId();\n if (src.kind === \"file\" && src.s3Key) {\n const copied = await adapter.copy({\n sourceKey: asS3Key(src.s3Key),\n destinationKey: asS3Key(id),\n });\n if (!copied.ok) return copied;\n }\n return store.createNode({\n id,\n tenantId,\n parentId: input.newParentId,\n name: input.newName ?? src.name,\n kind: src.kind,\n size: src.size,\n mimeType: src.mimeType,\n s3Key: src.kind === \"file\" ? id : \"\",\n ownerId: src.ownerId,\n metadata: src.metadata,\n });\n };\n\n const confirmUpload = async (\n input: ConfirmUploadInput,\n ): Promise<Result<FileNode, FileSystemError>> => {\n const tenantId = asTenantId(input.tenantId);\n await drainPendingOrphansFor(fs, store, tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const existing = await store.findByS3Key({ tenantId, s3Key: input.id });\n if (existing.ok && existing.value) return ok(existing.value);\n\n const st = await adapter.stat({ key: asS3Key(input.id) });\n const size = st.ok ? st.value.size : (input.size ?? 0);\n const mimeType = input.contentType ?? (st.ok ? st.value.contentType : \"\");\n if (!st.ok && input.size === undefined) return st;\n\n if (fs.quotaBytes != null) {\n const used = await store.sumSize({ tenantId });\n if (!used.ok) return used;\n if (used.value + size > fs.quotaBytes) {\n return err(\n new FileSystemError({\n code: \"QuotaExceeded\",\n message: `Tenant quota of ${fs.quotaBytes} bytes exceeded`,\n retryable: false,\n }),\n );\n }\n }\n\n return store.createNode({\n id: input.id,\n tenantId,\n parentId: input.parentId,\n name: input.name,\n kind: \"file\",\n size,\n mimeType,\n s3Key: input.id,\n ownerId: input.ownerId ? asUserId(input.ownerId) : asUserId(\"system\"),\n metadata: input.metadata,\n });\n };\n\n const reconcile = async (input?: {\n tenantId?: string;\n dryRun?: boolean;\n }): Promise<Result<ReconcileReport, FileSystemError>> => {\n if (!input?.tenantId) {\n return ok({\n orphans: [],\n scanned: 0,\n missingInS3: [],\n orphansInS3: [],\n fixed: 0,\n });\n }\n const tenantId = asTenantId(input.tenantId);\n const adapter = scopedFs(fs, tenantId).adapter;\n const dryRun = input.dryRun === true;\n let fixed = 0;\n\n const pending = await store.listPendingOrphans({ tenantId });\n if (!pending.ok) return pending;\n if (!dryRun) {\n for (const orphan of pending.value) {\n await adapter.delete({ key: asS3Key(orphan.s3Key) });\n const del = await store.deleteOrphan({ tenantId, id: orphan.id });\n if (del.ok) fixed += 1;\n }\n }\n\n const keys = await store.scanFileKeys({ tenantId });\n if (!keys.ok) return keys;\n const missingInS3: string[] = [];\n for (const row of keys.value) {\n const exists = await adapter.exists({ key: asS3Key(row.s3Key) });\n if (exists.ok && !exists.value.exists) missingInS3.push(row.s3Key);\n }\n\n const listed = await adapter.list({ prefix: \"\" as never });\n const orphansInS3: string[] = [];\n if (listed.ok) {\n const known = new Set(keys.value.map((k) => k.s3Key));\n for (const item of listed.value.items) {\n if (!known.has(item.key)) orphansInS3.push(item.key);\n }\n }\n\n return ok({\n orphans: pending.value.map((orphan) => ({\n id: orphan.id,\n tenantId: orphan.tenantId,\n s3Key: orphan.s3Key,\n op: \"delete\" as const,\n createdAt: orphan.createdAt,\n reason: orphan.reason,\n nodeId: orphan.metadataId ?? undefined,\n })),\n scanned: keys.value.length,\n missingInS3,\n orphansInS3,\n fixed,\n });\n };\n\n return {\n writeThroughFile,\n deleteThroughFile,\n purgeThroughFile,\n copyThroughFile,\n confirmUpload,\n reconcile,\n getOrphans: () => [],\n };\n};\n"]}
|