grist-widget-sdk 0.3.26 → 0.4.0
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/CHANGELOG.md +53 -0
- package/README.md +1 -1
- package/dist/app.cjs +1139 -4336
- package/dist/app.cjs.map +1 -1
- package/dist/app.d.cts +1 -3
- package/dist/app.d.ts +1 -3
- package/dist/app.js +9 -517
- package/dist/app.js.map +1 -1
- package/dist/chunk-4ZGVKGDF.js +204 -0
- package/dist/chunk-4ZGVKGDF.js.map +1 -0
- package/dist/{chunk-YQNMIL33.js → chunk-B5ZZNLVS.js} +528 -181
- package/dist/chunk-B5ZZNLVS.js.map +1 -0
- package/dist/chunk-O7NY46QY.js +1830 -0
- package/dist/chunk-O7NY46QY.js.map +1 -0
- package/dist/chunk-P6VTEKWO.js +618 -0
- package/dist/chunk-P6VTEKWO.js.map +1 -0
- package/dist/emulator/testing.cjs +2084 -391
- package/dist/emulator/testing.cjs.map +1 -1
- package/dist/emulator/testing.d.cts +55 -7
- package/dist/emulator/testing.d.ts +55 -7
- package/dist/emulator/testing.js +144 -19
- package/dist/emulator/testing.js.map +1 -1
- package/dist/emulator.cjs +59 -249
- package/dist/emulator.cjs.map +1 -1
- package/dist/emulator.d.cts +3 -5
- package/dist/emulator.d.ts +3 -5
- package/dist/emulator.js +5 -11
- package/dist/index.cjs +1373 -4859
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -260
- package/dist/index.d.ts +81 -260
- package/dist/index.js +8 -161
- package/dist/{inline-C7DkvuET.d.cts → templates-CGmRIQBV.d.cts} +89 -35
- package/dist/{inline-DpcT8tV9.d.ts → templates-Cq94qOcf.d.ts} +89 -35
- package/dist/{types-D3JxUCfL.d.cts → types-DBStn0Dk.d.cts} +2 -26
- package/dist/{types-D3JxUCfL.d.ts → types-DBStn0Dk.d.ts} +2 -26
- package/dist/use-grist-BK0eke9K.d.cts +358 -0
- package/dist/use-grist-C5DMZ3wU.d.ts +358 -0
- package/package.json +8 -37
- package/dist/advanced.cjs +0 -2799
- package/dist/advanced.cjs.map +0 -1
- package/dist/advanced.d.cts +0 -822
- package/dist/advanced.d.ts +0 -822
- package/dist/advanced.js +0 -875
- package/dist/advanced.js.map +0 -1
- package/dist/chunk-22U7WAY3.js +0 -463
- package/dist/chunk-22U7WAY3.js.map +0 -1
- package/dist/chunk-64SVRWW7.js +0 -758
- package/dist/chunk-64SVRWW7.js.map +0 -1
- package/dist/chunk-ELGVOHFD.js +0 -32
- package/dist/chunk-ELGVOHFD.js.map +0 -1
- package/dist/chunk-EPEBKXVN.js +0 -470
- package/dist/chunk-EPEBKXVN.js.map +0 -1
- package/dist/chunk-GTTD5HPO.js +0 -36
- package/dist/chunk-GTTD5HPO.js.map +0 -1
- package/dist/chunk-JASMM2YC.js +0 -243
- package/dist/chunk-JASMM2YC.js.map +0 -1
- package/dist/chunk-N3X46JW2.js +0 -37
- package/dist/chunk-N3X46JW2.js.map +0 -1
- package/dist/chunk-PDGEZ24B.js +0 -2366
- package/dist/chunk-PDGEZ24B.js.map +0 -1
- package/dist/chunk-PM3B4WYV.js +0 -12
- package/dist/chunk-PM3B4WYV.js.map +0 -1
- package/dist/chunk-REV5AUXD.js +0 -25
- package/dist/chunk-REV5AUXD.js.map +0 -1
- package/dist/chunk-TZB3OZA6.js +0 -1630
- package/dist/chunk-TZB3OZA6.js.map +0 -1
- package/dist/chunk-YQNMIL33.js.map +0 -1
- package/dist/create-grist-emulator-BCqp1BF9.d.ts +0 -81
- package/dist/create-grist-emulator-DBM8OSIR.d.cts +0 -81
- package/dist/emulator/devtools.cjs +0 -1404
- package/dist/emulator/devtools.cjs.map +0 -1
- package/dist/emulator/devtools.d.cts +0 -48
- package/dist/emulator/devtools.d.ts +0 -48
- package/dist/emulator/devtools.js +0 -508
- package/dist/emulator/devtools.js.map +0 -1
- package/dist/emulator/transports.cjs +0 -1132
- package/dist/emulator/transports.cjs.map +0 -1
- package/dist/emulator/transports.d.cts +0 -38
- package/dist/emulator/transports.d.ts +0 -38
- package/dist/emulator/transports.js +0 -12
- package/dist/emulator/transports.js.map +0 -1
- package/dist/templates-8k2LKoO-.d.cts +0 -24
- package/dist/templates-DIwi_mvI.d.ts +0 -24
- package/dist/use-grist-reads-DUMvJgV7.d.ts +0 -480
- package/dist/use-grist-reads-DpjVuI0H.d.cts +0 -480
- package/dist/use-grist-types-DdOLEJXN.d.cts +0 -499
- package/dist/use-grist-types-kwxoFeub.d.ts +0 -499
- package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.cts +0 -43
- package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.ts +0 -43
package/dist/emulator.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/emulator/index.ts","../src/emulator/api/command-api.ts","../src/emulator/core/mappings.ts","../src/emulator/api/custom-section-api.ts","../src/emulator/api/grist-api.ts","../src/sdk/helpers/grist-value-codec.ts","../src/sdk/helpers/grist-safe-parse.ts","../src/sdk/helpers/replica-normalize.ts","../src/emulator/core/document.ts","../src/emulator/core/action-engine.ts","../src/emulator/core/columnar.ts","../src/emulator/api/grist-doc-api.ts","../src/emulator/api/grist-view.ts","../src/emulator/api/widget-api.ts","../src/emulator/api/index.ts","../src/emulator/core/event-bus.ts","../src/emulator/theme-message.ts","../src/emulator/transports/iframe.ts","../src/sdk/helpers/grist-user-actions.ts","../src/emulator/transports/inline.ts","../src/emulator/validators.ts","../src/emulator/create-grist-emulator.ts","../src/emulator/templates.ts"],"sourcesContent":["/**\n * Public surface of the Grist emulator.\n *\n * Three sub-paths are exported on top of this barrel for advanced usage:\n * - `grist-widget-sdk/emulator/testing` → vitest helpers\n * - `grist-widget-sdk/emulator/devtools` → React Inspector component\n * - `grist-widget-sdk/emulator/transports` → low-level transports\n */\n\nexport type { GristReplicaDocument } from \"../sdk/replica-document\"\nexport { createGristEmulator } from \"./create-grist-emulator\"\nexport type { CreateGristEmulatorOptions, GristEmulator } from \"./create-grist-emulator\"\nexport { presets } from \"./templates\"\nexport { parseDocument, safeParseDocument } from \"./validators\"\nexport type {\n CreateDocumentInput,\n CreateDocumentTableInput,\n EmulatorColumn,\n EmulatorDocumentState,\n EmulatorEvent,\n EmulatorRowId,\n EmulatorTable,\n} from \"./core\"\nexport { EmulatorActionError, enrichEmulatorColumnMetadata, resolveMappings } from \"./core\"\nexport type { EmulatorApiBundle } from \"./api\"\nexport type { EmulatorTransport, InlineGristGlobal } from \"./transports\"\n","import type { EventBus } from \"../core/event-bus\"\nimport type { CommandApiImpl } from \"./types\"\n\n/**\n * `CommandAPI` host implementation. The widget's \"Edit Options\" gear and a\n * few keyboard shortcuts call into this. We forward the call name on the bus\n * so the inspector and tests can observe it; useful to assert\n * `onEditOptions` flows.\n */\nexport function createCommandApiImpl(bus: EventBus): CommandApiImpl {\n return {\n async run(name) {\n bus.emit({ type: \"user-action\", action: [\"RunCommand\", name] })\n },\n }\n}\n","/**\n * Resolves the `mappings` payload that `CustomSectionAPI.mappings()` returns.\n *\n * The playground emulator does **not** infer logical → real columns from\n * names. Mappings come only from `state.selection.mappings` (playground\n * document inspector or tests). When unset, returns `null`.\n */\n\nimport type { GristWidgetColumnMap } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"./types\"\n\nexport function resolveMappings(state: EmulatorDocumentState): GristWidgetColumnMap | null {\n if (state.selection.mappings !== undefined && state.selection.mappings !== null) {\n return state.selection.mappings\n }\n return null\n}\n","import { resolveMappings } from \"../core/mappings\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { GristWidgetConfiguration } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { CustomSectionApiImpl } from \"./types\"\n\n/**\n * `CustomSectionAPI` host implementation, called by `grist-plugin-api.js`\n * after `grist.ready()` to hand the host the widget's preferences:\n * required access, declared columns, allowSelectBy, hasCustomOptions, etc.\n *\n * Implementation:\n * - persists the configuration onto `state.configuration`,\n * - emits a `ready` event so the iframe transport knows it's safe to push\n * initial cursor / data / options messages,\n * - re-emits a `mappings-change` so the inspector and tests can react.\n */\nexport function createCustomSectionApiImpl(\n state: EmulatorDocumentState,\n bus: EventBus\n): CustomSectionApiImpl {\n return {\n async configure(settings) {\n const config: GristWidgetConfiguration = {\n requiredAccess: settings.requiredAccess as GristWidgetConfiguration[\"requiredAccess\"],\n columns: settings.columns as GristWidgetConfiguration[\"columns\"],\n allowSelectBy: settings.allowSelectBy as boolean | undefined,\n hasCustomOptions: settings.hasCustomOptions as boolean | undefined,\n }\n state.configuration = config\n bus.emit({ type: \"ready\", configuration: config })\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n\n async mappings() {\n return resolveMappings(state)\n },\n }\n}\n","import type { GristApiImpl } from \"./types\"\n\n/** `_grist_api` host implementation. Minimal v1 — extend as needed. */\nexport function createGristApiImpl(): GristApiImpl {\n return {\n async ping() {\n return \"pong\"\n },\n }\n}\n","/**\n * Encoding helpers for Grist cell values.\n *\n * Grist sends some types as marshalled tuples or numeric epochs. This file\n * exposes pure decode/encode functions so widget code never has to spelunk\n * Grist's wire format.\n *\n * References: Grist `grist/RowRecord` and `grist/DocActions` typings.\n */\n\nimport type { GristReplicaColumn } from \"../types\"\n\n/** `[\"E\", \"ErrorClass\", \"message\", traceback?]` — Grist error sentinel. */\nexport type GristEncodedError = [\"E\", string, string?, string?]\n/** `[\"L\", ...items]` — list (used for ChoiceList, RefList, Attachments). */\nexport type GristEncodedList = [\"L\", ...unknown[]]\n/** `[\"D\", epochSeconds, \"tz/Name\"]` — DateTime with timezone. */\nexport type GristEncodedDateTime = [\"D\", number, string]\n/** `[\"d\", epochSeconds]` — Date (no time). */\nexport type GristEncodedDate = [\"d\", number]\n/** `[\"R\", tableId, rowId]` — explicit reference. */\nexport type GristEncodedRef = [\"R\", string, number]\n/** `[\"r\", rowId]` — bare reference (when table is contextual). */\nexport type GristEncodedBareRef = [\"r\", number]\n/** `[\"P\", encoded]` — pending marker. */\nexport type GristEncodedPending = [\"P\"]\n\nexport type GristDecodedValue =\n | null\n | string\n | number\n | boolean\n | Date\n | GristDecodedValue[]\n | { __error: true; type: string; message?: string; traceback?: string }\n | { __ref: true; tableId?: string; rowId: number }\n\nconst MARSHALLED_TAGS = new Set([\"E\", \"L\", \"D\", \"d\", \"R\", \"r\", \"P\"])\n\nfunction isMarshalledTuple(value: unknown): value is unknown[] {\n return (\n Array.isArray(value) &&\n typeof value[0] === \"string\" &&\n value[0].length <= 2 &&\n MARSHALLED_TAGS.has(value[0])\n )\n}\n\n/**\n * Normalises a Grist `fetchTable` cell that points at a row in another table.\n * Most payloads use a bare numeric row id, but `Ref:*` values may appear as\n * `[\"R\", tableId, rowId]` or `[\"r\", rowId]` (same shape as {@link decodeGristValue}).\n */\nexport function coerceGristDocApiRefRowId(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value\n if (!Array.isArray(value) || value.length < 2) return undefined\n const tag = value[0]\n if (tag === \"R\" && typeof value[2] === \"number\" && Number.isFinite(value[2])) return value[2]\n if (tag === \"r\" && typeof value[1] === \"number\" && Number.isFinite(value[1])) return value[1]\n return undefined\n}\n\nfunction looksLikeAttachmentColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Attachments\"\n}\n\nfunction looksLikeChoiceListColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"ChoiceList\"\n}\n\nfunction looksLikeRefListColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"RefList:\")\n}\n\nfunction looksLikeRefColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"Ref:\")\n}\n\nfunction looksLikeDateColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Date\"\n}\n\nfunction looksLikeDateTimeColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"DateTime\")\n}\n\n/**\n * Decodes a Grist cell value into an idiomatic JS value.\n *\n * Pass the column's metadata (from `useGristSchema` or `_grist_Tables_column`)\n * for type-aware decoding (e.g. `Date` columns return `Date` even when stored as a number).\n */\nexport function decodeGristValue(value: unknown, column?: GristReplicaColumn): GristDecodedValue {\n if (value === null || value === undefined) return null\n\n if (isMarshalledTuple(value)) {\n const tag = value[0] as string\n switch (tag) {\n case \"E\":\n return {\n __error: true,\n type: typeof value[1] === \"string\" ? value[1] : \"Error\",\n message: typeof value[2] === \"string\" ? value[2] : undefined,\n traceback: typeof value[3] === \"string\" ? value[3] : undefined,\n }\n case \"L\":\n return value.slice(1).map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n case \"D\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"d\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"R\":\n return {\n __ref: true,\n tableId: typeof value[1] === \"string\" ? value[1] : undefined,\n rowId: typeof value[2] === \"number\" ? value[2] : 0,\n }\n case \"r\":\n return { __ref: true, rowId: typeof value[1] === \"number\" ? value[1] : 0 }\n case \"P\":\n return null\n default:\n return null\n }\n }\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (typeof value === \"number\" && Number.isFinite(value)) return new Date(value * 1000)\n }\n\n if (looksLikeRefColumn(column) && typeof value === \"number\") {\n return { __ref: true, rowId: value }\n }\n\n if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {\n return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n return null\n}\n\n/** Convenience: true when the cell is a Grist error sentinel. */\nexport function isGristCellError(value: unknown): value is GristEncodedError {\n return Array.isArray(value) && value[0] === \"E\"\n}\n\n/**\n * Encodes a JS value into Grist's expected wire form for a given column type.\n *\n * Use before passing values to `applyUserActions` or `TableOperations.update`\n * for `Date`, `DateTime`, `Ref`, `RefList`, and `ChoiceList` columns.\n */\nexport function encodeGristValue(value: unknown, column?: GristReplicaColumn): unknown {\n if (value === null || value === undefined) return null\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (value instanceof Date) return Math.floor(value.getTime() / 1000)\n if (typeof value === \"string\") {\n const parsed = Date.parse(value)\n if (!Number.isNaN(parsed)) return Math.floor(parsed / 1000)\n }\n if (typeof value === \"number\") return Math.floor(value)\n }\n\n if (looksLikeRefColumn(column)) {\n if (typeof value === \"number\") return value\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return (value as { rowId: number }).rowId\n }\n }\n\n if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {\n if (Array.isArray(value)) {\n const items = value.map((v) => {\n if (v && typeof v === \"object\" && \"rowId\" in v) return (v as { rowId: number }).rowId\n return v\n })\n return [\"L\", ...items]\n }\n }\n\n return value\n}\n","import { z, type ZodType } from \"zod\"\n\nimport type { GristReplicaColumn, GristRowRecord } from \"../types\"\nimport type { GristColumnarTable } from \"./grist-table-data\"\nimport { normalizeGristChoiceListEntries, type GristChoiceListEntry } from \"./grist-widget-options\"\nimport { decodeGristValue, type GristDecodedValue } from \"./grist-value-codec\"\n\nexport type GristSafeParseIssueCode =\n | \"grist_error\"\n | \"invalid_format\"\n | \"type_mismatch\"\n | \"helper_mismatch\"\n | \"zod_error\"\n\nexport type GristSafeParseIssue = {\n code: GristSafeParseIssueCode\n message: string\n}\n\nexport type GristSafeRefValue = {\n rowId: number\n display?: string | null\n}\n\nexport type GristSafeRefListValue = {\n rowIds: number[]\n displays?: string[]\n}\n\nexport const gristSafeRefValueSchema = z.object({\n rowId: z.number(),\n display: z.string().nullable().optional(),\n})\n\nexport const gristSafeRefListValueSchema = z.object({\n rowIds: z.array(z.number()),\n displays: z.array(z.string()).optional(),\n})\n\nexport const gristCellValueSchema = z.union([\n z.null(),\n z.string(),\n z.number(),\n z.boolean(),\n z.date(),\n z.array(z.unknown()),\n gristSafeRefValueSchema,\n gristSafeRefListValueSchema,\n])\n\nexport type GristCellValue = z.infer<typeof gristCellValueSchema>\n\nexport type GristSafeParseCellResult<TValue = unknown> = {\n ok: boolean\n typedValue: TValue | null\n displayValue: unknown\n raw: unknown\n issues: GristSafeParseIssue[]\n}\n\ntype RefMode = \"id\" | \"detailed\"\n\nexport type SafeParseGristValuesOptions<TValue = unknown> = {\n values: readonly unknown[]\n column?: GristReplicaColumn\n helperValues?: readonly unknown[]\n schema?: ZodType<TValue>\n fallbackUntypedToString?: boolean\n refMode?: RefMode\n}\n\nexport type SafeParseGristTableDataOptions = {\n columns?: Record<string, GristReplicaColumn>\n displayHelpersByRef?: Record<string, string>\n order?: \"none\" | \"id\" | \"grist\"\n fallbackUntypedToString?: boolean\n refMode?: RefMode\n}\n\nexport type GristSafeTableCellIssue = GristSafeParseIssue & {\n rowIndex: number\n colId: string\n}\n\nexport type GristSafeChoiceTokenMeta = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n valid: boolean\n}\n\nexport type GristSafeTableCellMeta = {\n rowIndex: number\n colId: string\n ok: boolean\n issues: GristSafeParseIssue[]\n choiceTokens?: GristSafeChoiceTokenMeta[]\n}\n\nexport type SafeParseGristTableDataResult<TRow extends Record<string, unknown> = Record<string, unknown>> = {\n rows: GristRowRecord<TRow>[]\n cellIssues: GristSafeTableCellIssue[]\n cellMeta: GristSafeTableCellMeta[]\n cellMetaByKey: Record<string, GristSafeTableCellMeta>\n cellResultsByColumn: Record<string, GristSafeParseCellResult[]>\n}\n\n/** Maps `Ref:*` / `RefList:*` column ids to their paired `gristHelper_*` column id (same rules as safe-parse). */\nexport function inferDisplayHelpersByRef(\n columns: Record<string, GristReplicaColumn>\n): Record<string, string> {\n const out: Record<string, string> = {}\n const helperColumns = Object.entries(columns).filter(([colId]) =>\n colId.startsWith(\"gristHelper_\")\n )\n const usedHelpers = new Set<string>()\n const colRefToColId = new Map<number, string>()\n for (const [colId, col] of Object.entries(columns)) {\n if (typeof col?.colRef === \"number\" && Number.isFinite(col.colRef)) {\n colRefToColId.set(col.colRef, colId)\n }\n }\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (typeof col.displayColRef === \"number\" && Number.isFinite(col.displayColRef)) {\n const helperColId = colRefToColId.get(col.displayColRef)\n if (helperColId) {\n out[colId] = helperColId\n usedHelpers.add(helperColId)\n continue\n }\n }\n const match = helperColumns.find(([, helper]) => {\n const formula = helper?.formula\n return typeof formula === \"string\" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`))\n })\n if (match) {\n out[colId] = match[0]\n usedHelpers.add(match[0])\n }\n }\n\n // Secondary fallback for schemas where helper formulas are unavailable:\n // pair unresolved Ref/RefList columns with nearest following gristHelper_*.\n const unresolvedRefs = Object.entries(columns)\n .filter(([colId, col]) => {\n const type = col?.type\n return (\n !out[colId] &&\n typeof type === \"string\" &&\n (type.startsWith(\"Ref:\") || type.startsWith(\"RefList:\"))\n )\n })\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n const helperByPos = helperColumns\n .filter(([helperId]) => !usedHelpers.has(helperId))\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n for (const [refId, refCol] of unresolvedRefs) {\n const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n const candidate = helperByPos.find(([, helperCol]) => {\n const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n return helperPos > refPos\n })\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n // If multiple unresolved refs remain, greedily map by order.\n for (const [refId] of unresolvedRefs) {\n if (out[refId]) continue\n const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId))\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n return out\n}\n\nfunction computeRowCount(data: Record<string, unknown[]>): number {\n const idCol = data.id\n if (Array.isArray(idCol)) return idCol.length\n for (const key of Object.keys(data)) {\n const col = data[key]\n if (Array.isArray(col)) return col.length\n }\n return 0\n}\n\nfunction manualSortKey(row: Record<string, unknown>): number | null {\n const v = row.manualSort\n if (typeof v === \"number\" && !Number.isNaN(v)) return v\n if (typeof v === \"string\" && v.trim() !== \"\") {\n const n = Number(v)\n if (!Number.isNaN(n)) return n\n }\n return null\n}\n\nfunction sortRowsByGristOrder<T = Record<string, unknown>>(\n rows: readonly GristRowRecord<T>[]\n): GristRowRecord<T>[] {\n const hasManual = rows.some((r) => manualSortKey(r as Record<string, unknown>) !== null)\n if (!hasManual) {\n return [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n }\n return [...rows].sort((a, b) => {\n const ma = manualSortKey(a as Record<string, unknown>)\n const mb = manualSortKey(b as Record<string, unknown>)\n if (ma !== null && mb !== null && ma !== mb) return ma - mb\n if (ma !== null && mb === null) return -1\n if (ma === null && mb !== null) return 1\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n })\n}\n\nfunction columnKind(column?: GristReplicaColumn):\n | \"text\"\n | \"numeric\"\n | \"int\"\n | \"bool\"\n | \"date\"\n | \"datetime\"\n | \"choice\"\n | \"choiceList\"\n | \"ref\"\n | \"refList\"\n | \"attachments\"\n | \"any\"\n | \"unknown\" {\n const type = column?.type\n if (!type) return \"unknown\"\n if (type === \"Text\") return \"text\"\n if (type === \"Numeric\") return \"numeric\"\n if (type === \"Int\") return \"int\"\n if (type === \"Bool\") return \"bool\"\n if (type === \"Date\") return \"date\"\n if (type === \"DateTime\" || type.startsWith(\"DateTime:\")) return \"datetime\"\n if (type === \"Choice\") return \"choice\"\n if (type === \"ChoiceList\") return \"choiceList\"\n if (type.startsWith(\"Ref:\")) return \"ref\"\n if (type.startsWith(\"RefList:\")) return \"refList\"\n if (type === \"Attachments\") return \"attachments\"\n if (type === \"Any\") return \"any\"\n return \"unknown\"\n}\n\nfunction primitiveToString(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === \"string\") return value\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value)\n }\n return null\n}\n\nfunction normalizeRefDisplay(value: unknown): { value?: string | null; issue?: GristSafeParseIssue } {\n if (value === null || value === undefined) return { value: null }\n if (typeof value === \"string\") return { value }\n if (typeof value === \"number\" || typeof value === \"boolean\") return { value: String(value) }\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"Ref display helper value should be a scalar value.\",\n },\n }\n}\n\nfunction normalizeRefListDisplays(value: unknown): { values?: string[]; issue?: GristSafeParseIssue } {\n if (value === null || value === undefined) return { values: [] }\n if (typeof value === \"string\") {\n const s = value.trim()\n if (s === \"\") return { values: [] }\n if (s.startsWith(\"[\")) {\n try {\n const parsed = JSON.parse(s)\n if (Array.isArray(parsed)) {\n return normalizeRefListDisplays(parsed)\n }\n } catch {\n // Keep existing error below for non-array/non-JSON helper strings.\n }\n }\n }\n if (!Array.isArray(value)) {\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"RefList display helper value should be an array.\",\n },\n }\n }\n // Grist list wire format may leak through as [\"L\", ...items].\n // Treat a leading \"L\" marker as metadata, not a display label.\n const items =\n value.length > 0 && value[0] === \"L\"\n ? value.slice(1)\n : value\n const out: string[] = []\n for (const item of items) {\n const s = primitiveToString(item)\n if (s === null) {\n return {\n issue: {\n code: \"helper_mismatch\",\n message: \"RefList helper items should be scalar values.\",\n },\n }\n }\n out.push(s)\n }\n return { values: out }\n}\n\nfunction normalizeRefValue(\n decoded: GristDecodedValue,\n helperValue: unknown,\n refMode: RefMode\n): { value: number | GristSafeRefValue | null; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded === null) return { value: null, issues }\n\n const rowId =\n typeof decoded === \"number\" && Number.isFinite(decoded)\n ? decoded\n : decoded && typeof decoded === \"object\" && \"__ref\" in decoded\n ? (decoded as { rowId: number }).rowId\n : null\n\n // Grist empty refs can surface as 0; treat as empty cell.\n if (rowId === 0) return { value: null, issues }\n if (rowId === null || !Number.isFinite(rowId)) {\n issues.push({\n code: \"type_mismatch\",\n message: \"Expected a Ref row id.\",\n })\n return { value: null, issues }\n }\n\n if (refMode === \"id\") return { value: rowId, issues }\n\n const helper = normalizeRefDisplay(helperValue)\n if (helper.issue) issues.push(helper.issue)\n return {\n value: { rowId, display: helper.value },\n issues,\n }\n}\n\nfunction normalizeRefListValue(\n decoded: GristDecodedValue,\n helperValue: unknown,\n refMode: RefMode\n): { value: number[] | GristSafeRefListValue | null; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded === null) return { value: null, issues }\n if (!Array.isArray(decoded)) {\n issues.push({\n code: \"type_mismatch\",\n message: \"Expected an array for RefList.\",\n })\n return { value: null, issues }\n }\n\n const rowIds: number[] = []\n for (const item of decoded) {\n if (typeof item === \"number\" && Number.isFinite(item) && item !== 0) {\n rowIds.push(item)\n continue\n }\n if (item && typeof item === \"object\" && \"__ref\" in item) {\n const rowId = (item as { rowId: number }).rowId\n if (typeof rowId === \"number\" && Number.isFinite(rowId) && rowId !== 0) {\n rowIds.push(rowId)\n continue\n }\n }\n issues.push({\n code: \"type_mismatch\",\n message: \"RefList items should be row ids.\",\n })\n return { value: null, issues }\n }\n\n if (refMode === \"id\") return { value: rowIds, issues }\n\n const helper = normalizeRefListDisplays(helperValue)\n if (helper.issue) {\n issues.push(helper.issue)\n } else if (helper.values && helper.values.length > 0 && helper.values.length !== rowIds.length) {\n issues.push({\n code: \"helper_mismatch\",\n message: \"RefList helper labels count does not match row ids count.\",\n })\n }\n return {\n value: { rowIds, displays: helper.values },\n issues,\n }\n}\n\nfunction normalizeByColumnKind(\n decoded: GristDecodedValue,\n kind: ReturnType<typeof columnKind>,\n helperValue: unknown,\n fallbackUntypedToString: boolean,\n refMode: RefMode\n): { value: unknown; issues: GristSafeParseIssue[] } {\n const issues: GristSafeParseIssue[] = []\n if (decoded && typeof decoded === \"object\" && \"__error\" in decoded) {\n issues.push({\n code: \"grist_error\",\n message: (decoded as { message?: string }).message ?? \"Grist returned a cell error.\",\n })\n return { value: null, issues }\n }\n\n switch (kind) {\n case \"ref\":\n return normalizeRefValue(decoded, helperValue, refMode)\n case \"refList\":\n return normalizeRefListValue(decoded, helperValue, refMode)\n case \"date\":\n case \"datetime\":\n if (decoded === null || decoded instanceof Date) return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a Date value.\" })\n return { value: null, issues }\n case \"bool\":\n if (decoded === null || typeof decoded === \"boolean\") return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a boolean value.\" })\n return { value: null, issues }\n case \"numeric\":\n if (decoded === null || (typeof decoded === \"number\" && Number.isFinite(decoded))) {\n return { value: decoded, issues }\n }\n issues.push({ code: \"type_mismatch\", message: \"Expected a numeric value.\" })\n return {\n value:\n typeof decoded === \"string\" ||\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\"\n ? decoded\n : null,\n issues,\n }\n case \"int\":\n if (decoded === null || (typeof decoded === \"number\" && Number.isInteger(decoded))) {\n return { value: decoded, issues }\n }\n issues.push({ code: \"type_mismatch\", message: \"Expected an integer value.\" })\n return {\n value:\n typeof decoded === \"string\" ||\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\"\n ? decoded\n : null,\n issues,\n }\n case \"choice\":\n case \"text\":\n if (decoded === null || typeof decoded === \"string\") return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a string value.\" })\n return { value: null, issues }\n case \"choiceList\":\n case \"attachments\":\n if (decoded === null || Array.isArray(decoded)) return { value: decoded, issues }\n issues.push({ code: \"type_mismatch\", message: \"Expected a list value.\" })\n return { value: null, issues }\n case \"any\":\n case \"unknown\":\n // Heuristic fallback: when schema typing is missing but a helper column is\n // attached, infer Ref/RefList from the decoded shape.\n if (helperValue !== undefined) {\n if (typeof decoded === \"number\" || (decoded && typeof decoded === \"object\" && \"__ref\" in decoded)) {\n return normalizeRefValue(decoded, helperValue, refMode)\n }\n if (Array.isArray(decoded)) {\n return normalizeRefListValue(decoded, helperValue, refMode)\n }\n }\n if (!fallbackUntypedToString) return { value: decoded, issues }\n if (decoded === null) return { value: null, issues }\n if (typeof decoded === \"string\") return { value: decoded, issues }\n if (\n typeof decoded === \"number\" ||\n typeof decoded === \"boolean\" ||\n decoded instanceof Date\n ) {\n return {\n value: decoded instanceof Date ? decoded.toISOString() : String(decoded),\n issues,\n }\n }\n if (Array.isArray(decoded)) {\n try {\n return { value: JSON.stringify(decoded), issues }\n } catch {\n issues.push({\n code: \"invalid_format\",\n message: \"Unable to stringify list value.\",\n })\n return { value: null, issues }\n }\n }\n issues.push({\n code: \"type_mismatch\",\n message: \"Untyped value could not be represented as a string.\",\n })\n return { value: null, issues }\n }\n}\n\nfunction buildChoiceTokens(\n col: GristReplicaColumn | undefined,\n value: unknown\n): GristSafeChoiceTokenMeta[] | undefined {\n const type = col?.type\n if (type !== \"Choice\" && type !== \"ChoiceList\") return undefined\n const entries = normalizeGristChoiceListEntries(col?.widgetOptions)\n const byValue = new Map<string, GristChoiceListEntry>(entries.map((entry) => [entry.value, entry]))\n\n if (type === \"Choice\") {\n if (value == null || typeof value !== \"string\" || value.trim() === \"\") return []\n const meta = byValue.get(value)\n if (!meta) return [{ value, label: value, valid: false }]\n return [\n {\n value,\n label: meta.label,\n fillColor: meta.fillColor,\n textColor: meta.textColor,\n valid: true,\n },\n ]\n }\n\n if (!Array.isArray(value)) return []\n const out: GristSafeChoiceTokenMeta[] = []\n for (const item of value) {\n const v = typeof item === \"string\" ? item : String(item)\n const meta = byValue.get(v)\n if (!meta) {\n out.push({ value: v, label: v, valid: false })\n continue\n }\n out.push({\n value: v,\n label: meta.label,\n fillColor: meta.fillColor,\n textColor: meta.textColor,\n valid: true,\n })\n }\n return out\n}\n\nexport function safeParseGristValues<TValue = unknown>(\n options: SafeParseGristValuesOptions<TValue>\n): GristSafeParseCellResult<TValue>[] {\n const fallbackUntypedToString = options.fallbackUntypedToString ?? true\n const refMode = options.refMode ?? \"id\"\n const kind = columnKind(options.column)\n return options.values.map((raw, index) => {\n const decoded = decodeGristValue(raw, options.column)\n const helperValue = options.helperValues?.[index]\n const normalized = normalizeByColumnKind(\n decoded,\n kind,\n helperValue,\n fallbackUntypedToString,\n refMode\n )\n const issues = [...normalized.issues]\n\n if (options.schema) {\n const result = options.schema.safeParse(normalized.value)\n if (!result.success) {\n issues.push({\n code: \"zod_error\",\n message: result.error.issues.map((issue) => issue.message).join(\"; \"),\n })\n }\n }\n\n return {\n ok: issues.length === 0,\n typedValue: normalized.value as TValue | null,\n displayValue: normalized.value,\n raw,\n issues,\n }\n })\n}\n\nexport function safeParseGristTableData<TRow extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: SafeParseGristTableDataOptions\n): SafeParseGristTableDataResult<TRow> {\n const columns = options?.columns ?? {}\n const inferredDisplayHelpersByRef = inferDisplayHelpersByRef(columns)\n const displayHelpersByRef: Record<string, string> = {\n ...inferredDisplayHelpersByRef,\n ...(options?.displayHelpersByRef ?? {}),\n }\n // Fallback convention: if `owner` exists and `gristHelper_owner` is fetched,\n // use it as display helper even when formula metadata is unavailable.\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (displayHelpersByRef[colId]) continue\n const byName = `gristHelper_${colId}`\n if (Array.isArray(data[byName])) {\n displayHelpersByRef[colId] = byName\n }\n }\n const fallbackUntypedToString = options?.fallbackUntypedToString ?? true\n const refMode = options?.refMode ?? \"id\"\n const colIds = Object.keys(data)\n const parsedByColumn: Record<string, GristSafeParseCellResult[]> = {}\n\n for (const colId of colIds) {\n const rawValues = Array.isArray(data[colId]) ? data[colId] : []\n const helperColId = displayHelpersByRef[colId]\n const helperValues = helperColId && Array.isArray(data[helperColId]) ? data[helperColId] : undefined\n parsedByColumn[colId] =\n colId === \"id\"\n ? rawValues.map((raw) => ({\n ok: typeof raw === \"number\" && Number.isFinite(raw),\n typedValue: typeof raw === \"number\" && Number.isFinite(raw) ? raw : null,\n displayValue: raw,\n raw,\n issues:\n typeof raw === \"number\" && Number.isFinite(raw)\n ? []\n : [{ code: \"type_mismatch\", message: \"Row id should be numeric.\" }],\n }))\n : safeParseGristValues({\n values: rawValues,\n column: columns[colId],\n helperValues,\n fallbackUntypedToString,\n refMode,\n })\n }\n\n const rowCount = computeRowCount(data)\n const rows: GristRowRecord<TRow>[] = []\n const cellIssues: GristSafeTableCellIssue[] = []\n const cellMeta: GristSafeTableCellMeta[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n const parsed = parsedByColumn[colId]?.[rowIndex]\n row[colId] = parsed?.typedValue ?? null\n const choiceTokens = buildChoiceTokens(columns[colId], parsed?.displayValue)\n if (parsed) {\n if (parsed.issues.length > 0 || (choiceTokens && choiceTokens.length > 0)) {\n cellMeta.push({\n rowIndex,\n colId,\n ok: parsed.ok,\n issues: parsed.issues,\n choiceTokens,\n })\n }\n }\n if (!parsed || parsed.issues.length === 0) continue\n for (const issue of parsed.issues) {\n cellIssues.push({ ...issue, rowIndex, colId })\n }\n }\n rows.push(row as GristRowRecord<TRow>)\n }\n\n const cellMetaByKey: Record<string, GristSafeTableCellMeta> = {}\n for (const meta of cellMeta) {\n const rowId = rows[meta.rowIndex]?.id\n if (typeof rowId !== \"number\") continue\n cellMetaByKey[`${rowId}:${meta.colId}`] = meta\n }\n\n const order = options?.order ?? \"grist\"\n if (order === \"none\") {\n return { rows, cellIssues, cellMeta, cellMetaByKey, cellResultsByColumn: parsedByColumn }\n }\n if (order === \"id\") {\n return {\n rows: [...rows].sort((a, b) => {\n const ida = typeof a.id === \"number\" ? a.id : 0\n const idb = typeof b.id === \"number\" ? b.id : 0\n return ida - idb\n }),\n cellIssues,\n cellMeta,\n cellMetaByKey,\n cellResultsByColumn: parsedByColumn,\n }\n }\n return {\n rows: sortRowsByGristOrder(rows),\n cellIssues,\n cellMeta,\n cellMetaByKey,\n cellResultsByColumn: parsedByColumn,\n }\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n","import { inferDisplayHelpersByRef } from \"../../sdk/helpers/grist-safe-parse\"\nimport { normalizeReplicaDocumentInput } from \"../../sdk/helpers/replica-normalize\"\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport type { GristReplicaDocument, GristReplicaTable } from \"../../sdk/replica-document\"\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nconst SYSTEM_COLUMN = \"id\"\n\nconst EMULATOR_JS_FORMULA_PLACEHOLDER = \"(emulator JavaScript formula)\"\n\n/** Replica table for {@link createDocument}; columns may include `formulaFn` / `inferredFormula` (emulator-only). */\nexport type CreateDocumentTableInput = Omit<GristReplicaTable, \"columns\"> & {\n columns?: Record<string, EmulatorColumn>\n}\n\n/** Replica document for {@link createDocument}; widens table columns to {@link EmulatorColumn}. */\nexport type CreateDocumentInput = Omit<GristReplicaDocument, \"tables\"> & {\n tables: Record<string, CreateDocumentTableInput>\n}\n\n/**\n * Ensure `formula` (original) and `inferredFormula` strings exist alongside optional `formulaFn`.\n */\nexport function enrichEmulatorColumnMetadata(col: EmulatorColumn): EmulatorColumn {\n const originalTrimmed = col.formula?.trim() ?? \"\"\n const explicitInferred = col.inferredFormula?.trim() ?? \"\"\n\n if (col.formulaFn) {\n const inferredFormula =\n explicitInferred || originalTrimmed || EMULATOR_JS_FORMULA_PLACEHOLDER\n return {\n ...col,\n ...(originalTrimmed ? { formula: col.formula } : {}),\n inferredFormula,\n }\n }\n\n if (explicitInferred || originalTrimmed) {\n return {\n ...col,\n inferredFormula: explicitInferred || originalTrimmed || undefined,\n }\n }\n\n return col\n}\n\n/** Order merged column metadata for stable `fetchTable` / RDG column order. */\nexport function sortEmulatorColumnsByParentPos(columns: Record<string, EmulatorColumn>): Record<string, EmulatorColumn> {\n const entries = Object.entries(columns)\n entries.sort(([ka, a], [kb, b]) => {\n const pa = a.parentPos\n const pb = b.parentPos\n if (pa !== undefined && pb !== undefined && pa !== pb) return pa - pb\n if (pa !== undefined && pb === undefined) return -1\n if (pa === undefined && pb !== undefined) return 1\n return ka.localeCompare(kb)\n })\n return Object.fromEntries(entries)\n}\n\nfunction inferColumnsFromRows(rows: GristRowRecord[]): Record<string, EmulatorColumn> {\n const columns: Record<string, EmulatorColumn> = {}\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (key === SYSTEM_COLUMN) continue\n if (!columns[key]) columns[key] = inferColumnType(row[key])\n }\n }\n return columns\n}\n\nfunction inferColumnType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction buildTable(tableId: string, input: CreateDocumentTableInput): EmulatorTable {\n const rows = input.rows ?? []\n const inferred = inferColumnsFromRows(rows)\n const merged: Record<string, EmulatorColumn> = {}\n for (const [colId, col] of Object.entries({ ...inferred, ...(input.columns ?? {}) })) {\n merged[colId] = enrichEmulatorColumnMetadata(col)\n }\n const columns = sortEmulatorColumnsByParentPos(merged)\n return {\n tableId,\n label: input.label,\n columns,\n rows: rows.map((row) => ({ ...row })),\n }\n}\n\n/**\n * Build an immutable initial document state from a user-provided\n * {@link GristReplicaDocument}. The state is **not** frozen — the action\n * engine mutates it in place under deterministic event diffusion.\n */\nexport function createDocument(input: CreateDocumentInput): EmulatorDocumentState {\n if (!input.tables || Object.keys(input.tables).length === 0) {\n throw new Error(\"createDocument: at least one table is required\")\n }\n\n const normalized = normalizeReplicaDocumentInput(input)\n\n const tables = new Map<string, EmulatorTable>()\n for (const [tableId, tableInput] of Object.entries(normalized.tables)) {\n tables.set(tableId, buildTable(tableId, tableInput))\n }\n\n const firstTableId = tables.keys().next().value as string\n const requestedTableId = normalized.selection?.tableId\n const selectedTableId =\n requestedTableId && tables.has(requestedTableId) ? requestedTableId : firstTableId\n const selectedTable = tables.get(selectedTableId)!\n const fallbackRowId =\n typeof selectedTable.rows[0]?.id === \"number\" ? selectedTable.rows[0].id : null\n const selection = {\n tableId: selectedTableId,\n rowId: normalized.selection?.rowId ?? fallbackRowId,\n mappings: normalized.selection?.mappings,\n cursor: normalized.selection?.cursor,\n } as EmulatorDocumentState[\"selection\"]\n\n return {\n docName: normalized.docName ?? \"Untitled emulator document\",\n tables,\n selection,\n widgetOptions: { ...(normalized.widgetOptions ?? {}) },\n widgetInteraction: { ...(normalized.widgetInteraction ?? {}) },\n configuration: normalized.configuration ?? null,\n accessToken: normalized.accessToken ?? null,\n }\n}\n\nexport function getTable(state: EmulatorDocumentState, tableId: string): EmulatorTable {\n const table = state.tables.get(tableId)\n if (!table) throw new Error(`Unknown table: ${tableId}`)\n return table\n}\n\nexport function getSelectedTable(state: EmulatorDocumentState): EmulatorTable {\n return getTable(state, state.selection.tableId)\n}\n\nexport function nextRowId(table: EmulatorTable): number {\n let max = 0\n for (const row of table.rows) {\n if (typeof row.id === \"number\" && row.id > max) max = row.id\n }\n return max + 1\n}\n\nexport function findRow(table: EmulatorTable, rowId: number): GristRowRecord | undefined {\n return table.rows.find((r) => r.id === rowId)\n}\n\nexport function findRowIndex(table: EmulatorTable, rowId: number): number {\n return table.rows.findIndex((r) => r.id === rowId)\n}\n\n/**\n * Re-evaluate every formula column for a given row in-place. Called by the\n * action engine after Add/Update operations.\n */\nexport function evaluateRowFormulas(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n for (const [colId, col] of Object.entries(table.columns)) {\n if (col.formulaFn) {\n try {\n row[colId] = col.formulaFn(row, { table, document: state })\n } catch (err) {\n row[colId] = formulaError(err)\n }\n }\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\n/** Pull stored row ids from a `RefList` cell (`[\"L\", ...]` or legacy shapes). */\nfunction extractRefListIdsFromWire(raw: unknown): number[] {\n if (raw == null) return []\n if (!Array.isArray(raw)) return []\n const items = raw[0] === \"L\" ? raw.slice(1) : raw\n const out: number[] = []\n for (const item of items) {\n if (typeof item === \"number\" && Number.isFinite(item) && item > 0) {\n out.push(Math.trunc(item))\n continue\n }\n if (item && typeof item === \"object\" && \"rowId\" in item) {\n const r = (item as { rowId: unknown }).rowId\n if (typeof r === \"number\" && Number.isFinite(r) && r > 0) {\n out.push(Math.trunc(r))\n continue\n }\n }\n const t = coerceGristDocApiRefRowId(item)\n if (t !== undefined && t > 0) out.push(Math.trunc(t))\n }\n return Array.from(new Set(out))\n}\n\nfunction fieldFromRefListHelperFormula(formula: string | undefined, refColId: string): string | null {\n if (!formula) return null\n const re = new RegExp(`\\\\$${escapeRegExp(refColId)}\\\\.([A-Za-z_]\\\\w*)`)\n const m = formula.match(re)\n return m?.[1] ?? null\n}\n\nfunction firstTextLikeColumnId(columns: Record<string, EmulatorColumn>): string | null {\n let best: { id: string; pos: number } | null = null\n for (const [colId, col] of Object.entries(columns)) {\n if (colId === \"id\" || colId.startsWith(\"gristHelper_\")) continue\n const t = col.type\n if (t !== \"Text\" && t !== \"Choice\") continue\n const pos = col.parentPos ?? 99999\n if (!best || pos < best.pos) best = { id: colId, pos }\n }\n return best?.id ?? null\n}\n\nfunction formatLabelFromCell(value: unknown): string {\n if (value == null) return \"\"\n if (typeof value === \"string\") return value.trim()\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n if (value instanceof Date) return value.toISOString()\n if (Array.isArray(value) && value[0] === \"E\") return \"\"\n if (typeof value === \"object\" && value && \"__ref\" in value) {\n const r = (value as { rowId?: unknown }).rowId\n return typeof r === \"number\" && Number.isFinite(r) ? String(r) : \"\"\n }\n return \"\"\n}\n\n/**\n * Keep `gristHelper_*` display columns aligned with `RefList:*` ids after writes.\n *\n * Real Grist evaluates helper formulas (`$multiref.Nom`); replica JSON only\n * carries the formula string (no `formulaFn`), so helpers would stay stale and\n * safe-parse would flag `helper_mismatch` with empty labels.\n *\n * Skips helpers that define `formulaFn` so custom JS formulas keep ownership.\n */\nexport function syncRefListDisplayHelpers(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n const displayHelpersByRef = inferDisplayHelpersByRef(table.columns)\n for (const [colId, col] of Object.entries(table.columns)) {\n const type = col.type\n if (typeof type !== \"string\" || !type.startsWith(\"RefList:\")) continue\n const helperColId = displayHelpersByRef[colId]\n if (!helperColId) continue\n const helperMeta = table.columns[helperColId]\n if (!helperMeta || helperMeta.formulaFn) continue\n\n const targetTableId = type.slice(\"RefList:\".length)\n const targetTable = state.tables.get(targetTableId)\n if (!targetTable) continue\n\n const ids = extractRefListIdsFromWire(row[colId])\n if (ids.length === 0) {\n row[helperColId] = []\n continue\n }\n\n const fieldId =\n fieldFromRefListHelperFormula(helperMeta.formula, colId) ??\n firstTextLikeColumnId(targetTable.columns)\n\n const labels = ids.map((rid) => {\n if (!fieldId) return String(rid)\n const trow = findRow(targetTable, rid)\n if (!trow) return String(rid)\n const lbl = formatLabelFromCell(trow[fieldId])\n return lbl !== \"\" ? lbl : String(rid)\n })\n row[helperColId] = labels\n }\n}\n\nfunction formulaError(err: unknown): unknown {\n // Match Grist's encoded error format: [\"E\", code, message]\n const message = err instanceof Error ? err.message : String(err)\n return [\"E\", \"Error\", message]\n}\n\n/**\n * Synthesise `_grist_Tables` metadata from the emulator's in-memory tables.\n * Returns Grist's columnar wire shape.\n */\nexport function synthesizeTablesMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const ids: number[] = []\n const tableIds: string[] = []\n const labels: (string | null)[] = []\n\n let nextId = 1\n for (const [tableId, table] of state.tables.entries()) {\n ids.push(nextId)\n tableIds.push(tableId)\n labels.push(table.label ?? null)\n nextId += 1\n }\n\n return {\n id: ids,\n tableId: tableIds,\n // Optional human-readable label; real Grist keeps more fields, but these\n // are sufficient for `buildReplicaDocumentFromDocApi` to resolve table ids.\n label: labels,\n }\n}\n\n/**\n * Synthesise `_grist_Tables_column` metadata from emulator tables/columns.\n * Mirrors the subset of fields consumed by `buildReplicaDocumentFromDocApi`.\n */\nexport function synthesizeTablesColumnMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const parentIds: number[] = []\n const colIds: string[] = []\n const columnIds: number[] = []\n const types: (string | null)[] = []\n const labels: (string | null)[] = []\n const parentPos: (number | null)[] = []\n const isFormula: boolean[] = []\n const formulas: (string | null)[] = []\n const descriptions: (string | null)[] = []\n const widgetOptions: unknown[] = []\n const displayCol: (number | null)[] = []\n const visibleCol: (number | null)[] = []\n\n // Mirror the synthetic table ids from `synthesizeTablesMeta`.\n const tableIdToInternalId = new Map<string, number>()\n {\n let nextId = 1\n for (const [tableId] of state.tables.entries()) {\n tableIdToInternalId.set(tableId, nextId)\n nextId += 1\n }\n }\n\n for (const [tableId, table] of state.tables.entries()) {\n const parentInternalId = tableIdToInternalId.get(tableId)\n if (parentInternalId === undefined) continue\n\n for (const [colId, col] of Object.entries(table.columns)) {\n parentIds.push(parentInternalId)\n colIds.push(colId)\n // Prefer explicit `colRef` when present; fall back to 1-based index of insertion.\n const ref = typeof col.colRef === \"number\" ? col.colRef : columnIds.length + 1\n columnIds.push(ref)\n types.push(col.type ?? null)\n labels.push(col.label ?? null)\n parentPos.push(col.parentPos ?? null)\n isFormula.push(Boolean(col.isFormula))\n const formula = typeof col.formula === \"string\" ? col.formula : null\n formulas.push(formula)\n descriptions.push(col.description ?? null)\n widgetOptions.push(col.widgetOptions ?? null)\n displayCol.push(typeof col.displayColRef === \"number\" ? col.displayColRef : null)\n visibleCol.push(typeof col.visibleColRef === \"number\" ? col.visibleColRef : null)\n }\n }\n\n return {\n parentId: parentIds,\n colId: colIds,\n id: columnIds,\n type: types,\n label: labels,\n parentPos,\n isFormula,\n formula: formulas,\n description: descriptions,\n // Also expose legacy `descr` for robustness.\n descr: descriptions,\n widgetOptions,\n displayCol,\n visibleCol,\n }\n}\n","/**\n * Pure action engine: applies Grist user actions to an\n * {@link EmulatorDocumentState} and emits the resulting events on the bus.\n *\n * This is the single place where state mutates. Every API impl ultimately\n * routes through `applyUserActions` so behaviour is consistent regardless of\n * the surface (`grist.docApi.applyUserActions`, `selectedTable.create`,\n * `setCursorPos`, etc.).\n *\n * Supported user actions:\n * - AddRecord, BulkAddRecord\n * - UpdateRecord, BulkUpdateRecord\n * - RemoveRecord, BulkRemoveRecord\n * - AddColumn, RemoveColumn, RenameColumn, ModifyColumn\n * - AddTable, RemoveTable, RenameTable\n *\n * Unknown actions throw a structured error instead of silently succeeding,\n * which surfaces protocol gaps loudly during widget development.\n */\n\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport {\n evaluateRowFormulas,\n findRow,\n findRowIndex,\n getTable,\n nextRowId,\n syncRefListDisplayHelpers,\n} from \"./document\"\nimport type { EventBus } from \"./event-bus\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nexport class EmulatorActionError extends Error {\n constructor(\n public readonly action: unknown,\n message: string\n ) {\n super(message)\n this.name = \"EmulatorActionError\"\n }\n}\n\nexport type ApplyUserActionResult = {\n /** Result mirroring Grist's `applyUserActions`: per-action retValues. */\n retValues: unknown[]\n /** Tables that received row-level changes (de-duped). */\n changedTableIds: string[]\n}\n\nexport function applyUserActions(\n state: EmulatorDocumentState,\n bus: EventBus,\n actions: unknown[][]\n): ApplyUserActionResult {\n const retValues: unknown[] = []\n const changed = new Set<string>()\n\n for (const action of actions) {\n bus.emit({ type: \"user-action\", action })\n const ret = applySingle(state, action, changed)\n retValues.push(ret)\n }\n\n for (const tableId of changed) {\n bus.emit({ type: \"data-change\", tableId })\n }\n\n return { retValues, changedTableIds: [...changed] }\n}\n\nfunction applySingle(\n state: EmulatorDocumentState,\n action: unknown[],\n changed: Set<string>\n): unknown {\n const [name, ...args] = action\n switch (name) {\n case \"AddRecord\":\n return addRecord(state, args, changed)\n case \"BulkAddRecord\":\n return bulkAddRecord(state, args, changed)\n case \"UpdateRecord\":\n return updateRecord(state, args, changed)\n case \"BulkUpdateRecord\":\n return bulkUpdateRecord(state, args, changed)\n case \"RemoveRecord\":\n return removeRecord(state, args, changed)\n case \"BulkRemoveRecord\":\n return bulkRemoveRecord(state, args, changed)\n case \"AddColumn\":\n return addColumn(state, args)\n case \"AddVisibleColumn\":\n // The emulator has no concept of section view fields, so the \"visible\"\n // part of `AddVisibleColumn` is a no-op here. We still create the\n // column so widgets that issue this user action (the higher-level form\n // recommended by Grist for \"add a column to the active view\") work\n // identically against the emulator.\n return addColumn(state, args)\n case \"RemoveColumn\":\n return removeColumn(state, args, changed)\n case \"RenameColumn\":\n return renameColumn(state, args, changed)\n case \"ModifyColumn\":\n return modifyColumn(state, args, changed)\n case \"AddTable\":\n return addTable(state, args)\n case \"RemoveTable\":\n return removeTable(state, args)\n case \"RenameTable\":\n return renameTable(state, args)\n default:\n throw new EmulatorActionError(action, `Unsupported user action: ${String(name)}`)\n }\n}\n\n// ---------- row ops ----------\n\nfunction addRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): number {\n const table = getTable(state, requireString(tableId, \"AddRecord.tableId\"))\n const id = typeof rowId === \"number\" ? rowId : nextRowId(table)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n const row = { id, ...normalizedValues }\n ensureColumns(table, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n changed.add(table.tableId)\n return id\n}\n\nfunction bulkAddRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): number[] {\n const table = getTable(state, requireString(tableId, \"BulkAddRecord.tableId\"))\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n const ids = Array.isArray(rowIds) ? rowIds : []\n const length = ids.length || lengthOf(cols)\n const out: number[] = []\n ensureColumns(table, cols, true)\n for (let i = 0; i < length; i++) {\n const id = typeof ids[i] === \"number\" ? (ids[i] as number) : nextRowId(table)\n const row: Record<string, unknown> & { id: number } = { id }\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][i]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n out.push(id)\n }\n changed.add(table.tableId)\n return out\n}\n\nfunction updateRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"UpdateRecord.tableId\"))\n const id = requireNumber(rowId, \"UpdateRecord.rowId\")\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"UpdateRecord\", tableId, rowId, values], `Row ${id} not found in ${table.tableId}`)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n ensureColumns(table, normalizedValues)\n Object.assign(row, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkUpdateRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkUpdateRecord.tableId\"))\n const ids = rowIds as number[]\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n ensureColumns(table, cols, true)\n ids.forEach((id, idx) => {\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"BulkUpdateRecord\", tableId, ids, cols], `Row ${id} not found in ${table.tableId}`)\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][idx]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n })\n changed.add(table.tableId)\n return null\n}\n\nfunction removeRecord(\n state: EmulatorDocumentState,\n [tableId, rowId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveRecord.tableId\"))\n const id = requireNumber(rowId, \"RemoveRecord.rowId\")\n const idx = findRowIndex(table, id)\n if (idx >= 0) table.rows.splice(idx, 1)\n if (state.selection.tableId === table.tableId && state.selection.rowId === id) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkRemoveRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkRemoveRecord.tableId\"))\n const ids = new Set(rowIds as number[])\n table.rows = table.rows.filter((r) => !ids.has(r.id))\n if (state.selection.tableId === table.tableId && typeof state.selection.rowId === \"number\" && ids.has(state.selection.rowId)) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- column ops ----------\n\nfunction addColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[]\n): null {\n const table = getTable(state, requireString(tableId, \"AddColumn.tableId\"))\n const col = requireString(colId, \"AddColumn.colId\")\n if (table.columns[col]) throw new EmulatorActionError([\"AddColumn\", tableId, colId], `Column ${col} already exists`)\n table.columns[col] = (info as EmulatorColumn) ?? {}\n for (const row of table.rows) {\n if (!(col in row)) row[col] = null\n }\n return null\n}\n\nfunction removeColumn(\n state: EmulatorDocumentState,\n [tableId, colId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveColumn.tableId\"))\n const col = requireString(colId, \"RemoveColumn.colId\")\n delete table.columns[col]\n for (const row of table.rows) delete row[col]\n changed.add(table.tableId)\n return null\n}\n\nfunction renameColumn(\n state: EmulatorDocumentState,\n [tableId, colId, newColId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RenameColumn.tableId\"))\n const from = requireString(colId, \"RenameColumn.colId\")\n const to = requireString(newColId, \"RenameColumn.newColId\")\n if (!table.columns[from]) throw new EmulatorActionError([\"RenameColumn\", tableId, from, to], `Column ${from} not found`)\n if (from === to) return null\n table.columns[to] = table.columns[from]\n delete table.columns[from]\n for (const row of table.rows) {\n if (from in row) {\n row[to] = row[from]\n delete row[from]\n }\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction modifyColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"ModifyColumn.tableId\"))\n const col = requireString(colId, \"ModifyColumn.colId\")\n if (!table.columns[col]) throw new EmulatorActionError([\"ModifyColumn\", tableId, colId], `Column ${col} not found`)\n table.columns[col] = { ...table.columns[col], ...(info as EmulatorColumn) }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- table ops ----------\n\nfunction addTable(state: EmulatorDocumentState, [tableId, columns]: unknown[]): string {\n const id = requireString(tableId, \"AddTable.tableId\")\n if (state.tables.has(id)) throw new EmulatorActionError([\"AddTable\", tableId], `Table ${id} already exists`)\n const cols: Record<string, EmulatorColumn> = {}\n for (const c of (columns as Array<{ id: string } & EmulatorColumn>) ?? []) {\n cols[c.id] = { ...c }\n }\n state.tables.set(id, { tableId: id, columns: cols, rows: [] })\n return id\n}\n\nfunction removeTable(state: EmulatorDocumentState, [tableId]: unknown[]): null {\n const id = requireString(tableId, \"RemoveTable.tableId\")\n state.tables.delete(id)\n if (state.selection.tableId === id) {\n const fallback = state.tables.keys().next().value as string | undefined\n if (fallback) {\n state.selection.tableId = fallback\n state.selection.rowId = null\n }\n }\n return null\n}\n\nfunction renameTable(state: EmulatorDocumentState, [from, to]: unknown[]): null {\n const fromId = requireString(from, \"RenameTable.from\")\n const toId = requireString(to, \"RenameTable.to\")\n const table = state.tables.get(fromId)\n if (!table) throw new EmulatorActionError([\"RenameTable\", fromId], `Table ${fromId} not found`)\n state.tables.delete(fromId)\n table.tableId = toId\n state.tables.set(toId, table)\n if (state.selection.tableId === fromId) state.selection.tableId = toId\n return null\n}\n\n// ---------- helpers ----------\n\nfunction ensureColumns(\n table: EmulatorTable,\n values: Record<string, unknown> | Record<string, unknown[]>,\n bulk = false\n): void {\n for (const col of Object.keys(values)) {\n if (!table.columns[col]) {\n const sample = bulk ? (values as Record<string, unknown[]>)[col]?.[0] : (values as Record<string, unknown>)[col]\n table.columns[col] = inferType(sample)\n }\n }\n}\n\nfunction inferType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction lengthOf(cols: Record<string, unknown[]>): number {\n for (const arr of Object.values(cols)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n\nfunction requireString(value: unknown, name: string): string {\n if (typeof value !== \"string\" || !value) throw new Error(`Expected non-empty string for ${name}`)\n return value\n}\n\nfunction requireNumber(value: unknown, name: string): number {\n if (typeof value !== \"number\" || Number.isNaN(value)) throw new Error(`Expected number for ${name}`)\n return value\n}\n\nfunction normalizeValuesForTable(\n table: EmulatorTable,\n values: Record<string, unknown>\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [colId, value] of Object.entries(values)) {\n out[colId] = normalizeCellValueForType(value, table.columns[colId]?.type)\n }\n return out\n}\n\nfunction normalizeColumnarForTable(\n table: EmulatorTable,\n columns: Record<string, unknown[]>\n): Record<string, unknown[]> {\n const out: Record<string, unknown[]> = {}\n for (const [colId, values] of Object.entries(columns)) {\n const type = table.columns[colId]?.type\n out[colId] = Array.isArray(values)\n ? values.map((value) => normalizeCellValueForType(value, type))\n : []\n }\n return out\n}\n\nfunction normalizeCellValueForType(value: unknown, type: string | undefined): unknown {\n if (value === null || value === undefined || typeof type !== \"string\") return value\n\n if (type.startsWith(\"Ref:\")) return normalizeRefValue(value)\n if (type.startsWith(\"RefList:\")) return normalizeRefListValue(value)\n return value\n}\n\n/**\n * Canonical ref row id for emulator storage (`Ref:*` columns).\n * Accepts bare ids, `\"12\"`, Grist tuples `[\"r\", id]` / `[\"R\", tableId, id]`,\n * and detailed-ref shapes `{ rowId }` used after safe-parse / RDG edits.\n */\nfunction extractRefRowId(value: unknown): number | null {\n if (value === null || value === undefined) return null\n if (value && typeof value === \"object\" && \"__ref\" in value) {\n const inner = (value as { rowId?: unknown }).rowId\n return extractRefRowId(inner)\n }\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return extractRefRowId((value as { rowId: unknown }).rowId)\n }\n const fromTuple = coerceGristDocApiRefRowId(value)\n if (fromTuple !== undefined && fromTuple > 0) return Math.trunc(fromTuple)\n return toPositiveInt(value)\n}\n\nfunction normalizeRefValue(value: unknown): number | null {\n return extractRefRowId(value)\n}\n\nfunction normalizeRefListValue(value: unknown): unknown[] {\n const toIdList = (items: unknown[]): number[] =>\n Array.from(\n new Set(items.map((item) => extractRefRowId(item)).filter((item): item is number => item !== null))\n )\n\n // Grist tuple form: [\"L\", ...ids]\n if (Array.isArray(value) && value[0] === \"L\") {\n return [\"L\", ...toIdList(value.slice(1))]\n }\n if (Array.isArray(value)) {\n return [\"L\", ...toIdList(value)]\n }\n if (typeof value === \"string\") {\n const tokens = value.split(\",\").map((t) => t.trim()).filter(Boolean)\n return [\"L\", ...toIdList(tokens)]\n }\n if (value && typeof value === \"object\" && Array.isArray((value as { rowIds?: unknown }).rowIds)) {\n return [\"L\", ...toIdList((value as { rowIds: unknown[] }).rowIds)]\n }\n return [\"L\"]\n}\n\nfunction toPositiveInt(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) return Math.trunc(value)\n if (typeof value === \"string\") {\n const n = Number.parseInt(value.trim(), 10)\n if (Number.isFinite(n) && n > 0) return n\n }\n return null\n}\n","/**\n * Helpers to project an {@link EmulatorTable}'s row-array storage into Grist's\n * columnar wire format expected by `fetchTable` / `fetchSelectedTable`:\n *\n * { id: number[], colA: unknown[], colB: unknown[], ... }\n *\n * When `keepEncoded` is `false` (Grist's default for these APIs), values are\n * passed through as-is — JS-native primitives (string / number / boolean /\n * Date / arrays) are valid Grist plugin values. When `keepEncoded` is `true`,\n * Date columns are emitted in tuple form (`[\"d\", epoch]`) so callers can\n * round-trip them.\n */\n\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorTable } from \"./types\"\n\nexport type ColumnarTable = Record<string, unknown[]>\n\nexport type ToColumnarOptions = {\n keepEncoded?: boolean\n}\n\nexport function rowsToColumnar(\n table: EmulatorTable,\n rows: readonly GristRowRecord[],\n options: ToColumnarOptions = {}\n): ColumnarTable {\n const cols = Object.keys(table.columns)\n const out: ColumnarTable = { id: rows.map((r) => r.id) }\n for (const col of cols) {\n out[col] = rows.map((r) => encodeForWire(r[col], table.columns[col]?.type, options.keepEncoded))\n }\n return out\n}\n\nexport function rowToRecord(\n table: EmulatorTable,\n row: GristRowRecord,\n options: ToColumnarOptions = {}\n): Record<string, unknown> {\n const out: Record<string, unknown> = { id: row.id }\n for (const col of Object.keys(table.columns)) {\n out[col] = encodeForWire(row[col], table.columns[col]?.type, options.keepEncoded)\n }\n return out\n}\n\nfunction encodeForWire(value: unknown, type: string | undefined, keepEncoded: boolean | undefined): unknown {\n if (value instanceof Date) {\n const epoch = Math.floor(value.getTime() / 1000)\n if (keepEncoded) {\n return type && type.startsWith(\"DateTime\") ? [\"D\", epoch, \"UTC\"] : [\"d\", epoch]\n }\n return epoch\n }\n return value\n}\n","import { applyUserActions } from \"../core/action-engine\"\nimport { rowsToColumnar } from \"../core/columnar\"\nimport { getTable, synthesizeTablesColumnMeta, synthesizeTablesMeta } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristDocApiImpl } from \"./types\"\n\n/**\n * `GristDocAPI` host implementation. Backs `grist.docApi.*` methods such as\n * `getDocName`, `listTables`, `fetchTable`, `applyUserActions` and\n * `getAccessToken`.\n *\n * `applyUserActions` is the only mutation entry point — every widget write\n * lands here, so tests can listen on the bus for `user-action` events to\n * assert exactly which actions a UI flow generated.\n */\nexport function createGristDocApiImpl(state: EmulatorDocumentState, bus: EventBus): GristDocApiImpl {\n return {\n async getDocName() {\n return state.docName\n },\n\n async listTables() {\n return [...state.tables.keys()]\n },\n\n async fetchTable(tableId) {\n if (tableId === \"_grist_Tables\") {\n return synthesizeTablesMeta(state)\n }\n if (tableId === \"_grist_Tables_column\") {\n return synthesizeTablesColumnMeta(state)\n }\n const table = getTable(state, tableId)\n return rowsToColumnar(table, table.rows)\n },\n\n async applyUserActions(actions) {\n const result = applyUserActions(state, bus, actions)\n return { retValues: result.retValues }\n },\n\n async getAccessToken() {\n if (!state.accessToken) {\n const err = new Error(\"getAccessToken not available (no token configured on emulator)\")\n // Mirror Grist's protocol: rejected stub call.\n throw err\n }\n return { ...state.accessToken }\n },\n }\n}\n","import { rowToRecord, rowsToColumnar } from \"../core/columnar\"\nimport { findRow, getSelectedTable } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristViewImpl } from \"./types\"\n\n/**\n * `GristView` host implementation.\n *\n * Exposes the section-scoped data API the widget uses through\n * `grist.docApi.fetchSelectedTable()`, `fetchSelectedRecord()` and\n * `setCursorPos()`. Reads from the emulator state, writes to the same state\n * via the action engine where applicable, and emits events on the bus so\n * subscribers (transports, inspector, tests) stay in sync.\n *\n * IMPORTANT: `fetchSelectedTable` always returns Grist's **columnar** wire\n * shape. The production `grist-plugin-api.js` wrapper (which the iframe\n * transport talks to) expects the raw RPC stub to return columnar and does\n * the `format: \"rows\"` transposition + `keepEncoded: false` decoding itself.\n * Returning rows here used to crash the wrapper's `mapValues(data, col =>\n * col.map(decodeObject))` pass — `data` was an array, `col` was a row object\n * with no `.map` method — so widgets observed `records === null` forever.\n * The inline transport mirrors the same wrapper semantics in\n * `transports/inline.ts` so widget code sees identical results in both modes.\n */\nexport function createGristViewImpl(state: EmulatorDocumentState, bus: EventBus): GristViewImpl {\n return {\n async fetchSelectedTable(options) {\n const table = getSelectedTable(state)\n return rowsToColumnar(table, table.rows, { keepEncoded: options?.keepEncoded })\n },\n\n async fetchSelectedRecord(rowId, options) {\n const table = getSelectedTable(state)\n const row = findRow(table, rowId)\n if (!row) throw new Error(`No row ${rowId} in ${table.tableId}`)\n return rowToRecord(table, row, { keepEncoded: options?.keepEncoded })\n },\n\n async allowSelectBy() {\n return state.configuration?.allowSelectBy ?? false\n },\n\n async setSelectedRows(rowIds) {\n if (!rowIds || rowIds.length === 0) {\n state.selection.rowId = null\n } else {\n state.selection.rowId = rowIds[0]\n }\n bus.emit({\n type: \"cursor-change\",\n tableId: state.selection.tableId,\n rowId: state.selection.rowId,\n })\n },\n\n async setCursorPos(cursor) {\n const tableId = state.selection.tableId\n if (typeof cursor.rowId === \"number\") state.selection.rowId = cursor.rowId\n state.selection.cursor = { ...state.selection.cursor, ...cursor }\n bus.emit({\n type: \"cursor-change\",\n tableId,\n rowId: state.selection.rowId,\n cursor: state.selection.cursor,\n })\n },\n }\n}\n","import type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { WidgetApiImpl } from \"./types\"\n\n/**\n * `WidgetAPI` host implementation, backing `grist.widgetApi.*`. Reads and\n * writes the per-widget options bag persisted on the emulator state. Each\n * mutation triggers an `options-change` event so subscribers (the transport\n * pushes an `onOptions` message; tests/inspector update accordingly) stay in\n * lock-step with the document.\n */\nexport function createWidgetApiImpl(state: EmulatorDocumentState, bus: EventBus): WidgetApiImpl {\n function emit() {\n bus.emit({\n type: \"options-change\",\n options: { ...state.widgetOptions },\n interaction: { ...state.widgetInteraction },\n })\n }\n\n return {\n async getOption(key) {\n return state.widgetOptions[key]\n },\n\n async setOption(key, value) {\n state.widgetOptions[key] = value\n emit()\n },\n\n async getOptions() {\n return Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n },\n\n async setOptions(options) {\n state.widgetOptions = { ...state.widgetOptions, ...options }\n emit()\n },\n\n async clearOptions() {\n state.widgetOptions = {}\n emit()\n },\n }\n}\n","/**\n * Bundles the six host-side Grist API implementations into one record so\n * transports (iframe, inline) can wire them up uniformly.\n */\n\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport { createCommandApiImpl } from \"./command-api\"\nimport { createCustomSectionApiImpl } from \"./custom-section-api\"\nimport { createGristApiImpl } from \"./grist-api\"\nimport { createGristDocApiImpl } from \"./grist-doc-api\"\nimport { createGristViewImpl } from \"./grist-view\"\nimport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\nimport { createWidgetApiImpl } from \"./widget-api\"\n\nexport type EmulatorApiBundle = {\n GristView: GristViewImpl\n GristDocAPI: GristDocApiImpl\n WidgetAPI: WidgetApiImpl\n CustomSectionAPI: CustomSectionApiImpl\n GristAPI: GristApiImpl\n CommandAPI: CommandApiImpl\n}\n\n/**\n * Build the implementations bound to a given document state and event bus.\n * Cheap to call — every method delegates to the (mutable) `state`.\n */\nexport function createApiBundle(state: EmulatorDocumentState, bus: EventBus): EmulatorApiBundle {\n return {\n GristView: createGristViewImpl(state, bus),\n GristDocAPI: createGristDocApiImpl(state, bus),\n WidgetAPI: createWidgetApiImpl(state, bus),\n CustomSectionAPI: createCustomSectionApiImpl(state, bus),\n GristAPI: createGristApiImpl(),\n CommandAPI: createCommandApiImpl(bus),\n }\n}\n\nexport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\n","/**\n * Tiny pub-sub used to broadcast every emulator state change to:\n * - the transports (which translate events into protocol messages),\n * - the React DevTools inspector (timeline view),\n * - the testing harness (assertions on emitted events).\n */\n\nimport type { GristCursorPos, GristWidgetColumnMap, GristWidgetInteraction } from \"../../sdk/types\"\n\nexport type EmulatorEvent =\n | { type: \"data-change\"; tableId: string }\n | { type: \"cursor-change\"; tableId: string; rowId: number | \"new\" | null; cursor?: GristCursorPos }\n | { type: \"options-change\"; options: Record<string, unknown>; interaction: GristWidgetInteraction }\n | { type: \"theme-change\"; message: Record<string, unknown> }\n | { type: \"ready\"; configuration: unknown }\n | { type: \"user-action\"; action: unknown[] }\n | { type: \"mappings-change\"; mappings: GristWidgetColumnMap | null }\n\nexport type EmulatorEventListener = (event: EmulatorEvent) => void\n\nexport type EventBus = {\n emit: (event: EmulatorEvent) => void\n on: (listener: EmulatorEventListener) => () => void\n history: () => readonly EmulatorEvent[]\n clear: () => void\n}\n\nexport type EventBusOptions = {\n /** Cap on history length (DevTools / tests). Defaults to 200. */\n historyLimit?: number\n}\n\nexport function createEventBus(options: EventBusOptions = {}): EventBus {\n const limit = options.historyLimit ?? 200\n const listeners = new Set<EmulatorEventListener>()\n const history: EmulatorEvent[] = []\n\n return {\n emit(event) {\n history.push(event)\n if (history.length > limit) history.shift()\n for (const fn of [...listeners]) {\n try {\n fn(event)\n } catch (err) {\n console.error(\"[grist-emulator] event listener threw:\", err)\n }\n }\n },\n on(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n history() {\n return history\n },\n clear() {\n history.length = 0\n },\n }\n}\n","export type GristThemeAppearance = \"light\" | \"dark\"\n\n/** Host → widget postMessage shape used by `grist-plugin-api.js` (`onThemeChange`). */\nexport type GristThemeHostMessage = {\n theme: {\n appearance: GristThemeAppearance\n name: string\n colors: Record<string, string>\n }\n fromReady?: boolean\n}\n\nexport function buildGristThemeHostMessage(\n appearance: GristThemeAppearance,\n options?: { fromReady?: boolean }\n): GristThemeHostMessage {\n return {\n theme: {\n appearance,\n name: appearance,\n colors: {},\n },\n ...(options?.fromReady ? { fromReady: true } : {}),\n }\n}\n","/**\n * Iframe transport — the production-fidelity path.\n *\n * - The iframe loads the real `https://docs.getgrist.com/grist-plugin-api.js`\n * so widget code talks to `window.grist` exactly like in production.\n * - The host (this file) instantiates a `grain-rpc` `Rpc` and wires:\n * * outgoing → `iframe.contentWindow.postMessage(msg, targetOrigin)`\n * * incoming → `window.addEventListener(\"message\", ...)` filtered by\n * `event.source === iframe.contentWindow`.\n * - The Rpc registers the six host impls under their canonical names so\n * `grist-plugin-api.js`'s stubs find them.\n * - Custom messages (cursor / data / options / theme) are pushed via\n * `rpc.postMessage(...)` which `grist-plugin-api.js` dispatches to its\n * internal \"message\" event listeners (the ones used by `onRecord` etc.).\n *\n * Sequence:\n * 1. Host calls `rpc.queueOutgoingUntilReadyMessage()` so messages are\n * buffered until the widget signals it is ready.\n * 2. Widget loads, runs `grist-plugin-api.js`, calls `grist.ready(...)`.\n * 3. Widget's `grist-plugin-api.js` posts a \"ready\" message → host's Rpc\n * flushes the buffered outgoing messages.\n * 4. Widget's `grist.ready(...)` triggers `CustomSectionAPI.configure(...)`\n * on us; we react by emitting initial state (options + cursor + data).\n */\n\nimport { MsgType, Rpc } from \"grain-rpc\"\n\nimport type { GristWidgetInteraction } from \"../../sdk/types\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\nimport { buildGristThemeHostMessage } from \"../theme-message\"\nimport type { EmulatorTransport, TransportContext } from \"./types\"\n\nexport type IframeTransportOptions = TransportContext & {\n iframe: HTMLIFrameElement\n /** `postMessage` target origin. Defaults to \"*\" — fine for emulator usage. */\n targetOrigin?: string\n}\n\nexport function createIframeTransport(options: IframeTransportOptions): EmulatorTransport {\n const { iframe, state, bus, api, targetOrigin = \"*\" } = options\n const timers = new Set<ReturnType<typeof setTimeout>>()\n\n const rpc = new Rpc({\n sendMessage: (msg) => {\n const target = iframe.contentWindow\n if (!target) return\n target.postMessage(msg, targetOrigin)\n },\n logger: { info: () => {}, warn: () => {} },\n })\n\n rpc.queueOutgoingUntilReadyMessage()\n\n /**\n * `grist-plugin-api.js` obtains `docApi` via `getStub(\"GristDocAPI@grist\", …)`, which sends\n * `RpcCall` messages with `mdest: \"grist\"`. In full Grist that forwarder reaches a doc-worker\n * `Rpc`; here all host impls live on this same `Rpc`, so forwarding to `this` would re-emit\n * the call to the iframe and the widget would reject it as `Unknown interface`. Strip `mdest`\n * so `GristDocAPI` resolves to our local `registerImpl` surface (same effective path as tests\n * that use `getStub(\"GristDocAPI\")` without `@grist`).\n */\n const receiveFromWidget = rpc.receiveMessage.bind(rpc)\n rpc.receiveMessage = (msg: unknown) => {\n if (\n msg &&\n typeof msg === \"object\" &&\n (msg as { mtype?: unknown }).mtype === MsgType.RpcCall &&\n (msg as { mdest?: unknown }).mdest === \"grist\"\n ) {\n const copy = { ...(msg as Record<string, unknown>) }\n delete copy.mdest\n receiveFromWidget(copy as never)\n return\n }\n receiveFromWidget(msg as never)\n }\n\n const onMessage = (event: MessageEvent) => {\n if (event.source !== iframe.contentWindow) return\n // Dev runtimes may post unrelated messages (HMR, devtools). Forwarding\n // them to grain-rpc can throw and disturb the ready handshake.\n if (!isRpcEnvelope(event.data)) return\n rpc.receiveMessage(event.data)\n }\n window.addEventListener(\"message\", onMessage)\n\n rpc.registerImpl(\"GristView\", api.GristView)\n rpc.registerImpl(\"GristDocAPI\", api.GristDocAPI)\n rpc.registerImpl(\"WidgetAPI\", api.WidgetAPI)\n rpc.registerImpl(\"CustomSectionAPI\", api.CustomSectionAPI)\n rpc.registerImpl(\"_grist_api\", api.GristAPI)\n rpc.registerImpl(\"CommandAPI\", api.CommandAPI)\n\n const buildInteraction = options.buildInteraction ?? defaultInteraction(state)\n const cursorOf = options.cursor ?? (() => state.selection.cursor)\n const initialCursorOf = options.initialCursor ?? (() => state.selection.rowId)\n\n type HostPushOptions = { mappingsChange?: boolean }\n\n function fireDataChange(tableId?: string, opts?: HostPushOptions) {\n safePostMessage({\n tableId: tableId ?? state.selection.tableId,\n dataChange: true,\n ...(opts?.mappingsChange ? { mappingsChange: true } : {}),\n })\n }\n function fireCursor(rowId?: number | \"new\" | null, opts?: HostPushOptions) {\n const id = rowId === undefined ? initialCursorOf() : rowId\n if (id === null) return\n safePostMessage({\n tableId: state.selection.tableId,\n rowId: id,\n cursor: cursorOf(),\n ...(opts?.mappingsChange ? { mappingsChange: true } : {}),\n })\n }\n function fireOptions() {\n safePostMessage({\n options: hasOptions(state.widgetOptions) ? { ...state.widgetOptions } : null,\n settings: { ...buildInteraction() },\n })\n }\n function fireTheme(message: Record<string, unknown>) {\n safePostMessage(message)\n }\n function emitInitialState(opts?: HostPushOptions) {\n fireOptions()\n if (options.initialTheme) {\n fireTheme(buildGristThemeHostMessage(options.initialTheme, { fromReady: true }))\n }\n fireDataChange(undefined, opts)\n fireCursor(undefined, opts)\n }\n\n function emitInitialStateWithReplay(opts?: HostPushOptions) {\n // Keep initial state delivery resilient when widget subscriptions are\n // attached slightly after ready (common in dev/HMR): send now, then replay\n // on the next microtask and next macrotask.\n emitInitialState(opts)\n queueMicrotask(() => emitInitialState(opts))\n const timer = setTimeout(() => {\n timers.delete(timer)\n emitInitialState(opts)\n }, 0)\n timers.add(timer)\n }\n\n // Bus → transport push. Listens on every emulator state mutation and pushes\n // the matching protocol message to the iframe.\n const offBus = bus.on((event: EmulatorEvent) => {\n switch (event.type) {\n case \"ready\":\n emitInitialStateWithReplay()\n break\n case \"data-change\":\n fireDataChange(event.tableId)\n break\n case \"cursor-change\": {\n const rowId = event.rowId === null ? state.selection.rowId : event.rowId\n if (rowId !== null) {\n safePostMessage({\n tableId: event.tableId,\n rowId,\n cursor: cursorOf(),\n })\n }\n // Match inline transport: cursor moves must also signal `dataChange` so\n // `grist-plugin-api.js` refetches the row and calls `onRecord` again.\n // Cursor-only postMessages left widgets stuck on the first row (#playground).\n fireDataChange(event.tableId)\n break\n }\n case \"options-change\":\n fireOptions()\n break\n case \"mappings-change\":\n // grist-plugin-api only refetches `sectionApi.mappings()` when `mappingsChange`\n // is set on the host message (see getMappingsIfChanged in grist-core).\n emitInitialStateWithReplay({ mappingsChange: true })\n break\n case \"theme-change\":\n fireTheme(event.message)\n break\n }\n })\n\n rpc.processIncoming()\n\n function safePostMessage(payload: Record<string, unknown>): void {\n try {\n rpc.postMessage(payload)\n } catch (err) {\n // Transport failures (broken iframe, crashed widget script, etc.) should\n // never break host-side emulator mutations. We keep the emulator state\n // authoritative and treat iframe delivery as best-effort.\n console.warn(\"[grist-emulator/iframe] failed to deliver postMessage\", err)\n }\n }\n\n return {\n dispose() {\n window.removeEventListener(\"message\", onMessage)\n offBus()\n for (const timer of timers) clearTimeout(timer)\n timers.clear()\n // grain-rpc 0.1.7 doesn't expose `close()`. We rely on listener removal\n // + GC to dispose the rpc instance.\n },\n fireDataChange,\n fireCursor,\n fireOptions,\n fireTheme,\n emitInitialState,\n }\n}\n\nfunction hasOptions(options: Record<string, unknown>): boolean {\n return Object.keys(options).length > 0\n}\n\nfunction isRpcEnvelope(data: unknown): data is { mtype: number } {\n if (!data || typeof data !== \"object\") return false\n return typeof (data as { mtype?: unknown }).mtype === \"number\"\n}\n\nfunction defaultInteraction(state: { widgetInteraction: GristWidgetInteraction; configuration: { requiredAccess?: string } | null }) {\n return (): GristWidgetInteraction => ({\n access_level: state.configuration?.requiredAccess ?? \"read table\",\n ...state.widgetInteraction,\n })\n}\n","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"BulkUpdateRecord\", tableId, rowIds, { col: value[], ... }]` — column arrays must align with `rowIds`. */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\n/** `[\"RenameTable\", tableId, newTableId]` */\nexport function gristRenameTableAction(tableId: string, newTableId: string): GristUserActionTuple {\n return [\"RenameTable\", tableId, newTableId]\n}\n\n/** `[\"RemoveTable\", tableId]` */\nexport function gristRemoveTableAction(tableId: string): GristUserActionTuple {\n return [\"RemoveTable\", tableId]\n}\n\n/** `[\"DuplicateTable\", tableId, newTableId, options?]` */\nexport function gristDuplicateTableAction(\n tableId: string,\n newTableId: string,\n options?: Record<string, unknown>\n): GristUserActionTuple {\n return options ? [\"DuplicateTable\", tableId, newTableId, options] : [\"DuplicateTable\", tableId, newTableId]\n}\n\n/** `[\"ReplaceTableData\", tableId, rowIds, columnarData]` */\nexport function gristReplaceTableDataAction(\n tableId: string,\n rowIds: Array<number | null>,\n columnarData: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"ReplaceTableData\", tableId, rowIds, columnarData]\n}\n\n/** `[\"SetDocumentInfo\", info]` */\nexport function gristSetDocumentInfoAction(info: Record<string, unknown>): GristUserActionTuple {\n return [\"SetDocumentInfo\", info]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","/**\n * Inline transport — synthesises a `window.grist` global wired directly to\n * the emulator state. No iframe, no postMessage, no serialization.\n *\n * Used for:\n * - SDK unit tests in jsdom (`renderWithGrist(...)`),\n * - IDE-style live previews where widget code lives in the same window\n * as the emulator host.\n *\n * The synthesised `grist` object exposes the **same** typed surface as the\n * production `grist-plugin-api.js` (see `hooks/grist-global.d.ts`). Hooks\n * call `grist.docApi.fetchTable(...)` etc. and get the answer directly from\n * the action engine.\n */\n\nimport type {\n GristCursorPos,\n GristFetchSelectedOptions,\n GristMinimalRecord,\n GristReadyOptions,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n} from \"../../sdk/types\"\nimport {\n gristAddRecordAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristRemoveRecordAction,\n gristUpdateRecordAction,\n} from \"../../sdk/helpers/grist-user-actions\"\nimport { applyUserActions } from \"../core/action-engine\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\nimport { findRow, getTable } from \"../core/document\"\nimport { resolveMappings } from \"../core/mappings\"\nimport { buildGristThemeHostMessage } from \"../theme-message\"\nimport type { EmulatorTransport, TransportContext } from \"./types\"\n\n/**\n * Shape of the synthesised global. Matches `globalThis.grist` from\n * `grist-global.d.ts`.\n */\nexport type InlineGristGlobal = {\n ready: (options?: GristReadyOptions) => Promise<void>\n onRecord: (\n cb: (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onRecords: (\n cb: (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onOptions: (cb: (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void) => void\n onNewRecord: (cb: (mappings: GristWidgetColumnMap | null) => void) => void\n mapColumnNames: (data: Record<string, unknown>) => Record<string, unknown> | null\n mapColumnNamesBack: (data: Record<string, unknown>) => Record<string, unknown>\n getOptions: () => Promise<Record<string, unknown> | null>\n getOption: (key: string) => Promise<unknown>\n setOption: (key: string, value: unknown) => Promise<void>\n setOptions: (options: Record<string, unknown>) => Promise<void>\n clearOptions: () => Promise<void>\n setCursorPos: (pos: GristCursorPos) => Promise<void>\n setSelectedRows: (rowIds: number[] | null) => Promise<void>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n docApi: {\n getDocName: () => Promise<string>\n listTables: () => Promise<string[]>\n fetchTable: (tableId: string) => Promise<Record<string, unknown[]>>\n applyUserActions: (actions: unknown[][], options?: { desc?: string }) => Promise<{ retValues: unknown[] }>\n getAccessToken?: (options?: { readOnly?: boolean }) => Promise<{ token: string; baseUrl: string }>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n }\n selectedTable: GristTableOperations\n getTable: (tableId?: string) => GristTableOperations\n sectionApi: {\n configure: (settings: GristReadyOptions) => Promise<void>\n mappings: () => Promise<GristWidgetColumnMap | null>\n }\n on: (eventName: string, listener: (...args: unknown[]) => void) => () => void\n}\n\nexport type InlineTransportOptions = TransportContext & {\n /**\n * Where to mount the synthesised `grist` global.\n * Defaults to the current window. Pass a different target (e.g. an iframe's\n * `contentWindow`) to install it in another realm.\n */\n target?: Window & typeof globalThis\n}\n\n/**\n * Returns an {@link EmulatorTransport} **and** the synthesised `grist`\n * object. `target.grist = global` is set as a side-effect for parity with\n * the production runtime.\n */\nexport function createInlineTransport(\n options: InlineTransportOptions\n): EmulatorTransport & { grist: InlineGristGlobal } {\n const { state, bus, api } = options\n const target = options.target ?? (globalThis as unknown as Window & typeof globalThis)\n\n // The SDK's `useGristAvailability` checks `window.self !== window.top`.\n // The inline transport runs in a top-level window where that's false. We\n // shim `top` so widget code thinks it's embedded — production doesn't use\n // this transport so there's no risk of leaking the shim.\n installFakeIframeContext(target)\n\n type RecordCb = (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void\n type RecordsCb = (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void\n type OptionsCb = (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void\n type NewRecordCb = (mappings: GristWidgetColumnMap | null) => void\n\n const recordCbs = new Map<RecordCb, GristFetchSelectedOptions | undefined>()\n const recordsCbs = new Map<RecordsCb, GristFetchSelectedOptions | undefined>()\n const optionsCbs = new Set<OptionsCb>()\n const newRecordCbs = new Set<NewRecordCb>()\n const generic = new Map<string, Set<(...args: unknown[]) => void>>()\n\n // Replay caches — production `grist-plugin-api.js` immediately delivers the\n // latest record / records / options to a freshly-subscribed listener, so\n // hooks that subscribe **after** `grist.ready()` still get the initial\n // payload. We mirror that behaviour here.\n type LastRecord = { record: Record<string, unknown> | null; mappings: GristWidgetColumnMap | null }\n type LastRecords = { records: Record<string, unknown>[]; mappings: GristWidgetColumnMap | null }\n type LastOptions = { options: Record<string, unknown> | null; interaction: GristWidgetInteraction }\n let lastRecord: LastRecord | null = null\n let lastRecords: LastRecords | null = null\n let lastOptions: LastOptions | null = null\n let lastNewRecord: GristWidgetColumnMap | null | undefined = undefined\n\n const buildInteraction = options.buildInteraction ?? (() => ({\n access_level: state.configuration?.requiredAccess ?? \"read table\",\n ...state.widgetInteraction,\n }))\n\n async function pushRecord(rowId: number | \"new\" | null) {\n const mappings = resolveMappings(state)\n if (rowId === \"new\") {\n lastNewRecord = mappings\n for (const cb of newRecordCbs) {\n try { cb(mappings) } catch (err) { logErr(err) }\n }\n lastRecord = { record: null, mappings }\n for (const [cb] of recordCbs) {\n try { cb(null, mappings) } catch (err) { logErr(err) }\n }\n return\n }\n if (rowId === null) {\n lastRecord = { record: null, mappings }\n for (const [cb] of recordCbs) {\n try { cb(null, mappings) } catch (err) { logErr(err) }\n }\n return\n }\n let record: Record<string, unknown> | null = null\n try {\n record = await api.GristView.fetchSelectedRecord(rowId)\n } catch (err) {\n logErr(err)\n }\n lastRecord = { record, mappings }\n for (const [cb, opts] of recordCbs) {\n try {\n const r = opts?.keepEncoded\n ? await api.GristView.fetchSelectedRecord(rowId, { keepEncoded: true })\n : record\n cb(r, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n async function pushRecords() {\n const mappings = resolveMappings(state)\n let baseRows: Record<string, unknown>[] = []\n try {\n const columnar = await api.GristView.fetchSelectedTable({})\n baseRows = columnsToRows(columnar)\n } catch (err) {\n logErr(err)\n }\n lastRecords = { records: baseRows, mappings }\n for (const [cb, opts] of recordsCbs) {\n try {\n const fetchOptions = coerceFetchOptions(opts)\n // Re-fetch only when the subscriber asked for a different shape\n // (e.g. `keepEncoded: true`). Otherwise reuse the decoded rows we\n // already have to avoid extra work and to match production where\n // the same fetch is broadcast to every listener.\n const rows = fetchOptions?.keepEncoded\n ? columnsToRows(await api.GristView.fetchSelectedTable({ keepEncoded: true }))\n : baseRows\n cb(rows, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n /**\n * Mirror what `viewApi.fetchSelectedTable` does inside `grist-plugin-api.js`:\n * the host RPC stub always returns columnar; the wrapper applies the\n * `format: \"rows\"` transpose (and would decode encoded values when\n * `keepEncoded: false` — a no-op here because our `rowsToColumnar` already\n * emits JS-native primitives in that case).\n *\n * Keeping this logic on the inline side guarantees that widgets see the\n * same result whether they go through the iframe transport (real plugin\n * wrapper) or the inline transport (this wrapper).\n */\n async function fetchSelectedTableShaped(\n opts: GristFetchSelectedOptions | undefined\n ): Promise<Record<string, unknown[]> | Record<string, unknown>[]> {\n const fetchOptions = coerceFetchOptions(opts)\n const columnar = (await api.GristView.fetchSelectedTable(\n fetchOptions ? { keepEncoded: fetchOptions.keepEncoded } : {}\n )) as Record<string, unknown[]>\n if (fetchOptions?.format === \"rows\") return columnsToRows(columnar)\n return columnar\n }\n\n function pushOptions() {\n const opts = Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n const interaction = buildInteraction()\n lastOptions = { options: opts, interaction }\n for (const cb of optionsCbs) {\n try { cb(opts, interaction) } catch (err) { logErr(err) }\n }\n }\n\n const offBus = bus.on(async (event: EmulatorEvent) => {\n switch (event.type) {\n case \"data-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"cursor-change\":\n await pushRecord(event.rowId)\n break\n case \"options-change\":\n pushOptions()\n break\n case \"ready\":\n pushOptions()\n if (options.initialTheme) {\n notify(\"message\", buildGristThemeHostMessage(options.initialTheme, { fromReady: true }))\n }\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"mappings-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"theme-change\":\n notify(\"message\", event.message)\n break\n }\n })\n\n function makeTableOps(tableId: string): GristTableOperations {\n return {\n async getTableId() { return tableId },\n async create(records, options) {\n const list = Array.isArray(records) ? records : [records]\n const ids: GristMinimalRecord[] = []\n for (const r of list) {\n const result = applyUserActions(state, bus, [\n gristAddRecordAction(tableId, parseFields(r.fields, options)),\n ])\n ids.push({ id: result.retValues[0] as number })\n }\n return Array.isArray(records) ? ids : ids[0]\n },\n async update(records: GristTableUpdateRecord | GristTableUpdateRecord[], options?: GristTableOpOptions) {\n const list = Array.isArray(records) ? records : [records]\n const actions = list.map((r) => gristUpdateRecordAction(tableId, r.id, parseFields(r.fields, options)))\n applyUserActions(state, bus, actions)\n },\n async upsert(records: GristTableUpsertRecord | GristTableUpsertRecord[], options?: GristTableUpsertOptions) {\n const list = Array.isArray(records) ? records : [records]\n const allowAdd = options?.add !== false\n const allowUpdate = options?.update !== false\n const table = getTable(state, tableId)\n const actions: unknown[][] = []\n for (const r of list) {\n const matches = table.rows.filter((row) =>\n Object.entries(r.require).every(([k, v]) => row[k] === v)\n )\n if (matches.length > 0) {\n if (!allowUpdate) continue\n const fields = parseFields(r.fields ?? {}, options)\n for (const m of matches) actions.push(gristUpdateRecordAction(tableId, m.id, fields))\n } else if (allowAdd) {\n actions.push(gristAddRecordAction(tableId, { ...r.require, ...parseFields(r.fields ?? {}, options) }))\n }\n }\n if (actions.length > 0) applyUserActions(state, bus, actions)\n },\n async destroy(recordIds: number | number[]) {\n if (Array.isArray(recordIds)) {\n applyUserActions(state, bus, [gristBulkRemoveRecordAction(tableId, recordIds)])\n } else {\n applyUserActions(state, bus, [gristRemoveRecordAction(tableId, recordIds)])\n }\n // touch the unused bulk-add reference for tree-shaking parity, no-op\n void gristBulkAddRecordAction\n void gristBulkUpdateRecordAction\n },\n }\n }\n\n function notify(event: string, ...args: unknown[]) {\n const set = generic.get(event)\n if (!set) return\n for (const fn of set) {\n try { fn(...args) } catch (err) { logErr(err) }\n }\n }\n\n const grist: InlineGristGlobal = {\n async ready(opts) {\n await api.CustomSectionAPI.configure(opts ? { ...opts, onEditOptions: undefined } as unknown as Record<string, unknown> : {})\n },\n\n onRecord(cb, opts) {\n recordCbs.set(cb, opts)\n // Replay last value so late subscribers don't miss the initial event.\n if (lastRecord) {\n try { cb(lastRecord.record, lastRecord.mappings) } catch (err) { logErr(err) }\n }\n },\n onRecords(cb, opts) {\n recordsCbs.set(cb, opts)\n if (lastRecords) {\n try { cb(lastRecords.records, lastRecords.mappings) } catch (err) { logErr(err) }\n }\n },\n onOptions(cb) {\n optionsCbs.add(cb)\n if (lastOptions) {\n try { cb(lastOptions.options, lastOptions.interaction) } catch (err) { logErr(err) }\n }\n },\n onNewRecord(cb) {\n newRecordCbs.add(cb)\n if (lastNewRecord !== undefined) {\n try { cb(lastNewRecord) } catch (err) { logErr(err) }\n }\n },\n\n mapColumnNames(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return null\n const out: Record<string, unknown> = {}\n let allMapped = true\n for (const [logical, real] of Object.entries(mappings)) {\n if (Array.isArray(real)) {\n out[logical] = real.map((r) => data[r])\n } else if (typeof real === \"string\") {\n out[logical] = data[real]\n } else {\n allMapped = false\n }\n }\n return allMapped ? out : null\n },\n mapColumnNamesBack(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return data\n const out: Record<string, unknown> = {}\n for (const [logical, real] of Object.entries(mappings)) {\n if (typeof real === \"string\" && logical in data) {\n out[real] = data[logical]\n }\n }\n return out\n },\n\n getOption: (k) => api.WidgetAPI.getOption(k),\n setOption: (k, v) => api.WidgetAPI.setOption(k, v),\n getOptions: () => api.WidgetAPI.getOptions(),\n setOptions: (o) => api.WidgetAPI.setOptions(o),\n clearOptions: () => api.WidgetAPI.clearOptions(),\n\n setCursorPos: (pos) => api.GristView.setCursorPos(pos),\n setSelectedRows: (rowIds) => api.GristView.setSelectedRows(rowIds),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) => api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n\n docApi: {\n getDocName: () => api.GristDocAPI.getDocName(),\n listTables: () => api.GristDocAPI.listTables(),\n fetchTable: (id) => api.GristDocAPI.fetchTable(id),\n applyUserActions: (actions, options) => api.GristDocAPI.applyUserActions(actions, options),\n getAccessToken: (opts) => api.GristDocAPI.getAccessToken(opts),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) =>\n api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n },\n\n get selectedTable() {\n return makeTableOps(state.selection.tableId)\n },\n\n getTable(tableId) {\n return makeTableOps(tableId ?? state.selection.tableId)\n },\n\n sectionApi: {\n configure: (settings) => api.CustomSectionAPI.configure(settings as unknown as Record<string, unknown>),\n mappings: () => api.CustomSectionAPI.mappings(),\n },\n\n on(eventName, listener) {\n let set = generic.get(eventName)\n if (!set) generic.set(eventName, (set = new Set()))\n set.add(listener)\n return () => set!.delete(listener)\n },\n }\n\n ;(target as unknown as { grist: InlineGristGlobal }).grist = grist\n\n return {\n grist,\n dispose() {\n offBus()\n // Restore the global (only if we still own it).\n const t = target as unknown as { grist?: unknown }\n if (t.grist === grist) delete t.grist\n recordCbs.clear()\n recordsCbs.clear()\n optionsCbs.clear()\n newRecordCbs.clear()\n generic.clear()\n lastRecord = null\n lastRecords = null\n lastOptions = null\n lastNewRecord = undefined\n },\n fireDataChange(tableId) {\n bus.emit({ type: \"data-change\", tableId: tableId ?? state.selection.tableId })\n },\n fireCursor(rowId) {\n const id = rowId === undefined ? state.selection.rowId : rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId: id })\n },\n fireOptions() {\n pushOptions()\n },\n fireTheme(message) {\n bus.emit({ type: \"theme-change\", message })\n },\n emitInitialState() {\n pushOptions()\n void pushRecords().then(() => pushRecord(state.selection.rowId))\n },\n }\n}\n\nfunction columnsToRows(columnar: Record<string, unknown[]>): Record<string, unknown>[] {\n const cols = Object.keys(columnar)\n if (cols.length === 0) return []\n const length = (columnar[cols[0]] ?? []).length\n const rows: Record<string, unknown>[] = []\n for (let i = 0; i < length; i++) {\n const row: Record<string, unknown> = {}\n for (const c of cols) row[c] = columnar[c][i]\n rows.push(row)\n }\n return rows\n}\n\nfunction parseFields(fields: Record<string, unknown>, _options?: GristTableOpOptions): Record<string, unknown> {\n // The emulator currently doesn't implement string-parsing; pass-through.\n // Hook into here to add date/number parsing when we surface that toggle.\n return { ...fields }\n}\n\nfunction coerceFetchOptions(\n opts: GristFetchSelectedOptions | undefined\n): { keepEncoded?: boolean; format?: \"rows\" | \"columns\" } | undefined {\n if (!opts) return undefined\n const format = opts.format === \"rows\" || opts.format === \"columns\" ? opts.format : undefined\n return { keepEncoded: opts.keepEncoded, format }\n}\n\nfunction logErr(err: unknown) {\n console.error(\"[grist-emulator/inline]\", err)\n}\n\n// Touch helpers to keep them tree-shake-friendly even if unused in current scope.\nvoid findRow\n\n/**\n * Make `window.self !== window.top` evaluate to `true`. The SDK uses this\n * exact comparison in `useGristAvailability` to detect an iframe environment.\n *\n * Inline transports run inside the host window (tests, IDE preview) and would\n * otherwise be flagged as \"not embedded\" — this shim is the same trick we use\n * in the testing harness and is safe because the inline transport is never\n * shipped to production.\n */\nfunction installFakeIframeContext(target: Window & typeof globalThis) {\n try {\n if (target.self !== target.top) return\n Object.defineProperty(target, \"top\", {\n configurable: true,\n get: () => ({}),\n })\n } catch {\n // Some environments lock these globals; ignore silently.\n }\n}\n","import { z } from \"zod\"\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst emulatorRowSchema = z\n .object({ id: z.number() })\n .catchall(z.unknown())\n\nconst formulaKindSchema = z.enum([\"computed\", \"trigger\", \"none\", \"empty_slot\"])\n\nconst replicaColumnSchema = z\n .object({\n colRef: z.number().optional(),\n type: z.string().optional(),\n label: z.string().optional(),\n parentPos: z.number().optional(),\n isFormula: z.boolean().optional(),\n formulaKind: formulaKindSchema.optional(),\n formula: z.string().optional(),\n description: z.string().optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n displayColRef: z.number().optional(),\n visibleColRef: z.number().optional(),\n })\n .strict()\n\nconst replicaTableSchema = z\n .object({\n label: z.string().optional(),\n columns: z.record(z.string(), replicaColumnSchema).optional(),\n rows: z.array(emulatorRowSchema).optional(),\n rowCount: z.number().optional(),\n dataOmitted: z.boolean().optional(),\n dataOmittedReason: z.string().optional(),\n error: z.string().optional(),\n })\n .strict()\n\nconst replicaSelectionSchema = z\n .object({\n tableId: z.string().optional(),\n rowId: z.union([z.number(), z.literal(\"new\"), z.null()]).optional(),\n mappings: z.unknown().nullable().optional(),\n cursor: z.unknown().optional(),\n })\n .strict()\n\nconst replicaWidgetConfigurationSchema = z\n .object({\n requiredAccess: z.string().optional(),\n columns: z.unknown().optional(),\n allowSelectBy: z.boolean().optional(),\n hasCustomOptions: z.boolean().optional(),\n })\n .strict()\n\nconst replicaAccessTokenSchema = z\n .object({\n token: z.string(),\n baseUrl: z.string(),\n ttlMsecs: z.number(),\n })\n .strict()\n\nconst replicaDocumentSchema = z\n .object({\n generatedAt: z.string(),\n source: z.string().optional(),\n docName: z.string().optional(),\n mode: z.enum([\"schema-only\", \"schema+samples\", \"schema+data\"]).optional(),\n tables: z.record(z.string(), replicaTableSchema),\n selection: replicaSelectionSchema.optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n widgetInteraction: z.unknown().optional(),\n configuration: replicaWidgetConfigurationSchema.optional(),\n accessToken: replicaAccessTokenSchema.nullable().optional(),\n })\n .strict()\n .refine((value) => Object.keys(value.tables).length > 0, {\n message: \"at least one table is required\",\n path: [\"tables\"],\n })\n\nfunction formatZodError(prefix: string, error: z.ZodError): Error {\n const details = error.issues\n .map((issue) => {\n const where = issue.path.length > 0 ? issue.path.join(\".\") : \"<root>\"\n return `${where}: ${issue.message}`\n })\n .join(\"; \")\n return new Error(`${prefix}: ${details}`)\n}\n\nexport function safeParseDocument(input: unknown) {\n return replicaDocumentSchema.safeParse(input)\n}\n\nexport function parseDocument(input: unknown): GristReplicaDocument {\n const result = safeParseDocument(input)\n if (!result.success) {\n throw formatZodError(\"parseDocument\", result.error)\n }\n return result.data as GristReplicaDocument\n}\n","/**\n * Top-level emulator factory. Produces a fully-wired emulator instance:\n *\n * - typed in-memory document state,\n * - shared event bus,\n * - the six host API impls,\n * - one transport (inline by default, iframe when an iframe is provided),\n * - imperative helpers (`mutate`, `apply`, `selectRow`, `selectTable`)\n * that drive the document via the action engine and emit corresponding\n * events.\n *\n * The instance is multi-instance friendly: nothing is stored on `window`.\n */\n\nimport { createApiBundle } from \"./api\"\nimport type { EmulatorApiBundle } from \"./api\"\nimport { applyUserActions } from \"./core/action-engine\"\nimport { createDocument } from \"./core/document\"\nimport { createEventBus } from \"./core/event-bus\"\nimport type { EventBus } from \"./core/event-bus\"\nimport { resolveMappings } from \"./core/mappings\"\nimport type { EmulatorDocumentState } from \"./core/types\"\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\nimport type { GristWidgetColumnMap } from \"../sdk/types\"\nimport { buildGristThemeHostMessage } from \"./theme-message\"\nimport { createIframeTransport, createInlineTransport } from \"./transports\"\nimport type { EmulatorTransport, InlineGristGlobal } from \"./transports\"\nimport { parseDocument } from \"./validators\"\n\nexport type CreateGristEmulatorOptions = {\n /** The starting document (must satisfy {@link parseDocument}). */\n document: GristReplicaDocument\n /**\n * Pick a transport:\n * - omit / \"inline\" → synthesises `window.grist` directly (or onto `target`),\n * - \"iframe\" → wires a real iframe loading `grist-plugin-api.js`.\n */\n transport?:\n | { kind: \"inline\"; target?: Window & typeof globalThis }\n | { kind: \"iframe\"; iframe: HTMLIFrameElement; targetOrigin?: string }\n /** Initial widget options exposed via `WidgetAPI`. */\n widgetOptions?: Record<string, unknown>\n /**\n * Initial widget interaction info (`access_level` and friends) sent\n * alongside `onOptions`. Defaults to `{ access_level: \"read table\" }`.\n */\n widgetInteraction?: Record<string, unknown>\n /** Initial document theme replayed on widget ready (host `message` channel). */\n initialTheme?: \"light\" | \"dark\"\n}\n\nexport type GristEmulator = {\n /** Underlying mutable document. Treat as read-only outside of `mutate(...)`. */\n state: EmulatorDocumentState\n bus: EventBus\n api: EmulatorApiBundle\n transport: EmulatorTransport\n /** Synthesised `grist` global (only for the inline transport). */\n grist?: InlineGristGlobal\n\n /** Apply a list of Grist user actions; emits the matching events. */\n apply: (actions: unknown[][]) => { retValues: unknown[] }\n /** Convenience helpers for tests and demos. */\n mutate: {\n addRow: (tableId: string, fields: Record<string, unknown>) => number\n updateRow: (tableId: string, rowId: number, fields: Record<string, unknown>) => void\n removeRow: (tableId: string, rowId: number) => void\n }\n selectRow: (rowId: number | \"new\" | null) => void\n selectTable: (tableId: string) => void\n /**\n * Set logical→real column mappings for the playground inspector (and tests).\n * Pass `undefined` to clear — `mappings()` becomes `null` until set again.\n */\n setColumnMappings: (mappings: GristWidgetColumnMap | undefined) => void\n setOptions: (options: Record<string, unknown>) => Promise<void>\n setInteraction: (interaction: Record<string, unknown>) => void\n /** Host theme controls (`grist.on(\"message\")` / `msg.theme`). */\n theme: {\n set: (theme: \"light\" | \"dark\") => void\n }\n /** Tear down the emulator. Idempotent. */\n dispose: () => void\n}\n\nexport function createGristEmulator(options: CreateGristEmulatorOptions): GristEmulator {\n const validatedDocument = parseDocument(options.document)\n const state = createDocument({\n ...validatedDocument,\n widgetOptions: options.widgetOptions ?? validatedDocument.widgetOptions,\n widgetInteraction:\n options.widgetInteraction ?? validatedDocument.widgetInteraction ?? { access_level: \"read table\" },\n })\n const bus = createEventBus()\n const api = createApiBundle(state, bus)\n\n const transportKind = options.transport?.kind ?? \"inline\"\n let transport: EmulatorTransport\n let grist: InlineGristGlobal | undefined\n\n if (transportKind === \"iframe\") {\n if (options.transport?.kind !== \"iframe\") throw new Error(\"transport mismatch\")\n transport = createIframeTransport({\n iframe: options.transport.iframe,\n targetOrigin: options.transport.targetOrigin,\n state,\n bus,\n api,\n initialTheme: options.initialTheme,\n })\n } else {\n const inline = createInlineTransport({\n state,\n bus,\n api,\n initialTheme: options.initialTheme,\n target: options.transport?.kind === \"inline\" ? options.transport.target : undefined,\n })\n transport = inline\n grist = inline.grist\n }\n\n function apply(actions: unknown[][]) {\n return applyUserActions(state, bus, actions)\n }\n\n return {\n state,\n bus,\n api,\n transport,\n grist,\n apply,\n mutate: {\n addRow: (tableId, fields) => apply([[\"AddRecord\", tableId, null, fields]]).retValues[0] as number,\n updateRow: (tableId, rowId, fields) => {\n apply([[\"UpdateRecord\", tableId, rowId, fields]])\n },\n removeRow: (tableId, rowId) => {\n apply([[\"RemoveRecord\", tableId, rowId]])\n },\n },\n selectRow(rowId) {\n state.selection.rowId = rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId })\n },\n selectTable(tableId) {\n if (!state.tables.has(tableId)) throw new Error(`Unknown table: ${tableId}`)\n state.selection.tableId = tableId\n const first = state.tables.get(tableId)!.rows[0]?.id ?? null\n state.selection.rowId = first\n bus.emit({ type: \"data-change\", tableId })\n bus.emit({ type: \"cursor-change\", tableId, rowId: first })\n },\n setColumnMappings(mappings) {\n if (mappings === undefined) {\n delete state.selection.mappings\n } else {\n state.selection.mappings = mappings\n }\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n async setOptions(opts) {\n await api.WidgetAPI.setOptions(opts)\n },\n setInteraction(interaction) {\n state.widgetInteraction = { ...interaction }\n bus.emit({ type: \"options-change\", options: { ...state.widgetOptions }, interaction: { ...interaction } })\n },\n theme: {\n set(next) {\n bus.emit({ type: \"theme-change\", message: buildGristThemeHostMessage(next) })\n },\n },\n dispose() {\n transport.dispose()\n bus.clear()\n },\n }\n}\n","/**\n * Document templates exposed at the top of the emulator API.\n *\n * Templates return plain data — they don't allocate state, the caller passes\n * the returned value into `createGristEmulator(...)` which performs the allocation.\n */\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst PRESET_GENERATED_AT = \"1970-01-01T00:00:00.000Z\"\n\nfunction replicaBase(overrides: Omit<GristReplicaDocument, \"generatedAt\">): GristReplicaDocument {\n return {\n generatedAt: PRESET_GENERATED_AT,\n ...overrides,\n }\n}\n\n/**\n * Useful templates for quick demos and tests.\n */\nexport const presets = {\n /**\n * Default starter fixture for demos / sandboxes that need a neutral document\n * without choosing a domain-specific preset.\n */\n defaultTemplate(): GristReplicaDocument {\n return replicaBase({\n docName: \"Default\",\n tables: {\n Table1: {\n label: \"Table1\",\n rows: [\n { id: 1, Name: \"Alice\" },\n { id: 2, Name: \"Bob\" },\n ],\n },\n },\n })\n },\n blank(): GristReplicaDocument {\n return replicaBase({\n docName: \"Blank\",\n tables: {\n Table1: { rows: [{ id: 1 }] },\n },\n })\n },\n todoList(): GristReplicaDocument {\n return replicaBase({\n docName: \"Todo list\",\n mode: \"schema+data\",\n tables: {\n Tasks: {\n label: \"Tasks\",\n columns: {\n title: { type: \"Text\", label: \"Title\" },\n done: { type: \"Bool\", label: \"Done\" },\n priority: { type: \"Choice\", label: \"Priority\" },\n },\n rows: [\n { id: 1, title: \"Buy milk\", done: false, priority: \"high\" },\n { id: 2, title: \"Write the SOTA emulator\", done: true, priority: \"high\" },\n { id: 3, title: \"Ship it\", done: false, priority: \"medium\" },\n ],\n },\n },\n })\n },\n contacts(): GristReplicaDocument {\n return replicaBase({\n docName: \"Contacts\",\n mode: \"schema+data\",\n tables: {\n Contacts: {\n label: \"Contacts\",\n columns: {\n firstName: { type: \"Text\" },\n lastName: { type: \"Text\" },\n email: { type: \"Text\" },\n company: { type: \"Text\" },\n },\n rows: [\n { id: 1, firstName: \"Ada\", lastName: \"Lovelace\", email: \"ada@analytical.engine\", company: \"British Crown\" },\n { id: 2, firstName: \"Linus\", lastName: \"Torvalds\", email: \"linus@kernel.org\", company: \"Linux Foundation\" },\n { id: 3, firstName: \"Margaret\", lastName: \"Hamilton\", email: \"margaret@apollo.nasa\", company: \"NASA\" },\n ],\n },\n },\n })\n },\n}\n"],"mappings":"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","names":["options","import_zod"]}
|
|
1
|
+
{"version":3,"sources":["../src/emulator/index.ts","../src/emulator/api/command-api.ts","../src/emulator/core/mappings.ts","../src/emulator/api/custom-section-api.ts","../src/emulator/api/grist-api.ts","../src/sdk/helpers/grist-value-codec.ts","../src/emulator/core/display-helpers.ts","../src/sdk/helpers/replica-normalize.ts","../src/emulator/core/document.ts","../src/emulator/core/action-engine.ts","../src/emulator/core/columnar.ts","../src/emulator/api/grist-doc-api.ts","../src/emulator/api/grist-view.ts","../src/emulator/api/widget-api.ts","../src/emulator/api/index.ts","../src/emulator/core/event-bus.ts","../src/emulator/theme-message.ts","../src/sdk/helpers/grist-user-actions.ts","../src/emulator/transports/inline.ts","../src/emulator/validators.ts","../src/emulator/create-grist-emulator.ts","../src/emulator/templates.ts"],"sourcesContent":["/**\n * Public surface of the Grist emulator.\n *\n * A test harness: `grist-widget-sdk/emulator/testing` (renderWithGrist,\n * smokeTestWidget) is built on it. To see a widget in a real Grist, use\n * `pnpm demo` or its demo page (`create-grist-widget demo --save`).\n */\n\nexport type { GristReplicaDocument } from \"../sdk/replica-document\"\nexport { createGristEmulator } from \"./create-grist-emulator\"\nexport type { CreateGristEmulatorOptions, GristEmulator } from \"./create-grist-emulator\"\nexport { presets } from \"./templates\"\nexport { parseDocument, safeParseDocument } from \"./validators\"\nexport type {\n CreateDocumentInput,\n CreateDocumentTableInput,\n EmulatorColumn,\n EmulatorDocumentState,\n EmulatorEvent,\n EmulatorRowId,\n EmulatorTable,\n} from \"./core\"\nexport { EmulatorActionError, enrichEmulatorColumnMetadata, resolveMappings } from \"./core\"\nexport type { EmulatorApiBundle } from \"./api\"\nexport type { EmulatorTransport, InlineGristGlobal } from \"./transports\"\n","import type { EventBus } from \"../core/event-bus\"\nimport type { CommandApiImpl } from \"./types\"\n\n/**\n * `CommandAPI` host implementation. The widget's \"Edit Options\" gear and a\n * few keyboard shortcuts call into this. We forward the call name on the bus\n * so the inspector and tests can observe it; useful to assert\n * `onEditOptions` flows.\n */\nexport function createCommandApiImpl(bus: EventBus): CommandApiImpl {\n return {\n async run(name) {\n bus.emit({ type: \"user-action\", action: [\"RunCommand\", name] })\n },\n }\n}\n","/**\n * Resolves the `mappings` payload that `CustomSectionAPI.mappings()` returns.\n *\n * The playground emulator does **not** infer logical → real columns from\n * names. Mappings come only from `state.selection.mappings` (playground\n * document inspector or tests). When unset, returns `null`.\n */\n\nimport type { GristWidgetColumnMap } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"./types\"\n\nexport function resolveMappings(state: EmulatorDocumentState): GristWidgetColumnMap | null {\n if (state.selection.mappings !== undefined && state.selection.mappings !== null) {\n return state.selection.mappings\n }\n return null\n}\n","import { resolveMappings } from \"../core/mappings\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { GristWidgetConfiguration } from \"../../sdk/types\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { CustomSectionApiImpl } from \"./types\"\n\n/**\n * `CustomSectionAPI` host implementation, called by `grist-plugin-api.js`\n * after `grist.ready()` to hand the host the widget's preferences:\n * required access, declared columns, allowSelectBy, hasCustomOptions, etc.\n *\n * Implementation:\n * - persists the configuration onto `state.configuration`,\n * - emits a `ready` event so the transport knows it is safe to push\n * initial cursor / data / options messages,\n * - re-emits a `mappings-change` so the inspector and tests can react.\n */\nexport function createCustomSectionApiImpl(\n state: EmulatorDocumentState,\n bus: EventBus\n): CustomSectionApiImpl {\n return {\n async configure(settings) {\n const config: GristWidgetConfiguration = {\n requiredAccess: settings.requiredAccess as GristWidgetConfiguration[\"requiredAccess\"],\n columns: settings.columns as GristWidgetConfiguration[\"columns\"],\n allowSelectBy: settings.allowSelectBy as boolean | undefined,\n hasCustomOptions: settings.hasCustomOptions as boolean | undefined,\n }\n state.configuration = config\n bus.emit({ type: \"ready\", configuration: config })\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n\n async mappings() {\n return resolveMappings(state)\n },\n }\n}\n","import type { GristApiImpl } from \"./types\"\n\n/** `_grist_api` host implementation. Minimal v1 — extend as needed. */\nexport function createGristApiImpl(): GristApiImpl {\n return {\n async ping() {\n return \"pong\"\n },\n }\n}\n","/**\n * Encoding helpers for Grist cell values.\n *\n * Grist sends some types as marshalled tuples or numeric epochs. This file\n * exposes pure decode/encode functions so widget code never has to spelunk\n * Grist's wire format.\n *\n * References: Grist `grist/RowRecord` and `grist/DocActions` typings.\n */\n\nimport type { GristReplicaColumn } from \"../types\"\n\n/** `[\"E\", \"ErrorClass\", \"message\", traceback?]` — Grist error sentinel. */\nexport type GristEncodedError = [\"E\", string, string?, string?]\n/** `[\"L\", ...items]` — list (used for ChoiceList, RefList, Attachments). */\nexport type GristEncodedList = [\"L\", ...unknown[]]\n/** `[\"D\", epochSeconds, \"tz/Name\"]` — DateTime with timezone. */\nexport type GristEncodedDateTime = [\"D\", number, string]\n/** `[\"d\", epochSeconds]` — Date (no time). */\nexport type GristEncodedDate = [\"d\", number]\n/** `[\"R\", tableId, rowId]` — explicit reference. */\nexport type GristEncodedRef = [\"R\", string, number]\n/** `[\"r\", rowId]` — bare reference (when table is contextual). */\nexport type GristEncodedBareRef = [\"r\", number]\n/** `[\"P\", encoded]` — pending marker. */\nexport type GristEncodedPending = [\"P\"]\n\nexport type GristDecodedValue =\n | null\n | string\n | number\n | boolean\n | Date\n | GristDecodedValue[]\n | { __error: true; type: string; message?: string; traceback?: string }\n | { __ref: true; tableId?: string; rowId: number }\n\nconst MARSHALLED_TAGS = new Set([\"E\", \"L\", \"D\", \"d\", \"R\", \"r\", \"P\"])\n\nfunction isMarshalledTuple(value: unknown): value is unknown[] {\n return (\n Array.isArray(value) &&\n typeof value[0] === \"string\" &&\n value[0].length <= 2 &&\n MARSHALLED_TAGS.has(value[0])\n )\n}\n\n/**\n * Normalises a Grist `fetchTable` cell that points at a row in another table.\n * Most payloads use a bare numeric row id, but `Ref:*` values may appear as\n * `[\"R\", tableId, rowId]` or `[\"r\", rowId]` (same shape as {@link decodeGristValue}).\n */\nexport function coerceGristDocApiRefRowId(value: unknown): number | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return value\n if (!Array.isArray(value) || value.length < 2) return undefined\n const tag = value[0]\n if (tag === \"R\" && typeof value[2] === \"number\" && Number.isFinite(value[2])) return value[2]\n if (tag === \"r\" && typeof value[1] === \"number\" && Number.isFinite(value[1])) return value[1]\n return undefined\n}\n\nfunction looksLikeAttachmentColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Attachments\"\n}\n\nfunction looksLikeChoiceListColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"ChoiceList\"\n}\n\nfunction looksLikeRefListColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"RefList:\")\n}\n\nfunction looksLikeRefColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"Ref:\")\n}\n\nfunction looksLikeDateColumn(column?: GristReplicaColumn): boolean {\n return column?.type === \"Date\"\n}\n\nfunction looksLikeDateTimeColumn(column?: GristReplicaColumn): boolean {\n return typeof column?.type === \"string\" && column.type.startsWith(\"DateTime\")\n}\n\n/**\n * Decodes a Grist cell value into an idiomatic JS value.\n *\n * Pass the column's metadata (from `useGristSchema` or `_grist_Tables_column`)\n * for type-aware decoding (e.g. `Date` columns return `Date` even when stored as a number).\n */\nexport function decodeGristValue(value: unknown, column?: GristReplicaColumn): GristDecodedValue {\n if (value === null || value === undefined) return null\n\n if (isMarshalledTuple(value)) {\n const tag = value[0] as string\n switch (tag) {\n case \"E\":\n return {\n __error: true,\n type: typeof value[1] === \"string\" ? value[1] : \"Error\",\n message: typeof value[2] === \"string\" ? value[2] : undefined,\n traceback: typeof value[3] === \"string\" ? value[3] : undefined,\n }\n case \"L\":\n return value.slice(1).map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n case \"D\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"d\":\n if (typeof value[1] === \"number\") return new Date(value[1] * 1000)\n return null\n case \"R\":\n return {\n __ref: true,\n tableId: typeof value[1] === \"string\" ? value[1] : undefined,\n rowId: typeof value[2] === \"number\" ? value[2] : 0,\n }\n case \"r\":\n return { __ref: true, rowId: typeof value[1] === \"number\" ? value[1] : 0 }\n case \"P\":\n return null\n default:\n return null\n }\n }\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (typeof value === \"number\" && Number.isFinite(value)) return new Date(value * 1000)\n }\n\n if (looksLikeRefColumn(column) && typeof value === \"number\") {\n return { __ref: true, rowId: value }\n }\n\n if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {\n return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return value\n if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, undefined)) as GristDecodedValue[]\n return null\n}\n\n/** Convenience: true when the cell is a Grist error sentinel. */\nexport function isGristCellError(value: unknown): value is GristEncodedError {\n return Array.isArray(value) && value[0] === \"E\"\n}\n\n/**\n * Encodes a JS value into Grist's expected wire form for a given column type.\n *\n * Use before passing values to `applyUserActions` or `TableOperations.update`\n * for `Date`, `DateTime`, `Ref`, `RefList`, and `ChoiceList` columns.\n */\nexport function encodeGristValue(value: unknown, column?: GristReplicaColumn): unknown {\n if (value === null || value === undefined) return null\n\n if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {\n if (value instanceof Date) return Math.floor(value.getTime() / 1000)\n if (typeof value === \"string\") {\n const parsed = Date.parse(value)\n if (!Number.isNaN(parsed)) return Math.floor(parsed / 1000)\n }\n if (typeof value === \"number\") return Math.floor(value)\n }\n\n if (looksLikeRefColumn(column)) {\n if (typeof value === \"number\") return value\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return (value as { rowId: number }).rowId\n }\n }\n\n if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {\n if (Array.isArray(value)) {\n const items = value.map((v) => {\n if (v && typeof v === \"object\" && \"rowId\" in v) return (v as { rowId: number }).rowId\n return v\n })\n return [\"L\", ...items]\n }\n }\n\n return value\n}\n","import type { GristReplicaColumn } from \"../../sdk/types\"\n\n/** Ref / RefList column → the gristHelper_ column holding its display values. */\nexport function inferDisplayHelpersByRef(\n columns: Record<string, GristReplicaColumn>\n): Record<string, string> {\n const out: Record<string, string> = {}\n const helperColumns = Object.entries(columns).filter(([colId]) =>\n colId.startsWith(\"gristHelper_\")\n )\n const usedHelpers = new Set<string>()\n const colRefToColId = new Map<number, string>()\n for (const [colId, col] of Object.entries(columns)) {\n if (typeof col?.colRef === \"number\" && Number.isFinite(col.colRef)) {\n colRefToColId.set(col.colRef, colId)\n }\n }\n for (const [colId, col] of Object.entries(columns)) {\n const type = col?.type\n if (typeof type !== \"string\" || (!type.startsWith(\"Ref:\") && !type.startsWith(\"RefList:\"))) {\n continue\n }\n if (typeof col.displayColRef === \"number\" && Number.isFinite(col.displayColRef)) {\n const helperColId = colRefToColId.get(col.displayColRef)\n if (helperColId) {\n out[colId] = helperColId\n usedHelpers.add(helperColId)\n continue\n }\n }\n const match = helperColumns.find(([, helper]) => {\n const formula = helper?.formula\n return typeof formula === \"string\" && (formula.includes(`$${colId}.`) || formula.includes(`$${colId}`))\n })\n if (match) {\n out[colId] = match[0]\n usedHelpers.add(match[0])\n }\n }\n\n // Secondary fallback for schemas where helper formulas are unavailable:\n // pair unresolved Ref/RefList columns with nearest following gristHelper_*.\n const unresolvedRefs = Object.entries(columns)\n .filter(([colId, col]) => {\n const type = col?.type\n return (\n !out[colId] &&\n typeof type === \"string\" &&\n (type.startsWith(\"Ref:\") || type.startsWith(\"RefList:\"))\n )\n })\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n const helperByPos = helperColumns\n .filter(([helperId]) => !usedHelpers.has(helperId))\n .sort((a, b) => (a[1]?.parentPos ?? Number.MAX_SAFE_INTEGER) - (b[1]?.parentPos ?? Number.MAX_SAFE_INTEGER))\n for (const [refId, refCol] of unresolvedRefs) {\n const refPos = refCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n const candidate = helperByPos.find(([, helperCol]) => {\n const helperPos = helperCol?.parentPos ?? Number.MAX_SAFE_INTEGER\n return helperPos > refPos\n })\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n // If multiple unresolved refs remain, greedily map by order.\n for (const [refId] of unresolvedRefs) {\n if (out[refId]) continue\n const candidate = helperByPos.find(([helperId]) => !usedHelpers.has(helperId))\n if (!candidate) continue\n out[refId] = candidate[0]\n usedHelpers.add(candidate[0])\n }\n return out\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n","import { inferDisplayHelpersByRef } from \"./display-helpers\"\nimport { normalizeReplicaDocumentInput } from \"../../sdk/helpers/replica-normalize\"\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport type { GristReplicaDocument, GristReplicaTable } from \"../../sdk/replica-document\"\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nconst SYSTEM_COLUMN = \"id\"\n\nconst EMULATOR_JS_FORMULA_PLACEHOLDER = \"(emulator JavaScript formula)\"\n\n/** Replica table for {@link createDocument}; columns may include `formulaFn` / `inferredFormula` (emulator-only). */\nexport type CreateDocumentTableInput = Omit<GristReplicaTable, \"columns\"> & {\n columns?: Record<string, EmulatorColumn>\n}\n\n/** Replica document for {@link createDocument}; widens table columns to {@link EmulatorColumn}. */\nexport type CreateDocumentInput = Omit<GristReplicaDocument, \"tables\"> & {\n tables: Record<string, CreateDocumentTableInput>\n}\n\n/**\n * Ensure `formula` (original) and `inferredFormula` strings exist alongside optional `formulaFn`.\n */\nexport function enrichEmulatorColumnMetadata(col: EmulatorColumn): EmulatorColumn {\n const originalTrimmed = col.formula?.trim() ?? \"\"\n const explicitInferred = col.inferredFormula?.trim() ?? \"\"\n\n if (col.formulaFn) {\n const inferredFormula =\n explicitInferred || originalTrimmed || EMULATOR_JS_FORMULA_PLACEHOLDER\n return {\n ...col,\n ...(originalTrimmed ? { formula: col.formula } : {}),\n inferredFormula,\n }\n }\n\n if (explicitInferred || originalTrimmed) {\n return {\n ...col,\n inferredFormula: explicitInferred || originalTrimmed || undefined,\n }\n }\n\n return col\n}\n\n/** Order merged column metadata for stable `fetchTable` / RDG column order. */\nexport function sortEmulatorColumnsByParentPos(columns: Record<string, EmulatorColumn>): Record<string, EmulatorColumn> {\n const entries = Object.entries(columns)\n entries.sort(([ka, a], [kb, b]) => {\n const pa = a.parentPos\n const pb = b.parentPos\n if (pa !== undefined && pb !== undefined && pa !== pb) return pa - pb\n if (pa !== undefined && pb === undefined) return -1\n if (pa === undefined && pb !== undefined) return 1\n return ka.localeCompare(kb)\n })\n return Object.fromEntries(entries)\n}\n\nfunction inferColumnsFromRows(rows: GristRowRecord[]): Record<string, EmulatorColumn> {\n const columns: Record<string, EmulatorColumn> = {}\n for (const row of rows) {\n for (const key of Object.keys(row)) {\n if (key === SYSTEM_COLUMN) continue\n if (!columns[key]) columns[key] = inferColumnType(row[key])\n }\n }\n return columns\n}\n\nfunction inferColumnType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction buildTable(tableId: string, input: CreateDocumentTableInput): EmulatorTable {\n const rows = input.rows ?? []\n const inferred = inferColumnsFromRows(rows)\n const merged: Record<string, EmulatorColumn> = {}\n for (const [colId, col] of Object.entries({ ...inferred, ...(input.columns ?? {}) })) {\n merged[colId] = enrichEmulatorColumnMetadata(col)\n }\n const columns = sortEmulatorColumnsByParentPos(merged)\n return {\n tableId,\n label: input.label,\n columns,\n rows: rows.map((row) => ({ ...row })),\n }\n}\n\n/**\n * Build an immutable initial document state from a user-provided\n * {@link GristReplicaDocument}. The state is **not** frozen — the action\n * engine mutates it in place under deterministic event diffusion.\n */\nexport function createDocument(input: CreateDocumentInput): EmulatorDocumentState {\n if (!input.tables || Object.keys(input.tables).length === 0) {\n throw new Error(\"createDocument: at least one table is required\")\n }\n\n const normalized = normalizeReplicaDocumentInput(input)\n\n const tables = new Map<string, EmulatorTable>()\n for (const [tableId, tableInput] of Object.entries(normalized.tables)) {\n tables.set(tableId, buildTable(tableId, tableInput))\n }\n\n const firstTableId = tables.keys().next().value as string\n const requestedTableId = normalized.selection?.tableId\n const selectedTableId =\n requestedTableId && tables.has(requestedTableId) ? requestedTableId : firstTableId\n const selectedTable = tables.get(selectedTableId)!\n const fallbackRowId =\n typeof selectedTable.rows[0]?.id === \"number\" ? selectedTable.rows[0].id : null\n const selection = {\n tableId: selectedTableId,\n rowId: normalized.selection?.rowId ?? fallbackRowId,\n mappings: normalized.selection?.mappings,\n cursor: normalized.selection?.cursor,\n } as EmulatorDocumentState[\"selection\"]\n\n return {\n docName: normalized.docName ?? \"Untitled emulator document\",\n tables,\n selection,\n widgetOptions: { ...(normalized.widgetOptions ?? {}) },\n widgetInteraction: { ...(normalized.widgetInteraction ?? {}) },\n configuration: normalized.configuration ?? null,\n accessToken: normalized.accessToken ?? null,\n }\n}\n\nexport function getTable(state: EmulatorDocumentState, tableId: string): EmulatorTable {\n const table = state.tables.get(tableId)\n if (!table) throw new Error(`Unknown table: ${tableId}`)\n return table\n}\n\nexport function getSelectedTable(state: EmulatorDocumentState): EmulatorTable {\n return getTable(state, state.selection.tableId)\n}\n\nexport function nextRowId(table: EmulatorTable): number {\n let max = 0\n for (const row of table.rows) {\n if (typeof row.id === \"number\" && row.id > max) max = row.id\n }\n return max + 1\n}\n\nexport function findRow(table: EmulatorTable, rowId: number): GristRowRecord | undefined {\n return table.rows.find((r) => r.id === rowId)\n}\n\nexport function findRowIndex(table: EmulatorTable, rowId: number): number {\n return table.rows.findIndex((r) => r.id === rowId)\n}\n\n/**\n * Re-evaluate every formula column for a given row in-place. Called by the\n * action engine after Add/Update operations.\n */\nexport function evaluateRowFormulas(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n for (const [colId, col] of Object.entries(table.columns)) {\n if (col.formulaFn) {\n try {\n row[colId] = col.formulaFn(row, { table, document: state })\n } catch (err) {\n row[colId] = formulaError(err)\n }\n }\n }\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n}\n\n/** Pull stored row ids from a `RefList` cell (`[\"L\", ...]` or legacy shapes). */\nfunction extractRefListIdsFromWire(raw: unknown): number[] {\n if (raw == null) return []\n if (!Array.isArray(raw)) return []\n const items = raw[0] === \"L\" ? raw.slice(1) : raw\n const out: number[] = []\n for (const item of items) {\n if (typeof item === \"number\" && Number.isFinite(item) && item > 0) {\n out.push(Math.trunc(item))\n continue\n }\n if (item && typeof item === \"object\" && \"rowId\" in item) {\n const r = (item as { rowId: unknown }).rowId\n if (typeof r === \"number\" && Number.isFinite(r) && r > 0) {\n out.push(Math.trunc(r))\n continue\n }\n }\n const t = coerceGristDocApiRefRowId(item)\n if (t !== undefined && t > 0) out.push(Math.trunc(t))\n }\n return Array.from(new Set(out))\n}\n\nfunction fieldFromRefListHelperFormula(formula: string | undefined, refColId: string): string | null {\n if (!formula) return null\n const re = new RegExp(`\\\\$${escapeRegExp(refColId)}\\\\.([A-Za-z_]\\\\w*)`)\n const m = formula.match(re)\n return m?.[1] ?? null\n}\n\nfunction firstTextLikeColumnId(columns: Record<string, EmulatorColumn>): string | null {\n let best: { id: string; pos: number } | null = null\n for (const [colId, col] of Object.entries(columns)) {\n if (colId === \"id\" || colId.startsWith(\"gristHelper_\")) continue\n const t = col.type\n if (t !== \"Text\" && t !== \"Choice\") continue\n const pos = col.parentPos ?? 99999\n if (!best || pos < best.pos) best = { id: colId, pos }\n }\n return best?.id ?? null\n}\n\nfunction formatLabelFromCell(value: unknown): string {\n if (value == null) return \"\"\n if (typeof value === \"string\") return value.trim()\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n if (value instanceof Date) return value.toISOString()\n if (Array.isArray(value) && value[0] === \"E\") return \"\"\n if (typeof value === \"object\" && value && \"__ref\" in value) {\n const r = (value as { rowId?: unknown }).rowId\n return typeof r === \"number\" && Number.isFinite(r) ? String(r) : \"\"\n }\n return \"\"\n}\n\n/**\n * Keep `gristHelper_*` display columns aligned with `RefList:*` ids after writes.\n *\n * Real Grist evaluates helper formulas (`$multiref.Nom`); replica JSON only\n * carries the formula string (no `formulaFn`), so helpers would stay stale and\n * safe-parse would flag `helper_mismatch` with empty labels.\n *\n * Skips helpers that define `formulaFn` so custom JS formulas keep ownership.\n */\nexport function syncRefListDisplayHelpers(\n state: EmulatorDocumentState,\n table: EmulatorTable,\n row: GristRowRecord\n): void {\n const displayHelpersByRef = inferDisplayHelpersByRef(table.columns)\n for (const [colId, col] of Object.entries(table.columns)) {\n const type = col.type\n if (typeof type !== \"string\" || !type.startsWith(\"RefList:\")) continue\n const helperColId = displayHelpersByRef[colId]\n if (!helperColId) continue\n const helperMeta = table.columns[helperColId]\n if (!helperMeta || helperMeta.formulaFn) continue\n\n const targetTableId = type.slice(\"RefList:\".length)\n const targetTable = state.tables.get(targetTableId)\n if (!targetTable) continue\n\n const ids = extractRefListIdsFromWire(row[colId])\n if (ids.length === 0) {\n row[helperColId] = []\n continue\n }\n\n const fieldId =\n fieldFromRefListHelperFormula(helperMeta.formula, colId) ??\n firstTextLikeColumnId(targetTable.columns)\n\n const labels = ids.map((rid) => {\n if (!fieldId) return String(rid)\n const trow = findRow(targetTable, rid)\n if (!trow) return String(rid)\n const lbl = formatLabelFromCell(trow[fieldId])\n return lbl !== \"\" ? lbl : String(rid)\n })\n row[helperColId] = labels\n }\n}\n\nfunction formulaError(err: unknown): unknown {\n // Match Grist's encoded error format: [\"E\", code, message]\n const message = err instanceof Error ? err.message : String(err)\n return [\"E\", \"Error\", message]\n}\n\n/**\n * Synthesise `_grist_Tables` metadata from the emulator's in-memory tables.\n * Returns Grist's columnar wire shape.\n */\nexport function synthesizeTablesMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const ids: number[] = []\n const tableIds: string[] = []\n const labels: (string | null)[] = []\n\n let nextId = 1\n for (const [tableId, table] of state.tables.entries()) {\n ids.push(nextId)\n tableIds.push(tableId)\n labels.push(table.label ?? null)\n nextId += 1\n }\n\n return {\n id: ids,\n tableId: tableIds,\n // Optional human-readable label; real Grist keeps more fields, but these\n // are sufficient for `buildReplicaDocumentFromDocApi` to resolve table ids.\n label: labels,\n }\n}\n\n/**\n * Synthesise `_grist_Tables_column` metadata from emulator tables/columns.\n * Mirrors the subset of fields consumed by `buildReplicaDocumentFromDocApi`.\n */\nexport function synthesizeTablesColumnMeta(state: EmulatorDocumentState): Record<string, unknown[]> {\n const parentIds: number[] = []\n const colIds: string[] = []\n const columnIds: number[] = []\n const types: (string | null)[] = []\n const labels: (string | null)[] = []\n const parentPos: (number | null)[] = []\n const isFormula: boolean[] = []\n const formulas: (string | null)[] = []\n const descriptions: (string | null)[] = []\n const widgetOptions: unknown[] = []\n const displayCol: (number | null)[] = []\n const visibleCol: (number | null)[] = []\n\n // Mirror the synthetic table ids from `synthesizeTablesMeta`.\n const tableIdToInternalId = new Map<string, number>()\n {\n let nextId = 1\n for (const [tableId] of state.tables.entries()) {\n tableIdToInternalId.set(tableId, nextId)\n nextId += 1\n }\n }\n\n for (const [tableId, table] of state.tables.entries()) {\n const parentInternalId = tableIdToInternalId.get(tableId)\n if (parentInternalId === undefined) continue\n\n for (const [colId, col] of Object.entries(table.columns)) {\n parentIds.push(parentInternalId)\n colIds.push(colId)\n // Prefer explicit `colRef` when present; fall back to 1-based index of insertion.\n const ref = typeof col.colRef === \"number\" ? col.colRef : columnIds.length + 1\n columnIds.push(ref)\n types.push(col.type ?? null)\n labels.push(col.label ?? null)\n parentPos.push(col.parentPos ?? null)\n isFormula.push(Boolean(col.isFormula))\n const formula = typeof col.formula === \"string\" ? col.formula : null\n formulas.push(formula)\n descriptions.push(col.description ?? null)\n widgetOptions.push(col.widgetOptions ?? null)\n displayCol.push(typeof col.displayColRef === \"number\" ? col.displayColRef : null)\n visibleCol.push(typeof col.visibleColRef === \"number\" ? col.visibleColRef : null)\n }\n }\n\n return {\n parentId: parentIds,\n colId: colIds,\n id: columnIds,\n type: types,\n label: labels,\n parentPos,\n isFormula,\n formula: formulas,\n description: descriptions,\n // Also expose legacy `descr` for robustness.\n descr: descriptions,\n widgetOptions,\n displayCol,\n visibleCol,\n }\n}\n","/**\n * Pure action engine: applies Grist user actions to an\n * {@link EmulatorDocumentState} and emits the resulting events on the bus.\n *\n * This is the single place where state mutates. Every API impl ultimately\n * routes through `applyUserActions` so behaviour is consistent regardless of\n * the surface (`grist.docApi.applyUserActions`, `selectedTable.create`,\n * `setCursorPos`, etc.).\n *\n * Supported user actions:\n * - AddRecord, BulkAddRecord\n * - UpdateRecord, BulkUpdateRecord\n * - RemoveRecord, BulkRemoveRecord\n * - AddColumn, RemoveColumn, RenameColumn, ModifyColumn\n * - AddTable, RemoveTable, RenameTable\n *\n * Unknown actions throw a structured error instead of silently succeeding,\n * which surfaces protocol gaps loudly during widget development.\n */\n\nimport { coerceGristDocApiRefRowId } from \"../../sdk/helpers/grist-value-codec\"\nimport {\n evaluateRowFormulas,\n findRow,\n findRowIndex,\n getTable,\n nextRowId,\n syncRefListDisplayHelpers,\n} from \"./document\"\nimport type { EventBus } from \"./event-bus\"\nimport type { EmulatorColumn, EmulatorDocumentState, EmulatorTable } from \"./types\"\n\nexport class EmulatorActionError extends Error {\n constructor(\n public readonly action: unknown,\n message: string\n ) {\n super(message)\n this.name = \"EmulatorActionError\"\n }\n}\n\nexport type ApplyUserActionResult = {\n /** Result mirroring Grist's `applyUserActions`: per-action retValues. */\n retValues: unknown[]\n /** Tables that received row-level changes (de-duped). */\n changedTableIds: string[]\n}\n\nexport function applyUserActions(\n state: EmulatorDocumentState,\n bus: EventBus,\n actions: unknown[][]\n): ApplyUserActionResult {\n const retValues: unknown[] = []\n const changed = new Set<string>()\n\n for (const action of actions) {\n bus.emit({ type: \"user-action\", action })\n const ret = applySingle(state, action, changed)\n retValues.push(ret)\n }\n\n for (const tableId of changed) {\n bus.emit({ type: \"data-change\", tableId })\n }\n\n return { retValues, changedTableIds: [...changed] }\n}\n\nfunction applySingle(\n state: EmulatorDocumentState,\n action: unknown[],\n changed: Set<string>\n): unknown {\n const [name, ...args] = action\n switch (name) {\n case \"AddRecord\":\n return addRecord(state, args, changed)\n case \"BulkAddRecord\":\n return bulkAddRecord(state, args, changed)\n case \"UpdateRecord\":\n return updateRecord(state, args, changed)\n case \"BulkUpdateRecord\":\n return bulkUpdateRecord(state, args, changed)\n case \"RemoveRecord\":\n return removeRecord(state, args, changed)\n case \"BulkRemoveRecord\":\n return bulkRemoveRecord(state, args, changed)\n case \"AddColumn\":\n return addColumn(state, args)\n case \"AddVisibleColumn\":\n // The emulator has no concept of section view fields, so the \"visible\"\n // part of `AddVisibleColumn` is a no-op here. We still create the\n // column so widgets that issue this user action (the higher-level form\n // recommended by Grist for \"add a column to the active view\") work\n // identically against the emulator.\n return addColumn(state, args)\n case \"RemoveColumn\":\n return removeColumn(state, args, changed)\n case \"RenameColumn\":\n return renameColumn(state, args, changed)\n case \"ModifyColumn\":\n return modifyColumn(state, args, changed)\n case \"AddTable\":\n return addTable(state, args)\n case \"RemoveTable\":\n return removeTable(state, args)\n case \"RenameTable\":\n return renameTable(state, args)\n default:\n throw new EmulatorActionError(action, `Unsupported user action: ${String(name)}`)\n }\n}\n\n// ---------- row ops ----------\n\nfunction addRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): number {\n const table = getTable(state, requireString(tableId, \"AddRecord.tableId\"))\n const id = typeof rowId === \"number\" ? rowId : nextRowId(table)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n const row = { id, ...normalizedValues }\n ensureColumns(table, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n changed.add(table.tableId)\n return id\n}\n\nfunction bulkAddRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): number[] {\n const table = getTable(state, requireString(tableId, \"BulkAddRecord.tableId\"))\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n const ids = Array.isArray(rowIds) ? rowIds : []\n const length = ids.length || lengthOf(cols)\n const out: number[] = []\n ensureColumns(table, cols, true)\n for (let i = 0; i < length; i++) {\n const id = typeof ids[i] === \"number\" ? (ids[i] as number) : nextRowId(table)\n const row: Record<string, unknown> & { id: number } = { id }\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][i]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n table.rows.push(row)\n out.push(id)\n }\n changed.add(table.tableId)\n return out\n}\n\nfunction updateRecord(\n state: EmulatorDocumentState,\n [tableId, rowId, values]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"UpdateRecord.tableId\"))\n const id = requireNumber(rowId, \"UpdateRecord.rowId\")\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"UpdateRecord\", tableId, rowId, values], `Row ${id} not found in ${table.tableId}`)\n const normalizedValues = normalizeValuesForTable(\n table,\n (values as Record<string, unknown>) ?? {}\n )\n ensureColumns(table, normalizedValues)\n Object.assign(row, normalizedValues)\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkUpdateRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds, columnar]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkUpdateRecord.tableId\"))\n const ids = rowIds as number[]\n const cols = normalizeColumnarForTable(\n table,\n (columnar as Record<string, unknown[]>) ?? {}\n )\n ensureColumns(table, cols, true)\n ids.forEach((id, idx) => {\n const row = findRow(table, id)\n if (!row) throw new EmulatorActionError([\"BulkUpdateRecord\", tableId, ids, cols], `Row ${id} not found in ${table.tableId}`)\n for (const colId of Object.keys(cols)) row[colId] = cols[colId][idx]\n evaluateRowFormulas(state, table, row)\n syncRefListDisplayHelpers(state, table, row)\n })\n changed.add(table.tableId)\n return null\n}\n\nfunction removeRecord(\n state: EmulatorDocumentState,\n [tableId, rowId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveRecord.tableId\"))\n const id = requireNumber(rowId, \"RemoveRecord.rowId\")\n const idx = findRowIndex(table, id)\n if (idx >= 0) table.rows.splice(idx, 1)\n if (state.selection.tableId === table.tableId && state.selection.rowId === id) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction bulkRemoveRecord(\n state: EmulatorDocumentState,\n [tableId, rowIds]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"BulkRemoveRecord.tableId\"))\n const ids = new Set(rowIds as number[])\n table.rows = table.rows.filter((r) => !ids.has(r.id))\n if (state.selection.tableId === table.tableId && typeof state.selection.rowId === \"number\" && ids.has(state.selection.rowId)) {\n state.selection.rowId = table.rows[0]?.id ?? null\n }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- column ops ----------\n\nfunction addColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[]\n): null {\n const table = getTable(state, requireString(tableId, \"AddColumn.tableId\"))\n const col = requireString(colId, \"AddColumn.colId\")\n if (table.columns[col]) throw new EmulatorActionError([\"AddColumn\", tableId, colId], `Column ${col} already exists`)\n table.columns[col] = (info as EmulatorColumn) ?? {}\n for (const row of table.rows) {\n if (!(col in row)) row[col] = null\n }\n return null\n}\n\nfunction removeColumn(\n state: EmulatorDocumentState,\n [tableId, colId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RemoveColumn.tableId\"))\n const col = requireString(colId, \"RemoveColumn.colId\")\n delete table.columns[col]\n for (const row of table.rows) delete row[col]\n changed.add(table.tableId)\n return null\n}\n\nfunction renameColumn(\n state: EmulatorDocumentState,\n [tableId, colId, newColId]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"RenameColumn.tableId\"))\n const from = requireString(colId, \"RenameColumn.colId\")\n const to = requireString(newColId, \"RenameColumn.newColId\")\n if (!table.columns[from]) throw new EmulatorActionError([\"RenameColumn\", tableId, from, to], `Column ${from} not found`)\n if (from === to) return null\n table.columns[to] = table.columns[from]\n delete table.columns[from]\n for (const row of table.rows) {\n if (from in row) {\n row[to] = row[from]\n delete row[from]\n }\n }\n changed.add(table.tableId)\n return null\n}\n\nfunction modifyColumn(\n state: EmulatorDocumentState,\n [tableId, colId, info]: unknown[],\n changed: Set<string>\n): null {\n const table = getTable(state, requireString(tableId, \"ModifyColumn.tableId\"))\n const col = requireString(colId, \"ModifyColumn.colId\")\n if (!table.columns[col]) throw new EmulatorActionError([\"ModifyColumn\", tableId, colId], `Column ${col} not found`)\n table.columns[col] = { ...table.columns[col], ...(info as EmulatorColumn) }\n changed.add(table.tableId)\n return null\n}\n\n// ---------- table ops ----------\n\nfunction addTable(state: EmulatorDocumentState, [tableId, columns]: unknown[]): string {\n const id = requireString(tableId, \"AddTable.tableId\")\n if (state.tables.has(id)) throw new EmulatorActionError([\"AddTable\", tableId], `Table ${id} already exists`)\n const cols: Record<string, EmulatorColumn> = {}\n for (const c of (columns as Array<{ id: string } & EmulatorColumn>) ?? []) {\n cols[c.id] = { ...c }\n }\n state.tables.set(id, { tableId: id, columns: cols, rows: [] })\n return id\n}\n\nfunction removeTable(state: EmulatorDocumentState, [tableId]: unknown[]): null {\n const id = requireString(tableId, \"RemoveTable.tableId\")\n state.tables.delete(id)\n if (state.selection.tableId === id) {\n const fallback = state.tables.keys().next().value as string | undefined\n if (fallback) {\n state.selection.tableId = fallback\n state.selection.rowId = null\n }\n }\n return null\n}\n\nfunction renameTable(state: EmulatorDocumentState, [from, to]: unknown[]): null {\n const fromId = requireString(from, \"RenameTable.from\")\n const toId = requireString(to, \"RenameTable.to\")\n const table = state.tables.get(fromId)\n if (!table) throw new EmulatorActionError([\"RenameTable\", fromId], `Table ${fromId} not found`)\n state.tables.delete(fromId)\n table.tableId = toId\n state.tables.set(toId, table)\n if (state.selection.tableId === fromId) state.selection.tableId = toId\n return null\n}\n\n// ---------- helpers ----------\n\nfunction ensureColumns(\n table: EmulatorTable,\n values: Record<string, unknown> | Record<string, unknown[]>,\n bulk = false\n): void {\n for (const col of Object.keys(values)) {\n if (!table.columns[col]) {\n const sample = bulk ? (values as Record<string, unknown[]>)[col]?.[0] : (values as Record<string, unknown>)[col]\n table.columns[col] = inferType(sample)\n }\n }\n}\n\nfunction inferType(sample: unknown): EmulatorColumn {\n switch (typeof sample) {\n case \"number\":\n return { type: \"Numeric\" }\n case \"boolean\":\n return { type: \"Bool\" }\n case \"string\":\n return { type: \"Text\" }\n default:\n return { type: \"Any\" }\n }\n}\n\nfunction lengthOf(cols: Record<string, unknown[]>): number {\n for (const arr of Object.values(cols)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n\nfunction requireString(value: unknown, name: string): string {\n if (typeof value !== \"string\" || !value) throw new Error(`Expected non-empty string for ${name}`)\n return value\n}\n\nfunction requireNumber(value: unknown, name: string): number {\n if (typeof value !== \"number\" || Number.isNaN(value)) throw new Error(`Expected number for ${name}`)\n return value\n}\n\nfunction normalizeValuesForTable(\n table: EmulatorTable,\n values: Record<string, unknown>\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [colId, value] of Object.entries(values)) {\n out[colId] = normalizeCellValueForType(value, table.columns[colId]?.type)\n }\n return out\n}\n\nfunction normalizeColumnarForTable(\n table: EmulatorTable,\n columns: Record<string, unknown[]>\n): Record<string, unknown[]> {\n const out: Record<string, unknown[]> = {}\n for (const [colId, values] of Object.entries(columns)) {\n const type = table.columns[colId]?.type\n out[colId] = Array.isArray(values)\n ? values.map((value) => normalizeCellValueForType(value, type))\n : []\n }\n return out\n}\n\nfunction normalizeCellValueForType(value: unknown, type: string | undefined): unknown {\n if (value === null || value === undefined || typeof type !== \"string\") return value\n\n if (type.startsWith(\"Ref:\")) return normalizeRefValue(value)\n if (type.startsWith(\"RefList:\")) return normalizeRefListValue(value)\n return value\n}\n\n/**\n * Canonical ref row id for emulator storage (`Ref:*` columns).\n * Accepts bare ids, `\"12\"`, Grist tuples `[\"r\", id]` / `[\"R\", tableId, id]`,\n * and detailed-ref shapes `{ rowId }` used after safe-parse / RDG edits.\n */\nfunction extractRefRowId(value: unknown): number | null {\n if (value === null || value === undefined) return null\n if (value && typeof value === \"object\" && \"__ref\" in value) {\n const inner = (value as { rowId?: unknown }).rowId\n return extractRefRowId(inner)\n }\n if (value && typeof value === \"object\" && \"rowId\" in value) {\n return extractRefRowId((value as { rowId: unknown }).rowId)\n }\n const fromTuple = coerceGristDocApiRefRowId(value)\n if (fromTuple !== undefined && fromTuple > 0) return Math.trunc(fromTuple)\n return toPositiveInt(value)\n}\n\nfunction normalizeRefValue(value: unknown): number | null {\n return extractRefRowId(value)\n}\n\nfunction normalizeRefListValue(value: unknown): unknown[] {\n const toIdList = (items: unknown[]): number[] =>\n Array.from(\n new Set(items.map((item) => extractRefRowId(item)).filter((item): item is number => item !== null))\n )\n\n // Grist tuple form: [\"L\", ...ids]\n if (Array.isArray(value) && value[0] === \"L\") {\n return [\"L\", ...toIdList(value.slice(1))]\n }\n if (Array.isArray(value)) {\n return [\"L\", ...toIdList(value)]\n }\n if (typeof value === \"string\") {\n const tokens = value.split(\",\").map((t) => t.trim()).filter(Boolean)\n return [\"L\", ...toIdList(tokens)]\n }\n if (value && typeof value === \"object\" && Array.isArray((value as { rowIds?: unknown }).rowIds)) {\n return [\"L\", ...toIdList((value as { rowIds: unknown[] }).rowIds)]\n }\n return [\"L\"]\n}\n\nfunction toPositiveInt(value: unknown): number | null {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) return Math.trunc(value)\n if (typeof value === \"string\") {\n const n = Number.parseInt(value.trim(), 10)\n if (Number.isFinite(n) && n > 0) return n\n }\n return null\n}\n","/**\n * Helpers to project an {@link EmulatorTable}'s row-array storage into Grist's\n * columnar wire format expected by `fetchTable` / `fetchSelectedTable`:\n *\n * { id: number[], colA: unknown[], colB: unknown[], ... }\n *\n * When `keepEncoded` is `false` (Grist's default for these APIs), values are\n * passed through as-is — JS-native primitives (string / number / boolean /\n * Date / arrays) are valid Grist plugin values. When `keepEncoded` is `true`,\n * Date columns are emitted in tuple form (`[\"d\", epoch]`) so callers can\n * round-trip them.\n */\n\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { EmulatorTable } from \"./types\"\n\nexport type ColumnarTable = Record<string, unknown[]>\n\nexport type ToColumnarOptions = {\n keepEncoded?: boolean\n}\n\nexport function rowsToColumnar(\n table: EmulatorTable,\n rows: readonly GristRowRecord[],\n options: ToColumnarOptions = {}\n): ColumnarTable {\n const cols = Object.keys(table.columns)\n const out: ColumnarTable = { id: rows.map((r) => r.id) }\n for (const col of cols) {\n out[col] = rows.map((r) => encodeForWire(r[col], table.columns[col]?.type, options.keepEncoded))\n }\n return out\n}\n\nexport function rowToRecord(\n table: EmulatorTable,\n row: GristRowRecord,\n options: ToColumnarOptions = {}\n): Record<string, unknown> {\n const out: Record<string, unknown> = { id: row.id }\n for (const col of Object.keys(table.columns)) {\n out[col] = encodeForWire(row[col], table.columns[col]?.type, options.keepEncoded)\n }\n return out\n}\n\nfunction encodeForWire(value: unknown, type: string | undefined, keepEncoded: boolean | undefined): unknown {\n if (value instanceof Date) {\n const epoch = Math.floor(value.getTime() / 1000)\n if (keepEncoded) {\n return type && type.startsWith(\"DateTime\") ? [\"D\", epoch, \"UTC\"] : [\"d\", epoch]\n }\n return epoch\n }\n return value\n}\n","import { applyUserActions } from \"../core/action-engine\"\nimport { rowsToColumnar } from \"../core/columnar\"\nimport { getTable, synthesizeTablesColumnMeta, synthesizeTablesMeta } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristDocApiImpl } from \"./types\"\n\n/**\n * `GristDocAPI` host implementation. Backs `grist.docApi.*` methods such as\n * `getDocName`, `listTables`, `fetchTable`, `applyUserActions` and\n * `getAccessToken`.\n *\n * `applyUserActions` is the only mutation entry point — every widget write\n * lands here, so tests can listen on the bus for `user-action` events to\n * assert exactly which actions a UI flow generated.\n */\nexport function createGristDocApiImpl(state: EmulatorDocumentState, bus: EventBus): GristDocApiImpl {\n return {\n async getDocName() {\n return state.docName\n },\n\n async listTables() {\n return [...state.tables.keys()]\n },\n\n async fetchTable(tableId) {\n if (tableId === \"_grist_Tables\") {\n return synthesizeTablesMeta(state)\n }\n if (tableId === \"_grist_Tables_column\") {\n return synthesizeTablesColumnMeta(state)\n }\n const table = getTable(state, tableId)\n return rowsToColumnar(table, table.rows)\n },\n\n async applyUserActions(actions) {\n const result = applyUserActions(state, bus, actions)\n return { retValues: result.retValues }\n },\n\n async getAccessToken() {\n if (!state.accessToken) {\n const err = new Error(\"getAccessToken not available (no token configured on emulator)\")\n // Mirror Grist's protocol: rejected stub call.\n throw err\n }\n return { ...state.accessToken }\n },\n }\n}\n","import { rowToRecord, rowsToColumnar } from \"../core/columnar\"\nimport { findRow, getSelectedTable } from \"../core/document\"\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { GristViewImpl } from \"./types\"\n\n/**\n * `GristView` host implementation.\n *\n * Exposes the section-scoped data API the widget uses through\n * `grist.docApi.fetchSelectedTable()`, `fetchSelectedRecord()` and\n * `setCursorPos()`. Reads from the emulator state, writes to the same state\n * via the action engine where applicable, and emits events on the bus so\n * subscribers (transports, inspector, tests) stay in sync.\n *\n * IMPORTANT: `fetchSelectedTable` always returns Grist's **columnar** wire\n * shape. The production `grist-plugin-api.js` wrapper (which the iframe\n * transport talks to) expects the raw RPC stub to return columnar and does\n * the `format: \"rows\"` transposition + `keepEncoded: false` decoding itself.\n * Returning rows here used to crash the wrapper's `mapValues(data, col =>\n * col.map(decodeObject))` pass — `data` was an array, `col` was a row object\n * with no `.map` method — so widgets observed `records === null` forever.\n * The inline transport mirrors the same wrapper semantics in\n * `transports/inline.ts` so widget code sees identical results in both modes.\n */\nexport function createGristViewImpl(state: EmulatorDocumentState, bus: EventBus): GristViewImpl {\n return {\n async fetchSelectedTable(options) {\n const table = getSelectedTable(state)\n return rowsToColumnar(table, table.rows, { keepEncoded: options?.keepEncoded })\n },\n\n async fetchSelectedRecord(rowId, options) {\n const table = getSelectedTable(state)\n const row = findRow(table, rowId)\n if (!row) throw new Error(`No row ${rowId} in ${table.tableId}`)\n return rowToRecord(table, row, { keepEncoded: options?.keepEncoded })\n },\n\n async allowSelectBy() {\n return state.configuration?.allowSelectBy ?? false\n },\n\n async setSelectedRows(rowIds) {\n if (!rowIds || rowIds.length === 0) {\n state.selection.rowId = null\n } else {\n state.selection.rowId = rowIds[0]\n }\n bus.emit({\n type: \"cursor-change\",\n tableId: state.selection.tableId,\n rowId: state.selection.rowId,\n })\n },\n\n async setCursorPos(cursor) {\n const tableId = state.selection.tableId\n if (typeof cursor.rowId === \"number\") state.selection.rowId = cursor.rowId\n state.selection.cursor = { ...state.selection.cursor, ...cursor }\n bus.emit({\n type: \"cursor-change\",\n tableId,\n rowId: state.selection.rowId,\n cursor: state.selection.cursor,\n })\n },\n }\n}\n","import type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport type { WidgetApiImpl } from \"./types\"\n\n/**\n * `WidgetAPI` host implementation, backing `grist.widgetApi.*`. Reads and\n * writes the per-widget options bag persisted on the emulator state. Each\n * mutation triggers an `options-change` event so subscribers (the transport\n * pushes an `onOptions` message; tests/inspector update accordingly) stay in\n * lock-step with the document.\n */\nexport function createWidgetApiImpl(state: EmulatorDocumentState, bus: EventBus): WidgetApiImpl {\n function emit() {\n bus.emit({\n type: \"options-change\",\n options: { ...state.widgetOptions },\n interaction: { ...state.widgetInteraction },\n })\n }\n\n return {\n async getOption(key) {\n return state.widgetOptions[key]\n },\n\n async setOption(key, value) {\n state.widgetOptions[key] = value\n emit()\n },\n\n async getOptions() {\n return Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n },\n\n // Replaces every option, as Grist's WidgetAPI.setOptions does.\n async setOptions(options) {\n state.widgetOptions = { ...options }\n emit()\n },\n\n async clearOptions() {\n state.widgetOptions = {}\n emit()\n },\n }\n}\n","/**\n * Bundles the six host-side Grist API implementations into one record so\n * inline transport can wire them up.\n */\n\nimport type { EventBus } from \"../core/event-bus\"\nimport type { EmulatorDocumentState } from \"../core/types\"\nimport { createCommandApiImpl } from \"./command-api\"\nimport { createCustomSectionApiImpl } from \"./custom-section-api\"\nimport { createGristApiImpl } from \"./grist-api\"\nimport { createGristDocApiImpl } from \"./grist-doc-api\"\nimport { createGristViewImpl } from \"./grist-view\"\nimport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\nimport { createWidgetApiImpl } from \"./widget-api\"\n\nexport type EmulatorApiBundle = {\n GristView: GristViewImpl\n GristDocAPI: GristDocApiImpl\n WidgetAPI: WidgetApiImpl\n CustomSectionAPI: CustomSectionApiImpl\n GristAPI: GristApiImpl\n CommandAPI: CommandApiImpl\n}\n\n/**\n * Build the implementations bound to a given document state and event bus.\n * Cheap to call — every method delegates to the (mutable) `state`.\n */\nexport function createApiBundle(state: EmulatorDocumentState, bus: EventBus): EmulatorApiBundle {\n return {\n GristView: createGristViewImpl(state, bus),\n GristDocAPI: createGristDocApiImpl(state, bus),\n WidgetAPI: createWidgetApiImpl(state, bus),\n CustomSectionAPI: createCustomSectionApiImpl(state, bus),\n GristAPI: createGristApiImpl(),\n CommandAPI: createCommandApiImpl(bus),\n }\n}\n\nexport type {\n CommandApiImpl,\n CustomSectionApiImpl,\n GristApiImpl,\n GristDocApiImpl,\n GristViewImpl,\n WidgetApiImpl,\n} from \"./types\"\n","/**\n * Tiny pub-sub used to broadcast every emulator state change to:\n * - the transports (which translate events into protocol messages),\n * - the React DevTools inspector (timeline view),\n * - the testing harness (assertions on emitted events).\n */\n\nimport type { GristCursorPos, GristWidgetColumnMap, GristWidgetInteraction } from \"../../sdk/types\"\n\nexport type EmulatorEvent =\n | { type: \"data-change\"; tableId: string }\n | { type: \"cursor-change\"; tableId: string; rowId: number | \"new\" | null; cursor?: GristCursorPos }\n | { type: \"options-change\"; options: Record<string, unknown>; interaction: GristWidgetInteraction }\n | { type: \"theme-change\"; message: Record<string, unknown> }\n | { type: \"ready\"; configuration: unknown }\n | { type: \"user-action\"; action: unknown[] }\n | { type: \"mappings-change\"; mappings: GristWidgetColumnMap | null }\n\nexport type EmulatorEventListener = (event: EmulatorEvent) => void\n\nexport type EventBus = {\n emit: (event: EmulatorEvent) => void\n on: (listener: EmulatorEventListener) => () => void\n history: () => readonly EmulatorEvent[]\n clear: () => void\n}\n\nexport type EventBusOptions = {\n /** Cap on history length (DevTools / tests). Defaults to 200. */\n historyLimit?: number\n}\n\nexport function createEventBus(options: EventBusOptions = {}): EventBus {\n const limit = options.historyLimit ?? 200\n const listeners = new Set<EmulatorEventListener>()\n const history: EmulatorEvent[] = []\n\n return {\n emit(event) {\n history.push(event)\n if (history.length > limit) history.shift()\n for (const fn of [...listeners]) {\n try {\n fn(event)\n } catch (err) {\n console.error(\"[grist-emulator] event listener threw:\", err)\n }\n }\n },\n on(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n history() {\n return history\n },\n clear() {\n history.length = 0\n },\n }\n}\n","export type GristThemeAppearance = \"light\" | \"dark\"\n\n/** Host → widget postMessage shape used by `grist-plugin-api.js` (`onThemeChange`). */\nexport type GristThemeHostMessage = {\n theme: {\n appearance: GristThemeAppearance\n name: string\n colors: Record<string, string>\n }\n fromReady?: boolean\n}\n\nexport function buildGristThemeHostMessage(\n appearance: GristThemeAppearance,\n options?: { fromReady?: boolean }\n): GristThemeHostMessage {\n return {\n theme: {\n appearance,\n name: appearance,\n colors: {},\n },\n ...(options?.fromReady ? { fromReady: true } : {}),\n }\n}\n","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","/**\n * Inline transport — synthesises a `window.grist` global wired directly to\n * the emulator state. No iframe, no postMessage, no serialization.\n *\n * Used for:\n * - SDK unit tests in jsdom (`renderWithGrist(...)`),\n * - IDE-style live previews where widget code lives in the same window\n * as the emulator host.\n *\n * The synthesised `grist` object exposes the **same** typed surface as the\n * production `grist-plugin-api.js` (see `hooks/grist-global.d.ts`). Hooks\n * call `grist.docApi.fetchTable(...)` etc. and get the answer directly from\n * the action engine.\n */\n\nimport type {\n GristCursorPos,\n GristFetchSelectedOptions,\n GristMinimalRecord,\n GristReadyOptions,\n GristTableOpOptions,\n GristTableOperations,\n GristTableUpdateRecord,\n GristTableUpsertOptions,\n GristTableUpsertRecord,\n GristWidgetColumnMap,\n GristWidgetInteraction,\n} from \"../../sdk/types\"\nimport {\n gristAddRecordAction,\n gristBulkAddRecordAction,\n gristBulkRemoveRecordAction,\n gristBulkUpdateRecordAction,\n gristRemoveRecordAction,\n gristUpdateRecordAction,\n} from \"../../sdk/helpers/grist-user-actions\"\nimport { applyUserActions } from \"../core/action-engine\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\nimport { findRow, getTable } from \"../core/document\"\nimport { resolveMappings } from \"../core/mappings\"\nimport { buildGristThemeHostMessage } from \"../theme-message\"\nimport type { EmulatorTransport, TransportContext } from \"./types\"\n\n/**\n * Shape of the synthesised global. Matches `globalThis.grist` from\n * `grist-global.d.ts`.\n */\nexport type InlineGristGlobal = {\n ready: (options?: GristReadyOptions) => Promise<void>\n onRecord: (\n cb: (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onRecords: (\n cb: (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void,\n options?: GristFetchSelectedOptions\n ) => void\n onOptions: (cb: (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void) => void\n onNewRecord: (cb: (mappings: GristWidgetColumnMap | null) => void) => void\n mapColumnNames: (data: Record<string, unknown>) => Record<string, unknown> | null\n mapColumnNamesBack: (data: Record<string, unknown>) => Record<string, unknown>\n getOptions: () => Promise<Record<string, unknown> | null>\n getOption: (key: string) => Promise<unknown>\n setOption: (key: string, value: unknown) => Promise<void>\n setOptions: (options: Record<string, unknown>) => Promise<void>\n clearOptions: () => Promise<void>\n setCursorPos: (pos: GristCursorPos) => Promise<void>\n setSelectedRows: (rowIds: number[] | null) => Promise<void>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n docApi: {\n getDocName: () => Promise<string>\n listTables: () => Promise<string[]>\n fetchTable: (tableId: string) => Promise<Record<string, unknown[]>>\n applyUserActions: (actions: unknown[][], options?: { desc?: string }) => Promise<{ retValues: unknown[] }>\n getAccessToken?: (options?: { readOnly?: boolean }) => Promise<{ token: string; baseUrl: string }>\n fetchSelectedTable: (options?: GristFetchSelectedOptions) => Promise<Record<string, unknown[]>>\n fetchSelectedRecord: (rowId: number, options?: GristFetchSelectedOptions) => Promise<Record<string, unknown>>\n }\n selectedTable: GristTableOperations\n getTable: (tableId?: string) => GristTableOperations\n sectionApi: {\n configure: (settings: GristReadyOptions) => Promise<void>\n mappings: () => Promise<GristWidgetColumnMap | null>\n }\n on: (eventName: string, listener: (...args: unknown[]) => void) => () => void\n}\n\nexport type InlineTransportOptions = TransportContext & {\n /**\n * Where to mount the synthesised `grist` global.\n * Defaults to the current window. Pass a different target (e.g. an iframe's\n * `contentWindow`) to install it in another realm.\n */\n target?: Window & typeof globalThis\n}\n\n/**\n * Returns an {@link EmulatorTransport} **and** the synthesised `grist`\n * object. `target.grist = global` is set as a side-effect for parity with\n * the production runtime.\n */\nexport function createInlineTransport(\n options: InlineTransportOptions\n): EmulatorTransport & { grist: InlineGristGlobal } {\n const { state, bus, api } = options\n const target = options.target ?? (globalThis as unknown as Window & typeof globalThis)\n\n // The SDK's `useGristAvailability` checks `window.self !== window.top`.\n // The inline transport runs in a top-level window where that's false. We\n // shim `top` so widget code thinks it's embedded — production doesn't use\n // this transport so there's no risk of leaking the shim.\n installFakeIframeContext(target)\n\n type RecordCb = (record: Record<string, unknown> | null, mappings?: GristWidgetColumnMap | null) => void\n type RecordsCb = (records: Record<string, unknown>[], mappings?: GristWidgetColumnMap | null) => void\n type OptionsCb = (options: Record<string, unknown> | null, interaction: GristWidgetInteraction) => void\n type NewRecordCb = (mappings: GristWidgetColumnMap | null) => void\n\n const recordCbs = new Map<RecordCb, GristFetchSelectedOptions | undefined>()\n const recordsCbs = new Map<RecordsCb, GristFetchSelectedOptions | undefined>()\n const optionsCbs = new Set<OptionsCb>()\n const newRecordCbs = new Set<NewRecordCb>()\n const generic = new Map<string, Set<(...args: unknown[]) => void>>()\n\n // Replay caches — production `grist-plugin-api.js` immediately delivers the\n // latest record / records / options to a freshly-subscribed listener, so\n // hooks that subscribe **after** `grist.ready()` still get the initial\n // payload. We mirror that behaviour here.\n type LastRecord = { record: Record<string, unknown> | null; mappings: GristWidgetColumnMap | null }\n type LastRecords = { records: Record<string, unknown>[]; mappings: GristWidgetColumnMap | null }\n type LastOptions = { options: Record<string, unknown> | null; interaction: GristWidgetInteraction }\n let lastRecord: LastRecord | null = null\n let lastRecords: LastRecords | null = null\n let lastOptions: LastOptions | null = null\n let lastNewRecord: GristWidgetColumnMap | null | undefined = undefined\n\n const buildInteraction = options.buildInteraction ?? (() => ({\n access_level: state.configuration?.requiredAccess ?? \"read table\",\n ...state.widgetInteraction,\n }))\n\n async function pushRecord(rowId: number | \"new\" | null) {\n const mappings = resolveMappings(state)\n if (rowId === \"new\") {\n // Grist's onRecord ignores the add-row (rowId \"new\"): only onNewRecord fires.\n lastNewRecord = mappings\n for (const cb of newRecordCbs) {\n try { cb(mappings) } catch (err) { logErr(err) }\n }\n return\n }\n if (rowId === null) {\n lastRecord = { record: null, mappings }\n for (const [cb] of recordCbs) {\n try { cb(null, mappings) } catch (err) { logErr(err) }\n }\n return\n }\n let record: Record<string, unknown> | null = null\n try {\n record = await api.GristView.fetchSelectedRecord(rowId)\n } catch (err) {\n logErr(err)\n }\n lastRecord = { record, mappings }\n for (const [cb, opts] of recordCbs) {\n try {\n const r = opts?.keepEncoded\n ? await api.GristView.fetchSelectedRecord(rowId, { keepEncoded: true })\n : record\n cb(r, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n async function pushRecords() {\n const mappings = resolveMappings(state)\n let baseRows: Record<string, unknown>[] = []\n try {\n const columnar = await api.GristView.fetchSelectedTable({})\n baseRows = columnsToRows(columnar)\n } catch (err) {\n logErr(err)\n }\n lastRecords = { records: baseRows, mappings }\n for (const [cb, opts] of recordsCbs) {\n try {\n const fetchOptions = coerceFetchOptions(opts)\n // Re-fetch only when the subscriber asked for a different shape\n // (e.g. `keepEncoded: true`). Otherwise reuse the decoded rows we\n // already have to avoid extra work and to match production where\n // the same fetch is broadcast to every listener.\n const rows = fetchOptions?.keepEncoded\n ? columnsToRows(await api.GristView.fetchSelectedTable({ keepEncoded: true }))\n : baseRows\n cb(rows, mappings)\n } catch (err) {\n logErr(err)\n }\n }\n }\n\n /**\n * Mirror what `viewApi.fetchSelectedTable` does inside `grist-plugin-api.js`:\n * the host RPC stub always returns columnar; the wrapper applies the\n * `format: \"rows\"` transpose (and would decode encoded values when\n * `keepEncoded: false` — a no-op here because our `rowsToColumnar` already\n * emits JS-native primitives in that case).\n *\n * Keeping this logic on the inline side guarantees that widgets see the\n * same result whether they go through the iframe transport (real plugin\n * wrapper) or the inline transport (this wrapper).\n */\n async function fetchSelectedTableShaped(\n opts: GristFetchSelectedOptions | undefined\n ): Promise<Record<string, unknown[]> | Record<string, unknown>[]> {\n const fetchOptions = coerceFetchOptions(opts)\n const columnar = (await api.GristView.fetchSelectedTable(\n fetchOptions ? { keepEncoded: fetchOptions.keepEncoded } : {}\n )) as Record<string, unknown[]>\n if (fetchOptions?.format === \"rows\") return columnsToRows(columnar)\n return columnar\n }\n\n function pushOptions() {\n const opts = Object.keys(state.widgetOptions).length > 0 ? { ...state.widgetOptions } : null\n const interaction = buildInteraction()\n lastOptions = { options: opts, interaction }\n for (const cb of optionsCbs) {\n try { cb(opts, interaction) } catch (err) { logErr(err) }\n }\n }\n\n const offBus = bus.on(async (event: EmulatorEvent) => {\n switch (event.type) {\n case \"data-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"cursor-change\":\n await pushRecord(event.rowId)\n break\n case \"options-change\":\n pushOptions()\n break\n case \"ready\":\n pushOptions()\n if (options.initialTheme) {\n notify(\"message\", buildGristThemeHostMessage(options.initialTheme, { fromReady: true }))\n }\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"mappings-change\":\n await pushRecords()\n await pushRecord(state.selection.rowId)\n break\n case \"theme-change\":\n notify(\"message\", event.message)\n break\n }\n })\n\n function makeTableOps(tableId: string): GristTableOperations {\n return {\n async getTableId() { return tableId },\n async create(records, options) {\n const list = Array.isArray(records) ? records : [records]\n const ids: GristMinimalRecord[] = []\n for (const r of list) {\n const result = applyUserActions(state, bus, [\n gristAddRecordAction(tableId, parseFields(r.fields, options)),\n ])\n ids.push({ id: result.retValues[0] as number })\n }\n return Array.isArray(records) ? ids : ids[0]\n },\n async update(records: GristTableUpdateRecord | GristTableUpdateRecord[], options?: GristTableOpOptions) {\n const list = Array.isArray(records) ? records : [records]\n const actions = list.map((r) => gristUpdateRecordAction(tableId, r.id, parseFields(r.fields, options)))\n applyUserActions(state, bus, actions)\n },\n async upsert(records: GristTableUpsertRecord | GristTableUpsertRecord[], options?: GristTableUpsertOptions) {\n const list = Array.isArray(records) ? records : [records]\n const allowAdd = options?.add !== false\n const allowUpdate = options?.update !== false\n const table = getTable(state, tableId)\n const actions: unknown[][] = []\n for (const r of list) {\n const matches = table.rows.filter((row) =>\n Object.entries(r.require).every(([k, v]) => row[k] === v)\n )\n if (matches.length > 0) {\n if (!allowUpdate) continue\n const fields = parseFields(r.fields ?? {}, options)\n for (const m of matches) actions.push(gristUpdateRecordAction(tableId, m.id, fields))\n } else if (allowAdd) {\n actions.push(gristAddRecordAction(tableId, { ...r.require, ...parseFields(r.fields ?? {}, options) }))\n }\n }\n if (actions.length > 0) applyUserActions(state, bus, actions)\n },\n async destroy(recordIds: number | number[]) {\n if (Array.isArray(recordIds)) {\n applyUserActions(state, bus, [gristBulkRemoveRecordAction(tableId, recordIds)])\n } else {\n applyUserActions(state, bus, [gristRemoveRecordAction(tableId, recordIds)])\n }\n // touch the unused bulk-add reference for tree-shaking parity, no-op\n void gristBulkAddRecordAction\n void gristBulkUpdateRecordAction\n },\n }\n }\n\n function notify(event: string, ...args: unknown[]) {\n const set = generic.get(event)\n if (!set) return\n for (const fn of set) {\n try { fn(...args) } catch (err) { logErr(err) }\n }\n }\n\n const grist: InlineGristGlobal = {\n async ready(opts) {\n await api.CustomSectionAPI.configure(opts ? { ...opts, onEditOptions: undefined } as unknown as Record<string, unknown> : {})\n },\n\n onRecord(cb, opts) {\n recordCbs.set(cb, opts)\n // Replay last value so late subscribers don't miss the initial event.\n if (lastRecord) {\n try { cb(lastRecord.record, lastRecord.mappings) } catch (err) { logErr(err) }\n }\n },\n onRecords(cb, opts) {\n recordsCbs.set(cb, opts)\n if (lastRecords) {\n try { cb(lastRecords.records, lastRecords.mappings) } catch (err) { logErr(err) }\n }\n },\n onOptions(cb) {\n optionsCbs.add(cb)\n if (lastOptions) {\n try { cb(lastOptions.options, lastOptions.interaction) } catch (err) { logErr(err) }\n }\n },\n onNewRecord(cb) {\n newRecordCbs.add(cb)\n if (lastNewRecord !== undefined) {\n try { cb(lastNewRecord) } catch (err) { logErr(err) }\n }\n },\n\n mapColumnNames(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return null\n const out: Record<string, unknown> = {}\n let allMapped = true\n for (const [logical, real] of Object.entries(mappings)) {\n if (Array.isArray(real)) {\n out[logical] = real.map((r) => data[r])\n } else if (typeof real === \"string\") {\n out[logical] = data[real]\n } else {\n allMapped = false\n }\n }\n return allMapped ? out : null\n },\n mapColumnNamesBack(data) {\n const mappings = resolveMappings(state)\n if (!mappings) return data\n const out: Record<string, unknown> = {}\n for (const [logical, real] of Object.entries(mappings)) {\n if (typeof real === \"string\" && logical in data) {\n out[real] = data[logical]\n }\n }\n return out\n },\n\n getOption: (k) => api.WidgetAPI.getOption(k),\n setOption: (k, v) => api.WidgetAPI.setOption(k, v),\n getOptions: () => api.WidgetAPI.getOptions(),\n setOptions: (o) => api.WidgetAPI.setOptions(o),\n clearOptions: () => api.WidgetAPI.clearOptions(),\n\n setCursorPos: (pos) => api.GristView.setCursorPos(pos),\n setSelectedRows: (rowIds) => api.GristView.setSelectedRows(rowIds),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) => api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n\n docApi: {\n getDocName: () => api.GristDocAPI.getDocName(),\n listTables: () => api.GristDocAPI.listTables(),\n fetchTable: (id) => api.GristDocAPI.fetchTable(id),\n applyUserActions: (actions, options) => api.GristDocAPI.applyUserActions(actions, options),\n getAccessToken: (opts) => api.GristDocAPI.getAccessToken(opts),\n fetchSelectedTable: (opts) =>\n fetchSelectedTableShaped(opts) as Promise<Record<string, unknown[]>>,\n fetchSelectedRecord: (rowId, opts) =>\n api.GristView.fetchSelectedRecord(rowId, coerceFetchOptions(opts)),\n },\n\n get selectedTable() {\n return makeTableOps(state.selection.tableId)\n },\n\n getTable(tableId) {\n return makeTableOps(tableId ?? state.selection.tableId)\n },\n\n sectionApi: {\n configure: (settings) => api.CustomSectionAPI.configure(settings as unknown as Record<string, unknown>),\n mappings: () => api.CustomSectionAPI.mappings(),\n },\n\n on(eventName, listener) {\n let set = generic.get(eventName)\n if (!set) generic.set(eventName, (set = new Set()))\n set.add(listener)\n return () => set!.delete(listener)\n },\n }\n\n ;(target as unknown as { grist: InlineGristGlobal }).grist = grist\n\n return {\n grist,\n dispose() {\n offBus()\n // Restore the global (only if we still own it).\n const t = target as unknown as { grist?: unknown }\n if (t.grist === grist) delete t.grist\n recordCbs.clear()\n recordsCbs.clear()\n optionsCbs.clear()\n newRecordCbs.clear()\n generic.clear()\n lastRecord = null\n lastRecords = null\n lastOptions = null\n lastNewRecord = undefined\n },\n fireDataChange(tableId) {\n bus.emit({ type: \"data-change\", tableId: tableId ?? state.selection.tableId })\n },\n fireCursor(rowId) {\n const id = rowId === undefined ? state.selection.rowId : rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId: id })\n },\n fireOptions() {\n pushOptions()\n },\n fireTheme(message) {\n bus.emit({ type: \"theme-change\", message })\n },\n emitInitialState() {\n pushOptions()\n void pushRecords().then(() => pushRecord(state.selection.rowId))\n },\n }\n}\n\nfunction columnsToRows(columnar: Record<string, unknown[]>): Record<string, unknown>[] {\n const cols = Object.keys(columnar)\n if (cols.length === 0) return []\n const length = (columnar[cols[0]] ?? []).length\n const rows: Record<string, unknown>[] = []\n for (let i = 0; i < length; i++) {\n const row: Record<string, unknown> = {}\n for (const c of cols) row[c] = columnar[c][i]\n rows.push(row)\n }\n return rows\n}\n\nfunction parseFields(fields: Record<string, unknown>, _options?: GristTableOpOptions): Record<string, unknown> {\n // The emulator currently doesn't implement string-parsing; pass-through.\n // Hook into here to add date/number parsing when we surface that toggle.\n return { ...fields }\n}\n\nfunction coerceFetchOptions(\n opts: GristFetchSelectedOptions | undefined\n): { keepEncoded?: boolean; format?: \"rows\" | \"columns\" } | undefined {\n if (!opts) return undefined\n const format = opts.format === \"rows\" || opts.format === \"columns\" ? opts.format : undefined\n return { keepEncoded: opts.keepEncoded, format }\n}\n\nfunction logErr(err: unknown) {\n console.error(\"[grist-emulator/inline]\", err)\n}\n\n// Touch helpers to keep them tree-shake-friendly even if unused in current scope.\nvoid findRow\n\n/**\n * Make `window.self !== window.top` evaluate to `true`. The SDK uses this\n * exact comparison in `useGristAvailability` to detect an iframe environment.\n *\n * Inline transports run inside the host window (tests, IDE preview) and would\n * otherwise be flagged as \"not embedded\" — this shim is the same trick we use\n * in the testing harness and is safe because the inline transport is never\n * shipped to production.\n */\nfunction installFakeIframeContext(target: Window & typeof globalThis) {\n try {\n if (target.self !== target.top) return\n Object.defineProperty(target, \"top\", {\n configurable: true,\n get: () => ({}),\n })\n } catch {\n // Some environments lock these globals; ignore silently.\n }\n}\n","import { z } from \"zod\"\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst emulatorRowSchema = z\n .object({ id: z.number() })\n .catchall(z.unknown())\n\nconst formulaKindSchema = z.enum([\"computed\", \"trigger\", \"none\", \"empty_slot\"])\n\nconst replicaColumnSchema = z\n .object({\n colRef: z.number().optional(),\n type: z.string().optional(),\n label: z.string().optional(),\n parentPos: z.number().optional(),\n isFormula: z.boolean().optional(),\n formulaKind: formulaKindSchema.optional(),\n formula: z.string().optional(),\n description: z.string().optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n displayColRef: z.number().optional(),\n visibleColRef: z.number().optional(),\n })\n .strict()\n\nconst replicaTableSchema = z\n .object({\n label: z.string().optional(),\n columns: z.record(z.string(), replicaColumnSchema).optional(),\n rows: z.array(emulatorRowSchema).optional(),\n rowCount: z.number().optional(),\n dataOmitted: z.boolean().optional(),\n dataOmittedReason: z.string().optional(),\n error: z.string().optional(),\n })\n .strict()\n\nconst replicaSelectionSchema = z\n .object({\n tableId: z.string().optional(),\n rowId: z.union([z.number(), z.literal(\"new\"), z.null()]).optional(),\n mappings: z.unknown().nullable().optional(),\n cursor: z.unknown().optional(),\n })\n .strict()\n\nconst replicaWidgetConfigurationSchema = z\n .object({\n requiredAccess: z.string().optional(),\n columns: z.unknown().optional(),\n allowSelectBy: z.boolean().optional(),\n hasCustomOptions: z.boolean().optional(),\n })\n .strict()\n\nconst replicaAccessTokenSchema = z\n .object({\n token: z.string(),\n baseUrl: z.string(),\n ttlMsecs: z.number(),\n })\n .strict()\n\nconst replicaDocumentSchema = z\n .object({\n generatedAt: z.string(),\n source: z.string().optional(),\n docName: z.string().optional(),\n mode: z.enum([\"schema-only\", \"schema+samples\", \"schema+data\"]).optional(),\n tables: z.record(z.string(), replicaTableSchema),\n selection: replicaSelectionSchema.optional(),\n widgetOptions: z.record(z.string(), z.unknown()).optional(),\n widgetInteraction: z.unknown().optional(),\n configuration: replicaWidgetConfigurationSchema.optional(),\n accessToken: replicaAccessTokenSchema.nullable().optional(),\n })\n .strict()\n .refine((value) => Object.keys(value.tables).length > 0, {\n message: \"at least one table is required\",\n path: [\"tables\"],\n })\n\nfunction formatZodError(prefix: string, error: z.ZodError): Error {\n const details = error.issues\n .map((issue) => {\n const where = issue.path.length > 0 ? issue.path.join(\".\") : \"<root>\"\n return `${where}: ${issue.message}`\n })\n .join(\"; \")\n return new Error(`${prefix}: ${details}`)\n}\n\nexport function safeParseDocument(input: unknown) {\n return replicaDocumentSchema.safeParse(input)\n}\n\nexport function parseDocument(input: unknown): GristReplicaDocument {\n const result = safeParseDocument(input)\n if (!result.success) {\n throw formatZodError(\"parseDocument\", result.error)\n }\n return result.data as GristReplicaDocument\n}\n","/**\n * Top-level emulator factory. Produces a fully-wired emulator instance:\n *\n * - typed in-memory document state,\n * - shared event bus,\n * - the six host API impls,\n * - the inline transport, which installs `grist` on the page,\n * - imperative helpers (`mutate`, `apply`, `selectRow`, `selectTable`)\n * that drive the document via the action engine and emit corresponding\n * events.\n *\n * The instance is multi-instance friendly: nothing is stored on `window`.\n */\n\nimport { createApiBundle } from \"./api\"\nimport type { EmulatorApiBundle } from \"./api\"\nimport { applyUserActions } from \"./core/action-engine\"\nimport { createDocument } from \"./core/document\"\nimport { createEventBus } from \"./core/event-bus\"\nimport type { EventBus } from \"./core/event-bus\"\nimport { resolveMappings } from \"./core/mappings\"\nimport type { EmulatorDocumentState } from \"./core/types\"\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\nimport type { GristWidgetColumnMap } from \"../sdk/types\"\nimport { buildGristThemeHostMessage } from \"./theme-message\"\nimport { createInlineTransport } from \"./transports\"\nimport type { EmulatorTransport, InlineGristGlobal } from \"./transports\"\nimport { parseDocument } from \"./validators\"\n\nexport type CreateGristEmulatorOptions = {\n /** The starting document (must satisfy {@link parseDocument}). */\n document: GristReplicaDocument\n /** Installs `grist` on `target` (default: the global object). */\n transport?: { kind: \"inline\"; target?: Window & typeof globalThis }\n /** Initial widget options exposed via `WidgetAPI`. */\n widgetOptions?: Record<string, unknown>\n /**\n * Initial widget interaction info (`access_level` and friends) sent\n * alongside `onOptions`. Without an `access_level`, Grist grants the access\n * the widget requests in `grist.ready()`.\n */\n widgetInteraction?: Record<string, unknown>\n /** Initial document theme replayed on widget ready (host `message` channel). */\n initialTheme?: \"light\" | \"dark\"\n}\n\nexport type GristEmulator = {\n /** Underlying mutable document. Treat as read-only outside of `mutate(...)`. */\n state: EmulatorDocumentState\n bus: EventBus\n api: EmulatorApiBundle\n transport: EmulatorTransport\n /** Synthesised `grist` global (only for the inline transport). */\n grist?: InlineGristGlobal\n\n /** Apply a list of Grist user actions; emits the matching events. */\n apply: (actions: unknown[][]) => { retValues: unknown[] }\n /** Convenience helpers for tests and demos. */\n mutate: {\n addRow: (tableId: string, fields: Record<string, unknown>) => number\n updateRow: (tableId: string, rowId: number, fields: Record<string, unknown>) => void\n removeRow: (tableId: string, rowId: number) => void\n }\n selectRow: (rowId: number | \"new\" | null) => void\n selectTable: (tableId: string) => void\n /**\n * Set logical→real column mappings, as a user mapping columns in Grist would.\n * Pass `undefined` to clear — `mappings()` becomes `null` until set again.\n */\n setColumnMappings: (mappings: GristWidgetColumnMap | undefined) => void\n setOptions: (options: Record<string, unknown>) => Promise<void>\n setInteraction: (interaction: Record<string, unknown>) => void\n /** Host theme controls (`grist.on(\"message\")` / `msg.theme`). */\n theme: {\n set: (theme: \"light\" | \"dark\") => void\n }\n /** Tear down the emulator. Idempotent. */\n dispose: () => void\n}\n\nexport function createGristEmulator(options: CreateGristEmulatorOptions): GristEmulator {\n const validatedDocument = parseDocument(options.document)\n const state = createDocument({\n ...validatedDocument,\n widgetOptions: options.widgetOptions ?? validatedDocument.widgetOptions,\n // No access_level by default: the emulator then grants the access the\n // widget asks for in grist.ready(), as a user accepting it in Grist would.\n widgetInteraction: options.widgetInteraction ?? validatedDocument.widgetInteraction ?? {},\n })\n const bus = createEventBus()\n const api = createApiBundle(state, bus)\n\n const inline = createInlineTransport({\n state,\n bus,\n api,\n initialTheme: options.initialTheme,\n target: options.transport?.target,\n })\n const transport: EmulatorTransport = inline\n const grist: InlineGristGlobal | undefined = inline.grist\n\n function apply(actions: unknown[][]) {\n return applyUserActions(state, bus, actions)\n }\n\n return {\n state,\n bus,\n api,\n transport,\n grist,\n apply,\n mutate: {\n addRow: (tableId, fields) => apply([[\"AddRecord\", tableId, null, fields]]).retValues[0] as number,\n updateRow: (tableId, rowId, fields) => {\n apply([[\"UpdateRecord\", tableId, rowId, fields]])\n },\n removeRow: (tableId, rowId) => {\n apply([[\"RemoveRecord\", tableId, rowId]])\n },\n },\n selectRow(rowId) {\n state.selection.rowId = rowId\n bus.emit({ type: \"cursor-change\", tableId: state.selection.tableId, rowId })\n },\n selectTable(tableId) {\n if (!state.tables.has(tableId)) throw new Error(`Unknown table: ${tableId}`)\n state.selection.tableId = tableId\n const first = state.tables.get(tableId)!.rows[0]?.id ?? null\n state.selection.rowId = first\n bus.emit({ type: \"data-change\", tableId })\n bus.emit({ type: \"cursor-change\", tableId, rowId: first })\n },\n setColumnMappings(mappings) {\n if (mappings === undefined) {\n delete state.selection.mappings\n } else {\n state.selection.mappings = mappings\n }\n bus.emit({ type: \"mappings-change\", mappings: resolveMappings(state) })\n },\n async setOptions(opts) {\n await api.WidgetAPI.setOptions(opts)\n },\n setInteraction(interaction) {\n state.widgetInteraction = { ...interaction }\n bus.emit({ type: \"options-change\", options: { ...state.widgetOptions }, interaction: { ...interaction } })\n },\n theme: {\n set(next) {\n bus.emit({ type: \"theme-change\", message: buildGristThemeHostMessage(next) })\n },\n },\n dispose() {\n transport.dispose()\n bus.clear()\n },\n }\n}\n","/**\n * Document templates exposed at the top of the emulator API.\n *\n * Templates return plain data — they don't allocate state, the caller passes\n * the returned value into `createGristEmulator(...)` which performs the allocation.\n */\n\nimport type { GristReplicaDocument } from \"../sdk/replica-document\"\n\nconst PRESET_GENERATED_AT = \"1970-01-01T00:00:00.000Z\"\n\nfunction replicaBase(overrides: Omit<GristReplicaDocument, \"generatedAt\">): GristReplicaDocument {\n return {\n generatedAt: PRESET_GENERATED_AT,\n ...overrides,\n }\n}\n\n/**\n * Useful templates for quick demos and tests.\n */\nexport const presets = {\n /**\n * Default starter fixture for demos / sandboxes that need a neutral document\n * without choosing a domain-specific preset.\n */\n defaultTemplate(): GristReplicaDocument {\n return replicaBase({\n docName: \"Default\",\n tables: {\n Table1: {\n label: \"Table1\",\n rows: [\n { id: 1, Name: \"Alice\" },\n { id: 2, Name: \"Bob\" },\n ],\n },\n },\n })\n },\n blank(): GristReplicaDocument {\n return replicaBase({\n docName: \"Blank\",\n tables: {\n Table1: { rows: [{ id: 1 }] },\n },\n })\n },\n todoList(): GristReplicaDocument {\n return replicaBase({\n docName: \"Todo list\",\n mode: \"schema+data\",\n tables: {\n Tasks: {\n label: \"Tasks\",\n columns: {\n title: { type: \"Text\", label: \"Title\" },\n done: { type: \"Bool\", label: \"Done\" },\n priority: { type: \"Choice\", label: \"Priority\" },\n },\n rows: [\n { id: 1, title: \"Buy milk\", done: false, priority: \"high\" },\n { id: 2, title: \"Write the SOTA emulator\", done: true, priority: \"high\" },\n { id: 3, title: \"Ship it\", done: false, priority: \"medium\" },\n ],\n },\n },\n })\n },\n contacts(): GristReplicaDocument {\n return replicaBase({\n docName: \"Contacts\",\n mode: \"schema+data\",\n tables: {\n Contacts: {\n label: \"Contacts\",\n columns: {\n firstName: { type: \"Text\" },\n lastName: { type: \"Text\" },\n email: { type: \"Text\" },\n company: { type: \"Text\" },\n },\n rows: [\n { id: 1, firstName: \"Ada\", lastName: \"Lovelace\", email: \"ada@analytical.engine\", company: \"British Crown\" },\n { id: 2, firstName: \"Linus\", lastName: \"Torvalds\", email: \"linus@kernel.org\", company: \"Linux Foundation\" },\n { id: 3, firstName: \"Margaret\", lastName: \"Hamilton\", email: \"margaret@apollo.nasa\", company: \"NASA\" },\n ],\n },\n },\n })\n },\n}\n"],"mappings":"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","names":["options"]}
|