@marktiderman/genesis-forms 0.3.1 → 0.4.1
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/README.md +85 -1
- package/dist/destinations.cjs +159 -6
- package/dist/destinations.cjs.map +1 -1
- package/dist/destinations.js +159 -6
- package/dist/destinations.js.map +1 -1
- package/dist/{engine-CPLtKVew.d.cts → engine-BkNuzlna.d.cts} +2 -1
- package/dist/{engine-DOrPgFDw.d.ts → engine-Dz9J5ej2.d.ts} +2 -1
- package/dist/index.cjs +859 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +205 -4
- package/dist/index.d.ts +205 -4
- package/dist/index.js +838 -23
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +767 -18
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +5 -1
- package/dist/server.d.ts +5 -1
- package/dist/server.js +767 -18
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +769 -18
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +769 -18
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/destinations/types.ts","../src/structured.ts","../src/fields.ts","../src/logic.ts","../src/recall.ts","../src/destinations/row.ts","../src/destinations/email.ts","../src/destinations/google-auth.ts","../src/destinations/sheets.ts","../src/destinations/webhook.ts"],"names":["out","used","state"],"mappings":"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","file":"destinations.cjs","sourcesContent":["/**\n * The contract every destination keeps. A destination sends one checked\n * submission somewhere (an inbox, a spreadsheet, a URL) and says whether a\n * failure is worth retrying. It never throws, never logs, and never puts a\n * secret, an answer or contact details in an error message.\n *\n * Storage is the app's: it keeps the outbox, claims due deliveries, counts\n * attempts and schedules retries. A destination only reports what happened.\n */\nimport type { FormDefinition, Json } from \"../types\";\n\n/** One cell of a flat response row. */\nexport type Cell = string | number | boolean;\n\n/**\n * What a destination delivers: a submission `validateSubmission` checked,\n * plus the id the app stored it under. `{ id, ...result.submission }` fits.\n */\nexport interface DeliverySubmission {\n /** The stored response's id. Every destination records it, so a resend is recognised. */\n id: string;\n /** Answers keyed by field id. */\n answers: Record<string, Json>;\n /** Untrusted URL and host inputs. */\n hidden?: Record<string, Json> | undefined;\n /** Trusted server inputs (account id, location…). */\n context?: Record<string, Json> | undefined;\n ending?: string | null | undefined;\n /** When it was submitted, as the app wants it shown: an ISO time, or a day such as `2026-10-22`. */\n submittedAt?: string | undefined;\n /**\n * Extra leading columns the app adds, in order, after `id` and `submitted_at`:\n * the form's slug and version, an account id, a location. Rows and emails show them;\n * the webhook sends them.\n */\n meta?: Record<string, Cell> | undefined;\n /** Labels the app attached, such as `low_rating`. The webhook sends them; a custom email can read them. */\n tags?: readonly string[] | undefined;\n}\n\nexport interface DeliveryOptions {\n /**\n * This delivery's id, stable across its retries. The email destination's\n * idempotency key and the webhook's `webhook-id`. Defaults to the submission id.\n */\n deliveryId?: string | undefined;\n /** What this destination cached last time (`DeliveryResult.state`). */\n state?: Record<string, Json> | undefined;\n /**\n * An earlier attempt of this delivery may have gone through (it timed out,\n * or its lease ran out). Destinations that can look first do: the sheet\n * skips rows whose id is already there.\n */\n redelivery?: boolean | undefined;\n /** Aborts the delivery. Each request also has its own timeout. */\n signal?: AbortSignal | undefined;\n}\n\n/** One submission in a batch: each carries its own definition and delivery id. */\nexport interface DeliveryItem {\n submission: DeliverySubmission;\n definition: FormDefinition;\n deliveryId?: string | undefined;\n}\n\nexport type DeliveryResult =\n | {\n ok: true;\n /** New state to keep for this destination, when it changed. */\n state?: Record<string, Json>;\n /** Submission ids already there (a redelivery), so nothing was sent for them. */\n skipped?: string[];\n }\n | DeliveryFailure;\n\nexport interface DeliveryFailure {\n ok: false;\n /**\n * `true`: the same request may succeed later (rate limited, the service\n * down, a timeout). `false`: it will not until someone changes the config\n * or credentials (a bad key, an unshared sheet, a 404 URL).\n */\n retryable: boolean;\n /**\n * Set when the service said when to come back (429, 503) or is plainly\n * down: retry after this many seconds. An app may choose not to count the\n * attempt, since it says nothing about the delivery itself.\n */\n retryAfterSeconds?: number;\n /** The HTTP status that refused it, if one did. */\n status?: number;\n /** Safe to store and log: a status and a short reason, never secrets, answers or contact details. */\n error: string;\n}\n\n/** Config is plain JSON the app stores per destination. Secrets never go in it. */\nexport type DestinationConfig = Readonly<Record<string, unknown>>;\n\nexport interface Destination {\n /** `\"email\"`, `\"sheet\"`, `\"webhook\"`, or an app's own. */\n readonly kind: string;\n /** Deliver one submission. Never throws. */\n deliver(\n submission: DeliverySubmission,\n definition: FormDefinition,\n config: DestinationConfig,\n options?: DeliveryOptions,\n ): Promise<DeliveryResult>;\n /**\n * Deliver several submissions to the same destination in one request where\n * the service allows it. All succeed or all fail together. Never throws.\n */\n deliverBatch?(\n items: readonly DeliveryItem[],\n config: DestinationConfig,\n options?: Omit<DeliveryOptions, \"deliveryId\">,\n ): Promise<DeliveryResult>;\n}\n\n/**\n * A failure with a message that is safe to store. Destinations throw it\n * internally and `deliveryFailure` turns it into a result; app-written\n * destinations may do the same.\n */\nexport class DeliveryError extends Error {\n override name = \"DeliveryError\";\n readonly retryable: boolean;\n readonly retryAfterSeconds: number | undefined;\n readonly status: number | undefined;\n constructor(\n message: string,\n options: { retryable?: boolean | undefined; retryAfterSeconds?: number | undefined; status?: number | undefined } = {},\n ) {\n super(message);\n this.retryable = options.retryable ?? false;\n this.retryAfterSeconds = options.retryAfterSeconds;\n this.status = options.status;\n }\n}\n\n/** Every outbound request gives up after this long, unless the destination is given another `timeoutMs`. */\nexport const REQUEST_TIMEOUT_MS = 10_000;\n\nconst IMF_FIXDATE = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \\d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d{4} \\d{2}:\\d{2}:\\d{2} GMT$/;\n\n/**\n * Seconds to wait from a Retry-After header, else the fallback. Only the\n * two forms RFC 9110 defines are read: delta-seconds (digits only) and an\n * IMF-fixdate (`Wed, 21 Oct 2026 07:28:00 GMT`); anything else (`-5`,\n * `1.5`, a loose date) gets the fallback. At least 1 second, at most a day.\n */\nexport function retryAfterSeconds(header: string | null | undefined, fallback = 60, now = Date.now()): number {\n const clamp = (s: number) => Math.min(86_400, Math.max(1, s));\n if (header) {\n const trimmed = header.trim();\n if (/^\\d+$/.test(trimmed)) return clamp(Number(trimmed));\n if (IMF_FIXDATE.test(trimmed)) {\n const at = Date.parse(trimmed);\n if (Number.isFinite(at)) return clamp(Math.ceil((at - now) / 1000));\n }\n }\n return fallback;\n}\n\n/** Whether an HTTP status is worth retrying unchanged: 408, 425, 429 and 5xx. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\n/**\n * The error for a refused request. Retryable statuses (see\n * `isRetryableStatus`) wait for the Retry-After header, else 60 seconds;\n * every other status is permanent.\n */\nexport function httpError(what: string, response: Response, detail?: string): DeliveryError {\n const status = response.status;\n const message = `${what} answered ${status}${detail ? ` (${detail})` : \"\"}`;\n if (isRetryableStatus(status)) {\n return new DeliveryError(message, {\n retryable: true,\n retryAfterSeconds: retryAfterSeconds(response.headers.get(\"retry-after\")),\n status,\n });\n }\n return new DeliveryError(message, { retryable: false, status });\n}\n\n/**\n * Any error as a failed result with a safe message. A `DeliveryError` keeps\n * its message; anything else is reduced to its kind (\"Timed out\", \"Network\n * error\"), because a raw message may hold a URL with a token in it.\n * Timeouts and aborts are retryable. A `TypeError` is permanent: it is\n * almost always a bug that a retry would only repeat. `timedFetch` turns\n * fetch's own network `TypeError` into a retryable `DeliveryError` first, so\n * an app destination that calls `fetch` directly should do the same.\n */\nexport function deliveryFailure(error: unknown): DeliveryFailure {\n if (error instanceof DeliveryError) {\n return {\n ok: false,\n retryable: error.retryable,\n error: error.message.slice(0, 500),\n ...(error.retryAfterSeconds !== undefined ? { retryAfterSeconds: error.retryAfterSeconds } : {}),\n ...(error.status !== undefined ? { status: error.status } : {}),\n };\n }\n const name = error instanceof Error ? error.name : \"\";\n if (name === \"TimeoutError\") return { ok: false, retryable: true, error: \"Timed out\" };\n if (name === \"AbortError\") return { ok: false, retryable: true, error: \"Aborted\" };\n if (name === \"TypeError\") return { ok: false, retryable: false, error: \"Unexpected error\" };\n return { ok: false, retryable: true, error: \"Unexpected error\" };\n}\n\n/** Shared by the built-in destinations. */\nexport interface HttpDeps {\n /** Defaults to the global `fetch`. */\n fetch?: typeof fetch | undefined;\n /** Per request. Default `REQUEST_TIMEOUT_MS`. */\n timeoutMs?: number | undefined;\n}\n\n/**\n * A request with a timeout, also aborted by the caller's signal. A network\n * failure (fetch rejects with a `TypeError`) becomes a retryable\n * `DeliveryError(\"Network error\")`; timeouts and aborts pass through.\n */\nexport async function timedFetch(\n deps: HttpDeps,\n url: string,\n init: RequestInit,\n signal: AbortSignal | undefined,\n): Promise<Response> {\n const timeout = AbortSignal.timeout(deps.timeoutMs ?? REQUEST_TIMEOUT_MS);\n const any = (AbortSignal as unknown as { any?: (signals: AbortSignal[]) => AbortSignal }).any;\n const combined = signal ? (any ? any([timeout, signal]) : signal.aborted ? signal : timeout) : timeout;\n // fetch rejects with a TypeError both for a network failure and for a\n // request that can never be sent (a newline in a header value, a bad URL).\n // Building the Request first separates the two: that one fails for good,\n // without echoing the value that broke it.\n try {\n // Without the body, so a stream body is never locked by the check.\n new Request(url, { method: init.method ?? \"GET\", headers: init.headers ?? {} });\n } catch {\n throw new DeliveryError(\"Invalid request (a header value or the URL is malformed)\", { retryable: false });\n }\n try {\n return await (deps.fetch ?? fetch)(url, { ...init, signal: combined });\n } catch (error) {\n if (error instanceof Error && error.name === \"TypeError\") throw new DeliveryError(\"Network error\", { retryable: true });\n throw error;\n }\n}\n\n/**\n * A factory option that may be a value or a function of the config (an\n * account, a secret). A function that throws fails the delivery\n * permanently with \"<what> could not be resolved\", never retried and never\n * echoing its message; to ask for a retry it can throw a retryable\n * `DeliveryError` itself.\n */\nexport async function resolveOption<T>(\n what: string,\n option: T | ((config: DestinationConfig) => T | Promise<T>),\n config: DestinationConfig,\n): Promise<T> {\n if (typeof option !== \"function\") return option;\n try {\n return await (option as (config: DestinationConfig) => T | Promise<T>)(config);\n } catch (error) {\n if (error instanceof DeliveryError) throw error;\n throw new DeliveryError(`${what} could not be resolved`);\n }\n}\n\n/** Lets go of a body we will not read, so the connection is freed. */\nexport function discard(response: Response): void {\n try {\n void response.body?.cancel().catch(() => {});\n } catch {\n // A mocked or already-read body.\n }\n}\n\n/** The string config value at `key`, trimmed, or \"\" (a snake_case `alias` is accepted too). */\nexport function configString(config: DestinationConfig, key: string, alias?: string): string {\n const raw = config[key] ?? (alias ? config[alias] : undefined);\n return typeof raw === \"string\" ? raw.trim() : \"\";\n}\n\n/** Bytes as base64url, no padding. */\nexport function base64url(bytes: Uint8Array | string): string {\n return base64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Bytes (or UTF-8 text) as standard base64. */\nexport function base64(bytes: Uint8Array | string): string {\n const raw = typeof bytes === \"string\" ? new TextEncoder().encode(bytes) : bytes;\n let s = \"\";\n for (let i = 0; i < raw.length; i++) s += String.fromCharCode(raw[i]!);\n return btoa(s);\n}\n\n/** Standard base64 (or base64url) as bytes. Throws on anything else. */\nexport function fromBase64(text: string): Uint8Array<ArrayBuffer> {\n const bin = atob(text.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** SHA-256 of a text, as lowercase hex. */\nexport async function sha256Hex(text: string): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(text));\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/** WebCrypto's key type, named without depending on the DOM lib. */\nexport type WebCryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;\n","import type { FieldTypeManifest } from \"./fields\";\nimport type { FieldBlock, Json } from \"./types\";\n\ntype JsonObject = { [key: string]: Json };\nconst isObject = (v: unknown): v is JsonObject => !!v && typeof v === \"object\" && !Array.isArray(v);\nfunction intProp(field: FieldBlock, name: string, fallback: number, floor = 1): number {\n const v = field.props?.[name];\n return typeof v === \"number\" && Number.isInteger(v) && v >= floor ? v : fallback;\n}\nfunction optionalIntProp(field: FieldBlock, name: string, floor = 0): number | undefined {\n const v = field.props?.[name];\n return typeof v === \"number\" && Number.isInteger(v) && v >= floor ? v : undefined;\n}\nconst blank = (v: unknown) => typeof v !== \"string\" || v.trim() === \"\";\n/**\n * Unanswered: nothing, or a list whose every entry is a blank one. Anything\n * else (a string, a list with a malformed entry) is an answer, so validation\n * rejects it instead of dropping it silently.\n */\nconst blankText = (v: unknown) => typeof v === \"string\" && v.trim() === \"\";\nconst emptyList = (value: Json | undefined, isBlank: (entry: Json) => boolean) =>\n value === undefined || value === null || (Array.isArray(value) && value.every(isBlank));\nconst plural = (n: number, one: string, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;\n\nexport function listLimits(field: FieldBlock) {\n return { min: optionalIntProp(field, \"min\") ?? 0, max: intProp(field, \"max\", 10), itemMaxLength: intProp(field, \"itemMaxLength\", 500) };\n}\nconst listItems = (value: Json | undefined): string[] =>\n Array.isArray(value) ? value.filter((v): v is string => typeof v === \"string\" && v.trim() !== \"\") : [];\n\nexport interface TableColumn { key: string; label: string; long?: boolean }\nexport const MAX_TABLE_COLUMNS = 6;\nexport const MAX_TABLE_CELL_LENGTH = 2000;\nexport function tableColumns(field: FieldBlock): TableColumn[] {\n const raw = field.props?.columns;\n if (!Array.isArray(raw)) return [];\n const seen = new Set<string>();\n const out: TableColumn[] = [];\n for (const c of raw) {\n if (!isObject(c) || typeof c.key !== \"string\" || !c.key || seen.has(c.key)) continue;\n seen.add(c.key);\n const column: TableColumn = { key: c.key, label: typeof c.label === \"string\" ? c.label : c.key };\n if (c.long === true) column.long = true;\n out.push(column);\n }\n return out;\n}\nexport function tableLimits(field: FieldBlock) {\n return { minRows: optionalIntProp(field, \"minRows\") ?? 0, maxRows: intProp(field, \"maxRows\", 3) };\n}\nconst filledRows = (value: Json | undefined): JsonObject[] =>\n Array.isArray(value) ? value.filter((r): r is JsonObject => isObject(r) && Object.values(r).some((c) => !blank(c))) : [];\n\nexport interface MediaNote { at: number; text: string }\nexport const MAX_TIMESTAMP_SECONDS = 86400;\nexport function formatTimestamp(seconds: number): string {\n const total = Number.isFinite(seconds) && seconds > 0 ? Math.floor(seconds) : 0;\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = String(total % 60).padStart(2, \"0\");\n return h ? `${h}:${String(m).padStart(2, \"0\")}:${s}` : `${m}:${s}`;\n}\nexport function parseTimestamp(text: string): number | null {\n const t = text.trim();\n if (!t) return null;\n const parts = t.split(\":\");\n if (parts.length > 3) return null;\n if (parts.length === 1) {\n if (!/^\\d+(\\.\\d+)?$/.test(t)) return null;\n const n = Number(t);\n return n <= MAX_TIMESTAMP_SECONDS ? n : null;\n }\n const last = parts.length - 1;\n let total = 0;\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]!;\n const ok = i === 0 ? /^\\d+$/.test(p) : i === last ? /^\\d{2}(\\.\\d+)?$/.test(p) : /^\\d{2}$/.test(p);\n if (!ok) return null;\n const n = Number(p);\n if (i > 0 && n >= 60) return null;\n total = total * 60 + n;\n }\n return total <= MAX_TIMESTAMP_SECONDS ? total : null;\n}\nconst isTimestamp = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v) && v >= 0 && v <= MAX_TIMESTAMP_SECONDS;\nconst notesWithText = (value: Json | undefined): JsonObject[] =>\n Array.isArray(value) ? value.filter((n): n is JsonObject => isObject(n) && !blank(n.text)) : [];\n\nexport interface Highlight { start: number; end: number; quote: string; note: string }\nexport const MAX_HIGHLIGHT_NOTE_LENGTH = 1000;\n/** The longest passage one highlight may quote; also bounds a quote the server can't check against `props.text`. */\nexport const MAX_HIGHLIGHT_QUOTE_LENGTH = 2000;\nexport const HIGHLIGHT_NOTE_MESSAGE = \"Add a note to each highlight.\";\nconst sourceText = (field: FieldBlock) => (typeof field.props?.text === \"string\" && field.props.text ? field.props.text : undefined);\n\n/**\n * The structured field types, whose answers are lists or records rather than one\n * value:\n * - `list`: several short answers, e.g. goals, action items, three things that went well.\n * - `table`: a small table each answer fills row by row, e.g. an action plan\n * (What / Who / By when), pros and cons.\n * - `media-notes`: notes pinned to times in a video or audio, e.g. lecture notes,\n * a recorded call review.\n * - `text-highlights`: highlight passages of a text and note on each, e.g.\n * annotating an article, a policy or a contract.\n *\n * They are registered like any other, but the builder offers them only to a\n * host that names them in its palette (`FormBuilder palette`), so forms that\n * never had them don't change.\n */\nexport const STRUCTURED_FIELD_TYPES = [\"list\", \"table\", \"media-notes\", \"text-highlights\"] as const;\n\nexport const structuredFieldTypes: FieldTypeManifest[] = [\n {\n type: \"list\", label: \"List\", category: \"text\", value: { json: true },\n // logic.ts `contains` on an array is exact item equality, same as multi-choice, so it is offered.\n operators: [\"contains\", \"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, blankText),\n validate: (value, field) => {\n if (!Array.isArray(value) || !value.every((v) => typeof v === \"string\")) return \"Enter a list of answers.\";\n const { min, max, itemMaxLength } = listLimits(field);\n if (value.some((v) => (v as string).trim().length > itemMaxLength)) return `Keep each item under ${itemMaxLength} characters.`;\n const count = listItems(value).length;\n if (count < min) return `Add at least ${plural(min, \"item\")}.`;\n if (count > max) return `Add at most ${plural(max, \"item\")}.`;\n return null;\n },\n normalize: (value) => (Array.isArray(value) ? listItems(value).map((v) => v.trim()) : value),\n summarize: (value) => listItems(value).map((v) => v.trim()).join(\"; \"),\n samples: (field) => {\n const { min, max } = listLimits(field);\n return [Array.from({ length: Math.min(Math.max(1, min), max) }, (_, i) => `Item ${i + 1}`)];\n },\n },\n {\n type: \"table\", label: \"Table\", category: \"advanced\", value: { json: true },\n operators: [\"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, (r) => isObject(r) && Object.values(r).every(blankText)),\n validate: (value, field) => {\n const columns = tableColumns(field);\n if (!columns.length) return \"This question has no columns.\";\n if (!Array.isArray(value) || !value.every(isObject)) return \"Fill in the rows.\";\n const keys = new Set(columns.map((c) => c.key));\n for (const row of value as JsonObject[]) {\n for (const [key, cell] of Object.entries(row)) {\n if (!keys.has(key)) return \"An answer names a column this question doesn't have.\";\n if (typeof cell !== \"string\") return \"Fill in the rows with text.\";\n if (cell.trim().length > MAX_TABLE_CELL_LENGTH) return `Keep each answer under ${MAX_TABLE_CELL_LENGTH} characters.`;\n }\n }\n const { minRows, maxRows } = tableLimits(field);\n const count = filledRows(value).length;\n if (count < minRows) return `Fill in at least ${plural(minRows, \"row\")}.`;\n if (count > maxRows) return `Fill in at most ${plural(maxRows, \"row\")}.`;\n return null;\n },\n normalize: (value) => Array.isArray(value)\n ? filledRows(value).map((row) => {\n const out: JsonObject = {};\n for (const [key, cell] of Object.entries(row)) if (typeof cell === \"string\") out[key] = cell.trim();\n return out;\n })\n : value,\n summarize: (value, field) => {\n const columns = tableColumns(field);\n return filledRows(value)\n .map((row) => columns.filter((c) => !blank(row[c.key])).map((c) => `${c.label}: ${(row[c.key] as string).trim()}`).join(\" · \"))\n .join(\" / \");\n },\n samples: (field) => {\n const columns = tableColumns(field);\n if (!columns.length) return [];\n const { minRows, maxRows } = tableLimits(field);\n const row = Object.fromEntries(columns.map((c) => [c.key, \"sample\"]));\n return [Array.from({ length: Math.min(Math.max(1, minRows), maxRows) }, () => ({ ...row }))];\n },\n },\n {\n type: \"media-notes\", label: \"Notes at moments\", category: \"media\", value: { json: true },\n operators: [\"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, (n) => isObject(n) && blankText(n.text)),\n validate: (value, field) => {\n if (!Array.isArray(value)) return \"Add notes.\";\n const textMaxLength = intProp(field, \"textMaxLength\", 1000);\n for (const note of value) {\n if (!isObject(note) || typeof note.text !== \"string\") return \"Add notes.\";\n if (!isTimestamp(note.at)) return \"Each note needs a time.\";\n if (note.text.trim().length > textMaxLength) return `Keep each note under ${textMaxLength} characters.`;\n }\n const maxNotes = intProp(field, \"maxNotes\", 20);\n return notesWithText(value).length > maxNotes ? `Add at most ${plural(maxNotes, \"note\")}.` : null;\n },\n normalize: (value) => Array.isArray(value)\n ? notesWithText(value).map((n) => ({ at: n.at as number, text: (n.text as string).trim() })).sort((a, b) => a.at - b.at)\n : value,\n summarize: (value) => notesWithText(value)\n .map((n) => ({ at: typeof n.at === \"number\" ? n.at : 0, text: (n.text as string).trim() }))\n .sort((a, b) => a.at - b.at)\n .map((n) => `${formatTimestamp(n.at)} ${n.text}`)\n .join(\"; \"),\n samples: () => [[{ at: 0, text: \"sample\" }]],\n },\n {\n type: \"text-highlights\", label: \"Highlights\", category: \"media\", value: { json: true },\n operators: [\"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, () => false),\n validate: (value, field) => {\n if (!Array.isArray(value)) return \"Highlight a passage.\";\n const maxHighlights = intProp(field, \"maxHighlights\", 20);\n if (value.length > maxHighlights) return `Add at most ${plural(maxHighlights, \"highlight\")}.`;\n const text = sourceText(field);\n for (const h of value) {\n if (!isObject(h) || !Number.isInteger(h.start) || !Number.isInteger(h.end) || typeof h.quote !== \"string\" || typeof h.note !== \"string\") {\n return \"Highlight a passage of the text.\";\n }\n const start = h.start as number;\n const end = h.end as number;\n if (start < 0 || end <= start || h.quote.length !== end - start) return \"Highlight a passage of the text.\";\n if (end - start > MAX_HIGHLIGHT_QUOTE_LENGTH) return `Highlight under ${MAX_HIGHLIGHT_QUOTE_LENGTH} characters at a time.`;\n if (text !== undefined && (end > text.length || text.slice(start, end) !== h.quote)) return \"A highlight doesn't match the text.\";\n if (h.note.trim() === \"\") return HIGHLIGHT_NOTE_MESSAGE;\n if (h.note.trim().length > MAX_HIGHLIGHT_NOTE_LENGTH) return `Keep each note under ${MAX_HIGHLIGHT_NOTE_LENGTH} characters.`;\n }\n return null;\n },\n normalize: (value) => Array.isArray(value)\n ? value.filter(isObject)\n .map((h) => ({ start: h.start as number, end: h.end as number, quote: h.quote as string, note: String(h.note).trim() }))\n .sort((a, b) => a.start - b.start || a.end - b.end)\n : value,\n summarize: (value) => Array.isArray(value)\n ? value.filter(isObject).map((h) => `\"${String(h.quote)}\" — ${String(h.note).trim()}`).join(\"; \")\n : \"\",\n samples: (field) => {\n const text = sourceText(field);\n if (text === undefined) return [[{ start: 0, end: 6, quote: \"sample\", note: \"sample\" }]];\n const end = Math.min(text.length, 20);\n return [[{ start: 0, end, quote: text.slice(0, end), note: \"sample\" }]];\n },\n },\n];\n","import type { Block, FieldBlock, Json, Operator } from \"./types\";\nimport { structuredFieldTypes } from \"./structured\";\n\n/**\n * A field type, without any UI. Renderers are registered separately per\n * platform (`genesis-forms-react`), so a manifest runs anywhere.\n */\nexport interface FieldTypeManifest {\n type: string;\n label: string;\n category: \"text\" | \"choice\" | \"scale\" | \"date\" | \"media\" | \"advanced\";\n /** `json: false` types must convert, so drafts and server replay never lose an answer. */\n value:\n | { json: true }\n | { json: false; serialize: (value: unknown) => Json; deserialize: (json: Json) => unknown };\n operators: Operator[];\n a11y: {\n semantics: \"control\" | \"group\";\n /** The HTML `autocomplete` token, such as `\"email\"` or `\"tel\"`. */\n autocomplete?: string;\n /** The HTML `inputmode` hint for on-screen keyboards, such as `\"email\"` or `\"tel\"`. */\n inputMode?: \"text\" | \"email\" | \"tel\" | \"numeric\" | \"decimal\" | \"url\" | \"search\";\n };\n isEmpty?: (value: Json | undefined) => boolean;\n /** Return an error message, or null when the (non-empty) value is valid. */\n validate?: (value: Json, field: FieldBlock) => string | null;\n /** Plain text for recall, exports and emails. */\n summarize?: (value: Json, field: FieldBlock) => string;\n /**\n * The form a (valid, non-empty) value is stored in, such as an email\n * without surrounding spaces. Applied by `engine.answers()` and the server.\n */\n normalize?: (value: Json, field: FieldBlock) => Json;\n /** Valid example answers, used by `coverage()` and other test tools to explore a path. */\n samples?: (field: FieldBlock) => Json[];\n}\n\n// One registry per process, shared by every entry point (index, server,\n// testing are bundled separately), so a plugin registered once is seen by all.\nconst REGISTRY = Symbol.for(\"@marktiderman/genesis-forms/field-types\");\nconst globalScope = globalThis as typeof globalThis & { [REGISTRY]?: Map<string, FieldTypeManifest> };\nconst registry: Map<string, FieldTypeManifest> = (globalScope[REGISTRY] ??= new Map());\n\nexport function registerFieldType(manifest: FieldTypeManifest): void {\n if (!manifest.type) throw new Error(\"registerFieldType: a field type needs a `type`.\");\n const value = manifest.value as { json: boolean; serialize?: unknown; deserialize?: unknown };\n if (\n !value.json &&\n (typeof value.serialize !== \"function\" || typeof value.deserialize !== \"function\")\n ) {\n throw new Error(\n `registerFieldType: \"${manifest.type}\" stores a non-JSON value, so it must provide both serialize and deserialize.`,\n );\n }\n registry.set(manifest.type, manifest);\n}\n\nexport function getFieldType(type: string): FieldTypeManifest | undefined {\n return registry.get(type);\n}\n\nexport function listFieldTypes(): FieldTypeManifest[] {\n return [...registry.values()];\n}\n\nexport function isEmptyValue(value: Json | undefined, field?: FieldBlock): boolean {\n const manifest = field ? registry.get(field.type) : undefined;\n if (manifest?.isEmpty) return manifest.isEmpty(value);\n if (value === undefined || value === null) return true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/** A value in its stored form (see `FieldTypeManifest.normalize`). */\nexport function normalizeValue(value: Json, field: FieldBlock): Json {\n const manifest = registry.get(field.type);\n return manifest?.normalize ? manifest.normalize(value, field) : value;\n}\n\n/** Whether a block holds personal or secret data: `sensitive: true`, or the `props.sensitive: true` alias. */\nexport function isSensitive(block: Block): boolean {\n return block.kind === \"field\" && (block.sensitive === true || block.props?.sensitive === true);\n}\n\nexport function summarizeValue(value: Json | undefined, field: FieldBlock): string {\n if (isEmptyValue(value, field)) return \"\";\n const manifest = registry.get(field.type);\n if (manifest?.summarize) return manifest.summarize(value as Json, field);\n if (Array.isArray(value)) return value.join(\", \");\n return String(value);\n}\n\n// ── Built-in types (R1) ──────────────────────────────────────────────────────\n\nexport interface ChoiceOption {\n value: string;\n label?: string;\n}\n\nexport function choiceOptions(field: FieldBlock): ChoiceOption[] {\n const raw = field.props?.options;\n if (!Array.isArray(raw)) return [];\n return raw.flatMap((o) =>\n o && typeof o === \"object\" && !Array.isArray(o) && typeof o.value === \"string\"\n ? [{ value: o.value, label: typeof o.label === \"string\" ? o.label : undefined }]\n : [],\n );\n}\n\nfunction optionLabel(field: FieldBlock, value: string): string {\n const option = choiceOptions(field).find((o) => o.value === value);\n return option?.label ?? value;\n}\n\nfunction intRange(field: FieldBlock, min: number, maxDefault: number) {\n const max = typeof field.props?.max === \"number\" ? field.props.max : maxDefault;\n return { min, max };\n}\n\nconst numberOps: Operator[] = [\"eq\", \"neq\", \"lt\", \"lte\", \"gt\", \"gte\", \"in\", \"answered\", \"empty\"];\nconst textOps: Operator[] = [\"eq\", \"neq\", \"contains\", \"answered\", \"empty\"];\n\nfunction maxLength(field: FieldBlock, fallback: number): number {\n return typeof field.props?.maxLength === \"number\" ? field.props.maxLength : fallback;\n}\n\nfunction textValidate(fallback: number) {\n return (value: Json, field: FieldBlock) => {\n if (typeof value !== \"string\") return \"Enter text.\";\n const limit = maxLength(field, fallback);\n return value.length > limit ? `Keep it under ${limit} characters.` : null;\n };\n}\n\n/** The longest address SMTP allows (RFC 5321). */\nconst MAX_EMAIL_LENGTH = 254;\n\n/**\n * `local@domain.tld`: no spaces, exactly one `@`, and a dot inside the domain.\n * A linear scan rather than a regex, so a hostile value cannot backtrack.\n */\nexport function isEmailAddress(value: string): boolean {\n if (value.length > MAX_EMAIL_LENGTH || /\\s/.test(value)) return false;\n const at = value.indexOf(\"@\");\n if (at < 1 || value.indexOf(\"@\", at + 1) !== -1) return false;\n const domain = value.slice(at + 1);\n // A dot with at least one character on each side.\n return domain.slice(1, -1).includes(\".\");\n}\n\n/** Longest phone number accepted, separators included. */\nconst MAX_PHONE_LENGTH = 32;\n\n/**\n * Digits with optional separators (spaces, `-`, `(`, `)`, `.`) and an\n * optional leading `+`; 7 to 15 digits (E.164 allows at most 15). One linear scan.\n */\nfunction isPhoneNumber(value: string): boolean {\n if (value.length > MAX_PHONE_LENGTH) return false;\n let digits = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value[i]!;\n if (c >= \"0\" && c <= \"9\") digits++;\n else if (c === \"+\") {\n if (i !== 0) return false;\n } else if (c !== \" \" && c !== \"-\" && c !== \"(\" && c !== \")\" && c !== \".\") return false;\n }\n return digits >= 7 && digits <= 15;\n}\n\nconst builtins: FieldTypeManifest[] = [\n {\n type: \"short-text\",\n label: \"Short text\",\n category: \"text\",\n value: { json: true },\n operators: textOps,\n a11y: { semantics: \"control\" },\n validate: textValidate(500),\n },\n {\n type: \"long-text\",\n label: \"Long text\",\n category: \"text\",\n value: { json: true },\n operators: textOps,\n a11y: { semantics: \"control\" },\n validate: textValidate(5000),\n },\n {\n type: \"email\",\n label: \"Email\",\n category: \"text\",\n value: { json: true },\n operators: textOps,\n a11y: { semantics: \"control\", autocomplete: \"email\", inputMode: \"email\" },\n validate: (value) =>\n typeof value === \"string\" && isEmailAddress(value.trim())\n ? null\n : \"Enter an email address like name@example.com.\",\n normalize: (value) => (typeof value === \"string\" ? value.trim() : value),\n },\n {\n type: \"phone\",\n label: \"Phone\",\n category: \"text\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"answered\", \"empty\"],\n a11y: { semantics: \"control\", autocomplete: \"tel\", inputMode: \"tel\" },\n validate: (value) =>\n typeof value === \"string\" && isPhoneNumber(value.trim())\n ? null\n : \"Enter a phone number with 7 to 15 digits.\",\n normalize: (value) => (typeof value === \"string\" ? value.trim() : value),\n summarize: (value) => String(value),\n },\n {\n type: \"rating\",\n label: \"Rating\",\n category: \"scale\",\n value: { json: true },\n operators: numberOps,\n a11y: { semantics: \"group\" },\n validate: (value, field) => {\n const { min, max } = intRange(field, 1, 5);\n return Number.isInteger(value) && (value as number) >= min && (value as number) <= max\n ? null\n : `Choose a rating from ${min} to ${max}.`;\n },\n summarize: (value, field) => `${value}/${intRange(field, 1, 5).max}`,\n },\n {\n type: \"nps\",\n label: \"Net Promoter Score\",\n category: \"scale\",\n value: { json: true },\n operators: numberOps,\n a11y: { semantics: \"group\" },\n validate: (value) =>\n Number.isInteger(value) && (value as number) >= 0 && (value as number) <= 10\n ? null\n : \"Choose a score from 0 to 10.\",\n summarize: (value) => `${value}/10`,\n },\n {\n type: \"single-choice\",\n label: \"Single choice\",\n category: \"choice\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"in\", \"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n validate: (value, field) =>\n typeof value === \"string\" && choiceOptions(field).some((o) => o.value === value)\n ? null\n : \"Choose one of the options.\",\n summarize: (value, field) => optionLabel(field, String(value)),\n },\n {\n type: \"multi-choice\",\n label: \"Multiple choice\",\n category: \"choice\",\n value: { json: true },\n operators: [\"contains\", \"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n validate: (value, field) => {\n const allowed = new Set(choiceOptions(field).map((o) => o.value));\n // Each option at most once, so a value is never longer than the option list.\n return Array.isArray(value) &&\n value.length <= allowed.size &&\n new Set(value).size === value.length &&\n value.every((v) => typeof v === \"string\" && allowed.has(v))\n ? null\n : \"Choose from the options.\";\n },\n summarize: (value, field) =>\n Array.isArray(value) ? value.map((v) => optionLabel(field, String(v))).join(\", \") : String(value),\n },\n {\n type: \"yes-no\",\n label: \"Yes / no\",\n category: \"choice\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n validate: (value) => (typeof value === \"boolean\" ? null : \"Choose yes or no.\"),\n summarize: (value) => (value ? \"Yes\" : \"No\"),\n },\n];\n\nfor (const manifest of [...builtins, ...structuredFieldTypes]) registerFieldType(manifest);\n","import { isEmptyValue } from \"./fields\";\nimport type { Block, Condition, FieldBlock, FormDefinition, Json, LogicRule, Operand } from \"./types\";\n\nexport interface EvalScope {\n values: Record<string, Json | undefined>;\n hidden: Record<string, Json | undefined>;\n fields: Map<string, FieldBlock>;\n}\n\n/** `record[key]` if it is the record's own property: `values.constructor` is not an answer. */\nexport function own<T>(record: Record<string, T>, key: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;\n}\n\nfunction resolve(operand: Operand, scope: EvalScope): Json | undefined {\n if (\"field\" in operand) return own(scope.values, operand.field);\n if (\"hidden\" in operand) return own(scope.hidden, operand.hidden);\n return operand.value;\n}\n\nfunction deepEqual(a: Json | undefined, b: Json | undefined): boolean {\n if (a === b) return true;\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));\n }\n return false;\n}\n\n/**\n * Evaluate a condition. Never throws. An empty value (unanswered, `null`,\n * blank text, an empty list: see `isEmptyValue`) is unanswered: it fails\n * every comparison, including `eq`, `in` and `contains`, and passes `neq`.\n */\nexport function evaluate(condition: Condition, scope: EvalScope): boolean {\n if (\"all\" in condition) return condition.all.every((c) => evaluate(c, scope));\n if (\"any\" in condition) return condition.any.some((c) => evaluate(c, scope));\n if (\"not\" in condition) return !evaluate(condition.not, scope);\n\n const left = resolve(condition.left, scope);\n const right = condition.right ? resolve(condition.right, scope) : undefined;\n const field = \"field\" in condition.left ? scope.fields.get(condition.left.field) : undefined;\n const unanswered = isEmptyValue(left, field);\n\n switch (condition.op) {\n case \"answered\":\n return !unanswered;\n case \"empty\":\n return unanswered;\n case \"eq\":\n return !unanswered && deepEqual(left, right);\n case \"neq\":\n // An unanswered field is \"not\" any value.\n return unanswered || !deepEqual(left, right);\n case \"lt\":\n case \"lte\":\n case \"gt\":\n case \"gte\": {\n if (typeof left !== \"number\" || typeof right !== \"number\") return false;\n if (condition.op === \"lt\") return left < right;\n if (condition.op === \"lte\") return left <= right;\n if (condition.op === \"gt\") return left > right;\n return left >= right;\n }\n case \"in\":\n return !unanswered && Array.isArray(right) && right.some((r) => deepEqual(r, left));\n case \"contains\":\n if (unanswered) return false;\n if (Array.isArray(left)) return left.some((l) => deepEqual(l, right));\n return (\n typeof left === \"string\" &&\n typeof right === \"string\" &&\n left.toLowerCase().includes(right.toLowerCase())\n );\n }\n}\n\n/** Blocks a respondent steps through: fields and content, in order. */\nexport function steps(def: FormDefinition): Block[] {\n return def.blocks.filter((b) => b.kind !== \"page-break\");\n}\n\nfunction visibilityRules(def: FormDefinition, blockId: string) {\n return (def.logic ?? []).filter(\n (r): r is Extract<LogicRule, { target: string }> =>\n (r.effect === \"show\" || r.effect === \"hide\") && r.target === blockId,\n );\n}\n\n/** Whether a field is withheld because the form is anonymous and the field identifies the respondent. */\nexport function withheld(def: FormDefinition, field: FieldBlock | undefined): boolean {\n return def.settings?.anonymous === true && field?.identifying === true;\n}\n\n/** Show/hide rules against a scope as given. A matching `hide` wins; any `show` must match. */\nfunction rulesAllow(def: FormDefinition, blockId: string, scope: EvalScope): boolean {\n if (withheld(def, scope.fields.get(blockId))) return false;\n const rules = visibilityRules(def, blockId);\n if (rules.some((r) => r.effect === \"hide\" && evaluate(r.when, scope))) return false;\n const shows = rules.filter((r) => r.effect === \"show\");\n return shows.length === 0 || shows.some((r) => evaluate(r.when, scope));\n}\n\nexport interface PathResult {\n /** Block ids the respondent will step through, given the answers on the path. */\n path: string[];\n /** The ending reached by a jump, or the default ending. */\n ending: string | null;\n}\n\nexport interface PathWalk extends PathResult {\n /**\n * The scope logic sees at a block: the values of the fields on the path\n * before it (and of the block itself, with `inclusive`), nothing else.\n */\n scopeAt(blockId: string, inclusive?: boolean): EvalScope;\n}\n\n/** One forward pass over the blocks. See `computePath`. */\nexport function walkPath(def: FormDefinition, scope: EvalScope): PathWalk {\n const list = steps(def);\n const index = new Map(list.map((b, i) => [b.id, i]));\n const position = new Map(def.blocks.map((b, i) => [b.id, i]));\n const jumps = (def.logic ?? []).filter(\n (r): r is Extract<LogicRule, { effect: \"jump\" }> => r.effect === \"jump\",\n );\n const defaultEnding = def.endings?.find((e) => e.id === \"default\")?.id ?? def.endings?.[0]?.id ?? null;\n\n // Values of the fields placed on the path so far. It only grows, so every\n // decision reads blocks already placed and the pass needs no fixed point.\n const placed = Object.create(null) as Record<string, Json | undefined>;\n const local: EvalScope = { values: placed, hidden: scope.hidden, fields: scope.fields };\n const path: string[] = [];\n const nextVisible = (from: number) => {\n for (let i = from; i < list.length; i++) if (rulesAllow(def, list[i]!.id, local)) return i;\n return list.length;\n };\n\n let ending = defaultEnding;\n let i = nextVisible(0);\n while (i < list.length) {\n const block = list[i]!;\n path.push(block.id);\n if (block.kind === \"field\") placed[block.id] = own(scope.values, block.id);\n const jump = jumps.find((r) => r.from === block.id && evaluate(r.when, local));\n if (jump) {\n if (typeof jump.to === \"object\") {\n ending = jump.to.ending;\n break;\n }\n const target = index.get(jump.to);\n if (target !== undefined && target > i) {\n i = nextVisible(target);\n continue;\n }\n }\n i = nextVisible(i + 1);\n }\n\n const scopeAt = (blockId: string, inclusive = false): EvalScope => {\n const at = position.get(blockId) ?? -1;\n const values = Object.create(null) as Record<string, Json | undefined>;\n for (const id of path) {\n const p = position.get(id)!;\n if (p > at || (p === at && !inclusive)) break;\n if (id in placed) values[id] = placed[id];\n }\n return { values, hidden: scope.hidden, fields: scope.fields };\n };\n return { path, ending, scopeAt };\n}\n\n/**\n * The respondent's path, derived from the answers on the path, so the client,\n * the server and a replay always agree. It is built in one forward pass: a\n * block's show/hide rules, and the jumps from it, see only the fields already\n * on the path before it (and, for a jump, the block itself). A field that is\n * hidden, jumped over or later in the form reads as unanswered, whatever\n * value it holds.\n *\n * A block jumped over is off the path and counts as hidden: it is not\n * validated and its value is cleared on submit. A jump never revisits a block;\n * a jump to an earlier block is ignored (the checker in `parseForm` reports it).\n */\nexport function computePath(def: FormDefinition, scope: EvalScope): PathResult {\n const { path, ending } = walkPath(def, scope);\n return { path, ending };\n}\n\n/**\n * Whether a block's show/hide rules let it be shown, ignoring jumps. The rules\n * read the answers on the path before the block, as in `computePath`. A block\n * with any `show` rule is hidden until one matches; a matching `hide` rule\n * always wins.\n */\nexport function ruleVisible(def: FormDefinition, blockId: string, scope: EvalScope): boolean {\n return rulesAllow(def, blockId, walkPath(def, scope).scopeAt(blockId));\n}\n\nexport function fieldMap(def: FormDefinition): Map<string, FieldBlock> {\n const map = new Map<string, FieldBlock>();\n for (const block of def.blocks) if (block.kind === \"field\") map.set(block.id, block);\n return map;\n}\n","import { summarizeValue } from \"./fields\";\nimport { own } from \"./logic\";\nimport type { FieldBlock, Json } from \"./types\";\n\nconst TOKEN = /\\{\\{\\s*(field|hidden):([A-Za-z0-9_-]+)\\s*(?:\\|([^}]*))?\\}\\}/g;\n\nexport interface RecallScope {\n /** Fields by key. */\n fieldsByKey: Map<string, FieldBlock>;\n values: Record<string, Json | undefined>;\n hidden: Record<string, Json | undefined>;\n}\n\n/**\n * Replace `{{field:key|fallback}}` and `{{hidden:name|fallback}}` tokens.\n * An unanswered value renders its fallback (default empty); the text is\n * never dropped.\n */\nexport function recall(text: string, scope: RecallScope): string {\n return text.replace(TOKEN, (_match, kind: string, name: string, fallback?: string) => {\n if (kind === \"field\") {\n const field = scope.fieldsByKey.get(name);\n const out = field ? summarizeValue(own(scope.values, field.id), field) : \"\";\n return out || (fallback ?? \"\").trim();\n }\n const value = own(scope.hidden, name);\n const out = value === undefined || value === null ? \"\" : String(value);\n return out || (fallback ?? \"\").trim();\n });\n}\n\n/** The keys a text recalls, for the checker. */\nexport function recallRefs(text: string): { kind: \"field\" | \"hidden\"; name: string }[] {\n return [...text.matchAll(TOKEN)].map((m) => ({ kind: m[1] as \"field\" | \"hidden\", name: m[2]! }));\n}\n","/**\n * One response as a flat row: the shape the sheet appends, the email lists\n * and the webhook sends alongside the raw answers.\n */\nimport { getFieldType, isEmptyValue, isSensitive, summarizeValue } from \"../fields\";\nimport { own, withheld } from \"../logic\";\nimport { recall } from \"../recall\";\nimport type { FieldBlock, FormDefinition, Json } from \"../types\";\nimport type { Cell, DeliverySubmission } from \"./types\";\n\nexport interface RowOptions {\n /**\n * Fields marked `sensitive`: `\"include\"` their values (default), `\"mask\"`\n * them as `[sensitive]`, or `\"omit\"` their columns.\n */\n sensitive?: \"include\" | \"mask\" | \"omit\" | undefined;\n}\n\nexport interface ResponseRow {\n /** Cells by column key. */\n row: Record<string, Cell>;\n /** The column keys in order: `id`, `submitted_at`, the meta keys, then one per field key. */\n columns: string[];\n /** Field labels by key, recall filled in from this submission. */\n labels: Record<string, string>;\n}\n\nexport const SENSITIVE_MASK = \"[sensitive]\";\n\n// Never used as column keys, so a hostile meta key cannot touch a prototype.\nconst RESERVED = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/**\n * One answer as a cell: numbers stay numbers (ratings, NPS), choices show\n * their labels, a list is joined with \", \", yes/no reads \"Yes\"/\"No\", and a\n * plugin type's `summarize` is used where it has one.\n */\nexport function answerCell(field: FieldBlock, value: Json | undefined): Cell {\n if (value === undefined || isEmptyValue(value, field)) return \"\";\n if (typeof value === \"number\") return value;\n const manifest = getFieldType(field.type);\n if (manifest?.summarize) return summarizeValue(value, field);\n if (typeof value === \"string\") return value;\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n if (Array.isArray(value) && value.every((v) => typeof v !== \"object\" || v === null)) {\n return value.map((v) => String(v)).join(\", \");\n }\n return JSON.stringify(value);\n}\n\n/**\n * The row for one submission. Columns: `id` (the response id), then\n * `submitted_at` when given, then the app's `meta` columns in order, then\n * one per field key in form order (blank when unanswered or hidden by\n * logic). Content blocks get no column. On an anonymous form, identifying\n * fields get no column at all, whatever the answers hold.\n */\nexport function responseRow(\n submission: DeliverySubmission,\n definition: FormDefinition,\n options: RowOptions = {},\n): ResponseRow {\n const row: Record<string, Cell> = {};\n const columns: string[] = [];\n const set = (key: string, value: Cell) => {\n if (RESERVED.has(key)) return;\n if (!Object.prototype.hasOwnProperty.call(row, key)) columns.push(key);\n row[key] = value;\n };\n set(\"id\", submission.id);\n if (submission.submittedAt !== undefined) set(\"submitted_at\", submission.submittedAt);\n for (const [key, value] of Object.entries(submission.meta ?? {})) {\n if (key !== \"id\" && key !== \"submitted_at\") set(key, value);\n }\n\n const fields = definition.blocks.filter((b): b is FieldBlock => b.kind === \"field\");\n const fieldsByKey = new Map(fields.map((f) => [f.key, f]));\n const sensitive = options.sensitive ?? \"include\";\n // Recall in a label must not leak what the row itself withholds or masks.\n const values: Record<string, Json> = {};\n for (const field of fields) {\n const value = own(submission.answers, field.id);\n if (value === undefined || withheld(definition, field)) continue;\n if (isSensitive(field) && sensitive !== \"include\") continue;\n values[field.id] = value;\n }\n const scope = { fieldsByKey, values, hidden: visibleInputs(submission, definition, sensitive) };\n const labels: Record<string, string> = {};\n for (const field of fields) {\n if (withheld(definition, field)) continue;\n if (isSensitive(field) && sensitive === \"omit\") continue;\n if (RESERVED.has(field.key)) continue;\n labels[field.key] = recall(field.label, scope).trim() || field.key;\n const cell = answerCell(field, own(submission.answers, field.id));\n set(field.key, isSensitive(field) && sensitive === \"mask\" && cell !== \"\" ? SENSITIVE_MASK : cell);\n }\n return { row, columns, labels };\n}\n\n/**\n * Hidden and server inputs as recall and the webhook may show them: on an\n * anonymous form identifying ones are left out, and sensitive ones are left\n * out unless `sensitive` is `\"include\"`.\n */\nexport function visibleInputs(\n submission: DeliverySubmission,\n definition: FormDefinition,\n sensitive: RowOptions[\"sensitive\"] = \"include\",\n): Record<string, Json> {\n const declared = new Map((definition.hidden ?? []).map((h) => [h.name, h]));\n const out: Record<string, Json> = {};\n for (const [name, value] of Object.entries({ ...submission.hidden, ...submission.context })) {\n const input = declared.get(name);\n if (RESERVED.has(name)) continue;\n if (input?.identifying && definition.settings?.anonymous === true) continue;\n if (input?.sensitive && sensitive !== \"include\") continue;\n out[name] = value;\n }\n return out;\n}\n\n/**\n * A cell that a spreadsheet will never run as a formula when the text is\n * opened elsewhere (a CSV export opened in Excel). Opt-in: use it when\n * writing CSV, not for the sheet destination, whose RAW writes are already\n * safe and would store the `'` literally. Text starting with `=`,\n * `@`, a tab or a carriage return gets a leading `'`, as OWASP recommends;\n * so does text starting with `+` or `-` unless it is only digits and\n * number punctuation (a phone number such as `+1 (555) 010-0000`, `-2.5`),\n * which cannot call a function or name a cell. Numbers and booleans are\n * returned as they are.\n */\nexport function escapeFormula(cell: Cell): Cell {\n if (typeof cell !== \"string\" || cell === \"\") return cell;\n const first = cell[0]!;\n if (first === \"=\" || first === \"@\" || first === \"\\t\" || first === \"\\r\") return `'${cell}`;\n if ((first === \"+\" || first === \"-\") && !/^[+-][\\d\\s().,+-]*$/.test(cell)) return `'${cell}`;\n return cell;\n}\n","/**\n * The email destination: one notification per submission, through any\n * provider that implements `EmailProvider`. `resendProvider` is built in.\n *\n * The body is built from the definition: each answered field's label (recall\n * filled in) and its value, in form order, after the app's meta columns.\n * Every value is HTML-escaped. Subjects and addresses are stripped of line\n * breaks and checked, so an answer can never add a header. Sensitive fields\n * are masked unless `sensitive: \"include\"` is set: an inbox is not a vault.\n */\nimport { isEmailAddress } from \"../fields\";\nimport { own } from \"../logic\";\nimport type { FormDefinition } from \"../types\";\nimport { responseRow, type ResponseRow, type RowOptions } from \"./row\";\nimport {\n configString,\n deliveryFailure,\n DeliveryError,\n discard,\n httpError,\n\n sha256Hex,\n timedFetch,\n type Cell,\n type DeliveryOptions,\n type DeliveryResult,\n type DeliverySubmission,\n type Destination,\n type DestinationConfig,\n type HttpDeps,\n} from \"./types\";\n\n/** One message, ready to send. Addresses are already checked. */\nexport interface EmailMessage {\n from: string;\n to: string[];\n replyTo?: string | undefined;\n subject: string;\n text: string;\n html: string;\n /** Stable across retries of one delivery: a provider that supports it sends once. */\n idempotencyKey: string;\n}\n\n/** Sends one message. Throws a `DeliveryError` (or any error) on failure. */\nexport interface EmailProvider {\n readonly name: string;\n send(message: EmailMessage, options: { signal?: AbortSignal | undefined }): Promise<void>;\n}\n\nexport interface EmailContent {\n subject: string;\n text: string;\n html: string;\n}\n\nexport interface EmailRenderInput {\n submission: DeliverySubmission;\n definition: FormDefinition;\n config: DestinationConfig;\n /** The submission as a row (sensitive values masked unless `sensitive: \"include\"`). */\n row: ResponseRow;\n}\n\n/** What the email destination reads from a destination's config. */\nexport interface EmailConfig {\n /** One address or a list (at most 50). */\n to: string | string[];\n /** Overrides the default subject (still stripped of line breaks). */\n subject?: string;\n}\n\nexport interface EmailDestinationOptions {\n provider: EmailProvider;\n /** `\"Feedback <feedback@send.example.com>\"` or a bare address. */\n from: string;\n /**\n * The Reply-To address: the key of an email field whose answer is used, or\n * a function returning an address (or null for none). Only a valid single\n * address is ever used.\n */\n replyTo?: string | ((input: EmailRenderInput) => string | null | undefined) | undefined;\n /** Builds the subject and bodies. Defaults to `renderEmail`. The subject is sanitized afterwards either way. */\n render?: ((input: EmailRenderInput) => EmailContent) | undefined;\n /** Sensitive fields: `\"mask\"` (default), `\"omit\"` or `\"include\"`. */\n sensitive?: RowOptions[\"sensitive\"];\n}\n\n/** Resend allows 50 recipients per email. */\nexport const MAX_RECIPIENTS = 50;\nconst MAX_SUBJECT_LENGTH = 200;\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/**\n * A header value on one line: control characters (CR, LF, NUL…) and Unicode\n * line separators become spaces, runs of spaces collapse, and it is cut to\n * `max` characters.\n */\nexport function headerSafe(text: string, max = MAX_SUBJECT_LENGTH): string {\n // eslint-disable-next-line no-control-regex\n const flat = text.replace(/[\\u0000-\\u001f\\u007f\\u2028\\u2029]+/g, \" \").replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\n/** A bare address that is safe as a header value: valid, one line, no display name. */\nexport function isSafeAddress(value: unknown): value is string {\n return typeof value === \"string\" && isEmailAddress(value) && !/[\\u0000-\\u001f\\u007f<>,;:\"()[\\]\\\\]/.test(value);\n}\n\n/**\n * A From value: a bare address, or `Name <address>` where the name has no\n * quotes, angle brackets or line breaks.\n */\nexport function isSafeFrom(value: string): boolean {\n const named = /^([^\"<>\\u0000-\\u001f\\u007f]{1,100}) <([^<>]+)>$/.exec(value);\n return named ? isSafeAddress(named[2]) : isSafeAddress(value);\n}\n\n/** Plain text and HTML bodies from label/value lines, every value escaped. */\nexport function emailBody(lines: readonly (readonly [string, Cell])[], footer?: string): { text: string; html: string } {\n const text = lines.map(([k, v]) => `${k}: ${v}`).join(\"\\n\") + (footer ? `\\n\\n${footer}` : \"\");\n // Paragraphs rather than a table: email clients render them alike everywhere.\n const font = \"font-family:sans-serif;font-size:14px;margin:0 0 12px\";\n const html =\n lines\n .map(\n ([k, v]) =>\n `<p style=\"${font}\"><span style=\"color:#666\">${escapeHtml(k)}</span><br>` +\n `<span style=\"white-space:pre-wrap\">${escapeHtml(String(v))}</span></p>`,\n )\n .join(\"\") +\n (footer ? `<p style=\"font-family:sans-serif;font-size:12px;color:#666\">${escapeHtml(footer)}</p>` : \"\");\n return { text, html };\n}\n\n/**\n * The default notification: subject `\"<form title>: new response\"` (or\n * `config.subject`), then the meta columns, each answered field by label,\n * the ending's title when the form has several, and the response id.\n */\nexport function renderEmail(input: EmailRenderInput): EmailContent {\n const { submission, definition, config, row } = input;\n const lines: [string, Cell][] = [];\n const fieldKeys = new Set(Object.keys(row.labels));\n for (const key of row.columns) {\n if (key === \"id\") continue;\n const value = row.row[key];\n if (value === undefined || value === \"\") continue;\n const label = fieldKeys.has(key) ? row.labels[key]! : key === \"submitted_at\" ? \"Submitted\" : key;\n lines.push([label, value]);\n }\n const endings = definition.endings ?? [];\n if (submission.ending && endings.length > 1) {\n const ending = endings.find((e) => e.id === submission.ending);\n if (ending) lines.push([\"Ending\", ending.title]);\n }\n if (!lines.length) lines.push([\"Answers\", \"(none)\"]);\n const subject = configString(config, \"subject\") || `${definition.title || definition.id}: new response`;\n return { subject, ...emailBody(lines, `Response ${submission.id}`) };\n}\n\n/** Recipients from config: a string or a list, each checked. Throws when there are none or too many. */\nfunction recipients(config: DestinationConfig): string[] {\n const raw = config[\"to\"];\n const list = (Array.isArray(raw) ? raw : typeof raw === \"string\" ? raw.split(\",\") : []).map((t) =>\n typeof t === \"string\" ? t.trim() : t,\n );\n const to = [...new Set(list.filter(isSafeAddress))];\n if (to.length !== list.filter((t) => t !== \"\").length) {\n throw new DeliveryError(\"The email destination has an invalid recipient\");\n }\n if (!to.length) throw new DeliveryError(\"The email destination has no recipients\");\n if (to.length > MAX_RECIPIENTS) throw new DeliveryError(`The email destination has more than ${MAX_RECIPIENTS} recipients`);\n return to;\n}\n\nfunction replyToAddress(option: EmailDestinationOptions[\"replyTo\"], input: EmailRenderInput): string | undefined {\n if (!option) return undefined;\n let value: unknown;\n if (typeof option === \"function\") value = option(input);\n else {\n const field = input.definition.blocks.find((b) => b.kind === \"field\" && b.key === option);\n value = field ? own(input.submission.answers, field.id) : undefined;\n // An anonymous form never gives away an identifying answer, not even as Reply-To.\n if (field?.kind === \"field\" && field.identifying && input.definition.settings?.anonymous) value = undefined;\n }\n const trimmed = typeof value === \"string\" ? value.trim() : value;\n return isSafeAddress(trimmed) ? trimmed : undefined;\n}\n\n/**\n * The idempotency key: the delivery id and the first 16 hex digits of\n * SHA-256 of the sorted recipients, so a retried delivery never sends twice\n * and one whose recipients changed meanwhile is a new send.\n */\nexport async function idempotencyKey(deliveryId: string, to: readonly string[]): Promise<string> {\n const hex = await sha256Hex([...to].sort().join(\",\"));\n return `${deliveryId.slice(0, 200)}:${hex.slice(0, 16)}`;\n}\n\nexport function emailDestination(options: EmailDestinationOptions): Destination {\n return {\n kind: \"email\",\n async deliver(submission, definition, config, deliveryOptions: DeliveryOptions = {}): Promise<DeliveryResult> {\n try {\n if (!isSafeFrom(options.from)) throw new DeliveryError(\"The email destination's from address is invalid\");\n const to = recipients(config);\n const row = responseRow(submission, definition, { sensitive: options.sensitive ?? \"mask\" });\n const input: EmailRenderInput = { submission, definition, config, row };\n const content = (options.render ?? renderEmail)(input);\n const replyTo = replyToAddress(options.replyTo, input);\n await options.provider.send(\n {\n from: options.from,\n to,\n ...(replyTo ? { replyTo } : {}),\n subject: headerSafe(content.subject) || \"New response\",\n text: content.text,\n html: content.html,\n idempotencyKey: await idempotencyKey(deliveryOptions.deliveryId ?? submission.id, to),\n },\n { signal: deliveryOptions.signal },\n );\n return { ok: true };\n } catch (error) {\n return deliveryFailure(error);\n }\n },\n };\n}\n\nexport const RESEND_API = \"https://api.resend.com/emails\";\n\nexport interface ResendOptions extends HttpDeps {\n apiKey: string;\n /** Default `RESEND_API`. */\n endpoint?: string | undefined;\n}\n\n/**\n * Resend's REST API. Sends the idempotency key, so a retry within Resend's\n * 24-hour window never sends twice. A 409 for a concurrent request with the\n * same key is retried; one for a key reused with a different body is not.\n */\nexport function resendProvider(options: ResendOptions): EmailProvider {\n return {\n name: \"resend\",\n async send(message, { signal }) {\n if (!options.apiKey) throw new DeliveryError(\"The Resend API key is not set\");\n const response = await timedFetch(\n options,\n options.endpoint ?? RESEND_API,\n {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${options.apiKey}`,\n \"content-type\": \"application/json\",\n \"idempotency-key\": message.idempotencyKey,\n },\n body: JSON.stringify({\n from: message.from,\n to: message.to,\n subject: message.subject,\n text: message.text,\n html: message.html,\n ...(message.replyTo ? { reply_to: message.replyTo } : {}),\n }),\n },\n signal,\n );\n if (response.ok) {\n discard(response);\n return;\n }\n // Resend's error `name` (such as \"validation_error\") is safe to keep; its message may echo input.\n let name: string | undefined;\n try {\n const body = (await response.json()) as { name?: unknown };\n if (typeof body.name === \"string\" && /^[a-z_]{1,64}$/.test(body.name)) name = body.name;\n } catch {\n // Not JSON.\n }\n if (response.status === 409 && name === \"concurrent_idempotent_requests\") {\n throw new DeliveryError(\"Resend answered 409 (concurrent_idempotent_requests)\", {\n retryable: true,\n retryAfterSeconds: 5,\n status: 409,\n });\n }\n throw httpError(\"Resend\", response, name);\n },\n };\n}\n","/**\n * An access token for a Google service account by the OAuth 2.0 JWT bearer\n * flow: sign a JWT with the account's private key (RS256, WebCrypto) and\n * trade it at Google's token endpoint. No googleapis dependency, so it runs\n * on Node 20+, edge runtimes and Workers alike.\n */\nimport {\n base64url,\n DeliveryError,\n discard,\n fromBase64,\n httpError,\n sha256Hex,\n timedFetch,\n type HttpDeps,\n type WebCryptoKey,\n} from \"./types\";\n\nexport const GOOGLE_TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nexport const SHEETS_SCOPE = \"https://www.googleapis.com/auth/spreadsheets\";\n\nexport interface GoogleServiceAccount {\n /** The service account's `client_email`. */\n clientEmail: string;\n /** Its `private_key`: a PKCS#8 PEM. The `\\n`-escaped form env vars often hold is accepted. */\n privateKey: string;\n}\n\n/** The PKCS#8 key bytes from a PEM. */\nfunction pemToPkcs8(pem: string): Uint8Array<ArrayBuffer> {\n const text = pem.replace(/\\\\n/g, \"\\n\");\n if (/-----BEGIN RSA PRIVATE KEY-----/.test(text)) {\n throw new DeliveryError(\"The Google private key is PKCS#1; convert it to PKCS#8 (BEGIN PRIVATE KEY)\");\n }\n const body = text.replace(/-----(BEGIN|END) PRIVATE KEY-----/g, \"\").replace(/\\s+/g, \"\");\n return fromBase64(body);\n}\n\n/** A signed RS256 JWT. Throws a `DeliveryError` when the key is not a valid PKCS#8 RSA key. */\nexport async function signJwt(claims: Record<string, unknown>, privateKeyPem: string): Promise<string> {\n let key: WebCryptoKey;\n try {\n key = await crypto.subtle.importKey(\n \"pkcs8\",\n pemToPkcs8(privateKeyPem),\n { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n } catch (error) {\n if (error instanceof DeliveryError) throw error;\n // Never the key or the platform's message, which may quote it.\n throw new DeliveryError(\"The Google private key is not a valid PKCS#8 RSA key\");\n }\n const unsigned = `${base64url(JSON.stringify({ alg: \"RS256\", typ: \"JWT\" }))}.${base64url(JSON.stringify(claims))}`;\n const signature = await crypto.subtle.sign(\"RSASSA-PKCS1-v1_5\", key, new TextEncoder().encode(unsigned));\n return `${unsigned}.${base64url(new Uint8Array(signature))}`;\n}\n\n// One per process, shared by every destination: a token is good for an hour.\nconst cache = new Map<string, { token: string; expiresAt: number }>();\n\n/** Forgets cached tokens (tests, or after rotating a key). */\nexport function clearGoogleTokenCache(): void {\n cache.clear();\n}\n\nexport interface GoogleTokenOptions extends HttpDeps {\n scope?: string | undefined;\n now?: (() => number) | undefined;\n signal?: AbortSignal | undefined;\n}\n\n/** A cached or fresh access token. Throws a `DeliveryError` with a safe message on failure. */\nexport async function googleAccessToken(account: GoogleServiceAccount, options: GoogleTokenOptions = {}): Promise<string> {\n const { clientEmail, privateKey } = account;\n if (!clientEmail || !privateKey) throw new DeliveryError(\"The Google service account email or private key is not set\");\n const scope = options.scope ?? SHEETS_SCOPE;\n const now = options.now?.() ?? Date.now();\n // The key's digest is part of the cache key: a hit returns a token without\n // signing anything, so email + scope alone would hand one tenant's live\n // token to any config naming that email with any key, and keep a rotated\n // or wrong key working until the token expires.\n const cacheKey = `${clientEmail} ${scope} ${await sha256Hex(privateKey.replace(/\\\\n/g, \"\\n\").trim())}`;\n const hit = cache.get(cacheKey);\n if (hit && hit.expiresAt - 60_000 > now) return hit.token;\n\n const iat = Math.floor(now / 1000);\n const assertion = await signJwt({ iss: clientEmail, scope, aud: GOOGLE_TOKEN_URL, iat, exp: iat + 3600 }, privateKey);\n const response = await timedFetch(\n options,\n GOOGLE_TOKEN_URL,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ grant_type: \"urn:ietf:params:oauth:grant-type:jwt-bearer\", assertion }).toString(),\n },\n options.signal,\n );\n if (!response.ok) {\n discard(response);\n throw httpError(\"Google token endpoint\", response);\n }\n const body = (await response.json()) as { access_token?: unknown; expires_in?: unknown };\n if (typeof body.access_token !== \"string\") throw new DeliveryError(\"Google token endpoint returned no access token\", { retryable: true });\n const ttl = typeof body.expires_in === \"number\" ? body.expires_in * 1000 : 3_600_000;\n cache.set(cacheKey, { token: body.access_token, expiresAt: now + ttl });\n return body.access_token;\n}\n","/**\n * The Google Sheets destination: appends one row per submission to a sheet\n * shared with a Google service account. Config: `{ spreadsheetId,\n * sheetName? }` (`spreadsheet_id` and `sheet_name` are accepted too).\n *\n * The tab is created when missing, the header row is written from the row's\n * column keys and gains a column for any new key without moving the others,\n * and an `id` column holds the response id, so a redelivery is not appended\n * twice. Every write is `valueInputOption=RAW`, so Sheets stores text as\n * typed and never runs it as a formula: `@team thanks` stays exactly that.\n * Text is therefore not escaped by default (a `'` would be stored literally).\n * Set `escapeFormulas` only when the sheet's text is exported and opened in\n * another spreadsheet that might run it (see `escapeFormula`).\n *\n * Quota: Google allows a service account about 60 reads and 60 writes a\n * minute. So the tab id, header and last row are kept in the destination's\n * state, and a normal delivery is one write: the append. The tab and header\n * are read again only when a row has a key the cached header lacks, or when\n * an append is refused. The id column is read only on a redelivery, and then\n * only its recent rows. `deliverBatch` appends many rows in one request.\n */\nimport type { Json } from \"../types\";\nimport { googleAccessToken, type GoogleServiceAccount } from \"./google-auth\";\nimport { escapeFormula, responseRow, type RowOptions } from \"./row\";\nimport {\n configString,\n deliveryFailure,\n DeliveryError,\n discard,\n httpError,\n resolveOption,\n timedFetch,\n type Cell,\n type DeliveryItem,\n type DeliveryOptions,\n type DeliveryResult,\n type Destination,\n type DestinationConfig,\n type HttpDeps,\n} from \"./types\";\n\nexport const SHEETS_API = \"https://sheets.googleapis.com/v4/spreadsheets\";\nexport const DEFAULT_SHEET_NAME = \"Responses\";\n/** How many of the latest rows a redelivery checks for its id. */\nexport const DEDUPE_WINDOW = 500;\n/**\n * How many rows the header read looks at to find the columns in use: the\n * header row and the first responses under it. Bounded, so a tab with years\n * of responses is never read whole just to learn its header.\n */\nexport const HEADER_SCAN_ROWS = 100;\n/** Header writes tried before a concurrent writer is reported as a retryable failure. */\nconst HEADER_WRITE_ATTEMPTS = 3;\n\n/** What the sheet destination reads from a destination's config. */\nexport interface SheetConfig {\n spreadsheetId: string;\n /** Default `\"Responses\"`. */\n sheetName?: string;\n}\n\nexport interface SheetsDestinationOptions extends HttpDeps {\n /** The service account, or a function that finds the one for a destination's config. */\n account: GoogleServiceAccount | ((config: DestinationConfig) => GoogleServiceAccount | Promise<GoogleServiceAccount>);\n /**\n * Prefix text a spreadsheet could run as a formula with `'` (see\n * `escapeFormula`), headers included. Default false: writes are RAW, so\n * Sheets never runs text as a formula, and the `'` would be stored as part\n * of the text. Turn it on only if the sheet is exported as CSV and opened\n * in another spreadsheet. Keep one setting per sheet: header keys are\n * escaped too, so switching it later adds new columns for escaped keys.\n */\n escapeFormulas?: boolean | undefined;\n /** Sensitive fields: `\"include\"` (default), `\"mask\"` or `\"omit\"`. */\n sensitive?: RowOptions[\"sensitive\"];\n now?: (() => number) | undefined;\n}\n\n/**\n * The existing header plus any keys it does not have yet, in the order they\n * arrive. A blank header cell keeps its place (dropping it would shift every\n * later column away from the values stored under it), as do blank header\n * cells over the `width` columns that hold responses; only blanks beyond\n * those are trimmed.\n */\nexport function mergeHeader(existing: readonly unknown[], keys: readonly string[], width = 0): string[] {\n const header = existing.map((h) => (h == null ? \"\" : String(h)));\n while (header.length < width) header.push(\"\");\n while (header.length > width && header[header.length - 1] === \"\") header.pop();\n for (const key of keys) if (key && !header.includes(key)) header.push(key);\n return header;\n}\n\n/** One cell per header column, blank where the row has no value; `escape` applies `escapeFormula` (default false). */\nexport function rowFor(header: readonly string[], row: Record<string, Cell>, escape = false): Cell[] {\n return header.map((h) => {\n const cell = Object.prototype.hasOwnProperty.call(row, h) ? (row[h] ?? \"\") : \"\";\n return escape ? escapeFormula(cell) : cell;\n });\n}\n\n/** A1 column letters: 0 → A, 25 → Z, 26 → AA. */\nexport function columnLetter(index: number): string {\n let n = index + 1;\n let s = \"\";\n while (n > 0) {\n const r = (n - 1) % 26;\n s = String.fromCharCode(65 + r) + s;\n n = Math.floor((n - 1) / 26);\n }\n return s;\n}\n\nconst quoteSheet = (name: string) => `'${name.replace(/'/g, \"''\")}'`;\n\n/** What the destination keeps between deliveries. Opaque to the app: store and pass it back. */\nexport interface SheetState {\n spreadsheet_id: string;\n sheet_name: string;\n sheet_id: number;\n header: string[];\n columns: number;\n /** The last row an append wrote (1-based), 0 when unknown. */\n last_row: number;\n}\n\nfunction readState(raw: Record<string, Json> | undefined, spreadsheetId: string, sheetName: string): SheetState | null {\n if (!raw) return null;\n const header = raw[\"header\"];\n if (\n raw[\"spreadsheet_id\"] !== spreadsheetId ||\n raw[\"sheet_name\"] !== sheetName ||\n typeof raw[\"sheet_id\"] !== \"number\" ||\n !Array.isArray(header) ||\n !header.every((h) => typeof h === \"string\") ||\n !header.includes(\"id\")\n ) {\n return null;\n }\n return {\n spreadsheet_id: spreadsheetId,\n sheet_name: sheetName,\n sheet_id: raw[\"sheet_id\"],\n header: header as string[],\n columns: typeof raw[\"columns\"] === \"number\" ? raw[\"columns\"] : header.length,\n last_row: typeof raw[\"last_row\"] === \"number\" ? raw[\"last_row\"] : 0,\n };\n}\n\n/** An append Google refused for a reason a fresh look at the tab may fix (renamed, deleted or resized). */\nclass StaleSheetError extends DeliveryError {}\n\ninterface SheetProps {\n sheetId: number;\n title: string;\n gridProperties?: { columnCount?: number };\n}\n\nfunction configOf(config: DestinationConfig) {\n const spreadsheetId = configString(config, \"spreadsheetId\", \"spreadsheet_id\");\n if (!spreadsheetId) throw new DeliveryError(\"The sheet destination has no spreadsheetId\");\n if (!/^[A-Za-z0-9_-]{10,200}$/.test(spreadsheetId)) throw new DeliveryError(\"The sheet destination's spreadsheetId is invalid\");\n const sheetName = configString(config, \"sheetName\", \"sheet_name\") || DEFAULT_SHEET_NAME;\n if (sheetName.length > 100) throw new DeliveryError(\"The sheet destination's sheetName is too long\");\n return { spreadsheetId, sheetName };\n}\n\nexport function sheetsDestination(options: SheetsDestinationOptions): Destination {\n async function run(\n items: readonly DeliveryItem[],\n config: DestinationConfig,\n deliveryOptions: Omit<DeliveryOptions, \"deliveryId\">,\n ): Promise<DeliveryResult> {\n if (!items.length) return { ok: true };\n const { spreadsheetId, sheetName } = configOf(config);\n const account = await resolveOption(\"The sheet destination's account\", options.account, config);\n const signal = deliveryOptions.signal;\n const token = await googleAccessToken(account, { ...options, signal });\n const base = `${SHEETS_API}/${encodeURIComponent(spreadsheetId)}`;\n const escape = options.escapeFormulas === true;\n\n const call = async <T>(what: string, url: string, init: RequestInit = {}): Promise<T> => {\n const response = await timedFetch(\n options,\n url,\n { ...init, headers: { authorization: `Bearer ${token}`, \"content-type\": \"application/json\" } },\n signal,\n );\n if (!response.ok) {\n discard(response);\n if (what === \"append\" && (response.status === 400 || response.status === 404)) {\n throw new StaleSheetError(`Google Sheets append answered ${response.status}`, { status: response.status });\n }\n if (response.status === 403 || response.status === 404) {\n throw new DeliveryError(\n `Google Sheets ${what} answered ${response.status}: is the sheet shared with ${account.clientEmail}?`,\n { status: response.status },\n );\n }\n throw httpError(`Google Sheets ${what}`, response);\n }\n return (await response.json()) as T;\n };\n const batchUpdate = (what: string, requests: unknown[]) =>\n call<{ replies?: { addSheet?: { properties?: SheetProps } }[] }>(what, `${base}:batchUpdate`, {\n method: \"POST\",\n body: JSON.stringify({ requests }),\n });\n const range = (a1: string) => `${base}/values/${encodeURIComponent(`${quoteSheet(sheetName)}!${a1}`)}`;\n\n const sensitive = options.sensitive ?? \"include\";\n // Column keys are escaped like cells (a builder-made key could start with \"=\"),\n // so the header as stored and read back matches the keys looked up in it.\n const columnKey = (key: string) => (escape ? String(escapeFormula(key)) : key);\n const rows = items.map((item) => {\n const { row, columns } = responseRow(item.submission, item.definition, { sensitive });\n const escaped: Record<string, Cell> = {};\n for (const key of columns) escaped[columnKey(key)] = row[key]!;\n return { row: escaped, columns: columns.map(columnKey) };\n });\n const keys = [...new Set(rows.flatMap((r) => r.columns))];\n\n /** Reads the tab and header, adds what is missing, and returns the fresh state. */\n async function setUp(previous: SheetState | null): Promise<SheetState> {\n const readTabs = async () => {\n const meta = await call<{ sheets?: { properties?: SheetProps }[] }>(\n \"read\",\n `${base}?fields=${encodeURIComponent(\"sheets.properties(sheetId,title,gridProperties.columnCount)\")}`,\n );\n return meta.sheets?.map((s) => s.properties).find((p) => p?.title === sheetName);\n };\n let sheet = await readTabs();\n if (!sheet) {\n try {\n const added = await batchUpdate(\"add tab\", [{ addSheet: { properties: { title: sheetName } } }]);\n sheet = added.replies?.[0]?.addSheet?.properties ?? { sheetId: 0, title: sheetName };\n } catch (error) {\n // Two first deliveries race: both saw no tab, and the loser's\n // addSheet answers 400 (\"already exists\"). Use the winner's tab.\n if (!(error instanceof DeliveryError) || error.status !== 400) throw error;\n sheet = await readTabs();\n if (!sheet) throw error;\n }\n }\n // Read by column: the values API drops trailing blank cells, so the header\n // row alone can look narrower than the responses under it (a column added\n // by hand). Column by column, the number returned is the width in use.\n const readHeader = async () => {\n const read = await call<{ values?: unknown[][] }>(\n \"read header\",\n `${range(`A1:ZZZ${HEADER_SCAN_ROWS}`)}?majorDimension=COLUMNS`,\n );\n const used = read.values ?? [];\n return { used: used.length, existing: used.map((column) => column[0] ?? \"\") };\n };\n let columns = sheet.gridProperties?.columnCount ?? 26;\n let { used, existing } = await readHeader();\n let header: string[] = [];\n // The header row is written whole, so two deliveries merging different\n // keys at once can overwrite each other. After a write, read it back: if\n // a key of ours is missing, merge onto what is there and write again.\n // The state keeps the header as read, so rows map onto the real columns.\n for (let attempt = 0; ; attempt++) {\n header = mergeHeader(existing, keys, used);\n // A new tab starts with the id column; one already in use gets it at the\n // end, so the columns already holding responses don't move.\n if (!header.includes(\"id\")) {\n if (used) header.push(\"id\");\n else header.unshift(\"id\");\n }\n const changed = header.length !== existing.length || header.some((h, i) => h !== String(existing[i] ?? \"\"));\n if (!changed) break;\n if (attempt >= HEADER_WRITE_ATTEMPTS) {\n throw new DeliveryError(\"Google Sheets header kept changing while it was written\", { retryable: true });\n }\n if (header.length > columns) {\n await batchUpdate(\"add columns\", [\n { appendDimension: { sheetId: sheet.sheetId, dimension: \"COLUMNS\", length: header.length - columns } },\n ]);\n columns = header.length;\n }\n await call(\"write header\", `${range(\"A1\")}?valueInputOption=RAW`, {\n method: \"PUT\",\n body: JSON.stringify({ values: [header] }),\n });\n if (existing.length === 0) {\n await batchUpdate(\"freeze header\", [\n {\n updateSheetProperties: {\n properties: { sheetId: sheet.sheetId, gridProperties: { frozenRowCount: 1 } },\n fields: \"gridProperties.frozenRowCount\",\n },\n },\n ]);\n }\n ({ used, existing } = await readHeader());\n }\n return {\n spreadsheet_id: spreadsheetId,\n sheet_name: sheetName,\n sheet_id: sheet.sheetId,\n header,\n columns,\n last_row: previous?.last_row ?? 0,\n };\n }\n\n let skipped: string[] = [];\n async function append(state: SheetState): Promise<SheetState> {\n // A redelivery may find its row already there: an earlier append went\n // through even though Google answered 5xx or the request timed out.\n let pending = items.map((item, i) => ({ id: item.submission.id, row: rows[i]!.row }));\n if (deliveryOptions.redelivery) {\n const column = columnLetter(state.header.indexOf(\"id\"));\n const from = state.last_row > 0 ? Math.max(2, state.last_row - DEDUPE_WINDOW) : 2;\n const ids = await call<{ values?: unknown[][] }>(\"read ids\", range(`${column}${from}:${column}`));\n const present = new Set((ids.values ?? []).map((r) => String(r?.[0] ?? \"\")));\n skipped = pending.filter((p) => present.has(p.id)).map((p) => p.id);\n pending = pending.filter((p) => !present.has(p.id));\n }\n if (!pending.length) return state;\n const result = await call<{ updates?: { updatedRange?: string } }>(\n \"append\",\n `${range(\"A1\")}:append?valueInputOption=RAW&insertDataOption=INSERT_ROWS`,\n { method: \"POST\", body: JSON.stringify({ values: pending.map((p) => rowFor(state.header, p.row, escape)) }) },\n );\n const last = /![A-Z]+\\d+:[A-Z]+(\\d+)$/.exec(result.updates?.updatedRange ?? \"\")?.[1];\n return { ...state, last_row: last ? Number(last) : state.last_row + pending.length };\n }\n\n const cached = readState(deliveryOptions.state, spreadsheetId, sheetName);\n const fresh = !cached || keys.some((k) => !cached.header.includes(k));\n let state = fresh ? await setUp(cached) : cached;\n try {\n state = await append(state);\n } catch (error) {\n if (!(error instanceof StaleSheetError) || fresh) throw error;\n state = await append(await setUp(cached));\n }\n return {\n ok: true,\n state: state as unknown as Record<string, Json>,\n ...(skipped.length ? { skipped } : {}),\n };\n }\n\n const guarded = async (...args: Parameters<typeof run>): Promise<DeliveryResult> => {\n try {\n return await run(...args);\n } catch (error) {\n return deliveryFailure(error);\n }\n };\n\n return {\n kind: \"sheet\",\n deliver: (submission, definition, config, deliveryOptions = {}) =>\n guarded([{ submission, definition, deliveryId: deliveryOptions.deliveryId }], config, deliveryOptions),\n deliverBatch: (items, config, deliveryOptions = {}) => guarded(items, config, deliveryOptions),\n };\n}\n","/**\n * The webhook destination: a signed JSON POST to a URL, following the\n * Standard Webhooks spec (standardwebhooks.com), so receivers can verify it\n * with any Standard Webhooks library, or with `verifyWebhook` here.\n *\n * Headers: `webhook-id` (the delivery id, stable across retries: receivers\n * dedupe on it), `webhook-timestamp` (Unix seconds) and `webhook-signature`\n * (`v1,<base64 HMAC-SHA256 of \"<id>.<timestamp>.<body>\">`). Receivers reject\n * a timestamp more than five minutes off, which stops replays.\n *\n * The URL comes from config, which an admin may type, so by default it must\n * be https, carry no credentials, and not name localhost or a private,\n * loopback or link-local address literally. Redirects are not followed. A\n * hostname that resolves to a private address is not caught here: if\n * untrusted users choose URLs, send from a network that cannot reach\n * internal services.\n */\nimport { own, withheld } from \"../logic\";\nimport { isSensitive } from \"../fields\";\nimport type { FieldBlock, FormDefinition, Json } from \"../types\";\nimport { responseRow, visibleInputs, type RowOptions } from \"./row\";\nimport {\n base64,\n configString,\n deliveryFailure,\n DeliveryError,\n discard,\n fromBase64,\n httpError,\n resolveOption,\n timedFetch,\n type DeliveryOptions,\n type DeliveryResult,\n type DeliverySubmission,\n type Destination,\n type DestinationConfig,\n type HttpDeps,\n type WebCryptoKey,\n} from \"./types\";\n\n/** What the webhook destination reads from a destination's config. */\nexport interface WebhookConfig {\n url: string;\n}\n\nexport interface WebhookDestinationOptions extends HttpDeps {\n /**\n * The signing secret: base64 of at least 16 random bytes, usually with\n * the `whsec_` prefix Standard Webhooks tools issue (`whsec_` plus base64\n * of 24 to 64 bytes is what the spec recommends). The prefix is optional;\n * the rest is always base64-decoded, as every Standard Webhooks library\n * does, so a receiver verifies with the same string. A secret that is not\n * base64 fails permanently. Or a function that finds the one for a\n * destination's config. Never put it in config.\n */\n secret: string | ((config: DestinationConfig) => string | Promise<string>);\n /** Allow `http:` URLs. Default false. */\n allowInsecureUrls?: boolean | undefined;\n /** Allow localhost and private, loopback and link-local address literals. Default false. */\n allowPrivateHosts?: boolean | undefined;\n /** Sensitive fields: `\"include\"` (default), `\"mask\"` or `\"omit\"`. */\n sensitive?: RowOptions[\"sensitive\"];\n /** The event type in the payload. Default `\"form.submitted\"`. */\n type?: string | undefined;\n now?: (() => number) | undefined;\n}\n\n/** The JSON body a webhook receives. */\nexport interface WebhookPayload {\n type: string;\n /** ISO time the delivery was sent. */\n timestamp: string;\n data: {\n form: { id: string; title: string };\n submission: {\n id: string;\n /** Answers keyed by field id. */\n answers: Record<string, Json>;\n hidden: Record<string, Json>;\n context: Record<string, Json>;\n ending: string | null;\n submittedAt: string | null;\n meta: Record<string, Json>;\n tags: string[];\n };\n /** The same submission as a flat row by column key: labels for choices, as the sheet shows it. */\n row: Record<string, Json>;\n };\n}\n\nconst MIN_SECRET_BYTES = 16;\nconst STRICT_BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n/**\n * The HMAC key bytes for a secret, decoded as the Standard Webhooks\n * reference libraries do: an optional `whsec_` prefix is dropped and the\n * rest is base64-decoded. Only padded standard base64 is accepted, the form\n * every reference library decodes the same way. Throws a `DeliveryError` for\n * a secret that is not base64 or is shorter than 16 bytes once decoded.\n */\nfunction secretKey(secret: string): Uint8Array<ArrayBuffer> {\n const encoded = secret.startsWith(\"whsec_\") ? secret.slice(6) : secret;\n if (!encoded || !STRICT_BASE64.test(encoded)) {\n throw new DeliveryError(\n \"The webhook secret must be base64, optionally prefixed with whsec_ (Standard Webhooks libraries base64-decode it)\",\n );\n }\n const bytes = fromBase64(encoded);\n if (bytes.length < MIN_SECRET_BYTES) throw new DeliveryError(`The webhook secret is shorter than ${MIN_SECRET_BYTES} bytes`);\n return bytes;\n}\n\nasync function hmacKey(secret: string, usage: \"sign\" | \"verify\"): Promise<WebCryptoKey> {\n return crypto.subtle.importKey(\"raw\", secretKey(secret), { name: \"HMAC\", hash: \"SHA-256\" }, false, [usage]);\n}\n\n/** The `webhook-signature` value for a message: `v1,<base64>`. */\nexport async function signWebhook(secret: string, id: string, timestamp: number, body: string): Promise<string> {\n const key = await hmacKey(secret, \"sign\");\n const mac = await crypto.subtle.sign(\"HMAC\", key, new TextEncoder().encode(`${id}.${timestamp}.${body}`));\n return `v1,${base64(new Uint8Array(mac))}`;\n}\n\nexport interface VerifyWebhookInput {\n /** The same secret the sender signs with (base64, optionally `whsec_`-prefixed). */\n secret: string;\n /** The request's headers: a `Headers` or a plain object. */\n headers: Headers | Record<string, string | string[] | undefined>;\n /** The raw body, exactly as received. */\n body: string;\n /** Default 300: a timestamp further off than this is refused. */\n toleranceSeconds?: number | undefined;\n now?: (() => number) | undefined;\n}\n\n/**\n * Checks a Standard Webhooks request: the timestamp is recent and one of the\n * space-separated `v1` signatures matches. Compares in constant time (by\n * WebCrypto `verify`). Never throws on a malformed request: returns false.\n */\nexport async function verifyWebhook(input: VerifyWebhookInput): Promise<boolean> {\n const header = (name: string): string => {\n if (typeof (input.headers as Headers).get === \"function\") return (input.headers as Headers).get(name) ?? \"\";\n const raw = (input.headers as Record<string, string | string[] | undefined>)[name];\n return Array.isArray(raw) ? (raw[0] ?? \"\") : (raw ?? \"\");\n };\n const id = header(\"webhook-id\");\n const timestamp = header(\"webhook-timestamp\");\n const signatures = header(\"webhook-signature\");\n if (!id || !/^\\d{1,12}$/.test(timestamp) || !signatures) return false;\n const now = Math.floor((input.now?.() ?? Date.now()) / 1000);\n if (Math.abs(now - Number(timestamp)) > (input.toleranceSeconds ?? 300)) return false;\n let key: WebCryptoKey;\n try {\n key = await hmacKey(input.secret, \"verify\");\n } catch {\n return false;\n }\n const data = new TextEncoder().encode(`${id}.${timestamp}.${input.body}`);\n for (const part of signatures.split(\" \")) {\n const [version, value] = part.split(\",\", 2);\n if (version !== \"v1\" || !value) continue;\n let mac: Uint8Array<ArrayBuffer>;\n try {\n mac = fromBase64(value);\n } catch {\n continue;\n }\n if (await crypto.subtle.verify(\"HMAC\", key, mac, data)) return true;\n }\n return false;\n}\n\nconst PRIVATE_HOSTNAME = /(^|\\.)(localhost|local|internal|localdomain|home\\.arpa)$/i;\n\n/** Whether a URL hostname is localhost or a private, loopback, link-local or unspecified address literal. */\nexport function isPrivateHost(hostname: string): boolean {\n const host = hostname.toLowerCase().replace(/\\.$/, \"\");\n if (PRIVATE_HOSTNAME.test(host)) return true;\n const v4 = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(host);\n if (v4) return isPrivateV4(v4.slice(1).map(Number) as [number, number, number, number]);\n if (host.startsWith(\"[\") && host.endsWith(\"]\")) {\n const v6 = host.slice(1, -1);\n if (v6 === \"::\" || v6 === \"::1\") return true;\n // IPv4-mapped (::ffff:a.b.c.d, which URL writes as ::ffff:xxxx:xxxx).\n const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(v6);\n if (mapped) {\n const hi = parseInt(mapped[1]!, 16);\n const lo = parseInt(mapped[2]!, 16);\n return isPrivateV4([hi >> 8, hi & 255, lo >> 8, lo & 255]);\n }\n const first = parseInt(v6.split(\":\")[0] || \"0\", 16);\n return (first & 0xfe00) === 0xfc00 || (first & 0xffc0) === 0xfe80; // fc00::/7, fe80::/10\n }\n return false;\n}\n\nfunction isPrivateV4([a, b]: [number, number, number, number]): boolean {\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\n/** The URL from config, checked. Throws a `DeliveryError` naming the rule it broke (never the URL, which may hold a token). */\nexport function checkWebhookUrl(\n raw: string,\n options: Pick<WebhookDestinationOptions, \"allowInsecureUrls\" | \"allowPrivateHosts\"> = {},\n): URL {\n if (!raw) throw new DeliveryError(\"The webhook destination has no url\");\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new DeliveryError(\"The webhook url is not a valid URL\");\n }\n if (url.protocol !== \"https:\" && !(options.allowInsecureUrls && url.protocol === \"http:\")) {\n throw new DeliveryError(\"The webhook url must use https\");\n }\n if (url.username || url.password) throw new DeliveryError(\"The webhook url must not contain credentials\");\n if (!options.allowPrivateHosts && isPrivateHost(url.hostname)) {\n throw new DeliveryError(\"The webhook url points at a private or local address\");\n }\n return url;\n}\n\n/** The payload for one submission. Identifying answers stay out on anonymous forms. */\nexport function webhookPayload(\n submission: DeliverySubmission,\n definition: FormDefinition,\n options: { sensitive?: RowOptions[\"sensitive\"]; type?: string | undefined; now?: number | undefined } = {},\n): WebhookPayload {\n const sensitive = options.sensitive ?? \"include\";\n const { row } = responseRow(submission, definition, { sensitive });\n const answers: Record<string, Json> = {};\n for (const block of definition.blocks) {\n if (block.kind !== \"field\") continue;\n const field = block as FieldBlock;\n const value = own(submission.answers, field.id);\n if (value === undefined || withheld(definition, field)) continue;\n if (isSensitive(field) && sensitive !== \"include\") {\n if (sensitive === \"mask\") answers[field.id] = \"[sensitive]\";\n continue;\n }\n answers[field.id] = value;\n }\n const inputs = visibleInputs(submission, definition, sensitive);\n const pick = (source: Record<string, Json> | undefined, allowed: Record<string, Json>) => {\n const out: Record<string, Json> = {};\n for (const [name, value] of Object.entries(source ?? {})) if (own(allowed, name) !== undefined) out[name] = value;\n return out;\n };\n return {\n type: options.type ?? \"form.submitted\",\n timestamp: new Date(options.now ?? Date.now()).toISOString(),\n data: {\n form: { id: definition.id, title: definition.title },\n submission: {\n id: submission.id,\n answers,\n hidden: pick(submission.hidden, inputs),\n context: pick(submission.context, inputs),\n ending: submission.ending ?? null,\n submittedAt: submission.submittedAt ?? null,\n meta: { ...submission.meta },\n tags: [...(submission.tags ?? [])],\n },\n row,\n },\n };\n}\n\nexport function webhookDestination(options: WebhookDestinationOptions): Destination {\n return {\n kind: \"webhook\",\n async deliver(submission, definition, config, deliveryOptions: DeliveryOptions = {}): Promise<DeliveryResult> {\n try {\n const url = checkWebhookUrl(configString(config, \"url\"), options);\n const secret = await resolveOption(\"The webhook secret\", options.secret, config);\n if (!secret) throw new DeliveryError(\"The webhook secret is not set\");\n const now = options.now?.() ?? Date.now();\n const id = deliveryOptions.deliveryId ?? submission.id;\n const timestamp = Math.floor(now / 1000);\n const body = JSON.stringify(\n webhookPayload(submission, definition, { sensitive: options.sensitive, type: options.type, now }),\n );\n const response = await timedFetch(\n options,\n url.toString(),\n {\n method: \"POST\",\n redirect: \"manual\",\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": \"genesis-forms-webhook/1\",\n \"webhook-id\": id,\n \"webhook-timestamp\": String(timestamp),\n \"webhook-signature\": await signWebhook(secret, id, timestamp, body),\n },\n body,\n },\n deliveryOptions.signal,\n );\n discard(response);\n if (response.status >= 200 && response.status < 300) return { ok: true };\n // `redirect: \"manual\"` gives a 3xx (or, in browsers, an opaque status 0).\n if (response.status === 0 || (response.status >= 300 && response.status < 400)) {\n throw new DeliveryError(`Webhook answered ${response.status || \"a redirect\"}: redirects are not followed`, {\n ...(response.status ? { status: response.status } : {}),\n });\n }\n throw httpError(\"Webhook\", response);\n } catch (error) {\n return deliveryFailure(error);\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/destinations/types.ts","../src/calculated.ts","../src/structured.ts","../src/fields.ts","../src/logic.ts","../src/recall.ts","../src/destinations/row.ts","../src/destinations/email.ts","../src/destinations/google-auth.ts","../src/destinations/sheets.ts","../src/destinations/webhook.ts"],"names":["numberOps","out","used","state"],"mappings":"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","file":"destinations.cjs","sourcesContent":["/**\n * The contract every destination keeps. A destination sends one checked\n * submission somewhere (an inbox, a spreadsheet, a URL) and says whether a\n * failure is worth retrying. It never throws, never logs, and never puts a\n * secret, an answer or contact details in an error message.\n *\n * Storage is the app's: it keeps the outbox, claims due deliveries, counts\n * attempts and schedules retries. A destination only reports what happened.\n */\nimport type { FormDefinition, Json } from \"../types\";\n\n/** One cell of a flat response row. */\nexport type Cell = string | number | boolean;\n\n/**\n * What a destination delivers: a submission `validateSubmission` checked,\n * plus the id the app stored it under. `{ id, ...result.submission }` fits.\n */\nexport interface DeliverySubmission {\n /** The stored response's id. Every destination records it, so a resend is recognised. */\n id: string;\n /** Answers keyed by field id. */\n answers: Record<string, Json>;\n /** Untrusted URL and host inputs. */\n hidden?: Record<string, Json> | undefined;\n /** Trusted server inputs (account id, location…). */\n context?: Record<string, Json> | undefined;\n ending?: string | null | undefined;\n /** When it was submitted, as the app wants it shown: an ISO time, or a day such as `2026-10-22`. */\n submittedAt?: string | undefined;\n /**\n * Extra leading columns the app adds, in order, after `id` and `submitted_at`:\n * the form's slug and version, an account id, a location. Rows and emails show them;\n * the webhook sends them.\n */\n meta?: Record<string, Cell> | undefined;\n /** Labels the app attached, such as `low_rating`. The webhook sends them; a custom email can read them. */\n tags?: readonly string[] | undefined;\n}\n\nexport interface DeliveryOptions {\n /**\n * This delivery's id, stable across its retries. The email destination's\n * idempotency key and the webhook's `webhook-id`. Defaults to the submission id.\n */\n deliveryId?: string | undefined;\n /** What this destination cached last time (`DeliveryResult.state`). */\n state?: Record<string, Json> | undefined;\n /**\n * An earlier attempt of this delivery may have gone through (it timed out,\n * or its lease ran out). Destinations that can look first do: the sheet\n * skips rows whose id is already there.\n */\n redelivery?: boolean | undefined;\n /** Aborts the delivery. Each request also has its own timeout. */\n signal?: AbortSignal | undefined;\n}\n\n/** One submission in a batch: each carries its own definition and delivery id. */\nexport interface DeliveryItem {\n submission: DeliverySubmission;\n definition: FormDefinition;\n deliveryId?: string | undefined;\n}\n\nexport type DeliveryResult =\n | {\n ok: true;\n /** New state to keep for this destination, when it changed. */\n state?: Record<string, Json>;\n /** Submission ids already there (a redelivery), so nothing was sent for them. */\n skipped?: string[];\n }\n | DeliveryFailure;\n\nexport interface DeliveryFailure {\n ok: false;\n /**\n * `true`: the same request may succeed later (rate limited, the service\n * down, a timeout). `false`: it will not until someone changes the config\n * or credentials (a bad key, an unshared sheet, a 404 URL).\n */\n retryable: boolean;\n /**\n * Set when the service said when to come back (429, 503) or is plainly\n * down: retry after this many seconds. An app may choose not to count the\n * attempt, since it says nothing about the delivery itself.\n */\n retryAfterSeconds?: number;\n /** The HTTP status that refused it, if one did. */\n status?: number;\n /** Safe to store and log: a status and a short reason, never secrets, answers or contact details. */\n error: string;\n}\n\n/** Config is plain JSON the app stores per destination. Secrets never go in it. */\nexport type DestinationConfig = Readonly<Record<string, unknown>>;\n\nexport interface Destination {\n /** `\"email\"`, `\"sheet\"`, `\"webhook\"`, or an app's own. */\n readonly kind: string;\n /** Deliver one submission. Never throws. */\n deliver(\n submission: DeliverySubmission,\n definition: FormDefinition,\n config: DestinationConfig,\n options?: DeliveryOptions,\n ): Promise<DeliveryResult>;\n /**\n * Deliver several submissions to the same destination in one request where\n * the service allows it. All succeed or all fail together. Never throws.\n */\n deliverBatch?(\n items: readonly DeliveryItem[],\n config: DestinationConfig,\n options?: Omit<DeliveryOptions, \"deliveryId\">,\n ): Promise<DeliveryResult>;\n}\n\n/**\n * A failure with a message that is safe to store. Destinations throw it\n * internally and `deliveryFailure` turns it into a result; app-written\n * destinations may do the same.\n */\nexport class DeliveryError extends Error {\n override name = \"DeliveryError\";\n readonly retryable: boolean;\n readonly retryAfterSeconds: number | undefined;\n readonly status: number | undefined;\n constructor(\n message: string,\n options: { retryable?: boolean | undefined; retryAfterSeconds?: number | undefined; status?: number | undefined } = {},\n ) {\n super(message);\n this.retryable = options.retryable ?? false;\n this.retryAfterSeconds = options.retryAfterSeconds;\n this.status = options.status;\n }\n}\n\n/** Every outbound request gives up after this long, unless the destination is given another `timeoutMs`. */\nexport const REQUEST_TIMEOUT_MS = 10_000;\n\nconst IMF_FIXDATE = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \\d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d{4} \\d{2}:\\d{2}:\\d{2} GMT$/;\n\n/**\n * Seconds to wait from a Retry-After header, else the fallback. Only the\n * two forms RFC 9110 defines are read: delta-seconds (digits only) and an\n * IMF-fixdate (`Wed, 21 Oct 2026 07:28:00 GMT`); anything else (`-5`,\n * `1.5`, a loose date) gets the fallback. At least 1 second, at most a day.\n */\nexport function retryAfterSeconds(header: string | null | undefined, fallback = 60, now = Date.now()): number {\n const clamp = (s: number) => Math.min(86_400, Math.max(1, s));\n if (header) {\n const trimmed = header.trim();\n if (/^\\d+$/.test(trimmed)) return clamp(Number(trimmed));\n if (IMF_FIXDATE.test(trimmed)) {\n const at = Date.parse(trimmed);\n if (Number.isFinite(at)) return clamp(Math.ceil((at - now) / 1000));\n }\n }\n return fallback;\n}\n\n/** Whether an HTTP status is worth retrying unchanged: 408, 425, 429 and 5xx. */\nexport function isRetryableStatus(status: number): boolean {\n return status === 408 || status === 425 || status === 429 || status >= 500;\n}\n\n/**\n * The error for a refused request. Retryable statuses (see\n * `isRetryableStatus`) wait for the Retry-After header, else 60 seconds;\n * every other status is permanent.\n */\nexport function httpError(what: string, response: Response, detail?: string): DeliveryError {\n const status = response.status;\n const message = `${what} answered ${status}${detail ? ` (${detail})` : \"\"}`;\n if (isRetryableStatus(status)) {\n return new DeliveryError(message, {\n retryable: true,\n retryAfterSeconds: retryAfterSeconds(response.headers.get(\"retry-after\")),\n status,\n });\n }\n return new DeliveryError(message, { retryable: false, status });\n}\n\n/**\n * Any error as a failed result with a safe message. A `DeliveryError` keeps\n * its message; anything else is reduced to its kind (\"Timed out\", \"Network\n * error\"), because a raw message may hold a URL with a token in it.\n * Timeouts and aborts are retryable. A `TypeError` is permanent: it is\n * almost always a bug that a retry would only repeat. `timedFetch` turns\n * fetch's own network `TypeError` into a retryable `DeliveryError` first, so\n * an app destination that calls `fetch` directly should do the same.\n */\nexport function deliveryFailure(error: unknown): DeliveryFailure {\n if (error instanceof DeliveryError) {\n return {\n ok: false,\n retryable: error.retryable,\n error: error.message.slice(0, 500),\n ...(error.retryAfterSeconds !== undefined ? { retryAfterSeconds: error.retryAfterSeconds } : {}),\n ...(error.status !== undefined ? { status: error.status } : {}),\n };\n }\n const name = error instanceof Error ? error.name : \"\";\n if (name === \"TimeoutError\") return { ok: false, retryable: true, error: \"Timed out\" };\n if (name === \"AbortError\") return { ok: false, retryable: true, error: \"Aborted\" };\n if (name === \"TypeError\") return { ok: false, retryable: false, error: \"Unexpected error\" };\n return { ok: false, retryable: true, error: \"Unexpected error\" };\n}\n\n/** Shared by the built-in destinations. */\nexport interface HttpDeps {\n /** Defaults to the global `fetch`. */\n fetch?: typeof fetch | undefined;\n /** Per request. Default `REQUEST_TIMEOUT_MS`. */\n timeoutMs?: number | undefined;\n}\n\n/**\n * A request with a timeout, also aborted by the caller's signal. A network\n * failure (fetch rejects with a `TypeError`) becomes a retryable\n * `DeliveryError(\"Network error\")`; timeouts and aborts pass through.\n */\nexport async function timedFetch(\n deps: HttpDeps,\n url: string,\n init: RequestInit,\n signal: AbortSignal | undefined,\n): Promise<Response> {\n const timeout = AbortSignal.timeout(deps.timeoutMs ?? REQUEST_TIMEOUT_MS);\n const any = (AbortSignal as unknown as { any?: (signals: AbortSignal[]) => AbortSignal }).any;\n const combined = signal ? (any ? any([timeout, signal]) : signal.aborted ? signal : timeout) : timeout;\n // fetch rejects with a TypeError both for a network failure and for a\n // request that can never be sent (a newline in a header value, a bad URL).\n // Building the Request first separates the two: that one fails for good,\n // without echoing the value that broke it.\n try {\n // Without the body, so a stream body is never locked by the check.\n new Request(url, { method: init.method ?? \"GET\", headers: init.headers ?? {} });\n } catch {\n throw new DeliveryError(\"Invalid request (a header value or the URL is malformed)\", { retryable: false });\n }\n try {\n return await (deps.fetch ?? fetch)(url, { ...init, signal: combined });\n } catch (error) {\n if (error instanceof Error && error.name === \"TypeError\") throw new DeliveryError(\"Network error\", { retryable: true });\n throw error;\n }\n}\n\n/**\n * A factory option that may be a value or a function of the config (an\n * account, a secret). A function that throws fails the delivery\n * permanently with \"<what> could not be resolved\", never retried and never\n * echoing its message; to ask for a retry it can throw a retryable\n * `DeliveryError` itself.\n */\nexport async function resolveOption<T>(\n what: string,\n option: T | ((config: DestinationConfig) => T | Promise<T>),\n config: DestinationConfig,\n): Promise<T> {\n if (typeof option !== \"function\") return option;\n try {\n return await (option as (config: DestinationConfig) => T | Promise<T>)(config);\n } catch (error) {\n if (error instanceof DeliveryError) throw error;\n throw new DeliveryError(`${what} could not be resolved`);\n }\n}\n\n/** Lets go of a body we will not read, so the connection is freed. */\nexport function discard(response: Response): void {\n try {\n void response.body?.cancel().catch(() => {});\n } catch {\n // A mocked or already-read body.\n }\n}\n\n/** The string config value at `key`, trimmed, or \"\" (a snake_case `alias` is accepted too). */\nexport function configString(config: DestinationConfig, key: string, alias?: string): string {\n const raw = config[key] ?? (alias ? config[alias] : undefined);\n return typeof raw === \"string\" ? raw.trim() : \"\";\n}\n\n/** Bytes as base64url, no padding. */\nexport function base64url(bytes: Uint8Array | string): string {\n return base64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** Bytes (or UTF-8 text) as standard base64. */\nexport function base64(bytes: Uint8Array | string): string {\n const raw = typeof bytes === \"string\" ? new TextEncoder().encode(bytes) : bytes;\n let s = \"\";\n for (let i = 0; i < raw.length; i++) s += String.fromCharCode(raw[i]!);\n return btoa(s);\n}\n\n/** Standard base64 (or base64url) as bytes. Throws on anything else. */\nexport function fromBase64(text: string): Uint8Array<ArrayBuffer> {\n const bin = atob(text.replace(/-/g, \"+\").replace(/_/g, \"/\"));\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** SHA-256 of a text, as lowercase hex. */\nexport async function sha256Hex(text: string): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(text));\n return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/** WebCrypto's key type, named without depending on the DOM lib. */\nexport type WebCryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;\n","import type { FieldTypeManifest } from \"./fields\";\nimport { evaluateFormula, formulaNumber, ownFormulaList, parseFormula, type FormulaNode, type FormulaRef, type FormulaValue } from \"./formula\";\nimport type { FieldBlock, FormDefinition, Json, Operator } from \"./types\";\n\n/** The calculated field type's registry key. */\nexport const CALCULATED_TYPE = \"calculated\";\n\n/**\n * Field types the builder offers only to a host that names them in its\n * palette, like `STRUCTURED_FIELD_TYPES`: `calculated` shows a value worked\n * out from other answers, so it is opt-in for hosts that want formulas.\n */\nexport const COMPUTED_FIELD_TYPES = [CALCULATED_TYPE] as const;\n\nexport type CalculatedFormat = \"number\" | \"percent\" | \"text\";\n/** Longest the formulas of one form may be, all together (`parseForm` checks it). */\nexport const MAX_FORM_FORMULA_LENGTH = 20_000;\n/** Most decimal places a calculated value may keep. */\nexport const MAX_CALCULATED_DECIMALS = 10;\n\nexport interface CalculatedProps {\n formula: string;\n format?: CalculatedFormat | undefined;\n decimals?: number | undefined;\n}\n\n/** A calculated field's settings, with anything malformed left out. */\nexport function calculatedProps(field: FieldBlock): CalculatedProps {\n const p = field.props ?? {};\n const out: CalculatedProps = { formula: typeof p.formula === \"string\" ? p.formula : \"\" };\n if (p.format === \"number\" || p.format === \"percent\" || p.format === \"text\") out.format = p.format;\n if (typeof p.decimals === \"number\" && Number.isInteger(p.decimals) && p.decimals >= 0 && p.decimals <= MAX_CALCULATED_DECIMALS) {\n out.decimals = p.decimals;\n }\n return out;\n}\n\nexport const isCalculated = (field: FieldBlock | undefined): boolean => field?.type === CALCULATED_TYPE;\n\nconst round = (n: number, decimals: number | undefined) => {\n if (decimals === undefined) return n;\n const r = Number(n.toFixed(decimals));\n return Object.is(r, -0) ? 0 : r;\n};\n\n/**\n * What a formula's result is stored as. `number` and `percent` keep a number\n * (`0.25` for 25%), rounded to `decimals`; `text` keeps text. Without a\n * format, numbers, text and true / false are kept as they are. A list, and\n * anything the format can't hold, is no value (`undefined`).\n */\nexport function calculatedValue(result: FormulaValue, field: FieldBlock): Json | undefined {\n const { format, decimals } = calculatedProps(field);\n if (result === null || Array.isArray(result)) return undefined;\n if (format === \"number\" || format === \"percent\") {\n const n = formulaNumber(result);\n return n === null ? undefined : round(n, decimals);\n }\n if (format === \"text\") {\n if (typeof result === \"number\") return decimals === undefined ? String(result) : result.toFixed(decimals);\n return typeof result === \"boolean\" ? (result ? \"Yes\" : \"No\") : result;\n }\n return typeof result === \"number\" ? round(result, decimals) : result;\n}\n\n/** A calculated value as shown: `12.5`, `25%`, the text, Yes / No. Empty when there is none. */\nexport function formatCalculated(value: Json | undefined, field: FieldBlock): string {\n if (value === undefined || value === null) return \"\";\n const { format, decimals } = calculatedProps(field);\n const fixed = (n: number) => (decimals === undefined ? String(Number(n.toFixed(6))) : n.toFixed(decimals));\n if (typeof value === \"number\") return format === \"percent\" ? `${fixed(value * 100)}%` : fixed(value);\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n return typeof value === \"string\" ? value : \"\";\n}\n\n/**\n * Most items a formula reads from one answer (a list's items, a table's\n * rows). A longer answer reads as blank, so one oversized value sent to the\n * server can't make every formula over it slow.\n */\nexport const MAX_FORMULA_ITEMS = 10_000;\n\n/**\n * Most list items and table rows all of a form's formulas read in one go\n * (each answer and column counted once, in form order). A formula that reads\n * an answer past the limit, or one over `MAX_FORMULA_ITEMS`, has no value\n * (blank, never a partial total), so many big answers can't make working\n * the values out slow either.\n */\nexport const MAX_SETTLE_ITEMS = 50_000;\n\nconst extract = (value: readonly Json[], column: string | undefined): FormulaValue[] =>\n column !== undefined\n ? value.flatMap((row): FormulaValue[] => {\n if (!row || typeof row !== \"object\" || Array.isArray(row)) return [];\n const cell = row[column];\n return typeof cell === \"string\" || typeof cell === \"number\" ? [cell] : [];\n })\n : value.flatMap((v): FormulaValue[] => (typeof v === \"string\" || typeof v === \"number\" || typeof v === \"boolean\" ? [v] : []));\n\n/**\n * The calculator's lists, by the answer's array and then the column (`\"\"`\n * for a list's own items), so an unchanged table is walked once. This relies\n * on answers being immutable, which the engine guarantees: it never changes a\n * value it holds (every update spreads a new `values`), the built-in\n * renderers always pass a new array, and `setValue` with the array already\n * held is ignored. A host must not change an answer array in place either\n * (see the README); pass a new one to `setValue`.\n */\nconst extracted = new WeakMap<readonly Json[], Map<string, readonly FormulaValue[]>>();\n\nfunction cachedList(value: readonly Json[], column: string | undefined): readonly FormulaValue[] {\n let byColumn = extracted.get(value);\n if (!byColumn) extracted.set(value, (byColumn = new Map()));\n const key = column ?? \"\";\n let list = byColumn.get(key);\n if (!list) byColumn.set(key, (list = ownFormulaList(extract(value, column))));\n return list;\n}\n\n/** `formulaInput` for the calculator: the same values, with lists kept per answer (see `cachedList`). */\nfunction readAnswer(value: Json | undefined, column: string | undefined): FormulaValue {\n if (Array.isArray(value)) return cachedList(value, column) as FormulaValue[];\n return column !== undefined ? null : formulaInput(value);\n}\n\n/**\n * The value a formula reads for an answer: numbers and text as they are, a\n * list's items, one table column's cells. A list or table of more than\n * `MAX_FORMULA_ITEMS` reads as blank. Each call builds a new list.\n */\nexport function formulaInput(value: Json | undefined, column?: string): FormulaValue {\n if (value === undefined || value === null) return null;\n if (Array.isArray(value) && value.length > MAX_FORMULA_ITEMS) return null;\n if (column !== undefined) {\n if (!Array.isArray(value)) return null;\n return extract(value, column);\n }\n if (Array.isArray(value)) return extract(value, undefined);\n return typeof value === \"object\" ? null : value;\n}\n\ninterface Compiled {\n field: FieldBlock;\n ast: FormulaNode | null;\n /** The answers it reads, each (answer, column) once (`id` is `undefined` for a key that is not a field). */\n reads: Read[];\n /** Each `ref` node of the formula, to its index in `reads`. */\n slots: Map<FormulaNode, number>;\n /** The inputs of the last evaluation and its result, reused while they are the same values. */\n last: { inputs: unknown[]; value: Json | undefined } | null;\n}\n\ninterface Read {\n id: string | undefined;\n column: string | undefined;\n /** `id` and `column` as one key, for the settle's item count. */\n key: string;\n}\n\nfunction refNodes(node: FormulaNode, out: Extract<FormulaNode, { kind: \"ref\" }>[] = []) {\n if (node.kind === \"ref\") out.push(node);\n else if (node.kind === \"unary\") refNodes(node.arg, out);\n else if (node.kind === \"binary\") (refNodes(node.left, out), refNodes(node.right, out));\n else if (node.kind === \"if\") (refNodes(node.test, out), refNodes(node.then, out), refNodes(node.else, out));\n else if (node.kind === \"call\") for (const a of node.args) refNodes(a, out);\n return out;\n}\n\n/** Stands for an answer that is off the path or unanswered. */\nconst UNREAD = Symbol(\"unread\");\n/** Stands for an answer too big to read: over `MAX_FORMULA_ITEMS`, or past `MAX_SETTLE_ITEMS`. */\nconst OVER = Symbol(\"over\");\n\n/**\n * Works out a form's calculated fields from its answers. `withCalculated`\n * returns `values` itself when nothing changed. Each formula reads the\n * answers on `path` only (an answer logic hides reads as blank) and the\n * calculated fields before it, in form order.\n */\nexport function calculator(definition: FormDefinition) {\n const compiled: Compiled[] = [];\n const idByKey = new Map<string, string>();\n for (const block of definition.blocks) {\n if (block.kind !== \"field\") continue;\n idByKey.set(block.key, block.id);\n }\n for (const block of definition.blocks) {\n if (block.kind !== \"field\" || !isCalculated(block)) continue;\n const parsed = parseFormula(calculatedProps(block).formula);\n const reads: Read[] = [];\n const slots = new Map<FormulaNode, number>();\n const byKey = new Map<string, number>();\n for (const ref of parsed.ok ? refNodes(parsed.ast) : []) {\n const id = idByKey.get(ref.key);\n const key = `${id ?? \"\"}\\u0000${ref.column ?? \"\"}`;\n let slot = byKey.get(key);\n if (slot === undefined) {\n slot = reads.push({ id, column: ref.column, key }) - 1;\n byKey.set(key, slot);\n }\n slots.set(ref, slot);\n }\n compiled.push({ field: block, ast: parsed.ok ? parsed.ast : null, reads, slots, last: null });\n }\n const withCalculated = (values: Record<string, Json | undefined>, path: readonly string[]) => {\n if (!compiled.length) return values;\n const visible = new Set(path);\n let next = values;\n // The items every formula may read, together: each list answer and table\n // column counts once, in form order, and one past the limit reads as blank.\n // It depends on the answers only, so a client and the server agree.\n let budget = MAX_SETTLE_ITEMS;\n const within = new Map<string, boolean>();\n const input = ({ id, key }: Read): unknown => {\n if (id === undefined || !visible.has(id) || !Object.prototype.hasOwnProperty.call(next, id)) return UNREAD;\n const value = next[id];\n if (!Array.isArray(value)) return value;\n let ok = within.get(key);\n if (ok === undefined) {\n // An answer over the per-answer limit is never read, so it uses none of the allowance.\n ok = value.length <= MAX_FORMULA_ITEMS && value.length <= budget;\n if (ok) budget -= value.length;\n within.set(key, ok);\n }\n return ok ? value : OVER;\n };\n for (const entry of compiled) {\n const { field, ast } = entry;\n // A formula is worked out again only when an answer it reads is a different value:\n // an engine settles on every answer, and most answers are to other questions.\n const inputs = entry.reads.map(input);\n let value: Json | undefined;\n if (entry.last && entry.last.inputs.length === inputs.length && entry.last.inputs.every((v, i) => v === inputs[i])) {\n value = entry.last.value;\n } else {\n const resolved: (FormulaValue | undefined)[] = new Array(inputs.length);\n const read = (ref: FormulaRef): FormulaValue => {\n const slot = entry.slots.get(ref as FormulaNode);\n if (slot === undefined) return null;\n let v = resolved[slot];\n if (v === undefined) {\n const raw = inputs[slot];\n v = resolved[slot] = raw === UNREAD ? null : readAnswer(raw as Json | undefined, entry.reads[slot]!.column);\n }\n return v;\n };\n // An answer too big to read leaves the value blank rather than a partial total.\n value = ast && !inputs.includes(OVER) ? calculatedValue(evaluateFormula(ast, read), field) : undefined;\n entry.last = { inputs, value };\n }\n const current = Object.prototype.hasOwnProperty.call(next, field.id) ? next[field.id] : undefined;\n if (current !== value) next = { ...next, [field.id]: value };\n }\n return next;\n };\n return { active: compiled.length > 0, withCalculated };\n}\n\nconst numberOps: Operator[] = [\"eq\", \"neq\", \"lt\", \"lte\", \"gt\", \"gte\", \"in\", \"answered\", \"empty\"];\n\nexport const calculatedFieldType: FieldTypeManifest = {\n type: CALCULATED_TYPE,\n label: \"Calculated\",\n category: \"advanced\",\n value: { json: true },\n operators: numberOps,\n a11y: { semantics: \"control\" },\n // The engine works the value out; any number, text or true / false it made is valid.\n validate: (value) => (typeof value === \"number\" || typeof value === \"string\" || typeof value === \"boolean\" ? null : \"This value is worked out from other answers.\"),\n summarize: (value, field) => formatCalculated(value, field),\n};\n","import type { FieldTypeManifest } from \"./fields\";\nimport type { FieldBlock, Json } from \"./types\";\n\ntype JsonObject = { [key: string]: Json };\nconst isObject = (v: unknown): v is JsonObject => !!v && typeof v === \"object\" && !Array.isArray(v);\nfunction intProp(field: FieldBlock, name: string, fallback: number, floor = 1): number {\n const v = field.props?.[name];\n return typeof v === \"number\" && Number.isInteger(v) && v >= floor ? v : fallback;\n}\nfunction optionalIntProp(field: FieldBlock, name: string, floor = 0): number | undefined {\n const v = field.props?.[name];\n return typeof v === \"number\" && Number.isInteger(v) && v >= floor ? v : undefined;\n}\nconst blank = (v: unknown) => typeof v !== \"string\" || v.trim() === \"\";\n/**\n * Unanswered: nothing, or a list whose every entry is a blank one. Anything\n * else (a string, a list with a malformed entry) is an answer, so validation\n * rejects it instead of dropping it silently.\n */\nconst blankText = (v: unknown) => typeof v === \"string\" && v.trim() === \"\";\nconst emptyList = (value: Json | undefined, isBlank: (entry: Json) => boolean) =>\n value === undefined || value === null || (Array.isArray(value) && value.every(isBlank));\nconst plural = (n: number, one: string, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;\n\nexport function listLimits(field: FieldBlock) {\n return { min: optionalIntProp(field, \"min\") ?? 0, max: intProp(field, \"max\", 10), itemMaxLength: intProp(field, \"itemMaxLength\", 500) };\n}\nconst listItems = (value: Json | undefined): string[] =>\n Array.isArray(value) ? value.filter((v): v is string => typeof v === \"string\" && v.trim() !== \"\") : [];\n\nexport interface TableColumn { key: string; label: string; long?: boolean }\nexport const MAX_TABLE_COLUMNS = 6;\nexport const MAX_TABLE_CELL_LENGTH = 2000;\nexport function tableColumns(field: FieldBlock): TableColumn[] {\n const raw = field.props?.columns;\n if (!Array.isArray(raw)) return [];\n const seen = new Set<string>();\n const out: TableColumn[] = [];\n for (const c of raw) {\n if (!isObject(c) || typeof c.key !== \"string\" || !c.key || seen.has(c.key)) continue;\n seen.add(c.key);\n const column: TableColumn = { key: c.key, label: typeof c.label === \"string\" ? c.label : c.key };\n if (c.long === true) column.long = true;\n out.push(column);\n }\n return out;\n}\nexport function tableLimits(field: FieldBlock) {\n return { minRows: optionalIntProp(field, \"minRows\") ?? 0, maxRows: intProp(field, \"maxRows\", 3) };\n}\nconst filledRows = (value: Json | undefined): JsonObject[] =>\n Array.isArray(value) ? value.filter((r): r is JsonObject => isObject(r) && Object.values(r).some((c) => !blank(c))) : [];\n\nexport interface MediaNote { at: number; text: string }\nexport const MAX_TIMESTAMP_SECONDS = 86400;\nexport function formatTimestamp(seconds: number): string {\n const total = Number.isFinite(seconds) && seconds > 0 ? Math.floor(seconds) : 0;\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = String(total % 60).padStart(2, \"0\");\n return h ? `${h}:${String(m).padStart(2, \"0\")}:${s}` : `${m}:${s}`;\n}\nexport function parseTimestamp(text: string): number | null {\n const t = text.trim();\n if (!t) return null;\n const parts = t.split(\":\");\n if (parts.length > 3) return null;\n if (parts.length === 1) {\n if (!/^\\d+(\\.\\d+)?$/.test(t)) return null;\n const n = Number(t);\n return n <= MAX_TIMESTAMP_SECONDS ? n : null;\n }\n const last = parts.length - 1;\n let total = 0;\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i]!;\n const ok = i === 0 ? /^\\d+$/.test(p) : i === last ? /^\\d{2}(\\.\\d+)?$/.test(p) : /^\\d{2}$/.test(p);\n if (!ok) return null;\n const n = Number(p);\n if (i > 0 && n >= 60) return null;\n total = total * 60 + n;\n }\n return total <= MAX_TIMESTAMP_SECONDS ? total : null;\n}\nconst isTimestamp = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v) && v >= 0 && v <= MAX_TIMESTAMP_SECONDS;\nconst notesWithText = (value: Json | undefined): JsonObject[] =>\n Array.isArray(value) ? value.filter((n): n is JsonObject => isObject(n) && !blank(n.text)) : [];\n\nexport interface Highlight { start: number; end: number; quote: string; note: string }\nexport const MAX_HIGHLIGHT_NOTE_LENGTH = 1000;\n/** The longest passage one highlight may quote; also bounds a quote the server can't check against `props.text`. */\nexport const MAX_HIGHLIGHT_QUOTE_LENGTH = 2000;\nexport const HIGHLIGHT_NOTE_MESSAGE = \"Add a note to each highlight.\";\nconst sourceText = (field: FieldBlock) => (typeof field.props?.text === \"string\" && field.props.text ? field.props.text : undefined);\n\n/**\n * The structured field types, whose answers are lists or records rather than one\n * value:\n * - `list`: several short answers, e.g. goals, action items, three things that went well.\n * - `table`: a small table each answer fills row by row, e.g. an action plan\n * (What / Who / By when), pros and cons.\n * - `media-notes`: notes pinned to times in a video or audio, e.g. lecture notes,\n * a recorded call review.\n * - `text-highlights`: highlight passages of a text and note on each, e.g.\n * annotating an article, a policy or a contract.\n *\n * They are registered like any other, but the builder offers them only to a\n * host that names them in its palette (`FormBuilder palette`), so forms that\n * never had them don't change.\n */\nexport const STRUCTURED_FIELD_TYPES = [\"list\", \"table\", \"media-notes\", \"text-highlights\"] as const;\n\nexport const structuredFieldTypes: FieldTypeManifest[] = [\n {\n type: \"list\", label: \"List\", category: \"text\", value: { json: true },\n // logic.ts `contains` on an array is exact item equality, same as multi-choice, so it is offered.\n operators: [\"contains\", \"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, blankText),\n validate: (value, field) => {\n if (!Array.isArray(value) || !value.every((v) => typeof v === \"string\")) return \"Enter a list of answers.\";\n const { min, max, itemMaxLength } = listLimits(field);\n if (value.some((v) => (v as string).trim().length > itemMaxLength)) return `Keep each item under ${itemMaxLength} characters.`;\n const count = listItems(value).length;\n if (count < min) return `Add at least ${plural(min, \"item\")}.`;\n if (count > max) return `Add at most ${plural(max, \"item\")}.`;\n return null;\n },\n normalize: (value) => (Array.isArray(value) ? listItems(value).map((v) => v.trim()) : value),\n summarize: (value) => listItems(value).map((v) => v.trim()).join(\"; \"),\n samples: (field) => {\n const { min, max } = listLimits(field);\n return [Array.from({ length: Math.min(Math.max(1, min), max) }, (_, i) => `Item ${i + 1}`)];\n },\n },\n {\n type: \"table\", label: \"Table\", category: \"advanced\", value: { json: true },\n operators: [\"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, (r) => isObject(r) && Object.values(r).every(blankText)),\n validate: (value, field) => {\n const columns = tableColumns(field);\n if (!columns.length) return \"This question has no columns.\";\n if (!Array.isArray(value) || !value.every(isObject)) return \"Fill in the rows.\";\n const keys = new Set(columns.map((c) => c.key));\n for (const row of value as JsonObject[]) {\n for (const [key, cell] of Object.entries(row)) {\n if (!keys.has(key)) return \"An answer names a column this question doesn't have.\";\n if (typeof cell !== \"string\") return \"Fill in the rows with text.\";\n if (cell.trim().length > MAX_TABLE_CELL_LENGTH) return `Keep each answer under ${MAX_TABLE_CELL_LENGTH} characters.`;\n }\n }\n const { minRows, maxRows } = tableLimits(field);\n const count = filledRows(value).length;\n if (count < minRows) return `Fill in at least ${plural(minRows, \"row\")}.`;\n if (count > maxRows) return `Fill in at most ${plural(maxRows, \"row\")}.`;\n return null;\n },\n normalize: (value) => Array.isArray(value)\n ? filledRows(value).map((row) => {\n const out: JsonObject = {};\n for (const [key, cell] of Object.entries(row)) if (typeof cell === \"string\") out[key] = cell.trim();\n return out;\n })\n : value,\n summarize: (value, field) => {\n const columns = tableColumns(field);\n return filledRows(value)\n .map((row) => columns.filter((c) => !blank(row[c.key])).map((c) => `${c.label}: ${(row[c.key] as string).trim()}`).join(\" · \"))\n .join(\" / \");\n },\n samples: (field) => {\n const columns = tableColumns(field);\n if (!columns.length) return [];\n const { minRows, maxRows } = tableLimits(field);\n const row = Object.fromEntries(columns.map((c) => [c.key, \"sample\"]));\n return [Array.from({ length: Math.min(Math.max(1, minRows), maxRows) }, () => ({ ...row }))];\n },\n },\n {\n type: \"media-notes\", label: \"Notes at moments\", category: \"media\", value: { json: true },\n operators: [\"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, (n) => isObject(n) && blankText(n.text)),\n validate: (value, field) => {\n if (!Array.isArray(value)) return \"Add notes.\";\n const textMaxLength = intProp(field, \"textMaxLength\", 1000);\n for (const note of value) {\n if (!isObject(note) || typeof note.text !== \"string\") return \"Add notes.\";\n if (!isTimestamp(note.at)) return \"Each note needs a time.\";\n if (note.text.trim().length > textMaxLength) return `Keep each note under ${textMaxLength} characters.`;\n }\n const maxNotes = intProp(field, \"maxNotes\", 20);\n return notesWithText(value).length > maxNotes ? `Add at most ${plural(maxNotes, \"note\")}.` : null;\n },\n normalize: (value) => Array.isArray(value)\n ? notesWithText(value).map((n) => ({ at: n.at as number, text: (n.text as string).trim() })).sort((a, b) => a.at - b.at)\n : value,\n summarize: (value) => notesWithText(value)\n .map((n) => ({ at: typeof n.at === \"number\" ? n.at : 0, text: (n.text as string).trim() }))\n .sort((a, b) => a.at - b.at)\n .map((n) => `${formatTimestamp(n.at)} ${n.text}`)\n .join(\"; \"),\n samples: () => [[{ at: 0, text: \"sample\" }]],\n },\n {\n type: \"text-highlights\", label: \"Highlights\", category: \"media\", value: { json: true },\n operators: [\"answered\", \"empty\"], a11y: { semantics: \"group\" },\n isEmpty: (value) => emptyList(value, () => false),\n validate: (value, field) => {\n if (!Array.isArray(value)) return \"Highlight a passage.\";\n const maxHighlights = intProp(field, \"maxHighlights\", 20);\n if (value.length > maxHighlights) return `Add at most ${plural(maxHighlights, \"highlight\")}.`;\n const text = sourceText(field);\n for (const h of value) {\n if (!isObject(h) || !Number.isInteger(h.start) || !Number.isInteger(h.end) || typeof h.quote !== \"string\" || typeof h.note !== \"string\") {\n return \"Highlight a passage of the text.\";\n }\n const start = h.start as number;\n const end = h.end as number;\n if (start < 0 || end <= start || h.quote.length !== end - start) return \"Highlight a passage of the text.\";\n if (end - start > MAX_HIGHLIGHT_QUOTE_LENGTH) return `Highlight under ${MAX_HIGHLIGHT_QUOTE_LENGTH} characters at a time.`;\n if (text !== undefined && (end > text.length || text.slice(start, end) !== h.quote)) return \"A highlight doesn't match the text.\";\n if (h.note.trim() === \"\") return HIGHLIGHT_NOTE_MESSAGE;\n if (h.note.trim().length > MAX_HIGHLIGHT_NOTE_LENGTH) return `Keep each note under ${MAX_HIGHLIGHT_NOTE_LENGTH} characters.`;\n }\n return null;\n },\n normalize: (value) => Array.isArray(value)\n ? value.filter(isObject)\n .map((h) => ({ start: h.start as number, end: h.end as number, quote: h.quote as string, note: String(h.note).trim() }))\n .sort((a, b) => a.start - b.start || a.end - b.end)\n : value,\n summarize: (value) => Array.isArray(value)\n ? value.filter(isObject).map((h) => `\"${String(h.quote)}\" — ${String(h.note).trim()}`).join(\"; \")\n : \"\",\n samples: (field) => {\n const text = sourceText(field);\n if (text === undefined) return [[{ start: 0, end: 6, quote: \"sample\", note: \"sample\" }]];\n const end = Math.min(text.length, 20);\n return [[{ start: 0, end, quote: text.slice(0, end), note: \"sample\" }]];\n },\n },\n];\n","import type { Block, FieldBlock, Json, Operator } from \"./types\";\nimport { calculatedFieldType } from \"./calculated\";\nimport { structuredFieldTypes } from \"./structured\";\n\n/**\n * A field type, without any UI. Renderers are registered separately per\n * platform (`genesis-forms-react`), so a manifest runs anywhere.\n */\nexport interface FieldTypeManifest {\n type: string;\n label: string;\n category: \"text\" | \"choice\" | \"scale\" | \"date\" | \"media\" | \"advanced\";\n /** `json: false` types must convert, so drafts and server replay never lose an answer. */\n value:\n | { json: true }\n | { json: false; serialize: (value: unknown) => Json; deserialize: (json: Json) => unknown };\n operators: Operator[];\n a11y: {\n semantics: \"control\" | \"group\";\n /** The HTML `autocomplete` token, such as `\"email\"` or `\"tel\"`. */\n autocomplete?: string;\n /** The HTML `inputmode` hint for on-screen keyboards, such as `\"email\"` or `\"tel\"`. */\n inputMode?: \"text\" | \"email\" | \"tel\" | \"numeric\" | \"decimal\" | \"url\" | \"search\";\n };\n isEmpty?: (value: Json | undefined) => boolean;\n /** Return an error message, or null when the (non-empty) value is valid. */\n validate?: (value: Json, field: FieldBlock) => string | null;\n /** Plain text for recall, exports and emails. */\n summarize?: (value: Json, field: FieldBlock) => string;\n /**\n * The form a (valid, non-empty) value is stored in, such as an email\n * without surrounding spaces. Applied by `engine.answers()` and the server.\n */\n normalize?: (value: Json, field: FieldBlock) => Json;\n /** Valid example answers, used by `coverage()` and other test tools to explore a path. */\n samples?: (field: FieldBlock) => Json[];\n}\n\n// One registry per process, shared by every entry point (index, server,\n// testing are bundled separately), so a plugin registered once is seen by all.\nconst REGISTRY = Symbol.for(\"@marktiderman/genesis-forms/field-types\");\nconst globalScope = globalThis as typeof globalThis & { [REGISTRY]?: Map<string, FieldTypeManifest> };\nconst registry: Map<string, FieldTypeManifest> = (globalScope[REGISTRY] ??= new Map());\n\nexport function registerFieldType(manifest: FieldTypeManifest): void {\n if (!manifest.type) throw new Error(\"registerFieldType: a field type needs a `type`.\");\n const value = manifest.value as { json: boolean; serialize?: unknown; deserialize?: unknown };\n if (\n !value.json &&\n (typeof value.serialize !== \"function\" || typeof value.deserialize !== \"function\")\n ) {\n throw new Error(\n `registerFieldType: \"${manifest.type}\" stores a non-JSON value, so it must provide both serialize and deserialize.`,\n );\n }\n registry.set(manifest.type, manifest);\n}\n\nexport function getFieldType(type: string): FieldTypeManifest | undefined {\n return registry.get(type);\n}\n\nexport function listFieldTypes(): FieldTypeManifest[] {\n return [...registry.values()];\n}\n\nexport function isEmptyValue(value: Json | undefined, field?: FieldBlock): boolean {\n const manifest = field ? registry.get(field.type) : undefined;\n if (manifest?.isEmpty) return manifest.isEmpty(value);\n if (value === undefined || value === null) return true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/** A value in its stored form (see `FieldTypeManifest.normalize`). */\nexport function normalizeValue(value: Json, field: FieldBlock): Json {\n const manifest = registry.get(field.type);\n return manifest?.normalize ? manifest.normalize(value, field) : value;\n}\n\n/** Whether a block holds personal or secret data: `sensitive: true`, or the `props.sensitive: true` alias. */\nexport function isSensitive(block: Block): boolean {\n return block.kind === \"field\" && (block.sensitive === true || block.props?.sensitive === true);\n}\n\nexport function summarizeValue(value: Json | undefined, field: FieldBlock): string {\n if (isEmptyValue(value, field)) return \"\";\n const manifest = registry.get(field.type);\n if (manifest?.summarize) return manifest.summarize(value as Json, field);\n if (Array.isArray(value)) return value.join(\", \");\n return String(value);\n}\n\n// ── Built-in types (R1) ──────────────────────────────────────────────────────\n\nexport interface ChoiceOption {\n value: string;\n label?: string;\n}\n\nexport function choiceOptions(field: FieldBlock): ChoiceOption[] {\n const raw = field.props?.options;\n if (!Array.isArray(raw)) return [];\n return raw.flatMap((o) =>\n o && typeof o === \"object\" && !Array.isArray(o) && typeof o.value === \"string\"\n ? [{ value: o.value, label: typeof o.label === \"string\" ? o.label : undefined }]\n : [],\n );\n}\n\nfunction optionLabel(field: FieldBlock, value: string): string {\n const option = choiceOptions(field).find((o) => o.value === value);\n return option?.label ?? value;\n}\n\nfunction intRange(field: FieldBlock, min: number, maxDefault: number) {\n const max = typeof field.props?.max === \"number\" ? field.props.max : maxDefault;\n return { min, max };\n}\n\nconst numberOps: Operator[] = [\"eq\", \"neq\", \"lt\", \"lte\", \"gt\", \"gte\", \"in\", \"answered\", \"empty\"];\nconst textOps: Operator[] = [\"eq\", \"neq\", \"contains\", \"answered\", \"empty\"];\n\nfunction maxLength(field: FieldBlock, fallback: number): number {\n return typeof field.props?.maxLength === \"number\" ? field.props.maxLength : fallback;\n}\n\nfunction textValidate(fallback: number) {\n return (value: Json, field: FieldBlock) => {\n if (typeof value !== \"string\") return \"Enter text.\";\n const limit = maxLength(field, fallback);\n return value.length > limit ? `Keep it under ${limit} characters.` : null;\n };\n}\n\n/** The longest address SMTP allows (RFC 5321). */\nconst MAX_EMAIL_LENGTH = 254;\n\n/**\n * `local@domain.tld`: no spaces, exactly one `@`, and a dot inside the domain.\n * A linear scan rather than a regex, so a hostile value cannot backtrack.\n */\nexport function isEmailAddress(value: string): boolean {\n if (value.length > MAX_EMAIL_LENGTH || /\\s/.test(value)) return false;\n const at = value.indexOf(\"@\");\n if (at < 1 || value.indexOf(\"@\", at + 1) !== -1) return false;\n const domain = value.slice(at + 1);\n // A dot with at least one character on each side.\n return domain.slice(1, -1).includes(\".\");\n}\n\n/** Longest phone number accepted, separators included. */\nconst MAX_PHONE_LENGTH = 32;\n\n/**\n * Digits with optional separators (spaces, `-`, `(`, `)`, `.`) and an\n * optional leading `+`; 7 to 15 digits (E.164 allows at most 15). One linear scan.\n */\nfunction isPhoneNumber(value: string): boolean {\n if (value.length > MAX_PHONE_LENGTH) return false;\n let digits = 0;\n for (let i = 0; i < value.length; i++) {\n const c = value[i]!;\n if (c >= \"0\" && c <= \"9\") digits++;\n else if (c === \"+\") {\n if (i !== 0) return false;\n } else if (c !== \" \" && c !== \"-\" && c !== \"(\" && c !== \")\" && c !== \".\") return false;\n }\n return digits >= 7 && digits <= 15;\n}\n\nconst builtins: FieldTypeManifest[] = [\n {\n type: \"short-text\",\n label: \"Short text\",\n category: \"text\",\n value: { json: true },\n operators: textOps,\n a11y: { semantics: \"control\" },\n validate: textValidate(500),\n },\n {\n type: \"long-text\",\n label: \"Long text\",\n category: \"text\",\n value: { json: true },\n operators: textOps,\n a11y: { semantics: \"control\" },\n validate: textValidate(5000),\n },\n {\n type: \"email\",\n label: \"Email\",\n category: \"text\",\n value: { json: true },\n operators: textOps,\n a11y: { semantics: \"control\", autocomplete: \"email\", inputMode: \"email\" },\n validate: (value) =>\n typeof value === \"string\" && isEmailAddress(value.trim())\n ? null\n : \"Enter an email address like name@example.com.\",\n normalize: (value) => (typeof value === \"string\" ? value.trim() : value),\n },\n {\n type: \"phone\",\n label: \"Phone\",\n category: \"text\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"answered\", \"empty\"],\n a11y: { semantics: \"control\", autocomplete: \"tel\", inputMode: \"tel\" },\n validate: (value) =>\n typeof value === \"string\" && isPhoneNumber(value.trim())\n ? null\n : \"Enter a phone number with 7 to 15 digits.\",\n normalize: (value) => (typeof value === \"string\" ? value.trim() : value),\n summarize: (value) => String(value),\n },\n {\n type: \"rating\",\n label: \"Rating\",\n category: \"scale\",\n value: { json: true },\n operators: numberOps,\n a11y: { semantics: \"group\" },\n validate: (value, field) => {\n const { min, max } = intRange(field, 1, 5);\n return Number.isInteger(value) && (value as number) >= min && (value as number) <= max\n ? null\n : `Choose a rating from ${min} to ${max}.`;\n },\n summarize: (value, field) => {\n const { max } = intRange(field, 1, 5);\n const end = scaleEndLabel(field, value as number, 1, max);\n return end ? `${value}/${max} (${end})` : `${value}/${max}`;\n },\n },\n {\n type: \"nps\",\n label: \"Net Promoter Score\",\n category: \"scale\",\n value: { json: true },\n operators: numberOps,\n a11y: { semantics: \"group\" },\n validate: (value) =>\n Number.isInteger(value) && (value as number) >= 0 && (value as number) <= 10\n ? null\n : \"Choose a score from 0 to 10.\",\n summarize: (value, field) => {\n const end = scaleEndLabel(field, value as number, 0, 10);\n return end ? `${value}/10 (${end})` : `${value}/10`;\n },\n },\n {\n type: \"single-choice\",\n label: \"Single choice\",\n category: \"choice\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"in\", \"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n validate: (value, field) =>\n typeof value === \"string\" && choiceOptions(field).some((o) => o.value === value)\n ? null\n : \"Choose one of the options.\",\n summarize: (value, field) => optionLabel(field, String(value)),\n },\n {\n type: \"multi-choice\",\n label: \"Multiple choice\",\n category: \"choice\",\n value: { json: true },\n operators: [\"contains\", \"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n validate: (value, field) => {\n const allowed = new Set(choiceOptions(field).map((o) => o.value));\n // Each option at most once, so a value is never longer than the option list.\n return Array.isArray(value) &&\n value.length <= allowed.size &&\n new Set(value).size === value.length &&\n value.every((v) => typeof v === \"string\" && allowed.has(v))\n ? null\n : \"Choose from the options.\";\n },\n summarize: (value, field) =>\n Array.isArray(value) ? value.map((v) => optionLabel(field, String(v))).join(\", \") : String(value),\n },\n {\n type: \"yes-no\",\n label: \"Yes / no\",\n category: \"choice\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n validate: (value) => (typeof value === \"boolean\" ? null : \"Choose yes or no.\"),\n summarize: (value) => (value ? \"Yes\" : \"No\"),\n },\n {\n type: \"dropdown\",\n label: \"Dropdown\",\n category: \"choice\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"in\", \"answered\", \"empty\"],\n a11y: { semantics: \"control\" },\n validate: (value, field) =>\n typeof value === \"string\" && choiceOptions(field).some((o) => o.value === value)\n ? null\n : \"Choose one of the options.\",\n summarize: (value, field) => optionLabel(field, String(value)),\n },\n {\n type: \"number\",\n label: \"Number\",\n category: \"text\",\n value: { json: true },\n operators: numberOps,\n a11y: { semantics: \"control\", inputMode: \"decimal\" },\n validate: (value, field) => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return \"Enter a number.\";\n const { min, max, step } = numberLimits(field);\n if (min !== undefined && max !== undefined && (value < min || value > max)) {\n return `Enter a number from ${min} to ${max}.`;\n }\n if (min !== undefined && value < min) return `Enter ${min} or more.`;\n if (max !== undefined && value > max) return `Enter ${max} or less.`;\n if (step !== undefined && !onStep(value, min ?? 0, step)) {\n return step === 1 && Number.isInteger(min ?? 0)\n ? \"Enter a whole number.\"\n : `Enter a number in steps of ${step}.`;\n }\n return null;\n },\n summarize: (value) => String(value),\n samples: (field) => {\n const { min, max } = numberLimits(field);\n return [min, max, 0, 1].filter((v): v is number => v !== undefined);\n },\n },\n {\n type: \"date\",\n label: \"Date\",\n category: \"date\",\n value: { json: true },\n operators: [\"eq\", \"neq\", \"answered\", \"empty\"],\n a11y: { semantics: \"control\" },\n validate: (value, field) => {\n if (typeof value !== \"string\" || !isIsoDate(value.trim())) return \"Enter a date like 2026-10-22.\";\n const date = value.trim();\n const { min, max } = dateLimits(field);\n if (min && max && (date < min || date > max)) return `Choose a date from ${min} to ${max}.`;\n if (min && date < min) return `Choose ${min} or later.`;\n if (max && date > max) return `Choose ${max} or earlier.`;\n return null;\n },\n normalize: (value) => (typeof value === \"string\" ? value.trim() : value),\n samples: (field) => {\n const { min, max } = dateLimits(field);\n return [min ?? max ?? \"2000-01-01\"];\n },\n },\n {\n type: \"consent\",\n label: \"Consent checkbox\",\n category: \"choice\",\n value: { json: true },\n operators: [\"answered\", \"empty\"],\n a11y: { semantics: \"group\" },\n // Unchecked is unanswered, so a required consent must be checked.\n isEmpty: (value) => value === undefined || value === null || value === false,\n validate: (value) => (value === true ? null : \"Check the box to agree.\"),\n summarize: () => \"Agreed\",\n samples: () => [true],\n },\n];\n\n/** The optional words under the ends of a rating or NPS scale (\"Poor\", \"Great\"). */\nexport function scaleLabels(field: FieldBlock): { low?: string; high?: string } {\n const out: { low?: string; high?: string } = {};\n const low = field.props?.lowLabel;\n const high = field.props?.highLabel;\n if (typeof low === \"string\" && low.trim()) out.low = low.trim();\n if (typeof high === \"string\" && high.trim()) out.high = high.trim();\n return out;\n}\n\n/** How a rating is drawn: `\"numbers\"` (default) or `\"stars\"`. */\nexport function ratingDisplay(field: FieldBlock): \"numbers\" | \"stars\" {\n return field.props?.display === \"stars\" ? \"stars\" : \"numbers\";\n}\n\nfunction scaleEndLabel(field: FieldBlock, value: number, min: number, max: number): string | undefined {\n const { low, high } = scaleLabels(field);\n return value === min ? low : value === max ? high : undefined;\n}\n\nconst finite = (v: Json | undefined): number | undefined =>\n typeof v === \"number\" && Number.isFinite(v) ? v : undefined;\n\n/** A `number` field's limits: `min`, `max` and `step` (each optional; `step` is above 0). */\nexport function numberLimits(field: FieldBlock): { min?: number; max?: number; step?: number } {\n const out: { min?: number; max?: number; step?: number } = {};\n const min = finite(field.props?.min);\n const max = finite(field.props?.max);\n const step = finite(field.props?.step);\n if (min !== undefined) out.min = min;\n if (max !== undefined) out.max = max;\n if (step !== undefined && step > 0) out.step = step;\n return out;\n}\n\n/** Whether `value` is `base` plus a whole number of `step`s, allowing for floating-point error. */\nfunction onStep(value: number, base: number, step: number): boolean {\n const n = (value - base) / step;\n return Math.abs(n - Math.round(n)) < 1e-9 * Math.max(1, Math.abs(n));\n}\n\n/** `YYYY-MM-DD`, a real calendar day (no 2026-02-30), years 0001 to 9999. */\nexport function isIsoDate(value: string): boolean {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return false;\n const [y, m, d] = value.split(\"-\").map(Number) as [number, number, number];\n if (y < 1 || m < 1 || m > 12 || d < 1) return false;\n const days = [31, y % 4 === 0 && (y % 100 !== 0 || y % 400 === 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n return d <= days[m - 1]!;\n}\n\n/** A `date` field's earliest and latest days (`YYYY-MM-DD`), when set. */\nexport function dateLimits(field: FieldBlock): { min?: string; max?: string } {\n const out: { min?: string; max?: string } = {};\n const min = field.props?.min;\n const max = field.props?.max;\n if (typeof min === \"string\" && isIsoDate(min)) out.min = min;\n if (typeof max === \"string\" && isIsoDate(max)) out.max = max;\n return out;\n}\n\nfor (const manifest of [...builtins, ...structuredFieldTypes, calculatedFieldType]) registerFieldType(manifest);\n","import { isEmptyValue } from \"./fields\";\nimport type { Block, Condition, FieldBlock, FormDefinition, Json, LogicRule, Operand } from \"./types\";\n\nexport interface EvalScope {\n values: Record<string, Json | undefined>;\n hidden: Record<string, Json | undefined>;\n fields: Map<string, FieldBlock>;\n}\n\n/** `record[key]` if it is the record's own property: `values.constructor` is not an answer. */\nexport function own<T>(record: Record<string, T>, key: string): T | undefined {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;\n}\n\nfunction resolve(operand: Operand, scope: EvalScope): Json | undefined {\n if (\"field\" in operand) return own(scope.values, operand.field);\n if (\"hidden\" in operand) return own(scope.hidden, operand.hidden);\n return operand.value;\n}\n\nfunction deepEqual(a: Json | undefined, b: Json | undefined): boolean {\n if (a === b) return true;\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));\n }\n return false;\n}\n\n/**\n * Evaluate a condition. Never throws. An empty value (unanswered, `null`,\n * blank text, an empty list: see `isEmptyValue`) is unanswered: it fails\n * every comparison, including `eq`, `in` and `contains`, and passes `neq`.\n */\nexport function evaluate(condition: Condition, scope: EvalScope): boolean {\n if (\"all\" in condition) return condition.all.every((c) => evaluate(c, scope));\n if (\"any\" in condition) return condition.any.some((c) => evaluate(c, scope));\n if (\"not\" in condition) return !evaluate(condition.not, scope);\n\n const left = resolve(condition.left, scope);\n const right = condition.right ? resolve(condition.right, scope) : undefined;\n const field = \"field\" in condition.left ? scope.fields.get(condition.left.field) : undefined;\n const unanswered = isEmptyValue(left, field);\n\n switch (condition.op) {\n case \"answered\":\n return !unanswered;\n case \"empty\":\n return unanswered;\n case \"eq\":\n return !unanswered && deepEqual(left, right);\n case \"neq\":\n // An unanswered field is \"not\" any value.\n return unanswered || !deepEqual(left, right);\n case \"lt\":\n case \"lte\":\n case \"gt\":\n case \"gte\": {\n if (typeof left !== \"number\" || typeof right !== \"number\") return false;\n if (condition.op === \"lt\") return left < right;\n if (condition.op === \"lte\") return left <= right;\n if (condition.op === \"gt\") return left > right;\n return left >= right;\n }\n case \"in\":\n return !unanswered && Array.isArray(right) && right.some((r) => deepEqual(r, left));\n case \"contains\":\n if (unanswered) return false;\n if (Array.isArray(left)) return left.some((l) => deepEqual(l, right));\n return (\n typeof left === \"string\" &&\n typeof right === \"string\" &&\n left.toLowerCase().includes(right.toLowerCase())\n );\n }\n}\n\n/** Blocks a respondent steps through: fields and content, in order. */\nexport function steps(def: FormDefinition): Block[] {\n return def.blocks.filter((b) => b.kind !== \"page-break\");\n}\n\nfunction visibilityRules(def: FormDefinition, blockId: string) {\n return (def.logic ?? []).filter(\n (r): r is Extract<LogicRule, { target: string }> =>\n (r.effect === \"show\" || r.effect === \"hide\") && r.target === blockId,\n );\n}\n\n/** Whether a field is withheld because the form is anonymous and the field identifies the respondent. */\nexport function withheld(def: FormDefinition, field: FieldBlock | undefined): boolean {\n return def.settings?.anonymous === true && field?.identifying === true;\n}\n\n/** Show/hide rules against a scope as given. A matching `hide` wins; any `show` must match. */\nfunction rulesAllow(def: FormDefinition, blockId: string, scope: EvalScope): boolean {\n if (withheld(def, scope.fields.get(blockId))) return false;\n const rules = visibilityRules(def, blockId);\n if (rules.some((r) => r.effect === \"hide\" && evaluate(r.when, scope))) return false;\n const shows = rules.filter((r) => r.effect === \"show\");\n return shows.length === 0 || shows.some((r) => evaluate(r.when, scope));\n}\n\nexport interface PathResult {\n /** Block ids the respondent will step through, given the answers on the path. */\n path: string[];\n /** The ending reached by a jump, or the default ending. */\n ending: string | null;\n}\n\nexport interface PathWalk extends PathResult {\n /**\n * The scope logic sees at a block: the values of the fields on the path\n * before it (and of the block itself, with `inclusive`), nothing else.\n */\n scopeAt(blockId: string, inclusive?: boolean): EvalScope;\n}\n\n/** One forward pass over the blocks. See `computePath`. */\nexport function walkPath(def: FormDefinition, scope: EvalScope): PathWalk {\n const list = steps(def);\n const index = new Map(list.map((b, i) => [b.id, i]));\n const position = new Map(def.blocks.map((b, i) => [b.id, i]));\n const jumps = (def.logic ?? []).filter(\n (r): r is Extract<LogicRule, { effect: \"jump\" }> => r.effect === \"jump\",\n );\n const defaultEnding = def.endings?.find((e) => e.id === \"default\")?.id ?? def.endings?.[0]?.id ?? null;\n\n // Values of the fields placed on the path so far. It only grows, so every\n // decision reads blocks already placed and the pass needs no fixed point.\n const placed = Object.create(null) as Record<string, Json | undefined>;\n const local: EvalScope = { values: placed, hidden: scope.hidden, fields: scope.fields };\n const path: string[] = [];\n const nextVisible = (from: number) => {\n for (let i = from; i < list.length; i++) if (rulesAllow(def, list[i]!.id, local)) return i;\n return list.length;\n };\n\n let ending = defaultEnding;\n let i = nextVisible(0);\n while (i < list.length) {\n const block = list[i]!;\n path.push(block.id);\n if (block.kind === \"field\") placed[block.id] = own(scope.values, block.id);\n const jump = jumps.find((r) => r.from === block.id && evaluate(r.when, local));\n if (jump) {\n if (typeof jump.to === \"object\") {\n ending = jump.to.ending;\n break;\n }\n const target = index.get(jump.to);\n if (target !== undefined && target > i) {\n i = nextVisible(target);\n continue;\n }\n }\n i = nextVisible(i + 1);\n }\n\n const scopeAt = (blockId: string, inclusive = false): EvalScope => {\n const at = position.get(blockId) ?? -1;\n const values = Object.create(null) as Record<string, Json | undefined>;\n for (const id of path) {\n const p = position.get(id)!;\n if (p > at || (p === at && !inclusive)) break;\n if (id in placed) values[id] = placed[id];\n }\n return { values, hidden: scope.hidden, fields: scope.fields };\n };\n return { path, ending, scopeAt };\n}\n\n/**\n * The respondent's path, derived from the answers on the path, so the client,\n * the server and a replay always agree. It is built in one forward pass: a\n * block's show/hide rules, and the jumps from it, see only the fields already\n * on the path before it (and, for a jump, the block itself). A field that is\n * hidden, jumped over or later in the form reads as unanswered, whatever\n * value it holds.\n *\n * A block jumped over is off the path and counts as hidden: it is not\n * validated and its value is cleared on submit. A jump never revisits a block;\n * a jump to an earlier block is ignored (the checker in `parseForm` reports it).\n */\nexport function computePath(def: FormDefinition, scope: EvalScope): PathResult {\n const { path, ending } = walkPath(def, scope);\n return { path, ending };\n}\n\n/**\n * Whether a block's show/hide rules let it be shown, ignoring jumps. The rules\n * read the answers on the path before the block, as in `computePath`. A block\n * with any `show` rule is hidden until one matches; a matching `hide` rule\n * always wins.\n */\nexport function ruleVisible(def: FormDefinition, blockId: string, scope: EvalScope): boolean {\n return rulesAllow(def, blockId, walkPath(def, scope).scopeAt(blockId));\n}\n\nexport function fieldMap(def: FormDefinition): Map<string, FieldBlock> {\n const map = new Map<string, FieldBlock>();\n for (const block of def.blocks) if (block.kind === \"field\") map.set(block.id, block);\n return map;\n}\n","import { summarizeValue } from \"./fields\";\nimport { own } from \"./logic\";\nimport type { FieldBlock, Json } from \"./types\";\n\nconst TOKEN = /\\{\\{\\s*(field|hidden):([A-Za-z0-9_-]+)\\s*(?:\\|([^}]*))?\\}\\}/g;\n\nexport interface RecallScope {\n /** Fields by key. */\n fieldsByKey: Map<string, FieldBlock>;\n values: Record<string, Json | undefined>;\n hidden: Record<string, Json | undefined>;\n}\n\n/**\n * Replace `{{field:key|fallback}}` and `{{hidden:name|fallback}}` tokens.\n * An unanswered value renders its fallback (default empty); the text is\n * never dropped.\n */\nexport function recall(text: string, scope: RecallScope): string {\n return text.replace(TOKEN, (_match, kind: string, name: string, fallback?: string) => {\n if (kind === \"field\") {\n const field = scope.fieldsByKey.get(name);\n const out = field ? summarizeValue(own(scope.values, field.id), field) : \"\";\n return out || (fallback ?? \"\").trim();\n }\n const value = own(scope.hidden, name);\n const out = value === undefined || value === null ? \"\" : String(value);\n return out || (fallback ?? \"\").trim();\n });\n}\n\n/** The keys a text recalls, for the checker. */\nexport function recallRefs(text: string): { kind: \"field\" | \"hidden\"; name: string }[] {\n return [...text.matchAll(TOKEN)].map((m) => ({ kind: m[1] as \"field\" | \"hidden\", name: m[2]! }));\n}\n","/**\n * One response as a flat row: the shape the sheet appends, the email lists\n * and the webhook sends alongside the raw answers.\n */\nimport { getFieldType, isEmptyValue, isSensitive, summarizeValue } from \"../fields\";\nimport { own, withheld } from \"../logic\";\nimport { recall } from \"../recall\";\nimport type { FieldBlock, FormDefinition, Json } from \"../types\";\nimport type { Cell, DeliverySubmission } from \"./types\";\n\nexport interface RowOptions {\n /**\n * Fields marked `sensitive`: `\"include\"` their values (default), `\"mask\"`\n * them as `[sensitive]`, or `\"omit\"` their columns.\n */\n sensitive?: \"include\" | \"mask\" | \"omit\" | undefined;\n}\n\nexport interface ResponseRow {\n /** Cells by column key. */\n row: Record<string, Cell>;\n /** The column keys in order: `id`, `submitted_at`, the meta keys, then one per field key. */\n columns: string[];\n /** Field labels by key, recall filled in from this submission. */\n labels: Record<string, string>;\n}\n\nexport const SENSITIVE_MASK = \"[sensitive]\";\n\n// Never used as column keys, so a hostile meta key cannot touch a prototype.\nconst RESERVED = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\n/**\n * One answer as a cell: numbers stay numbers (ratings, NPS), choices show\n * their labels, a list is joined with \", \", yes/no reads \"Yes\"/\"No\", and a\n * plugin type's `summarize` is used where it has one.\n */\nexport function answerCell(field: FieldBlock, value: Json | undefined): Cell {\n if (value === undefined || isEmptyValue(value, field)) return \"\";\n if (typeof value === \"number\") return value;\n const manifest = getFieldType(field.type);\n if (manifest?.summarize) return summarizeValue(value, field);\n if (typeof value === \"string\") return value;\n if (typeof value === \"boolean\") return value ? \"Yes\" : \"No\";\n if (Array.isArray(value) && value.every((v) => typeof v !== \"object\" || v === null)) {\n return value.map((v) => String(v)).join(\", \");\n }\n return JSON.stringify(value);\n}\n\n/**\n * The row for one submission. Columns: `id` (the response id), then\n * `submitted_at` when given, then the app's `meta` columns in order, then\n * one per field key in form order (blank when unanswered or hidden by\n * logic). Content blocks get no column. On an anonymous form, identifying\n * fields get no column at all, whatever the answers hold.\n */\nexport function responseRow(\n submission: DeliverySubmission,\n definition: FormDefinition,\n options: RowOptions = {},\n): ResponseRow {\n const row: Record<string, Cell> = {};\n const columns: string[] = [];\n const set = (key: string, value: Cell) => {\n if (RESERVED.has(key)) return;\n if (!Object.prototype.hasOwnProperty.call(row, key)) columns.push(key);\n row[key] = value;\n };\n set(\"id\", submission.id);\n if (submission.submittedAt !== undefined) set(\"submitted_at\", submission.submittedAt);\n for (const [key, value] of Object.entries(submission.meta ?? {})) {\n if (key !== \"id\" && key !== \"submitted_at\") set(key, value);\n }\n\n const fields = definition.blocks.filter((b): b is FieldBlock => b.kind === \"field\");\n const fieldsByKey = new Map(fields.map((f) => [f.key, f]));\n const sensitive = options.sensitive ?? \"include\";\n // Recall in a label must not leak what the row itself withholds or masks.\n const values: Record<string, Json> = {};\n for (const field of fields) {\n const value = own(submission.answers, field.id);\n if (value === undefined || withheld(definition, field)) continue;\n if (isSensitive(field) && sensitive !== \"include\") continue;\n values[field.id] = value;\n }\n const scope = { fieldsByKey, values, hidden: visibleInputs(submission, definition, sensitive) };\n const labels: Record<string, string> = {};\n for (const field of fields) {\n if (withheld(definition, field)) continue;\n if (isSensitive(field) && sensitive === \"omit\") continue;\n if (RESERVED.has(field.key)) continue;\n labels[field.key] = recall(field.label, scope).trim() || field.key;\n const cell = answerCell(field, own(submission.answers, field.id));\n set(field.key, isSensitive(field) && sensitive === \"mask\" && cell !== \"\" ? SENSITIVE_MASK : cell);\n }\n return { row, columns, labels };\n}\n\n/**\n * Hidden and server inputs as recall and the webhook may show them: on an\n * anonymous form identifying ones are left out, and sensitive ones are left\n * out unless `sensitive` is `\"include\"`.\n */\nexport function visibleInputs(\n submission: DeliverySubmission,\n definition: FormDefinition,\n sensitive: RowOptions[\"sensitive\"] = \"include\",\n): Record<string, Json> {\n const declared = new Map((definition.hidden ?? []).map((h) => [h.name, h]));\n const out: Record<string, Json> = {};\n for (const [name, value] of Object.entries({ ...submission.hidden, ...submission.context })) {\n const input = declared.get(name);\n if (RESERVED.has(name)) continue;\n if (input?.identifying && definition.settings?.anonymous === true) continue;\n if (input?.sensitive && sensitive !== \"include\") continue;\n out[name] = value;\n }\n return out;\n}\n\n/**\n * A cell that a spreadsheet will never run as a formula when the text is\n * opened elsewhere (a CSV export opened in Excel). Opt-in: use it when\n * writing CSV, not for the sheet destination, whose RAW writes are already\n * safe and would store the `'` literally. Text starting with `=`,\n * `@`, a tab or a carriage return gets a leading `'`, as OWASP recommends;\n * so does text starting with `+` or `-` unless it is only digits and\n * number punctuation (a phone number such as `+1 (555) 010-0000`, `-2.5`),\n * which cannot call a function or name a cell. Numbers and booleans are\n * returned as they are.\n */\nexport function escapeFormula(cell: Cell): Cell {\n if (typeof cell !== \"string\" || cell === \"\") return cell;\n const first = cell[0]!;\n if (first === \"=\" || first === \"@\" || first === \"\\t\" || first === \"\\r\") return `'${cell}`;\n if ((first === \"+\" || first === \"-\") && !/^[+-][\\d\\s().,+-]*$/.test(cell)) return `'${cell}`;\n return cell;\n}\n","/**\n * The email destination: one notification per submission, through any\n * provider that implements `EmailProvider`. `resendProvider` is built in.\n *\n * The body is built from the definition: each answered field's label (recall\n * filled in) and its value, in form order, after the app's meta columns.\n * Every value is HTML-escaped. Subjects and addresses are stripped of line\n * breaks and checked, so an answer can never add a header. Sensitive fields\n * are masked unless `sensitive: \"include\"` is set: an inbox is not a vault.\n */\nimport { isEmailAddress } from \"../fields\";\nimport { own } from \"../logic\";\nimport type { FormDefinition } from \"../types\";\nimport { responseRow, type ResponseRow, type RowOptions } from \"./row\";\nimport {\n configString,\n deliveryFailure,\n DeliveryError,\n discard,\n httpError,\n\n sha256Hex,\n timedFetch,\n type Cell,\n type DeliveryOptions,\n type DeliveryResult,\n type DeliverySubmission,\n type Destination,\n type DestinationConfig,\n type HttpDeps,\n} from \"./types\";\n\n/** One message, ready to send. Addresses are already checked. */\nexport interface EmailMessage {\n from: string;\n to: string[];\n replyTo?: string | undefined;\n subject: string;\n text: string;\n html: string;\n /** Stable across retries of one delivery: a provider that supports it sends once. */\n idempotencyKey: string;\n}\n\n/** Sends one message. Throws a `DeliveryError` (or any error) on failure. */\nexport interface EmailProvider {\n readonly name: string;\n send(message: EmailMessage, options: { signal?: AbortSignal | undefined }): Promise<void>;\n}\n\nexport interface EmailContent {\n subject: string;\n text: string;\n html: string;\n}\n\nexport interface EmailRenderInput {\n submission: DeliverySubmission;\n definition: FormDefinition;\n config: DestinationConfig;\n /** The submission as a row (sensitive values masked unless `sensitive: \"include\"`). */\n row: ResponseRow;\n}\n\n/** What the email destination reads from a destination's config. */\nexport interface EmailConfig {\n /** One address or a list (at most 50). */\n to: string | string[];\n /** Overrides the default subject (still stripped of line breaks). */\n subject?: string;\n}\n\nexport interface EmailDestinationOptions {\n provider: EmailProvider;\n /** `\"Feedback <feedback@send.example.com>\"` or a bare address. */\n from: string;\n /**\n * The Reply-To address: the key of an email field whose answer is used, or\n * a function returning an address (or null for none). Only a valid single\n * address is ever used.\n */\n replyTo?: string | ((input: EmailRenderInput) => string | null | undefined) | undefined;\n /** Builds the subject and bodies. Defaults to `renderEmail`. The subject is sanitized afterwards either way. */\n render?: ((input: EmailRenderInput) => EmailContent) | undefined;\n /** Sensitive fields: `\"mask\"` (default), `\"omit\"` or `\"include\"`. */\n sensitive?: RowOptions[\"sensitive\"];\n}\n\n/** Resend allows 50 recipients per email. */\nexport const MAX_RECIPIENTS = 50;\nconst MAX_SUBJECT_LENGTH = 200;\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n/**\n * A header value on one line: control characters (CR, LF, NUL…) and Unicode\n * line separators become spaces, runs of spaces collapse, and it is cut to\n * `max` characters.\n */\nexport function headerSafe(text: string, max = MAX_SUBJECT_LENGTH): string {\n // eslint-disable-next-line no-control-regex\n const flat = text.replace(/[\\u0000-\\u001f\\u007f\\u2028\\u2029]+/g, \" \").replace(/\\s+/g, \" \").trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\n/** A bare address that is safe as a header value: valid, one line, no display name. */\nexport function isSafeAddress(value: unknown): value is string {\n return typeof value === \"string\" && isEmailAddress(value) && !/[\\u0000-\\u001f\\u007f<>,;:\"()[\\]\\\\]/.test(value);\n}\n\n/**\n * A From value: a bare address, or `Name <address>` where the name has no\n * quotes, angle brackets or line breaks.\n */\nexport function isSafeFrom(value: string): boolean {\n const named = /^([^\"<>\\u0000-\\u001f\\u007f]{1,100}) <([^<>]+)>$/.exec(value);\n return named ? isSafeAddress(named[2]) : isSafeAddress(value);\n}\n\n/** Plain text and HTML bodies from label/value lines, every value escaped. */\nexport function emailBody(lines: readonly (readonly [string, Cell])[], footer?: string): { text: string; html: string } {\n const text = lines.map(([k, v]) => `${k}: ${v}`).join(\"\\n\") + (footer ? `\\n\\n${footer}` : \"\");\n // Paragraphs rather than a table: email clients render them alike everywhere.\n const font = \"font-family:sans-serif;font-size:14px;margin:0 0 12px\";\n const html =\n lines\n .map(\n ([k, v]) =>\n `<p style=\"${font}\"><span style=\"color:#666\">${escapeHtml(k)}</span><br>` +\n `<span style=\"white-space:pre-wrap\">${escapeHtml(String(v))}</span></p>`,\n )\n .join(\"\") +\n (footer ? `<p style=\"font-family:sans-serif;font-size:12px;color:#666\">${escapeHtml(footer)}</p>` : \"\");\n return { text, html };\n}\n\n/**\n * The default notification: subject `\"<form title>: new response\"` (or\n * `config.subject`), then the meta columns, each answered field by label,\n * the ending's title when the form has several, and the response id.\n */\nexport function renderEmail(input: EmailRenderInput): EmailContent {\n const { submission, definition, config, row } = input;\n const lines: [string, Cell][] = [];\n const fieldKeys = new Set(Object.keys(row.labels));\n for (const key of row.columns) {\n if (key === \"id\") continue;\n const value = row.row[key];\n if (value === undefined || value === \"\") continue;\n const label = fieldKeys.has(key) ? row.labels[key]! : key === \"submitted_at\" ? \"Submitted\" : key;\n lines.push([label, value]);\n }\n const endings = definition.endings ?? [];\n if (submission.ending && endings.length > 1) {\n const ending = endings.find((e) => e.id === submission.ending);\n if (ending) lines.push([\"Ending\", ending.title]);\n }\n if (!lines.length) lines.push([\"Answers\", \"(none)\"]);\n const subject = configString(config, \"subject\") || `${definition.title || definition.id}: new response`;\n return { subject, ...emailBody(lines, `Response ${submission.id}`) };\n}\n\n/** Recipients from config: a string or a list, each checked. Throws when there are none or too many. */\nfunction recipients(config: DestinationConfig): string[] {\n const raw = config[\"to\"];\n const list = (Array.isArray(raw) ? raw : typeof raw === \"string\" ? raw.split(\",\") : []).map((t) =>\n typeof t === \"string\" ? t.trim() : t,\n );\n const to = [...new Set(list.filter(isSafeAddress))];\n if (to.length !== list.filter((t) => t !== \"\").length) {\n throw new DeliveryError(\"The email destination has an invalid recipient\");\n }\n if (!to.length) throw new DeliveryError(\"The email destination has no recipients\");\n if (to.length > MAX_RECIPIENTS) throw new DeliveryError(`The email destination has more than ${MAX_RECIPIENTS} recipients`);\n return to;\n}\n\nfunction replyToAddress(option: EmailDestinationOptions[\"replyTo\"], input: EmailRenderInput): string | undefined {\n if (!option) return undefined;\n let value: unknown;\n if (typeof option === \"function\") value = option(input);\n else {\n const field = input.definition.blocks.find((b) => b.kind === \"field\" && b.key === option);\n value = field ? own(input.submission.answers, field.id) : undefined;\n // An anonymous form never gives away an identifying answer, not even as Reply-To.\n if (field?.kind === \"field\" && field.identifying && input.definition.settings?.anonymous) value = undefined;\n }\n const trimmed = typeof value === \"string\" ? value.trim() : value;\n return isSafeAddress(trimmed) ? trimmed : undefined;\n}\n\n/**\n * The idempotency key: the delivery id and the first 16 hex digits of\n * SHA-256 of the sorted recipients, so a retried delivery never sends twice\n * and one whose recipients changed meanwhile is a new send.\n */\nexport async function idempotencyKey(deliveryId: string, to: readonly string[]): Promise<string> {\n const hex = await sha256Hex([...to].sort().join(\",\"));\n return `${deliveryId.slice(0, 200)}:${hex.slice(0, 16)}`;\n}\n\nexport function emailDestination(options: EmailDestinationOptions): Destination {\n return {\n kind: \"email\",\n async deliver(submission, definition, config, deliveryOptions: DeliveryOptions = {}): Promise<DeliveryResult> {\n try {\n if (!isSafeFrom(options.from)) throw new DeliveryError(\"The email destination's from address is invalid\");\n const to = recipients(config);\n const row = responseRow(submission, definition, { sensitive: options.sensitive ?? \"mask\" });\n const input: EmailRenderInput = { submission, definition, config, row };\n const content = (options.render ?? renderEmail)(input);\n const replyTo = replyToAddress(options.replyTo, input);\n await options.provider.send(\n {\n from: options.from,\n to,\n ...(replyTo ? { replyTo } : {}),\n subject: headerSafe(content.subject) || \"New response\",\n text: content.text,\n html: content.html,\n idempotencyKey: await idempotencyKey(deliveryOptions.deliveryId ?? submission.id, to),\n },\n { signal: deliveryOptions.signal },\n );\n return { ok: true };\n } catch (error) {\n return deliveryFailure(error);\n }\n },\n };\n}\n\nexport const RESEND_API = \"https://api.resend.com/emails\";\n\nexport interface ResendOptions extends HttpDeps {\n apiKey: string;\n /** Default `RESEND_API`. */\n endpoint?: string | undefined;\n}\n\n/**\n * Resend's REST API. Sends the idempotency key, so a retry within Resend's\n * 24-hour window never sends twice. A 409 for a concurrent request with the\n * same key is retried; one for a key reused with a different body is not.\n */\nexport function resendProvider(options: ResendOptions): EmailProvider {\n return {\n name: \"resend\",\n async send(message, { signal }) {\n if (!options.apiKey) throw new DeliveryError(\"The Resend API key is not set\");\n const response = await timedFetch(\n options,\n options.endpoint ?? RESEND_API,\n {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${options.apiKey}`,\n \"content-type\": \"application/json\",\n \"idempotency-key\": message.idempotencyKey,\n },\n body: JSON.stringify({\n from: message.from,\n to: message.to,\n subject: message.subject,\n text: message.text,\n html: message.html,\n ...(message.replyTo ? { reply_to: message.replyTo } : {}),\n }),\n },\n signal,\n );\n if (response.ok) {\n discard(response);\n return;\n }\n // Resend's error `name` (such as \"validation_error\") is safe to keep; its message may echo input.\n let name: string | undefined;\n try {\n const body = (await response.json()) as { name?: unknown };\n if (typeof body.name === \"string\" && /^[a-z_]{1,64}$/.test(body.name)) name = body.name;\n } catch {\n // Not JSON.\n }\n if (response.status === 409 && name === \"concurrent_idempotent_requests\") {\n throw new DeliveryError(\"Resend answered 409 (concurrent_idempotent_requests)\", {\n retryable: true,\n retryAfterSeconds: 5,\n status: 409,\n });\n }\n throw httpError(\"Resend\", response, name);\n },\n };\n}\n","/**\n * An access token for a Google service account by the OAuth 2.0 JWT bearer\n * flow: sign a JWT with the account's private key (RS256, WebCrypto) and\n * trade it at Google's token endpoint. No googleapis dependency, so it runs\n * on Node 20+, edge runtimes and Workers alike.\n */\nimport {\n base64url,\n DeliveryError,\n discard,\n fromBase64,\n httpError,\n sha256Hex,\n timedFetch,\n type HttpDeps,\n type WebCryptoKey,\n} from \"./types\";\n\nexport const GOOGLE_TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nexport const SHEETS_SCOPE = \"https://www.googleapis.com/auth/spreadsheets\";\n\nexport interface GoogleServiceAccount {\n /** The service account's `client_email`. */\n clientEmail: string;\n /** Its `private_key`: a PKCS#8 PEM. The `\\n`-escaped form env vars often hold is accepted. */\n privateKey: string;\n}\n\n/** The PKCS#8 key bytes from a PEM. */\nfunction pemToPkcs8(pem: string): Uint8Array<ArrayBuffer> {\n const text = pem.replace(/\\\\n/g, \"\\n\");\n if (/-----BEGIN RSA PRIVATE KEY-----/.test(text)) {\n throw new DeliveryError(\"The Google private key is PKCS#1; convert it to PKCS#8 (BEGIN PRIVATE KEY)\");\n }\n const body = text.replace(/-----(BEGIN|END) PRIVATE KEY-----/g, \"\").replace(/\\s+/g, \"\");\n return fromBase64(body);\n}\n\n/** A signed RS256 JWT. Throws a `DeliveryError` when the key is not a valid PKCS#8 RSA key. */\nexport async function signJwt(claims: Record<string, unknown>, privateKeyPem: string): Promise<string> {\n let key: WebCryptoKey;\n try {\n key = await crypto.subtle.importKey(\n \"pkcs8\",\n pemToPkcs8(privateKeyPem),\n { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n } catch (error) {\n if (error instanceof DeliveryError) throw error;\n // Never the key or the platform's message, which may quote it.\n throw new DeliveryError(\"The Google private key is not a valid PKCS#8 RSA key\");\n }\n const unsigned = `${base64url(JSON.stringify({ alg: \"RS256\", typ: \"JWT\" }))}.${base64url(JSON.stringify(claims))}`;\n const signature = await crypto.subtle.sign(\"RSASSA-PKCS1-v1_5\", key, new TextEncoder().encode(unsigned));\n return `${unsigned}.${base64url(new Uint8Array(signature))}`;\n}\n\n// One per process, shared by every destination: a token is good for an hour.\nconst cache = new Map<string, { token: string; expiresAt: number }>();\n\n/** Forgets cached tokens (tests, or after rotating a key). */\nexport function clearGoogleTokenCache(): void {\n cache.clear();\n}\n\nexport interface GoogleTokenOptions extends HttpDeps {\n scope?: string | undefined;\n now?: (() => number) | undefined;\n signal?: AbortSignal | undefined;\n}\n\n/** A cached or fresh access token. Throws a `DeliveryError` with a safe message on failure. */\nexport async function googleAccessToken(account: GoogleServiceAccount, options: GoogleTokenOptions = {}): Promise<string> {\n const { clientEmail, privateKey } = account;\n if (!clientEmail || !privateKey) throw new DeliveryError(\"The Google service account email or private key is not set\");\n const scope = options.scope ?? SHEETS_SCOPE;\n const now = options.now?.() ?? Date.now();\n // The key's digest is part of the cache key: a hit returns a token without\n // signing anything, so email + scope alone would hand one tenant's live\n // token to any config naming that email with any key, and keep a rotated\n // or wrong key working until the token expires.\n const cacheKey = `${clientEmail} ${scope} ${await sha256Hex(privateKey.replace(/\\\\n/g, \"\\n\").trim())}`;\n const hit = cache.get(cacheKey);\n if (hit && hit.expiresAt - 60_000 > now) return hit.token;\n\n const iat = Math.floor(now / 1000);\n const assertion = await signJwt({ iss: clientEmail, scope, aud: GOOGLE_TOKEN_URL, iat, exp: iat + 3600 }, privateKey);\n const response = await timedFetch(\n options,\n GOOGLE_TOKEN_URL,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({ grant_type: \"urn:ietf:params:oauth:grant-type:jwt-bearer\", assertion }).toString(),\n },\n options.signal,\n );\n if (!response.ok) {\n discard(response);\n throw httpError(\"Google token endpoint\", response);\n }\n const body = (await response.json()) as { access_token?: unknown; expires_in?: unknown };\n if (typeof body.access_token !== \"string\") throw new DeliveryError(\"Google token endpoint returned no access token\", { retryable: true });\n const ttl = typeof body.expires_in === \"number\" ? body.expires_in * 1000 : 3_600_000;\n cache.set(cacheKey, { token: body.access_token, expiresAt: now + ttl });\n return body.access_token;\n}\n","/**\n * The Google Sheets destination: appends one row per submission to a sheet\n * shared with a Google service account. Config: `{ spreadsheetId,\n * sheetName? }` (`spreadsheet_id` and `sheet_name` are accepted too).\n *\n * The tab is created when missing, the header row is written from the row's\n * column keys and gains a column for any new key without moving the others,\n * and an `id` column holds the response id, so a redelivery is not appended\n * twice. Every write is `valueInputOption=RAW`, so Sheets stores text as\n * typed and never runs it as a formula: `@team thanks` stays exactly that.\n * Text is therefore not escaped by default (a `'` would be stored literally).\n * Set `escapeFormulas` only when the sheet's text is exported and opened in\n * another spreadsheet that might run it (see `escapeFormula`).\n *\n * Quota: Google allows a service account about 60 reads and 60 writes a\n * minute. So the tab id, header and last row are kept in the destination's\n * state, and a normal delivery is one write: the append. The tab and header\n * are read again only when a row has a key the cached header lacks, or when\n * an append is refused. The id column is read only on a redelivery, and then\n * only its recent rows. `deliverBatch` appends many rows in one request.\n */\nimport type { Json } from \"../types\";\nimport { googleAccessToken, type GoogleServiceAccount } from \"./google-auth\";\nimport { escapeFormula, responseRow, type RowOptions } from \"./row\";\nimport {\n configString,\n deliveryFailure,\n DeliveryError,\n discard,\n httpError,\n resolveOption,\n timedFetch,\n type Cell,\n type DeliveryItem,\n type DeliveryOptions,\n type DeliveryResult,\n type Destination,\n type DestinationConfig,\n type HttpDeps,\n} from \"./types\";\n\nexport const SHEETS_API = \"https://sheets.googleapis.com/v4/spreadsheets\";\nexport const DEFAULT_SHEET_NAME = \"Responses\";\n/** How many of the latest rows a redelivery checks for its id. */\nexport const DEDUPE_WINDOW = 500;\n/**\n * How many rows the header read looks at to find the columns in use: the\n * header row and the first responses under it. Bounded, so a tab with years\n * of responses is never read whole just to learn its header.\n */\nexport const HEADER_SCAN_ROWS = 100;\n/** Header writes tried before a concurrent writer is reported as a retryable failure. */\nconst HEADER_WRITE_ATTEMPTS = 3;\n\n/** What the sheet destination reads from a destination's config. */\nexport interface SheetConfig {\n spreadsheetId: string;\n /** Default `\"Responses\"`. */\n sheetName?: string;\n}\n\nexport interface SheetsDestinationOptions extends HttpDeps {\n /** The service account, or a function that finds the one for a destination's config. */\n account: GoogleServiceAccount | ((config: DestinationConfig) => GoogleServiceAccount | Promise<GoogleServiceAccount>);\n /**\n * Prefix text a spreadsheet could run as a formula with `'` (see\n * `escapeFormula`), headers included. Default false: writes are RAW, so\n * Sheets never runs text as a formula, and the `'` would be stored as part\n * of the text. Turn it on only if the sheet is exported as CSV and opened\n * in another spreadsheet. Keep one setting per sheet: header keys are\n * escaped too, so switching it later adds new columns for escaped keys.\n */\n escapeFormulas?: boolean | undefined;\n /** Sensitive fields: `\"include\"` (default), `\"mask\"` or `\"omit\"`. */\n sensitive?: RowOptions[\"sensitive\"];\n now?: (() => number) | undefined;\n}\n\n/**\n * The existing header plus any keys it does not have yet, in the order they\n * arrive. A blank header cell keeps its place (dropping it would shift every\n * later column away from the values stored under it), as do blank header\n * cells over the `width` columns that hold responses; only blanks beyond\n * those are trimmed.\n */\nexport function mergeHeader(existing: readonly unknown[], keys: readonly string[], width = 0): string[] {\n const header = existing.map((h) => (h == null ? \"\" : String(h)));\n while (header.length < width) header.push(\"\");\n while (header.length > width && header[header.length - 1] === \"\") header.pop();\n for (const key of keys) if (key && !header.includes(key)) header.push(key);\n return header;\n}\n\n/** One cell per header column, blank where the row has no value; `escape` applies `escapeFormula` (default false). */\nexport function rowFor(header: readonly string[], row: Record<string, Cell>, escape = false): Cell[] {\n return header.map((h) => {\n const cell = Object.prototype.hasOwnProperty.call(row, h) ? (row[h] ?? \"\") : \"\";\n return escape ? escapeFormula(cell) : cell;\n });\n}\n\n/** A1 column letters: 0 → A, 25 → Z, 26 → AA. */\nexport function columnLetter(index: number): string {\n let n = index + 1;\n let s = \"\";\n while (n > 0) {\n const r = (n - 1) % 26;\n s = String.fromCharCode(65 + r) + s;\n n = Math.floor((n - 1) / 26);\n }\n return s;\n}\n\nconst quoteSheet = (name: string) => `'${name.replace(/'/g, \"''\")}'`;\n\n/** What the destination keeps between deliveries. Opaque to the app: store and pass it back. */\nexport interface SheetState {\n spreadsheet_id: string;\n sheet_name: string;\n sheet_id: number;\n header: string[];\n columns: number;\n /** The last row an append wrote (1-based), 0 when unknown. */\n last_row: number;\n}\n\nfunction readState(raw: Record<string, Json> | undefined, spreadsheetId: string, sheetName: string): SheetState | null {\n if (!raw) return null;\n const header = raw[\"header\"];\n if (\n raw[\"spreadsheet_id\"] !== spreadsheetId ||\n raw[\"sheet_name\"] !== sheetName ||\n typeof raw[\"sheet_id\"] !== \"number\" ||\n !Array.isArray(header) ||\n !header.every((h) => typeof h === \"string\") ||\n !header.includes(\"id\")\n ) {\n return null;\n }\n return {\n spreadsheet_id: spreadsheetId,\n sheet_name: sheetName,\n sheet_id: raw[\"sheet_id\"],\n header: header as string[],\n columns: typeof raw[\"columns\"] === \"number\" ? raw[\"columns\"] : header.length,\n last_row: typeof raw[\"last_row\"] === \"number\" ? raw[\"last_row\"] : 0,\n };\n}\n\n/** An append Google refused for a reason a fresh look at the tab may fix (renamed, deleted or resized). */\nclass StaleSheetError extends DeliveryError {}\n\ninterface SheetProps {\n sheetId: number;\n title: string;\n gridProperties?: { columnCount?: number };\n}\n\nfunction configOf(config: DestinationConfig) {\n const spreadsheetId = configString(config, \"spreadsheetId\", \"spreadsheet_id\");\n if (!spreadsheetId) throw new DeliveryError(\"The sheet destination has no spreadsheetId\");\n if (!/^[A-Za-z0-9_-]{10,200}$/.test(spreadsheetId)) throw new DeliveryError(\"The sheet destination's spreadsheetId is invalid\");\n const sheetName = configString(config, \"sheetName\", \"sheet_name\") || DEFAULT_SHEET_NAME;\n if (sheetName.length > 100) throw new DeliveryError(\"The sheet destination's sheetName is too long\");\n return { spreadsheetId, sheetName };\n}\n\nexport function sheetsDestination(options: SheetsDestinationOptions): Destination {\n async function run(\n items: readonly DeliveryItem[],\n config: DestinationConfig,\n deliveryOptions: Omit<DeliveryOptions, \"deliveryId\">,\n ): Promise<DeliveryResult> {\n if (!items.length) return { ok: true };\n const { spreadsheetId, sheetName } = configOf(config);\n const account = await resolveOption(\"The sheet destination's account\", options.account, config);\n const signal = deliveryOptions.signal;\n const token = await googleAccessToken(account, { ...options, signal });\n const base = `${SHEETS_API}/${encodeURIComponent(spreadsheetId)}`;\n const escape = options.escapeFormulas === true;\n\n const call = async <T>(what: string, url: string, init: RequestInit = {}): Promise<T> => {\n const response = await timedFetch(\n options,\n url,\n { ...init, headers: { authorization: `Bearer ${token}`, \"content-type\": \"application/json\" } },\n signal,\n );\n if (!response.ok) {\n discard(response);\n if (what === \"append\" && (response.status === 400 || response.status === 404)) {\n throw new StaleSheetError(`Google Sheets append answered ${response.status}`, { status: response.status });\n }\n if (response.status === 403 || response.status === 404) {\n throw new DeliveryError(\n `Google Sheets ${what} answered ${response.status}: is the sheet shared with ${account.clientEmail}?`,\n { status: response.status },\n );\n }\n throw httpError(`Google Sheets ${what}`, response);\n }\n return (await response.json()) as T;\n };\n const batchUpdate = (what: string, requests: unknown[]) =>\n call<{ replies?: { addSheet?: { properties?: SheetProps } }[] }>(what, `${base}:batchUpdate`, {\n method: \"POST\",\n body: JSON.stringify({ requests }),\n });\n const range = (a1: string) => `${base}/values/${encodeURIComponent(`${quoteSheet(sheetName)}!${a1}`)}`;\n\n const sensitive = options.sensitive ?? \"include\";\n // Column keys are escaped like cells (a builder-made key could start with \"=\"),\n // so the header as stored and read back matches the keys looked up in it.\n const columnKey = (key: string) => (escape ? String(escapeFormula(key)) : key);\n const rows = items.map((item) => {\n const { row, columns } = responseRow(item.submission, item.definition, { sensitive });\n const escaped: Record<string, Cell> = {};\n for (const key of columns) escaped[columnKey(key)] = row[key]!;\n return { row: escaped, columns: columns.map(columnKey) };\n });\n const keys = [...new Set(rows.flatMap((r) => r.columns))];\n\n /** Reads the tab and header, adds what is missing, and returns the fresh state. */\n async function setUp(previous: SheetState | null): Promise<SheetState> {\n const readTabs = async () => {\n const meta = await call<{ sheets?: { properties?: SheetProps }[] }>(\n \"read\",\n `${base}?fields=${encodeURIComponent(\"sheets.properties(sheetId,title,gridProperties.columnCount)\")}`,\n );\n return meta.sheets?.map((s) => s.properties).find((p) => p?.title === sheetName);\n };\n let sheet = await readTabs();\n if (!sheet) {\n try {\n const added = await batchUpdate(\"add tab\", [{ addSheet: { properties: { title: sheetName } } }]);\n sheet = added.replies?.[0]?.addSheet?.properties ?? { sheetId: 0, title: sheetName };\n } catch (error) {\n // Two first deliveries race: both saw no tab, and the loser's\n // addSheet answers 400 (\"already exists\"). Use the winner's tab.\n if (!(error instanceof DeliveryError) || error.status !== 400) throw error;\n sheet = await readTabs();\n if (!sheet) throw error;\n }\n }\n // Read by column: the values API drops trailing blank cells, so the header\n // row alone can look narrower than the responses under it (a column added\n // by hand). Column by column, the number returned is the width in use.\n const readHeader = async () => {\n const read = await call<{ values?: unknown[][] }>(\n \"read header\",\n `${range(`A1:ZZZ${HEADER_SCAN_ROWS}`)}?majorDimension=COLUMNS`,\n );\n const used = read.values ?? [];\n return { used: used.length, existing: used.map((column) => column[0] ?? \"\") };\n };\n let columns = sheet.gridProperties?.columnCount ?? 26;\n let { used, existing } = await readHeader();\n let header: string[] = [];\n // The header row is written whole, so two deliveries merging different\n // keys at once can overwrite each other. After a write, read it back: if\n // a key of ours is missing, merge onto what is there and write again.\n // The state keeps the header as read, so rows map onto the real columns.\n for (let attempt = 0; ; attempt++) {\n header = mergeHeader(existing, keys, used);\n // A new tab starts with the id column; one already in use gets it at the\n // end, so the columns already holding responses don't move.\n if (!header.includes(\"id\")) {\n if (used) header.push(\"id\");\n else header.unshift(\"id\");\n }\n const changed = header.length !== existing.length || header.some((h, i) => h !== String(existing[i] ?? \"\"));\n if (!changed) break;\n if (attempt >= HEADER_WRITE_ATTEMPTS) {\n throw new DeliveryError(\"Google Sheets header kept changing while it was written\", { retryable: true });\n }\n if (header.length > columns) {\n await batchUpdate(\"add columns\", [\n { appendDimension: { sheetId: sheet.sheetId, dimension: \"COLUMNS\", length: header.length - columns } },\n ]);\n columns = header.length;\n }\n await call(\"write header\", `${range(\"A1\")}?valueInputOption=RAW`, {\n method: \"PUT\",\n body: JSON.stringify({ values: [header] }),\n });\n if (existing.length === 0) {\n await batchUpdate(\"freeze header\", [\n {\n updateSheetProperties: {\n properties: { sheetId: sheet.sheetId, gridProperties: { frozenRowCount: 1 } },\n fields: \"gridProperties.frozenRowCount\",\n },\n },\n ]);\n }\n ({ used, existing } = await readHeader());\n }\n return {\n spreadsheet_id: spreadsheetId,\n sheet_name: sheetName,\n sheet_id: sheet.sheetId,\n header,\n columns,\n last_row: previous?.last_row ?? 0,\n };\n }\n\n let skipped: string[] = [];\n async function append(state: SheetState): Promise<SheetState> {\n // A redelivery may find its row already there: an earlier append went\n // through even though Google answered 5xx or the request timed out.\n let pending = items.map((item, i) => ({ id: item.submission.id, row: rows[i]!.row }));\n if (deliveryOptions.redelivery) {\n const column = columnLetter(state.header.indexOf(\"id\"));\n const from = state.last_row > 0 ? Math.max(2, state.last_row - DEDUPE_WINDOW) : 2;\n const ids = await call<{ values?: unknown[][] }>(\"read ids\", range(`${column}${from}:${column}`));\n const present = new Set((ids.values ?? []).map((r) => String(r?.[0] ?? \"\")));\n skipped = pending.filter((p) => present.has(p.id)).map((p) => p.id);\n pending = pending.filter((p) => !present.has(p.id));\n }\n if (!pending.length) return state;\n const result = await call<{ updates?: { updatedRange?: string } }>(\n \"append\",\n `${range(\"A1\")}:append?valueInputOption=RAW&insertDataOption=INSERT_ROWS`,\n { method: \"POST\", body: JSON.stringify({ values: pending.map((p) => rowFor(state.header, p.row, escape)) }) },\n );\n const last = /![A-Z]+\\d+:[A-Z]+(\\d+)$/.exec(result.updates?.updatedRange ?? \"\")?.[1];\n return { ...state, last_row: last ? Number(last) : state.last_row + pending.length };\n }\n\n const cached = readState(deliveryOptions.state, spreadsheetId, sheetName);\n const fresh = !cached || keys.some((k) => !cached.header.includes(k));\n let state = fresh ? await setUp(cached) : cached;\n try {\n state = await append(state);\n } catch (error) {\n if (!(error instanceof StaleSheetError) || fresh) throw error;\n state = await append(await setUp(cached));\n }\n return {\n ok: true,\n state: state as unknown as Record<string, Json>,\n ...(skipped.length ? { skipped } : {}),\n };\n }\n\n const guarded = async (...args: Parameters<typeof run>): Promise<DeliveryResult> => {\n try {\n return await run(...args);\n } catch (error) {\n return deliveryFailure(error);\n }\n };\n\n return {\n kind: \"sheet\",\n deliver: (submission, definition, config, deliveryOptions = {}) =>\n guarded([{ submission, definition, deliveryId: deliveryOptions.deliveryId }], config, deliveryOptions),\n deliverBatch: (items, config, deliveryOptions = {}) => guarded(items, config, deliveryOptions),\n };\n}\n","/**\n * The webhook destination: a signed JSON POST to a URL, following the\n * Standard Webhooks spec (standardwebhooks.com), so receivers can verify it\n * with any Standard Webhooks library, or with `verifyWebhook` here.\n *\n * Headers: `webhook-id` (the delivery id, stable across retries: receivers\n * dedupe on it), `webhook-timestamp` (Unix seconds) and `webhook-signature`\n * (`v1,<base64 HMAC-SHA256 of \"<id>.<timestamp>.<body>\">`). Receivers reject\n * a timestamp more than five minutes off, which stops replays.\n *\n * The URL comes from config, which an admin may type, so by default it must\n * be https, carry no credentials, and not name localhost or a private,\n * loopback or link-local address literally. Redirects are not followed. A\n * hostname that resolves to a private address is not caught here: if\n * untrusted users choose URLs, send from a network that cannot reach\n * internal services.\n */\nimport { own, withheld } from \"../logic\";\nimport { isSensitive } from \"../fields\";\nimport type { FieldBlock, FormDefinition, Json } from \"../types\";\nimport { responseRow, visibleInputs, type RowOptions } from \"./row\";\nimport {\n base64,\n configString,\n deliveryFailure,\n DeliveryError,\n discard,\n fromBase64,\n httpError,\n resolveOption,\n timedFetch,\n type DeliveryOptions,\n type DeliveryResult,\n type DeliverySubmission,\n type Destination,\n type DestinationConfig,\n type HttpDeps,\n type WebCryptoKey,\n} from \"./types\";\n\n/** What the webhook destination reads from a destination's config. */\nexport interface WebhookConfig {\n url: string;\n}\n\nexport interface WebhookDestinationOptions extends HttpDeps {\n /**\n * The signing secret: base64 of at least 16 random bytes, usually with\n * the `whsec_` prefix Standard Webhooks tools issue (`whsec_` plus base64\n * of 24 to 64 bytes is what the spec recommends). The prefix is optional;\n * the rest is always base64-decoded, as every Standard Webhooks library\n * does, so a receiver verifies with the same string. A secret that is not\n * base64 fails permanently. Or a function that finds the one for a\n * destination's config. Never put it in config.\n */\n secret: string | ((config: DestinationConfig) => string | Promise<string>);\n /** Allow `http:` URLs. Default false. */\n allowInsecureUrls?: boolean | undefined;\n /** Allow localhost and private, loopback and link-local address literals. Default false. */\n allowPrivateHosts?: boolean | undefined;\n /** Sensitive fields: `\"include\"` (default), `\"mask\"` or `\"omit\"`. */\n sensitive?: RowOptions[\"sensitive\"];\n /** The event type in the payload. Default `\"form.submitted\"`. */\n type?: string | undefined;\n now?: (() => number) | undefined;\n}\n\n/** The JSON body a webhook receives. */\nexport interface WebhookPayload {\n type: string;\n /** ISO time the delivery was sent. */\n timestamp: string;\n data: {\n form: { id: string; title: string };\n submission: {\n id: string;\n /** Answers keyed by field id. */\n answers: Record<string, Json>;\n hidden: Record<string, Json>;\n context: Record<string, Json>;\n ending: string | null;\n submittedAt: string | null;\n meta: Record<string, Json>;\n tags: string[];\n };\n /** The same submission as a flat row by column key: labels for choices, as the sheet shows it. */\n row: Record<string, Json>;\n };\n}\n\nconst MIN_SECRET_BYTES = 16;\nconst STRICT_BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n/**\n * The HMAC key bytes for a secret, decoded as the Standard Webhooks\n * reference libraries do: an optional `whsec_` prefix is dropped and the\n * rest is base64-decoded. Only padded standard base64 is accepted, the form\n * every reference library decodes the same way. Throws a `DeliveryError` for\n * a secret that is not base64 or is shorter than 16 bytes once decoded.\n */\nfunction secretKey(secret: string): Uint8Array<ArrayBuffer> {\n const encoded = secret.startsWith(\"whsec_\") ? secret.slice(6) : secret;\n if (!encoded || !STRICT_BASE64.test(encoded)) {\n throw new DeliveryError(\n \"The webhook secret must be base64, optionally prefixed with whsec_ (Standard Webhooks libraries base64-decode it)\",\n );\n }\n const bytes = fromBase64(encoded);\n if (bytes.length < MIN_SECRET_BYTES) throw new DeliveryError(`The webhook secret is shorter than ${MIN_SECRET_BYTES} bytes`);\n return bytes;\n}\n\nasync function hmacKey(secret: string, usage: \"sign\" | \"verify\"): Promise<WebCryptoKey> {\n return crypto.subtle.importKey(\"raw\", secretKey(secret), { name: \"HMAC\", hash: \"SHA-256\" }, false, [usage]);\n}\n\n/** The `webhook-signature` value for a message: `v1,<base64>`. */\nexport async function signWebhook(secret: string, id: string, timestamp: number, body: string): Promise<string> {\n const key = await hmacKey(secret, \"sign\");\n const mac = await crypto.subtle.sign(\"HMAC\", key, new TextEncoder().encode(`${id}.${timestamp}.${body}`));\n return `v1,${base64(new Uint8Array(mac))}`;\n}\n\nexport interface VerifyWebhookInput {\n /** The same secret the sender signs with (base64, optionally `whsec_`-prefixed). */\n secret: string;\n /** The request's headers: a `Headers` or a plain object. */\n headers: Headers | Record<string, string | string[] | undefined>;\n /** The raw body, exactly as received. */\n body: string;\n /** Default 300: a timestamp further off than this is refused. */\n toleranceSeconds?: number | undefined;\n now?: (() => number) | undefined;\n}\n\n/**\n * Checks a Standard Webhooks request: the timestamp is recent and one of the\n * space-separated `v1` signatures matches. Compares in constant time (by\n * WebCrypto `verify`). Never throws on a malformed request: returns false.\n */\nexport async function verifyWebhook(input: VerifyWebhookInput): Promise<boolean> {\n const header = (name: string): string => {\n if (typeof (input.headers as Headers).get === \"function\") return (input.headers as Headers).get(name) ?? \"\";\n const raw = (input.headers as Record<string, string | string[] | undefined>)[name];\n return Array.isArray(raw) ? (raw[0] ?? \"\") : (raw ?? \"\");\n };\n const id = header(\"webhook-id\");\n const timestamp = header(\"webhook-timestamp\");\n const signatures = header(\"webhook-signature\");\n if (!id || !/^\\d{1,12}$/.test(timestamp) || !signatures) return false;\n const now = Math.floor((input.now?.() ?? Date.now()) / 1000);\n if (Math.abs(now - Number(timestamp)) > (input.toleranceSeconds ?? 300)) return false;\n let key: WebCryptoKey;\n try {\n key = await hmacKey(input.secret, \"verify\");\n } catch {\n return false;\n }\n const data = new TextEncoder().encode(`${id}.${timestamp}.${input.body}`);\n for (const part of signatures.split(\" \")) {\n const [version, value] = part.split(\",\", 2);\n if (version !== \"v1\" || !value) continue;\n let mac: Uint8Array<ArrayBuffer>;\n try {\n mac = fromBase64(value);\n } catch {\n continue;\n }\n if (await crypto.subtle.verify(\"HMAC\", key, mac, data)) return true;\n }\n return false;\n}\n\nconst PRIVATE_HOSTNAME = /(^|\\.)(localhost|local|internal|localdomain|home\\.arpa)$/i;\n\n/** Whether a URL hostname is localhost or a private, loopback, link-local or unspecified address literal. */\nexport function isPrivateHost(hostname: string): boolean {\n const host = hostname.toLowerCase().replace(/\\.$/, \"\");\n if (PRIVATE_HOSTNAME.test(host)) return true;\n const v4 = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(host);\n if (v4) return isPrivateV4(v4.slice(1).map(Number) as [number, number, number, number]);\n if (host.startsWith(\"[\") && host.endsWith(\"]\")) {\n const v6 = host.slice(1, -1);\n if (v6 === \"::\" || v6 === \"::1\") return true;\n // IPv4-mapped (::ffff:a.b.c.d, which URL writes as ::ffff:xxxx:xxxx).\n const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(v6);\n if (mapped) {\n const hi = parseInt(mapped[1]!, 16);\n const lo = parseInt(mapped[2]!, 16);\n return isPrivateV4([hi >> 8, hi & 255, lo >> 8, lo & 255]);\n }\n const first = parseInt(v6.split(\":\")[0] || \"0\", 16);\n return (first & 0xfe00) === 0xfc00 || (first & 0xffc0) === 0xfe80; // fc00::/7, fe80::/10\n }\n return false;\n}\n\nfunction isPrivateV4([a, b]: [number, number, number, number]): boolean {\n return (\n a === 0 ||\n a === 10 ||\n a === 127 ||\n (a === 100 && b >= 64 && b <= 127) ||\n (a === 169 && b === 254) ||\n (a === 172 && b >= 16 && b <= 31) ||\n (a === 192 && b === 168) ||\n (a === 198 && (b === 18 || b === 19)) ||\n a >= 224\n );\n}\n\n/** The URL from config, checked. Throws a `DeliveryError` naming the rule it broke (never the URL, which may hold a token). */\nexport function checkWebhookUrl(\n raw: string,\n options: Pick<WebhookDestinationOptions, \"allowInsecureUrls\" | \"allowPrivateHosts\"> = {},\n): URL {\n if (!raw) throw new DeliveryError(\"The webhook destination has no url\");\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new DeliveryError(\"The webhook url is not a valid URL\");\n }\n if (url.protocol !== \"https:\" && !(options.allowInsecureUrls && url.protocol === \"http:\")) {\n throw new DeliveryError(\"The webhook url must use https\");\n }\n if (url.username || url.password) throw new DeliveryError(\"The webhook url must not contain credentials\");\n if (!options.allowPrivateHosts && isPrivateHost(url.hostname)) {\n throw new DeliveryError(\"The webhook url points at a private or local address\");\n }\n return url;\n}\n\n/** The payload for one submission. Identifying answers stay out on anonymous forms. */\nexport function webhookPayload(\n submission: DeliverySubmission,\n definition: FormDefinition,\n options: { sensitive?: RowOptions[\"sensitive\"]; type?: string | undefined; now?: number | undefined } = {},\n): WebhookPayload {\n const sensitive = options.sensitive ?? \"include\";\n const { row } = responseRow(submission, definition, { sensitive });\n const answers: Record<string, Json> = {};\n for (const block of definition.blocks) {\n if (block.kind !== \"field\") continue;\n const field = block as FieldBlock;\n const value = own(submission.answers, field.id);\n if (value === undefined || withheld(definition, field)) continue;\n if (isSensitive(field) && sensitive !== \"include\") {\n if (sensitive === \"mask\") answers[field.id] = \"[sensitive]\";\n continue;\n }\n answers[field.id] = value;\n }\n const inputs = visibleInputs(submission, definition, sensitive);\n const pick = (source: Record<string, Json> | undefined, allowed: Record<string, Json>) => {\n const out: Record<string, Json> = {};\n for (const [name, value] of Object.entries(source ?? {})) if (own(allowed, name) !== undefined) out[name] = value;\n return out;\n };\n return {\n type: options.type ?? \"form.submitted\",\n timestamp: new Date(options.now ?? Date.now()).toISOString(),\n data: {\n form: { id: definition.id, title: definition.title },\n submission: {\n id: submission.id,\n answers,\n hidden: pick(submission.hidden, inputs),\n context: pick(submission.context, inputs),\n ending: submission.ending ?? null,\n submittedAt: submission.submittedAt ?? null,\n meta: { ...submission.meta },\n tags: [...(submission.tags ?? [])],\n },\n row,\n },\n };\n}\n\nexport function webhookDestination(options: WebhookDestinationOptions): Destination {\n return {\n kind: \"webhook\",\n async deliver(submission, definition, config, deliveryOptions: DeliveryOptions = {}): Promise<DeliveryResult> {\n try {\n const url = checkWebhookUrl(configString(config, \"url\"), options);\n const secret = await resolveOption(\"The webhook secret\", options.secret, config);\n if (!secret) throw new DeliveryError(\"The webhook secret is not set\");\n const now = options.now?.() ?? Date.now();\n const id = deliveryOptions.deliveryId ?? submission.id;\n const timestamp = Math.floor(now / 1000);\n const body = JSON.stringify(\n webhookPayload(submission, definition, { sensitive: options.sensitive, type: options.type, now }),\n );\n const response = await timedFetch(\n options,\n url.toString(),\n {\n method: \"POST\",\n redirect: \"manual\",\n headers: {\n \"content-type\": \"application/json\",\n \"user-agent\": \"genesis-forms-webhook/1\",\n \"webhook-id\": id,\n \"webhook-timestamp\": String(timestamp),\n \"webhook-signature\": await signWebhook(secret, id, timestamp, body),\n },\n body,\n },\n deliveryOptions.signal,\n );\n discard(response);\n if (response.status >= 200 && response.status < 300) return { ok: true };\n // `redirect: \"manual\"` gives a 3xx (or, in browsers, an opaque status 0).\n if (response.status === 0 || (response.status >= 300 && response.status < 400)) {\n throw new DeliveryError(`Webhook answered ${response.status || \"a redirect\"}: redirects are not followed`, {\n ...(response.status ? { status: response.status } : {}),\n });\n }\n throw httpError(\"Webhook\", response);\n } catch (error) {\n return deliveryFailure(error);\n }\n },\n };\n}\n"]}
|