grist-widget-sdk 0.2.15 → 0.3.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 +6 -0
- package/dist/advanced.js +3 -2
- package/dist/advanced.js.map +1 -1
- package/dist/{chunk-ER6UWHZA.js → chunk-7GXVEZ2J.js} +2 -2
- package/dist/{chunk-KOVYBNPJ.js → chunk-D5GBS2NT.js} +8 -31
- package/dist/chunk-D5GBS2NT.js.map +1 -0
- package/dist/chunk-N3X46JW2.js +37 -0
- package/dist/chunk-N3X46JW2.js.map +1 -0
- package/dist/emulator/devtools.cjs +37 -0
- package/dist/emulator/devtools.cjs.map +1 -1
- package/dist/emulator/devtools.js +28 -0
- package/dist/emulator/devtools.js.map +1 -1
- package/dist/emulator/testing.js +2 -1
- package/dist/emulator/testing.js.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-KOVYBNPJ.js.map +0 -1
- /package/dist/{chunk-ER6UWHZA.js.map → chunk-7GXVEZ2J.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/emulator/devtools/index.ts","../../src/emulator/devtools/inspector.tsx","../../src/sdk/helpers/grist-user-actions.ts","../../src/emulator/core/mappings.ts","../../src/emulator/devtools/use-emulator-state.ts","../../src/emulator/devtools/use-rows.ts","../../src/sdk/helpers/grist-value-codec.ts","../../src/sdk/helpers/grist-safe-parse.ts","../../src/sdk/helpers/grist-widget-options.ts","../../src/sdk/helpers/grist-table-data.ts","../../src/emulator/core/columnar.ts","../../src/emulator/devtools/use-columns.ts","../../src/sdk/helpers/grist-columns-filters.ts"],"sourcesContent":["export { EmulatorInspector } from \"./inspector\"\nexport type { EmulatorInspectorProps } from \"./inspector\"\nexport { fetchEmulatorRows, useEmulatorRows } from \"./use-rows\"\nexport type { UseEmulatorRowsResult } from \"./use-rows\"\nexport { useEmulatorColumns } from \"./use-columns\"\nexport type {\n EmulatorColumnsTableView,\n UseEmulatorColumnsResult,\n} from \"./use-columns\"\nexport { useEmulatorSnapshot } from \"./use-emulator-state\"\n","/**\n * `<EmulatorInspector />` — drop-in DevTools for the playground / IDE.\n *\n * Capabilities:\n * - Multi-table picker with row count + label\n * - Inline row editor (Add / Update / Delete) routed through the emulator's\n * action engine — every edit produces real Grist user actions on the bus.\n * - Cursor selector that drives `onRecord` for the widget under test.\n * - Widget options & mappings panel.\n * - Live event timeline (last 50 events) with pretty formatting.\n *\n * The component owns no state of its own beyond UI accordion toggles —\n * everything is read off the emulator and re-renders via {@link\n * useEmulatorSnapshot}.\n */\n\nimport type { CSSProperties, ReactNode } from \"react\"\nimport { useState } from \"react\"\n\nimport { gristAddRecordAction, gristRemoveRecordAction, gristUpdateRecordAction } from \"../../sdk/helpers/grist-user-actions\"\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport { resolveMappings } from \"../core/mappings\"\nimport { useEmulatorSnapshot } from \"./use-emulator-state\"\n\nexport type EmulatorInspectorProps = {\n emulator: GristEmulator\n /** Override visual style. */\n className?: string\n /** Default `true`. Set to `false` to render only the toolbar. */\n showTimeline?: boolean\n}\n\nexport function EmulatorInspector({ emulator, className, showTimeline = true }: EmulatorInspectorProps) {\n const { state, history } = useEmulatorSnapshot(emulator)\n const tableIds = [...state.tables.keys()]\n const selectedTableId = state.selection.tableId\n const table = state.tables.get(selectedTableId)\n const columnIds = table ? Object.keys(table.columns) : []\n\n const onSelectTable = (tableId: string) => emulator.selectTable(tableId)\n const onSelectRow = (rowId: number | \"new\" | null) => emulator.selectRow(rowId)\n const onAddRow = () => {\n if (!table) return\n const fields: Record<string, unknown> = {}\n for (const col of columnIds) fields[col] = \"\"\n emulator.apply([gristAddRecordAction(selectedTableId, fields)])\n }\n const onDeleteRow = (rowId: number) => {\n emulator.apply([gristRemoveRecordAction(selectedTableId, rowId)])\n }\n const onEditCell = (rowId: number, colId: string, value: string) => {\n emulator.apply([gristUpdateRecordAction(selectedTableId, rowId, { [colId]: value })])\n }\n\n return (\n <div className={className} style={baseStyle}>\n <div style={headerStyle}>\n <span style={badgeStyle}>EMULATOR</span>\n <strong>{state.docName}</strong>\n <span style={mutedStyle}>· {tableIds.length} table{tableIds.length === 1 ? \"\" : \"s\"}</span>\n </div>\n\n <div style={{ display: \"flex\", gap: 6, padding: \"8px 12px\", flexWrap: \"wrap\" }}>\n {tableIds.map((id) => {\n const t = state.tables.get(id)!\n const active = id === selectedTableId\n return (\n <button\n key={id}\n type=\"button\"\n onClick={() => onSelectTable(id)}\n style={active ? tabActiveStyle : tabStyle}\n >\n {t.label ?? id}\n <span style={mutedStyle}> · {t.rows.length}</span>\n </button>\n )\n })}\n </div>\n\n <Section title=\"Rows\">\n {!table ? (\n <p style={mutedStyle}>No table selected.</p>\n ) : (\n <div>\n <div style={{ display: \"flex\", gap: 6, marginBottom: 6 }}>\n <button type=\"button\" onClick={onAddRow} style={primaryBtnStyle}>+ Row</button>\n <button type=\"button\" onClick={() => onSelectRow(\"new\")} style={ghostBtnStyle}>Cursor → new</button>\n <button type=\"button\" onClick={() => onSelectRow(null)} style={ghostBtnStyle}>Cursor → none</button>\n </div>\n <div style={{ overflowX: \"auto\" }}>\n <table style={tableStyle}>\n <thead>\n <tr style={{ borderBottom: \"1px solid #2a2f37\" }}>\n <th style={thStyle}>id</th>\n {columnIds.map((col) => (\n <th key={col} style={thStyle}>\n {table.columns[col]?.label ?? col}\n </th>\n ))}\n <th style={thStyle}></th>\n </tr>\n </thead>\n <tbody>\n {table.rows.map((row) => {\n const rowId = row.id\n const active = state.selection.rowId === rowId\n return (\n <tr\n key={rowId}\n style={active ? trActiveStyle : trStyle}\n onClick={() => onSelectRow(rowId)}\n >\n <td style={tdStyle}>{rowId}</td>\n {columnIds.map((col) => (\n <td key={col} style={tdStyle}>\n <input\n value={formatCell(row[col])}\n style={inputStyle}\n onClick={(event) => event.stopPropagation()}\n onChange={(event) => onEditCell(rowId, col, event.target.value)}\n />\n </td>\n ))}\n <td style={tdStyle}>\n <button\n type=\"button\"\n style={dangerBtnStyle}\n onClick={(event) => {\n event.stopPropagation()\n onDeleteRow(rowId)\n }}\n >\n Delete\n </button>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </Section>\n\n <Section title=\"Selection / mappings\">\n <div style={kvStyle}>\n <KV k=\"tableId\" v={state.selection.tableId} />\n <KV k=\"rowId\" v={String(state.selection.rowId)} />\n <KV k=\"mappings\" v={JSON.stringify(resolveMappings(state))} />\n <KV k=\"configuration\" v={JSON.stringify(state.configuration)} />\n </div>\n </Section>\n\n <Section title=\"Widget options\">\n <pre style={preStyle}>{JSON.stringify(state.widgetOptions, null, 2)}</pre>\n <KV k=\"interaction\" v={JSON.stringify(state.widgetInteraction)} />\n </Section>\n\n {showTimeline && (\n <Section title={`Event timeline (${history.length})`}>\n <div style={{ maxHeight: 200, overflow: \"auto\", fontFamily: \"monospace\", fontSize: 11 }}>\n {history.slice(-50).reverse().map((event, idx) => (\n <div key={idx} style={timelineRowStyle}>\n <span style={typeBadgeStyle(event.type)}>{event.type}</span>\n <span style={mutedStyle}>{summariseEvent(event)}</span>\n </div>\n ))}\n {history.length === 0 && <p style={mutedStyle}>No events yet.</p>}\n </div>\n </Section>\n )}\n </div>\n )\n}\n\nfunction Section({ title, children }: { title: string; children: ReactNode }) {\n const [open, setOpen] = useState(true)\n return (\n <div style={{ borderTop: \"1px solid #2a2f37\" }}>\n <button type=\"button\" style={sectionHeaderStyle} onClick={() => setOpen((v) => !v)}>\n <span>{open ? \"▾\" : \"▸\"}</span>\n <strong>{title}</strong>\n </button>\n {open && <div style={{ padding: \"0 12px 12px\" }}>{children}</div>}\n </div>\n )\n}\n\nfunction KV({ k, v }: { k: string; v: ReactNode }) {\n return (\n <div style={kvRowStyle}>\n <span style={mutedStyle}>{k}</span>\n <code style={{ fontFamily: \"monospace\", fontSize: 11 }}>{v}</code>\n </div>\n )\n}\n\nfunction summariseEvent(event: { type: string } & Record<string, unknown>): string {\n switch (event.type) {\n case \"user-action\":\n return JSON.stringify(event.action)\n case \"data-change\":\n return `tableId=${String(event.tableId)}`\n case \"cursor-change\":\n return `tableId=${String(event.tableId)} rowId=${String(event.rowId)}`\n case \"options-change\":\n return JSON.stringify(event.options)\n case \"ready\":\n return JSON.stringify(event.configuration)\n case \"theme-change\":\n return JSON.stringify(event.message)\n case \"mappings-change\":\n return JSON.stringify(event.mappings)\n default:\n return \"\"\n }\n}\n\nfunction formatCell(value: unknown): string {\n if (value === null || value === undefined) return \"\"\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n return JSON.stringify(value)\n}\n\n// --- styles -----------------------------------------------------------------\n\nconst baseStyle: CSSProperties = {\n background: \"#15171c\",\n color: \"#e6e6e6\",\n fontFamily: \"system-ui, sans-serif\",\n fontSize: 13,\n border: \"1px solid #2a2f37\",\n borderRadius: 8,\n overflow: \"hidden\",\n}\nconst headerStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"10px 12px\",\n background: \"#0f1115\",\n borderBottom: \"1px solid #2a2f37\",\n}\nconst badgeStyle: CSSProperties = {\n background: \"#3a8e57\",\n color: \"#fff\",\n padding: \"1px 6px\",\n borderRadius: 4,\n fontSize: 10,\n letterSpacing: 0.5,\n}\nconst mutedStyle: CSSProperties = { color: \"#9ba1ad\" }\nconst sectionHeaderStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n width: \"100%\",\n background: \"transparent\",\n color: \"inherit\",\n border: \"none\",\n padding: \"10px 12px\",\n textAlign: \"left\" as const,\n cursor: \"pointer\",\n}\nconst tabStyle: CSSProperties = {\n background: \"#1c1f26\",\n color: \"#cfd2d8\",\n border: \"1px solid #2a2f37\",\n borderRadius: 6,\n padding: \"4px 10px\",\n cursor: \"pointer\",\n}\nconst tabActiveStyle: CSSProperties = { ...tabStyle, background: \"#27313f\", borderColor: \"#3a4f6e\", color: \"#fff\" }\nconst primaryBtnStyle: CSSProperties = {\n background: \"#3a8e57\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: 6,\n padding: \"4px 10px\",\n cursor: \"pointer\",\n}\nconst ghostBtnStyle: CSSProperties = {\n background: \"transparent\",\n color: \"#cfd2d8\",\n border: \"1px solid #2a2f37\",\n borderRadius: 6,\n padding: \"4px 10px\",\n cursor: \"pointer\",\n}\nconst dangerBtnStyle: CSSProperties = {\n background: \"transparent\",\n color: \"#e58f8f\",\n border: \"1px solid #4a2226\",\n borderRadius: 6,\n padding: \"2px 8px\",\n cursor: \"pointer\",\n}\nconst tableStyle: CSSProperties = { width: \"100%\", borderCollapse: \"collapse\" as const, fontSize: 12 }\nconst thStyle: CSSProperties = { textAlign: \"left\" as const, padding: \"4px 6px\", color: \"#9ba1ad\", fontWeight: 500 }\nconst trStyle: CSSProperties = { borderBottom: \"1px solid #1f232b\" }\nconst trActiveStyle: CSSProperties = { ...trStyle, background: \"#1d2733\" }\nconst tdStyle: CSSProperties = { padding: \"4px 6px\" }\nconst inputStyle: CSSProperties = {\n width: \"100%\",\n background: \"#0f1115\",\n color: \"#e6e6e6\",\n border: \"1px solid #2a2f37\",\n borderRadius: 4,\n padding: \"2px 4px\",\n fontSize: 12,\n fontFamily: \"monospace\",\n}\nconst preStyle: CSSProperties = {\n background: \"#0f1115\",\n border: \"1px solid #2a2f37\",\n borderRadius: 4,\n padding: 8,\n fontSize: 11,\n fontFamily: \"monospace\",\n margin: 0,\n whiteSpace: \"pre-wrap\",\n}\nconst kvStyle: CSSProperties = { display: \"flex\", flexDirection: \"column\" as const, gap: 4 }\nconst kvRowStyle: CSSProperties = { display: \"flex\", gap: 8 }\nconst timelineRowStyle: CSSProperties = {\n display: \"flex\",\n gap: 8,\n padding: \"2px 0\",\n borderBottom: \"1px solid #1f232b\",\n}\nfunction typeBadgeStyle(type: string): CSSProperties {\n const colour = ({\n \"user-action\": \"#a06bff\",\n \"data-change\": \"#3a8e57\",\n \"cursor-change\": \"#3a87b8\",\n \"options-change\": \"#b8893a\",\n ready: \"#888\",\n \"theme-change\": \"#888\",\n \"mappings-change\": \"#888\",\n } as Record<string, string>)[type] ?? \"#888\"\n return {\n background: colour,\n color: \"#fff\",\n padding: \"1px 6px\",\n borderRadius: 4,\n fontSize: 10,\n flexShrink: 0,\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 * 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 { useSyncExternalStore } from \"react\"\n\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\n\n/**\n * React-friendly snapshot of the emulator state. Re-renders whenever the\n * event bus fires (so the inspector stays in lock-step with widget actions).\n */\nexport function useEmulatorSnapshot(emulator: GristEmulator) {\n const subscribe = (notify: () => void) => {\n return emulator.bus.on(() => notify())\n }\n const getSnapshot = () => snapshotKey(emulator)\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n return {\n state: emulator.state,\n history: emulator.bus.history(),\n }\n}\n\n/**\n * A monotonic-ish key that changes on every event. We tag each event with\n * its index in the history so React detects changes cheaply.\n */\nfunction snapshotKey(emulator: GristEmulator): string {\n const history = emulator.bus.history()\n const last = history[history.length - 1]\n return `${history.length}:${eventTag(last)}`\n}\n\nfunction eventTag(event: EmulatorEvent | undefined): string {\n if (!event) return \"empty\"\n switch (event.type) {\n case \"data-change\":\n return `data:${event.tableId}`\n case \"cursor-change\":\n return `cursor:${event.tableId}:${String(event.rowId)}`\n case \"options-change\":\n return `options:${Object.keys(event.options).length}`\n case \"ready\":\n return \"ready\"\n case \"user-action\":\n return `action:${(event.action[0] as string | undefined) ?? \"?\"}`\n case \"mappings-change\":\n return \"mappings\"\n case \"theme-change\":\n return \"theme\"\n }\n}\n","import { useEffect, useState } from \"react\"\n\nimport {\n materializeGristRowsFromColumnar,\n safeParseRowsToDisplayRows,\n} from \"../../sdk/helpers/grist-table-data\"\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport { rowsToColumnar } from \"../core/columnar\"\nimport { useEmulatorSnapshot } from \"./use-emulator-state\"\n\nexport type UseEmulatorRowsResult<T extends Record<string, unknown> = Record<string, unknown>> = {\n rows: GristRowRecord<T>[]\n invalidCellKeys: Set<string>\n}\n\n/**\n * Build display-ready rows from emulator in-memory state (same parse pipeline as\n * {@link fetchGristTableRows}, without `docApi.fetchTable`).\n */\nexport function fetchEmulatorRows<T extends Record<string, unknown> = Record<string, unknown>>(\n emulator: GristEmulator,\n tableId: string\n): UseEmulatorRowsResult<T> {\n const table = emulator.state.tables.get(tableId)\n if (!table) {\n return { rows: [], invalidCellKeys: new Set() }\n }\n\n let cellMetaByKey: Record<string, { issues: Array<{ code: string }> }> = {}\n const data = rowsToColumnar(table, table.rows)\n const parsedRows = materializeGristRowsFromColumnar<T>(data, {\n columns: table.columns,\n order: \"grist\",\n safeParse: {\n refMode: \"detailed\",\n },\n onSafeParseCellMetaByKey: (metaByKey) => {\n cellMetaByKey = metaByKey as Record<string, { issues: Array<{ code: string }> }>\n },\n })\n const rows = safeParseRowsToDisplayRows(parsedRows) as GristRowRecord<T>[]\n const invalidCellKeys = new Set<string>()\n for (const [cellKey, meta] of Object.entries(cellMetaByKey)) {\n const hasIssue = meta.issues.some(\n (issue) => issue.code === \"type_mismatch\" || issue.code === \"invalid_format\"\n )\n if (hasIssue) invalidCellKeys.add(cellKey)\n }\n return { rows, invalidCellKeys }\n}\n\nexport function useEmulatorRows<T extends Record<string, unknown> = Record<string, unknown>>(\n emulator: GristEmulator,\n tableId: string | undefined | null\n): UseEmulatorRowsResult<T> {\n const { history } = useEmulatorSnapshot(emulator)\n const [result, setResult] = useState<UseEmulatorRowsResult<T>>({\n rows: [],\n invalidCellKeys: new Set(),\n })\n\n useEffect(() => {\n let cancelled = false\n if (!tableId) {\n queueMicrotask(() => {\n if (!cancelled) setResult({ rows: [], invalidCellKeys: new Set() })\n })\n return () => {\n cancelled = true\n }\n }\n\n try {\n const next = fetchEmulatorRows<T>(emulator, tableId)\n if (!cancelled) setResult(next)\n } catch {\n const table = emulator.state.tables.get(tableId)\n if (!cancelled) {\n setResult({\n rows: (table?.rows ?? []) as GristRowRecord<T>[],\n invalidCellKeys: new Set(),\n })\n }\n }\n\n return () => {\n cancelled = true\n }\n }, [emulator, tableId, history.length])\n\n return result\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","/**\n * Grist stores column widget configuration in `_grist_Tables_column.widgetOptions`\n * as a JSON string. Choice fields use `choices: string[]` plus optional\n * `choiceOptions: Record<string, Style>` (e.g. `fillColor`, `textColor`).\n *\n * @see https://github.com/gristlabs/grist-core/blob/main/app/client/widgets/ChoiceEditor.js\n */\n\n/** One selectable choice for UI (value stored in the cell is `value`). */\nexport type GristChoiceListEntry = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n}\n\n/**\n * Parse a cell value from `_grist_Tables_column.widgetOptions` into a plain object.\n */\nexport function parseGristWidgetOptionsCell(raw: unknown): Record<string, unknown> | undefined {\n if (raw == null || raw === \"\") return undefined\n if (typeof raw === \"string\") {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n return undefined\n }\n return undefined\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>\n }\n return undefined\n}\n\nfunction readStyleColor(style: Record<string, unknown>, key: string): string | undefined {\n const v = style[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/**\n * Normalizes Grist Choice / ChoiceList widgetOptions into a flat list for dropdowns.\n * `choices` entries are string labels (the stored cell value). Per-choice styling\n * lives in `choiceOptions[label]`.\n */\nexport function normalizeGristChoiceListEntries(\n widgetOptions: Record<string, unknown> | undefined\n): GristChoiceListEntry[] {\n if (!widgetOptions) return []\n const rawChoices = widgetOptions.choices\n if (!Array.isArray(rawChoices)) return []\n\n const choiceOptionsRaw = widgetOptions.choiceOptions\n const choiceOptions: Record<string, Record<string, unknown>> =\n choiceOptionsRaw &&\n typeof choiceOptionsRaw === \"object\" &&\n !Array.isArray(choiceOptionsRaw)\n ? (choiceOptionsRaw as Record<string, Record<string, unknown>>)\n : {}\n\n const out: GristChoiceListEntry[] = []\n for (const c of rawChoices) {\n const value = typeof c === \"string\" ? c : c != null ? String(c) : \"\"\n if (!value) continue\n const style = choiceOptions[value] ?? {}\n out.push({\n value,\n label: value,\n fillColor: readStyleColor(style, \"fillColor\"),\n textColor: readStyleColor(style, \"textColor\"),\n })\n }\n return out\n}\n","import type { GristDocApi, GristReplicaColumn, GristRowRecord } from \"../types\"\nimport { decodeGristValue } from \"./grist-value-codec\"\nimport {\n type GristSafeParseCellResult,\n type GristSafeTableCellMeta,\n safeParseGristTableData,\n type GristSafeTableCellIssue,\n type SafeParseGristTableDataOptions,\n} from \"./grist-safe-parse\"\n\n/**\n * Column-oriented table payload from `grist.docApi.fetchTable`.\n */\nexport type GristColumnarTable = Record<string, unknown[]>\nexport type GristTableRowsOrder = \"none\" | \"id\" | \"grist\"\nexport type FetchGristTableRowsOptions = {\n /** Optional schema metadata map to decode cells (except `id`) with `decodeGristValue`. */\n columns?: Record<string, GristReplicaColumn>\n /**\n * Row ordering strategy.\n * - `grist` (default): `manualSort` ascending when present, fallback `id`.\n * - `id`: numeric `id` ascending.\n * - `none`: preserve raw `fetchTable` row order.\n */\n order?: GristTableRowsOrder\n /**\n * Enable safe parsing with issue reporting.\n * - `true`: use safe parsing with defaults.\n * - object: pass safe-parse options (`displayHelpersByRef`, `refMode`, ...).\n */\n safeParse?: boolean | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n /** Optional callback fired with per-cell parse issues when `safeParse` is enabled. */\n onSafeParseIssues?: (issues: GristSafeTableCellIssue[]) => void\n /** Optional callback fired with enriched per-cell safe-parse metadata. */\n onSafeParseCellMeta?: (meta: GristSafeTableCellMeta[]) => void\n /** Optional callback fired with keyed per-cell metadata (`${rowId}:${colId}`). */\n onSafeParseCellMetaByKey?: (metaByKey: Record<string, GristSafeTableCellMeta>) => void\n}\n\nfunction inferDisplayHelpersByNameFromData(data: GristColumnarTable): Record<string, string> {\n const out: Record<string, string> = {}\n for (const colId of Object.keys(data)) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n const baseColId = colId.slice(\"gristHelper_\".length)\n if (!baseColId) continue\n if (!Array.isArray(data[baseColId])) continue\n out[baseColId] = colId\n }\n return out\n}\n\nfunction enrichSafeParseColumnsFromData(\n data: GristColumnarTable,\n columns?: Record<string, GristReplicaColumn>\n): Record<string, GristReplicaColumn> {\n const out: Record<string, GristReplicaColumn> = { ...(columns ?? {}) }\n const keys = Object.keys(data)\n const positionByColId = new Map<string, number>(keys.map((colId, index) => [colId, index + 1]))\n\n // Ensure helper columns exist in safe-parse metadata even when caller schema\n // excluded them (common for UI schemas). Parent positions are synthesized from\n // fetchTable key order so helper/ref fallback matching still works.\n for (const colId of keys) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n if (out[colId]) continue\n out[colId] = {\n type: \"Any\",\n label: colId,\n parentPos: positionByColId.get(colId),\n }\n }\n return out\n}\n\nfunction rowsFromSafeCellResults(\n parsedByColumn: Record<string, GristSafeParseCellResult[]>\n): GristRowRecord<Record<string, unknown>>[] {\n const colIds = Object.keys(parsedByColumn)\n const rowCount = colIds.reduce((max, colId) => {\n const len = parsedByColumn[colId]?.length ?? 0\n return Math.max(max, len)\n }, 0)\n const rows: GristRowRecord<Record<string, unknown>>[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n row[colId] = parsedByColumn[colId]?.[rowIndex] ?? null\n }\n rows.push(row as GristRowRecord<Record<string, unknown>>)\n }\n return rows\n}\n\nfunction safeCellRowId(row: Record<string, unknown>): number | null {\n const idCell = row.id\n if (!idCell || typeof idCell !== \"object\" || !(\"typedValue\" in idCell)) return null\n const typed = (idCell as { typedValue?: unknown }).typedValue\n return typeof typed === \"number\" && Number.isFinite(typed) ? typed : null\n}\n\nfunction orderSafeCellRowsByParsedRows(\n rows: GristRowRecord<Record<string, unknown>>[],\n orderedParsedRows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n const byId = new Map<number, GristRowRecord<Record<string, unknown>>[]>()\n for (const row of rows) {\n const id = safeCellRowId(row)\n if (id === null) continue\n const bucket = byId.get(id)\n if (bucket) bucket.push(row)\n else byId.set(id, [row])\n }\n const out: GristRowRecord<Record<string, unknown>>[] = []\n for (const parsedRow of orderedParsedRows) {\n const id = typeof parsedRow.id === \"number\" ? parsedRow.id : null\n if (id === null) continue\n const bucket = byId.get(id)\n if (!bucket || bucket.length === 0) continue\n const next = bucket.shift()\n if (next) out.push(next)\n }\n // Preserve any unexpected leftovers (defensive).\n for (const bucket of byId.values()) {\n out.push(...bucket)\n }\n return out\n}\n\n/**\n * Project safe-parse rows to UI display rows by taking each cell's `displayValue`.\n * Useful for grids that render human-friendly values while keeping safe-cell\n * objects available for logic and metadata.\n */\nexport function safeParseRowsToDisplayRows(\n rows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n return rows.map((row) => {\n const out: Record<string, unknown> = {}\n for (const [colId, cell] of Object.entries(row)) {\n if (cell && typeof cell === \"object\" && \"displayValue\" in cell) {\n out[colId] = (cell as { displayValue: unknown }).displayValue\n } else {\n out[colId] = cell\n }\n }\n return out as GristRowRecord<Record<string, unknown>>\n })\n}\n\n/** Row count from columnar `fetchTable` data (prefers `id` column length). */\nexport function 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\n/**\n * Decode columnar `fetchTable` into replica row objects (same convention as the playground grid).\n */\nexport function decodeColumnarToReplicaRows(\n data: GristColumnarTable,\n columnIds: string[],\n columns: Record<string, GristReplicaColumn>,\n maxRows?: number\n): GristRowRecord[] {\n const nFull = computeRowCount(data)\n const n = maxRows !== undefined ? Math.min(nFull, maxRows) : nFull\n const out: GristRowRecord[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of columnIds) {\n const arr = data[k]\n const raw = Array.isArray(arr) ? arr[i] : undefined\n if (k === \"id\") {\n row[k] = raw\n } else {\n row[k] = decodeGristValue(raw, columns[k]) as unknown\n }\n }\n out.push(row as GristRowRecord)\n }\n return out\n}\n\n/** Turn `fetchTable` output into row objects (order follows the `id` column). */\nexport function tableDataToRows<T = Record<string, unknown>>(\n data: GristColumnarTable\n): GristRowRecord<T>[] {\n const idCol = data.id\n if (!Array.isArray(idCol) || idCol.length === 0) return []\n const keys = Object.keys(data)\n const n = idCol.length\n const rows: GristRowRecord<T>[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[i] : undefined\n }\n rows.push(row as GristRowRecord<T>)\n }\n return rows\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\n/**\n * Sort rows by Grist's display order: `manualSort` ascending when present on\n * any row, otherwise numeric `id` ascending.\n */\nexport function 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\n/** Row index where `id` matches `rowId`, or `null`. */\nexport function findRowIndexById(data: GristColumnarTable, rowId: number | string): number | null {\n const idCol = data.id\n if (!Array.isArray(idCol)) return null\n const idx = idCol.findIndex((v) => v === rowId || (typeof v === \"number\" && v === Number(rowId)))\n return idx === -1 ? null : idx\n}\n\n/** Single row at `index`, or `null` if out of range. */\nexport function rowAtIndex<T = Record<string, unknown>>(\n data: GristColumnarTable,\n index: number\n): GristRowRecord<T> | null {\n const idCol = data.id\n if (!Array.isArray(idCol) || index < 0 || index >= idCol.length) return null\n const keys = Object.keys(data)\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[index] : undefined\n }\n return row as GristRowRecord<T>\n}\n\n/**\n * Fetch a single row from any table by id. Convenience around\n * `docApi.fetchTable` + {@link findRowIndexById} + {@link rowAtIndex}.\n */\nexport async function fetchGristRow<T = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n rowId: number\n): Promise<GristRowRecord<T> | null> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n const index = findRowIndexById(data, rowId)\n if (index === null) return null\n return rowAtIndex<T>(data, index)\n}\n\n/**\n * Same row materialization as {@link fetchGristTableRows} after `fetchTable`\n * returns columnar data. Hosts that already have columnar data (e.g. the\n * emulator building from in-memory rows) can use this and skip `docApi.fetchTable`.\n */\nexport function materializeGristRowsFromColumnar<T extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: FetchGristTableRowsOptions\n): GristRowRecord<T>[] {\n const order = options?.order ?? \"grist\"\n if (options?.safeParse) {\n const safeOptions = options.safeParse === true ? {} : options.safeParse\n const columnsForSafeParse = enrichSafeParseColumnsFromData(data, options?.columns)\n const displayHelpersByRef = {\n ...inferDisplayHelpersByNameFromData(data),\n ...(safeOptions.displayHelpersByRef ?? {}),\n }\n const parsed = safeParseGristTableData<T>(data, {\n ...safeOptions,\n columns: columnsForSafeParse,\n displayHelpersByRef,\n order,\n })\n options.onSafeParseIssues?.(parsed.cellIssues)\n options.onSafeParseCellMeta?.(parsed.cellMeta)\n options.onSafeParseCellMetaByKey?.(parsed.cellMetaByKey)\n const rawSafeRows = rowsFromSafeCellResults(parsed.cellResultsByColumn)\n const orderedSafeRows =\n order === \"none\"\n ? rawSafeRows\n : orderSafeCellRowsByParsedRows(rawSafeRows, parsed.rows as ReadonlyArray<Record<string, unknown>>)\n return orderedSafeRows as GristRowRecord<T>[]\n }\n\n let rows: GristRowRecord<T>[]\n if (options?.columns) {\n const columnIds = Object.keys(data)\n rows = decodeColumnarToReplicaRows(data, columnIds, options.columns) as GristRowRecord<T>[]\n } else {\n rows = tableDataToRows<T>(data)\n }\n\n if (order === \"none\") return rows\n if (order === \"id\") {\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 sortRowsByGristOrder(rows)\n}\n\n/**\n * Fetch a table and return rows as objects, optionally decoded from schema and sorted.\n */\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options: FetchGristTableRowsOptions & { safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\"> }\n): Promise<GristRowRecord<{ [K in keyof T]: GristSafeParseCellResult<T[K]> | null }>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n return materializeGristRowsFromColumnar<T>(data, options)\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 { useMemo } from \"react\"\n\nimport type { GristReplicaColumn, GristReplicaDocument, GristReplicaTable } from \"../../sdk/replica-document\"\nimport { isGristNoiseColumn } from \"../../sdk/helpers/grist-columns-filters\"\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport { useEmulatorSnapshot } from \"./use-emulator-state\"\n\nexport type EmulatorColumnsTableView = GristReplicaTable & { tableId: string }\n\nexport type UseEmulatorColumnsResult = {\n document: GristReplicaDocument\n table: EmulatorColumnsTableView | null\n isNoiseColumnId: (colId: string, col?: GristReplicaColumn) => boolean\n sortColumnIds: (colIds: string[], columns: Record<string, GristReplicaColumn>) => string[]\n}\n\nexport function useEmulatorColumns(emulator: GristEmulator): UseEmulatorColumnsResult {\n const { state } = useEmulatorSnapshot(emulator)\n const requestedTableId = state.selection.tableId\n\n const document = useMemo<GristReplicaDocument>(() => {\n const tables: Record<string, GristReplicaTable> = {}\n for (const [tableId, table] of state.tables.entries()) {\n const filteredColumns = Object.fromEntries(\n Object.entries(table.columns).filter(([colId, col]) => {\n return !isGristNoiseColumn(colId, col, {\n excludeId: true,\n excludeGristHelpers: true,\n excludeLoggingColumns: true,\n excludeManualSort: true,\n })\n })\n )\n tables[tableId] = {\n label: table.label,\n columns: filteredColumns,\n rows: table.rows.map((row) => ({ ...row })),\n rowCount: table.rows.length,\n }\n }\n return {\n generatedAt: new Date().toISOString(),\n docName: state.docName,\n mode: \"schema+data\",\n source: \"emulator-devtools\",\n tables,\n }\n }, [state])\n\n const table = useMemo<EmulatorColumnsTableView | null>(() => {\n if (!requestedTableId) return null\n const slice = document.tables[requestedTableId]\n if (!slice) return null\n return { tableId: requestedTableId, ...slice }\n }, [document, requestedTableId])\n\n const isNoiseColumnId = useMemo(\n () =>\n (colId: string, col?: GristReplicaColumn): boolean =>\n isGristNoiseColumn(colId, col, {\n excludeId: true,\n excludeGristHelpers: true,\n excludeLoggingColumns: true,\n excludeManualSort: true,\n }),\n []\n )\n\n const sortColumnIds = useMemo(\n () => (colIds: string[], columns: Record<string, GristReplicaColumn>): string[] => {\n return [...colIds].sort((a, b) => {\n const la = (columns[a]?.label || a).toLowerCase()\n const lb = (columns[b]?.label || b).toLowerCase()\n if (la !== lb) return la.localeCompare(lb)\n return a.localeCompare(b)\n })\n },\n []\n )\n\n return { document, table, isNoiseColumnId, sortColumnIds }\n}\n","export type GristColumnLike = {\n formula?: string\n}\n\nexport type GristNoiseColumnsOptions = {\n excludeId?: boolean\n excludeGristHelpers?: boolean\n excludeLoggingColumns?: boolean\n /**\n * When `true`, treat Grist's `manualSort` column as noise (omit from filtered replicas).\n * Default `false` — `manualSort` is kept unless you opt in.\n */\n excludeManualSort?: boolean\n}\n\nconst NOISE_COLUMN_FORMULAS = new Set([\"now()\"])\n\nfunction normalizeFormulaForComparison(formula: string): string {\n return formula.trim().toLowerCase().replace(/\\s+/g, \"\")\n}\n\n/**\n * Grist-centric \"technical column\" detection used by document hooks and widgets.\n *\n * - `id` (when {@link GristNoiseColumnsOptions.excludeId} is true — default)\n * - `manualSort` (only when {@link GristNoiseColumnsOptions.excludeManualSort} is true)\n * - `gristHelper_*` (when `excludeGristHelpers` is true — default)\n * - trigger/logging formulas (`NOW()`, `user.*`) (when `excludeLoggingColumns` is true — default)\n */\nexport function isGristNoiseColumn(\n colId: string,\n col?: GristColumnLike,\n options?: GristNoiseColumnsOptions\n): boolean {\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n\n if (excludeId && colId === \"id\") return true\n if (excludeManualSort && colId === \"manualSort\") return true\n if (excludeGristHelpers && colId.startsWith(\"gristHelper_\")) return true\n\n if (excludeLoggingColumns) {\n const formula = typeof col?.formula === \"string\" ? normalizeFormulaForComparison(col.formula) : \"\"\n if (formula && NOISE_COLUMN_FORMULAS.has(formula)) return true\n if (formula.startsWith(\"user.\")) return true\n }\n\n return false\n}\n"],"mappings":"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","names":["import_react","import_react","computeRowCount","manualSortKey","sortRowsByGristOrder","sortRowsByGristOrder","import_react","table"]}
|
|
1
|
+
{"version":3,"sources":["../../src/emulator/devtools/index.ts","../../src/emulator/devtools/inspector.tsx","../../src/sdk/helpers/grist-user-actions.ts","../../src/sdk/internal/handshake/access.ts","../../src/emulator/core/mappings.ts","../../src/emulator/devtools/use-emulator-state.ts","../../src/emulator/devtools/use-rows.ts","../../src/sdk/helpers/grist-value-codec.ts","../../src/sdk/helpers/grist-safe-parse.ts","../../src/sdk/helpers/grist-widget-options.ts","../../src/sdk/helpers/grist-table-data.ts","../../src/emulator/core/columnar.ts","../../src/emulator/devtools/use-columns.ts","../../src/sdk/helpers/grist-columns-filters.ts"],"sourcesContent":["export { EmulatorInspector } from \"./inspector\"\nexport type { EmulatorInspectorProps } from \"./inspector\"\nexport { fetchEmulatorRows, useEmulatorRows } from \"./use-rows\"\nexport type { UseEmulatorRowsResult } from \"./use-rows\"\nexport { useEmulatorColumns } from \"./use-columns\"\nexport type {\n EmulatorColumnsTableView,\n UseEmulatorColumnsResult,\n} from \"./use-columns\"\nexport { useEmulatorSnapshot } from \"./use-emulator-state\"\n","/**\n * `<EmulatorInspector />` — drop-in DevTools for the playground / IDE.\n *\n * Capabilities:\n * - Multi-table picker with row count + label\n * - Inline row editor (Add / Update / Delete) routed through the emulator's\n * action engine — every edit produces real Grist user actions on the bus.\n * - Cursor selector that drives `onRecord` for the widget under test.\n * - Widget options & mappings panel.\n * - Live event timeline (last 50 events) with pretty formatting.\n *\n * The component owns no state of its own beyond UI accordion toggles —\n * everything is read off the emulator and re-renders via {@link\n * useEmulatorSnapshot}.\n */\n\nimport type { CSSProperties, ReactNode } from \"react\"\nimport { useState } from \"react\"\n\nimport { gristAddRecordAction, gristRemoveRecordAction, gristUpdateRecordAction } from \"../../sdk/helpers/grist-user-actions\"\nimport { gristAccessLevelLabel } from \"../../sdk/internal/handshake/access\"\nimport type { GristRequiredAccess } from \"../../sdk/types\"\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport { resolveMappings } from \"../core/mappings\"\nimport { useEmulatorSnapshot } from \"./use-emulator-state\"\n\nconst ACCESS_LEVELS: readonly GristRequiredAccess[] = [\"none\", \"read table\", \"full\"]\n\nexport type EmulatorInspectorProps = {\n emulator: GristEmulator\n /** Override visual style. */\n className?: string\n /** Default `true`. Set to `false` to render only the toolbar. */\n showTimeline?: boolean\n}\n\nexport function EmulatorInspector({ emulator, className, showTimeline = true }: EmulatorInspectorProps) {\n const { state, history } = useEmulatorSnapshot(emulator)\n const tableIds = [...state.tables.keys()]\n const selectedTableId = state.selection.tableId\n const table = state.tables.get(selectedTableId)\n const columnIds = table ? Object.keys(table.columns) : []\n\n const onSelectTable = (tableId: string) => emulator.selectTable(tableId)\n const onSelectRow = (rowId: number | \"new\" | null) => emulator.selectRow(rowId)\n const onAddRow = () => {\n if (!table) return\n const fields: Record<string, unknown> = {}\n for (const col of columnIds) fields[col] = \"\"\n emulator.apply([gristAddRecordAction(selectedTableId, fields)])\n }\n const onDeleteRow = (rowId: number) => {\n emulator.apply([gristRemoveRecordAction(selectedTableId, rowId)])\n }\n const onEditCell = (rowId: number, colId: string, value: string) => {\n emulator.apply([gristUpdateRecordAction(selectedTableId, rowId, { [colId]: value })])\n }\n\n const grantedAccessLevel = (state.widgetInteraction.access_level as GristRequiredAccess | undefined) ?? \"read table\"\n const onSetAccessLevel = (level: GristRequiredAccess) => {\n emulator.setInteraction({ ...state.widgetInteraction, access_level: level })\n }\n\n return (\n <div className={className} style={baseStyle}>\n <div style={headerStyle}>\n <span style={badgeStyle}>EMULATOR</span>\n <strong>{state.docName}</strong>\n <span style={mutedStyle}>· {tableIds.length} table{tableIds.length === 1 ? \"\" : \"s\"}</span>\n </div>\n\n <div style={{ display: \"flex\", gap: 6, padding: \"8px 12px\", flexWrap: \"wrap\" }}>\n {tableIds.map((id) => {\n const t = state.tables.get(id)!\n const active = id === selectedTableId\n return (\n <button\n key={id}\n type=\"button\"\n onClick={() => onSelectTable(id)}\n style={active ? tabActiveStyle : tabStyle}\n >\n {t.label ?? id}\n <span style={mutedStyle}> · {t.rows.length}</span>\n </button>\n )\n })}\n </div>\n\n <Section title=\"Rows\">\n {!table ? (\n <p style={mutedStyle}>No table selected.</p>\n ) : (\n <div>\n <div style={{ display: \"flex\", gap: 6, marginBottom: 6 }}>\n <button type=\"button\" onClick={onAddRow} style={primaryBtnStyle}>+ Row</button>\n <button type=\"button\" onClick={() => onSelectRow(\"new\")} style={ghostBtnStyle}>Cursor → new</button>\n <button type=\"button\" onClick={() => onSelectRow(null)} style={ghostBtnStyle}>Cursor → none</button>\n </div>\n <div style={{ overflowX: \"auto\" }}>\n <table style={tableStyle}>\n <thead>\n <tr style={{ borderBottom: \"1px solid #2a2f37\" }}>\n <th style={thStyle}>id</th>\n {columnIds.map((col) => (\n <th key={col} style={thStyle}>\n {table.columns[col]?.label ?? col}\n </th>\n ))}\n <th style={thStyle}></th>\n </tr>\n </thead>\n <tbody>\n {table.rows.map((row) => {\n const rowId = row.id\n const active = state.selection.rowId === rowId\n return (\n <tr\n key={rowId}\n style={active ? trActiveStyle : trStyle}\n onClick={() => onSelectRow(rowId)}\n >\n <td style={tdStyle}>{rowId}</td>\n {columnIds.map((col) => (\n <td key={col} style={tdStyle}>\n <input\n value={formatCell(row[col])}\n style={inputStyle}\n onClick={(event) => event.stopPropagation()}\n onChange={(event) => onEditCell(rowId, col, event.target.value)}\n />\n </td>\n ))}\n <td style={tdStyle}>\n <button\n type=\"button\"\n style={dangerBtnStyle}\n onClick={(event) => {\n event.stopPropagation()\n onDeleteRow(rowId)\n }}\n >\n Delete\n </button>\n </td>\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n </Section>\n\n <Section title=\"Selection / mappings\">\n <div style={kvStyle}>\n <KV k=\"tableId\" v={state.selection.tableId} />\n <KV k=\"rowId\" v={String(state.selection.rowId)} />\n <KV k=\"mappings\" v={JSON.stringify(resolveMappings(state))} />\n <KV k=\"configuration\" v={JSON.stringify(state.configuration)} />\n </div>\n </Section>\n\n <Section title=\"Access level\">\n <div style={{ display: \"flex\", gap: 6, marginBottom: 6, flexWrap: \"wrap\" }}>\n {ACCESS_LEVELS.map((level) => (\n <button\n key={level}\n type=\"button\"\n onClick={() => onSetAccessLevel(level)}\n style={level === grantedAccessLevel ? tabActiveStyle : tabStyle}\n title={gristAccessLevelLabel(level)}\n >\n {level}\n </button>\n ))}\n </div>\n <p style={mutedStyle}>\n Granted to the widget via <code>access_level</code> — {gristAccessLevelLabel(grantedAccessLevel)}.\n </p>\n </Section>\n\n <Section title=\"Widget options\">\n <pre style={preStyle}>{JSON.stringify(state.widgetOptions, null, 2)}</pre>\n <KV k=\"interaction\" v={JSON.stringify(state.widgetInteraction)} />\n </Section>\n\n {showTimeline && (\n <Section title={`Event timeline (${history.length})`}>\n <div style={{ maxHeight: 200, overflow: \"auto\", fontFamily: \"monospace\", fontSize: 11 }}>\n {history.slice(-50).reverse().map((event, idx) => (\n <div key={idx} style={timelineRowStyle}>\n <span style={typeBadgeStyle(event.type)}>{event.type}</span>\n <span style={mutedStyle}>{summariseEvent(event)}</span>\n </div>\n ))}\n {history.length === 0 && <p style={mutedStyle}>No events yet.</p>}\n </div>\n </Section>\n )}\n </div>\n )\n}\n\nfunction Section({ title, children }: { title: string; children: ReactNode }) {\n const [open, setOpen] = useState(true)\n return (\n <div style={{ borderTop: \"1px solid #2a2f37\" }}>\n <button type=\"button\" style={sectionHeaderStyle} onClick={() => setOpen((v) => !v)}>\n <span>{open ? \"▾\" : \"▸\"}</span>\n <strong>{title}</strong>\n </button>\n {open && <div style={{ padding: \"0 12px 12px\" }}>{children}</div>}\n </div>\n )\n}\n\nfunction KV({ k, v }: { k: string; v: ReactNode }) {\n return (\n <div style={kvRowStyle}>\n <span style={mutedStyle}>{k}</span>\n <code style={{ fontFamily: \"monospace\", fontSize: 11 }}>{v}</code>\n </div>\n )\n}\n\nfunction summariseEvent(event: { type: string } & Record<string, unknown>): string {\n switch (event.type) {\n case \"user-action\":\n return JSON.stringify(event.action)\n case \"data-change\":\n return `tableId=${String(event.tableId)}`\n case \"cursor-change\":\n return `tableId=${String(event.tableId)} rowId=${String(event.rowId)}`\n case \"options-change\":\n return JSON.stringify(event.options)\n case \"ready\":\n return JSON.stringify(event.configuration)\n case \"theme-change\":\n return JSON.stringify(event.message)\n case \"mappings-change\":\n return JSON.stringify(event.mappings)\n default:\n return \"\"\n }\n}\n\nfunction formatCell(value: unknown): string {\n if (value === null || value === undefined) return \"\"\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") return String(value)\n return JSON.stringify(value)\n}\n\n// --- styles -----------------------------------------------------------------\n\nconst baseStyle: CSSProperties = {\n background: \"#15171c\",\n color: \"#e6e6e6\",\n fontFamily: \"system-ui, sans-serif\",\n fontSize: 13,\n border: \"1px solid #2a2f37\",\n borderRadius: 8,\n overflow: \"hidden\",\n}\nconst headerStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"10px 12px\",\n background: \"#0f1115\",\n borderBottom: \"1px solid #2a2f37\",\n}\nconst badgeStyle: CSSProperties = {\n background: \"#3a8e57\",\n color: \"#fff\",\n padding: \"1px 6px\",\n borderRadius: 4,\n fontSize: 10,\n letterSpacing: 0.5,\n}\nconst mutedStyle: CSSProperties = { color: \"#9ba1ad\" }\nconst sectionHeaderStyle: CSSProperties = {\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n width: \"100%\",\n background: \"transparent\",\n color: \"inherit\",\n border: \"none\",\n padding: \"10px 12px\",\n textAlign: \"left\" as const,\n cursor: \"pointer\",\n}\nconst tabStyle: CSSProperties = {\n background: \"#1c1f26\",\n color: \"#cfd2d8\",\n border: \"1px solid #2a2f37\",\n borderRadius: 6,\n padding: \"4px 10px\",\n cursor: \"pointer\",\n}\nconst tabActiveStyle: CSSProperties = { ...tabStyle, background: \"#27313f\", borderColor: \"#3a4f6e\", color: \"#fff\" }\nconst primaryBtnStyle: CSSProperties = {\n background: \"#3a8e57\",\n color: \"#fff\",\n border: \"none\",\n borderRadius: 6,\n padding: \"4px 10px\",\n cursor: \"pointer\",\n}\nconst ghostBtnStyle: CSSProperties = {\n background: \"transparent\",\n color: \"#cfd2d8\",\n border: \"1px solid #2a2f37\",\n borderRadius: 6,\n padding: \"4px 10px\",\n cursor: \"pointer\",\n}\nconst dangerBtnStyle: CSSProperties = {\n background: \"transparent\",\n color: \"#e58f8f\",\n border: \"1px solid #4a2226\",\n borderRadius: 6,\n padding: \"2px 8px\",\n cursor: \"pointer\",\n}\nconst tableStyle: CSSProperties = { width: \"100%\", borderCollapse: \"collapse\" as const, fontSize: 12 }\nconst thStyle: CSSProperties = { textAlign: \"left\" as const, padding: \"4px 6px\", color: \"#9ba1ad\", fontWeight: 500 }\nconst trStyle: CSSProperties = { borderBottom: \"1px solid #1f232b\" }\nconst trActiveStyle: CSSProperties = { ...trStyle, background: \"#1d2733\" }\nconst tdStyle: CSSProperties = { padding: \"4px 6px\" }\nconst inputStyle: CSSProperties = {\n width: \"100%\",\n background: \"#0f1115\",\n color: \"#e6e6e6\",\n border: \"1px solid #2a2f37\",\n borderRadius: 4,\n padding: \"2px 4px\",\n fontSize: 12,\n fontFamily: \"monospace\",\n}\nconst preStyle: CSSProperties = {\n background: \"#0f1115\",\n border: \"1px solid #2a2f37\",\n borderRadius: 4,\n padding: 8,\n fontSize: 11,\n fontFamily: \"monospace\",\n margin: 0,\n whiteSpace: \"pre-wrap\",\n}\nconst kvStyle: CSSProperties = { display: \"flex\", flexDirection: \"column\" as const, gap: 4 }\nconst kvRowStyle: CSSProperties = { display: \"flex\", gap: 8 }\nconst timelineRowStyle: CSSProperties = {\n display: \"flex\",\n gap: 8,\n padding: \"2px 0\",\n borderBottom: \"1px solid #1f232b\",\n}\nfunction typeBadgeStyle(type: string): CSSProperties {\n const colour = ({\n \"user-action\": \"#a06bff\",\n \"data-change\": \"#3a8e57\",\n \"cursor-change\": \"#3a87b8\",\n \"options-change\": \"#b8893a\",\n ready: \"#888\",\n \"theme-change\": \"#888\",\n \"mappings-change\": \"#888\",\n } as Record<string, string>)[type] ?? \"#888\"\n return {\n background: colour,\n color: \"#fff\",\n padding: \"1px 6px\",\n borderRadius: 4,\n fontSize: 10,\n flexShrink: 0,\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 * Access-level helpers used by the handshake state machine.\n *\n * Kept in a tiny dedicated file because the same ranking is needed by the\n * reducer (`widened` flag, future re-negotiation logic) and potentially by\n * effects (decide whether to re-issue `grist.ready`).\n */\n\nimport type { GristRequiredAccess } from \"../../types\"\n\n/** Strictly-ordered ranking. Higher rank = stronger access. */\nexport const ACCESS_RANK: Record<GristRequiredAccess, number> = {\n none: 0,\n \"read table\": 1,\n full: 2,\n}\n\nconst GRIST_ACCESS_LEVELS: readonly GristRequiredAccess[] = [\"none\", \"read table\", \"full\"]\n\n/** Parse `interaction.access_level` / `accessLevel` from Grist `onOptions`. */\nexport function parseGristRequiredAccess(\n raw: string | undefined\n): GristRequiredAccess | null {\n if (!raw) return null\n return (GRIST_ACCESS_LEVELS as readonly string[]).includes(raw)\n ? (raw as GristRequiredAccess)\n : null\n}\n\n/** True when the host-granted level meets what the widget declared in `grist.ready`. */\nexport function isAccessSufficient(\n granted: GristRequiredAccess,\n required: GristRequiredAccess\n): boolean {\n return ACCESS_RANK[granted] >= ACCESS_RANK[required]\n}\n\n/** Creator-panel label for a Grist access level (for user-facing copy). */\nexport function gristAccessLevelLabel(level: GristRequiredAccess): string {\n switch (level) {\n case \"none\":\n return \"No document access\"\n case \"read table\":\n return \"Read selected table\"\n case \"full\":\n return \"Full document access\"\n }\n}\n\nexport function formatInsufficientAccessMessage(\n required: GristRequiredAccess,\n _granted: GristRequiredAccess\n): string {\n const need = gristAccessLevelLabel(required)\n return `Set Access level to at least \"${need}\" in the Custom widget settings.`\n}\n\nexport function isAccessWidening(\n previous: GristRequiredAccess | null,\n next: GristRequiredAccess\n): boolean {\n if (previous === null) return true\n return ACCESS_RANK[next] > ACCESS_RANK[previous]\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 { useSyncExternalStore } from \"react\"\n\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport type { EmulatorEvent } from \"../core/event-bus\"\n\n/**\n * React-friendly snapshot of the emulator state. Re-renders whenever the\n * event bus fires (so the inspector stays in lock-step with widget actions).\n */\nexport function useEmulatorSnapshot(emulator: GristEmulator) {\n const subscribe = (notify: () => void) => {\n return emulator.bus.on(() => notify())\n }\n const getSnapshot = () => snapshotKey(emulator)\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n return {\n state: emulator.state,\n history: emulator.bus.history(),\n }\n}\n\n/**\n * A monotonic-ish key that changes on every event. We tag each event with\n * its index in the history so React detects changes cheaply.\n */\nfunction snapshotKey(emulator: GristEmulator): string {\n const history = emulator.bus.history()\n const last = history[history.length - 1]\n return `${history.length}:${eventTag(last)}`\n}\n\nfunction eventTag(event: EmulatorEvent | undefined): string {\n if (!event) return \"empty\"\n switch (event.type) {\n case \"data-change\":\n return `data:${event.tableId}`\n case \"cursor-change\":\n return `cursor:${event.tableId}:${String(event.rowId)}`\n case \"options-change\":\n return `options:${Object.keys(event.options).length}`\n case \"ready\":\n return \"ready\"\n case \"user-action\":\n return `action:${(event.action[0] as string | undefined) ?? \"?\"}`\n case \"mappings-change\":\n return \"mappings\"\n case \"theme-change\":\n return \"theme\"\n }\n}\n","import { useEffect, useState } from \"react\"\n\nimport {\n materializeGristRowsFromColumnar,\n safeParseRowsToDisplayRows,\n} from \"../../sdk/helpers/grist-table-data\"\nimport type { GristRowRecord } from \"../../sdk/types\"\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport { rowsToColumnar } from \"../core/columnar\"\nimport { useEmulatorSnapshot } from \"./use-emulator-state\"\n\nexport type UseEmulatorRowsResult<T extends Record<string, unknown> = Record<string, unknown>> = {\n rows: GristRowRecord<T>[]\n invalidCellKeys: Set<string>\n}\n\n/**\n * Build display-ready rows from emulator in-memory state (same parse pipeline as\n * {@link fetchGristTableRows}, without `docApi.fetchTable`).\n */\nexport function fetchEmulatorRows<T extends Record<string, unknown> = Record<string, unknown>>(\n emulator: GristEmulator,\n tableId: string\n): UseEmulatorRowsResult<T> {\n const table = emulator.state.tables.get(tableId)\n if (!table) {\n return { rows: [], invalidCellKeys: new Set() }\n }\n\n let cellMetaByKey: Record<string, { issues: Array<{ code: string }> }> = {}\n const data = rowsToColumnar(table, table.rows)\n const parsedRows = materializeGristRowsFromColumnar<T>(data, {\n columns: table.columns,\n order: \"grist\",\n safeParse: {\n refMode: \"detailed\",\n },\n onSafeParseCellMetaByKey: (metaByKey) => {\n cellMetaByKey = metaByKey as Record<string, { issues: Array<{ code: string }> }>\n },\n })\n const rows = safeParseRowsToDisplayRows(parsedRows) as GristRowRecord<T>[]\n const invalidCellKeys = new Set<string>()\n for (const [cellKey, meta] of Object.entries(cellMetaByKey)) {\n const hasIssue = meta.issues.some(\n (issue) => issue.code === \"type_mismatch\" || issue.code === \"invalid_format\"\n )\n if (hasIssue) invalidCellKeys.add(cellKey)\n }\n return { rows, invalidCellKeys }\n}\n\nexport function useEmulatorRows<T extends Record<string, unknown> = Record<string, unknown>>(\n emulator: GristEmulator,\n tableId: string | undefined | null\n): UseEmulatorRowsResult<T> {\n const { history } = useEmulatorSnapshot(emulator)\n const [result, setResult] = useState<UseEmulatorRowsResult<T>>({\n rows: [],\n invalidCellKeys: new Set(),\n })\n\n useEffect(() => {\n let cancelled = false\n if (!tableId) {\n queueMicrotask(() => {\n if (!cancelled) setResult({ rows: [], invalidCellKeys: new Set() })\n })\n return () => {\n cancelled = true\n }\n }\n\n try {\n const next = fetchEmulatorRows<T>(emulator, tableId)\n if (!cancelled) setResult(next)\n } catch {\n const table = emulator.state.tables.get(tableId)\n if (!cancelled) {\n setResult({\n rows: (table?.rows ?? []) as GristRowRecord<T>[],\n invalidCellKeys: new Set(),\n })\n }\n }\n\n return () => {\n cancelled = true\n }\n }, [emulator, tableId, history.length])\n\n return result\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","/**\n * Grist stores column widget configuration in `_grist_Tables_column.widgetOptions`\n * as a JSON string. Choice fields use `choices: string[]` plus optional\n * `choiceOptions: Record<string, Style>` (e.g. `fillColor`, `textColor`).\n *\n * @see https://github.com/gristlabs/grist-core/blob/main/app/client/widgets/ChoiceEditor.js\n */\n\n/** One selectable choice for UI (value stored in the cell is `value`). */\nexport type GristChoiceListEntry = {\n value: string\n label: string\n fillColor?: string\n textColor?: string\n}\n\n/**\n * Parse a cell value from `_grist_Tables_column.widgetOptions` into a plain object.\n */\nexport function parseGristWidgetOptionsCell(raw: unknown): Record<string, unknown> | undefined {\n if (raw == null || raw === \"\") return undefined\n if (typeof raw === \"string\") {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n return undefined\n }\n return undefined\n }\n if (typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>\n }\n return undefined\n}\n\nfunction readStyleColor(style: Record<string, unknown>, key: string): string | undefined {\n const v = style[key]\n return typeof v === \"string\" ? v : undefined\n}\n\n/**\n * Normalizes Grist Choice / ChoiceList widgetOptions into a flat list for dropdowns.\n * `choices` entries are string labels (the stored cell value). Per-choice styling\n * lives in `choiceOptions[label]`.\n */\nexport function normalizeGristChoiceListEntries(\n widgetOptions: Record<string, unknown> | undefined\n): GristChoiceListEntry[] {\n if (!widgetOptions) return []\n const rawChoices = widgetOptions.choices\n if (!Array.isArray(rawChoices)) return []\n\n const choiceOptionsRaw = widgetOptions.choiceOptions\n const choiceOptions: Record<string, Record<string, unknown>> =\n choiceOptionsRaw &&\n typeof choiceOptionsRaw === \"object\" &&\n !Array.isArray(choiceOptionsRaw)\n ? (choiceOptionsRaw as Record<string, Record<string, unknown>>)\n : {}\n\n const out: GristChoiceListEntry[] = []\n for (const c of rawChoices) {\n const value = typeof c === \"string\" ? c : c != null ? String(c) : \"\"\n if (!value) continue\n const style = choiceOptions[value] ?? {}\n out.push({\n value,\n label: value,\n fillColor: readStyleColor(style, \"fillColor\"),\n textColor: readStyleColor(style, \"textColor\"),\n })\n }\n return out\n}\n","import type { GristDocApi, GristReplicaColumn, GristRowRecord } from \"../types\"\nimport { decodeGristValue } from \"./grist-value-codec\"\nimport {\n type GristSafeParseCellResult,\n type GristSafeTableCellMeta,\n safeParseGristTableData,\n type GristSafeTableCellIssue,\n type SafeParseGristTableDataOptions,\n} from \"./grist-safe-parse\"\n\n/**\n * Column-oriented table payload from `grist.docApi.fetchTable`.\n */\nexport type GristColumnarTable = Record<string, unknown[]>\nexport type GristTableRowsOrder = \"none\" | \"id\" | \"grist\"\nexport type FetchGristTableRowsOptions = {\n /** Optional schema metadata map to decode cells (except `id`) with `decodeGristValue`. */\n columns?: Record<string, GristReplicaColumn>\n /**\n * Row ordering strategy.\n * - `grist` (default): `manualSort` ascending when present, fallback `id`.\n * - `id`: numeric `id` ascending.\n * - `none`: preserve raw `fetchTable` row order.\n */\n order?: GristTableRowsOrder\n /**\n * Enable safe parsing with issue reporting.\n * - `true`: use safe parsing with defaults.\n * - object: pass safe-parse options (`displayHelpersByRef`, `refMode`, ...).\n */\n safeParse?: boolean | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\">\n /** Optional callback fired with per-cell parse issues when `safeParse` is enabled. */\n onSafeParseIssues?: (issues: GristSafeTableCellIssue[]) => void\n /** Optional callback fired with enriched per-cell safe-parse metadata. */\n onSafeParseCellMeta?: (meta: GristSafeTableCellMeta[]) => void\n /** Optional callback fired with keyed per-cell metadata (`${rowId}:${colId}`). */\n onSafeParseCellMetaByKey?: (metaByKey: Record<string, GristSafeTableCellMeta>) => void\n}\n\nfunction inferDisplayHelpersByNameFromData(data: GristColumnarTable): Record<string, string> {\n const out: Record<string, string> = {}\n for (const colId of Object.keys(data)) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n const baseColId = colId.slice(\"gristHelper_\".length)\n if (!baseColId) continue\n if (!Array.isArray(data[baseColId])) continue\n out[baseColId] = colId\n }\n return out\n}\n\nfunction enrichSafeParseColumnsFromData(\n data: GristColumnarTable,\n columns?: Record<string, GristReplicaColumn>\n): Record<string, GristReplicaColumn> {\n const out: Record<string, GristReplicaColumn> = { ...(columns ?? {}) }\n const keys = Object.keys(data)\n const positionByColId = new Map<string, number>(keys.map((colId, index) => [colId, index + 1]))\n\n // Ensure helper columns exist in safe-parse metadata even when caller schema\n // excluded them (common for UI schemas). Parent positions are synthesized from\n // fetchTable key order so helper/ref fallback matching still works.\n for (const colId of keys) {\n if (!colId.startsWith(\"gristHelper_\")) continue\n if (out[colId]) continue\n out[colId] = {\n type: \"Any\",\n label: colId,\n parentPos: positionByColId.get(colId),\n }\n }\n return out\n}\n\nfunction rowsFromSafeCellResults(\n parsedByColumn: Record<string, GristSafeParseCellResult[]>\n): GristRowRecord<Record<string, unknown>>[] {\n const colIds = Object.keys(parsedByColumn)\n const rowCount = colIds.reduce((max, colId) => {\n const len = parsedByColumn[colId]?.length ?? 0\n return Math.max(max, len)\n }, 0)\n const rows: GristRowRecord<Record<string, unknown>>[] = []\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n const row: Record<string, unknown> = {}\n for (const colId of colIds) {\n row[colId] = parsedByColumn[colId]?.[rowIndex] ?? null\n }\n rows.push(row as GristRowRecord<Record<string, unknown>>)\n }\n return rows\n}\n\nfunction safeCellRowId(row: Record<string, unknown>): number | null {\n const idCell = row.id\n if (!idCell || typeof idCell !== \"object\" || !(\"typedValue\" in idCell)) return null\n const typed = (idCell as { typedValue?: unknown }).typedValue\n return typeof typed === \"number\" && Number.isFinite(typed) ? typed : null\n}\n\nfunction orderSafeCellRowsByParsedRows(\n rows: GristRowRecord<Record<string, unknown>>[],\n orderedParsedRows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n const byId = new Map<number, GristRowRecord<Record<string, unknown>>[]>()\n for (const row of rows) {\n const id = safeCellRowId(row)\n if (id === null) continue\n const bucket = byId.get(id)\n if (bucket) bucket.push(row)\n else byId.set(id, [row])\n }\n const out: GristRowRecord<Record<string, unknown>>[] = []\n for (const parsedRow of orderedParsedRows) {\n const id = typeof parsedRow.id === \"number\" ? parsedRow.id : null\n if (id === null) continue\n const bucket = byId.get(id)\n if (!bucket || bucket.length === 0) continue\n const next = bucket.shift()\n if (next) out.push(next)\n }\n // Preserve any unexpected leftovers (defensive).\n for (const bucket of byId.values()) {\n out.push(...bucket)\n }\n return out\n}\n\n/**\n * Project safe-parse rows to UI display rows by taking each cell's `displayValue`.\n * Useful for grids that render human-friendly values while keeping safe-cell\n * objects available for logic and metadata.\n */\nexport function safeParseRowsToDisplayRows(\n rows: ReadonlyArray<Record<string, unknown>>\n): GristRowRecord<Record<string, unknown>>[] {\n return rows.map((row) => {\n const out: Record<string, unknown> = {}\n for (const [colId, cell] of Object.entries(row)) {\n if (cell && typeof cell === \"object\" && \"displayValue\" in cell) {\n out[colId] = (cell as { displayValue: unknown }).displayValue\n } else {\n out[colId] = cell\n }\n }\n return out as GristRowRecord<Record<string, unknown>>\n })\n}\n\n/** Row count from columnar `fetchTable` data (prefers `id` column length). */\nexport function 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\n/**\n * Decode columnar `fetchTable` into replica row objects (same convention as the playground grid).\n */\nexport function decodeColumnarToReplicaRows(\n data: GristColumnarTable,\n columnIds: string[],\n columns: Record<string, GristReplicaColumn>,\n maxRows?: number\n): GristRowRecord[] {\n const nFull = computeRowCount(data)\n const n = maxRows !== undefined ? Math.min(nFull, maxRows) : nFull\n const out: GristRowRecord[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of columnIds) {\n const arr = data[k]\n const raw = Array.isArray(arr) ? arr[i] : undefined\n if (k === \"id\") {\n row[k] = raw\n } else {\n row[k] = decodeGristValue(raw, columns[k]) as unknown\n }\n }\n out.push(row as GristRowRecord)\n }\n return out\n}\n\n/** Turn `fetchTable` output into row objects (order follows the `id` column). */\nexport function tableDataToRows<T = Record<string, unknown>>(\n data: GristColumnarTable\n): GristRowRecord<T>[] {\n const idCol = data.id\n if (!Array.isArray(idCol) || idCol.length === 0) return []\n const keys = Object.keys(data)\n const n = idCol.length\n const rows: GristRowRecord<T>[] = []\n for (let i = 0; i < n; i++) {\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[i] : undefined\n }\n rows.push(row as GristRowRecord<T>)\n }\n return rows\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\n/**\n * Sort rows by Grist's display order: `manualSort` ascending when present on\n * any row, otherwise numeric `id` ascending.\n */\nexport function 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\n/** Row index where `id` matches `rowId`, or `null`. */\nexport function findRowIndexById(data: GristColumnarTable, rowId: number | string): number | null {\n const idCol = data.id\n if (!Array.isArray(idCol)) return null\n const idx = idCol.findIndex((v) => v === rowId || (typeof v === \"number\" && v === Number(rowId)))\n return idx === -1 ? null : idx\n}\n\n/** Single row at `index`, or `null` if out of range. */\nexport function rowAtIndex<T = Record<string, unknown>>(\n data: GristColumnarTable,\n index: number\n): GristRowRecord<T> | null {\n const idCol = data.id\n if (!Array.isArray(idCol) || index < 0 || index >= idCol.length) return null\n const keys = Object.keys(data)\n const row: Record<string, unknown> = {}\n for (const k of keys) {\n const col = data[k]\n row[k] = Array.isArray(col) ? col[index] : undefined\n }\n return row as GristRowRecord<T>\n}\n\n/**\n * Fetch a single row from any table by id. Convenience around\n * `docApi.fetchTable` + {@link findRowIndexById} + {@link rowAtIndex}.\n */\nexport async function fetchGristRow<T = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n rowId: number\n): Promise<GristRowRecord<T> | null> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n const index = findRowIndexById(data, rowId)\n if (index === null) return null\n return rowAtIndex<T>(data, index)\n}\n\n/**\n * Same row materialization as {@link fetchGristTableRows} after `fetchTable`\n * returns columnar data. Hosts that already have columnar data (e.g. the\n * emulator building from in-memory rows) can use this and skip `docApi.fetchTable`.\n */\nexport function materializeGristRowsFromColumnar<T extends Record<string, unknown> = Record<string, unknown>>(\n data: GristColumnarTable,\n options?: FetchGristTableRowsOptions\n): GristRowRecord<T>[] {\n const order = options?.order ?? \"grist\"\n if (options?.safeParse) {\n const safeOptions = options.safeParse === true ? {} : options.safeParse\n const columnsForSafeParse = enrichSafeParseColumnsFromData(data, options?.columns)\n const displayHelpersByRef = {\n ...inferDisplayHelpersByNameFromData(data),\n ...(safeOptions.displayHelpersByRef ?? {}),\n }\n const parsed = safeParseGristTableData<T>(data, {\n ...safeOptions,\n columns: columnsForSafeParse,\n displayHelpersByRef,\n order,\n })\n options.onSafeParseIssues?.(parsed.cellIssues)\n options.onSafeParseCellMeta?.(parsed.cellMeta)\n options.onSafeParseCellMetaByKey?.(parsed.cellMetaByKey)\n const rawSafeRows = rowsFromSafeCellResults(parsed.cellResultsByColumn)\n const orderedSafeRows =\n order === \"none\"\n ? rawSafeRows\n : orderSafeCellRowsByParsedRows(rawSafeRows, parsed.rows as ReadonlyArray<Record<string, unknown>>)\n return orderedSafeRows as GristRowRecord<T>[]\n }\n\n let rows: GristRowRecord<T>[]\n if (options?.columns) {\n const columnIds = Object.keys(data)\n rows = decodeColumnarToReplicaRows(data, columnIds, options.columns) as GristRowRecord<T>[]\n } else {\n rows = tableDataToRows<T>(data)\n }\n\n if (order === \"none\") return rows\n if (order === \"id\") {\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 sortRowsByGristOrder(rows)\n}\n\n/**\n * Fetch a table and return rows as objects, optionally decoded from schema and sorted.\n */\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options: FetchGristTableRowsOptions & { safeParse: true | Omit<SafeParseGristTableDataOptions, \"columns\" | \"order\"> }\n): Promise<GristRowRecord<{ [K in keyof T]: GristSafeParseCellResult<T[K]> | null }>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]>\nexport async function fetchGristTableRows<T extends Record<string, unknown> = Record<string, unknown>>(\n docApi: GristDocApi,\n tableId: string,\n options?: FetchGristTableRowsOptions\n): Promise<GristRowRecord<T>[]> {\n const data = (await docApi.fetchTable(tableId)) as GristColumnarTable\n return materializeGristRowsFromColumnar<T>(data, options)\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 { useMemo } from \"react\"\n\nimport type { GristReplicaColumn, GristReplicaDocument, GristReplicaTable } from \"../../sdk/replica-document\"\nimport { isGristNoiseColumn } from \"../../sdk/helpers/grist-columns-filters\"\nimport type { GristEmulator } from \"../create-grist-emulator\"\nimport { useEmulatorSnapshot } from \"./use-emulator-state\"\n\nexport type EmulatorColumnsTableView = GristReplicaTable & { tableId: string }\n\nexport type UseEmulatorColumnsResult = {\n document: GristReplicaDocument\n table: EmulatorColumnsTableView | null\n isNoiseColumnId: (colId: string, col?: GristReplicaColumn) => boolean\n sortColumnIds: (colIds: string[], columns: Record<string, GristReplicaColumn>) => string[]\n}\n\nexport function useEmulatorColumns(emulator: GristEmulator): UseEmulatorColumnsResult {\n const { state } = useEmulatorSnapshot(emulator)\n const requestedTableId = state.selection.tableId\n\n const document = useMemo<GristReplicaDocument>(() => {\n const tables: Record<string, GristReplicaTable> = {}\n for (const [tableId, table] of state.tables.entries()) {\n const filteredColumns = Object.fromEntries(\n Object.entries(table.columns).filter(([colId, col]) => {\n return !isGristNoiseColumn(colId, col, {\n excludeId: true,\n excludeGristHelpers: true,\n excludeLoggingColumns: true,\n excludeManualSort: true,\n })\n })\n )\n tables[tableId] = {\n label: table.label,\n columns: filteredColumns,\n rows: table.rows.map((row) => ({ ...row })),\n rowCount: table.rows.length,\n }\n }\n return {\n generatedAt: new Date().toISOString(),\n docName: state.docName,\n mode: \"schema+data\",\n source: \"emulator-devtools\",\n tables,\n }\n }, [state])\n\n const table = useMemo<EmulatorColumnsTableView | null>(() => {\n if (!requestedTableId) return null\n const slice = document.tables[requestedTableId]\n if (!slice) return null\n return { tableId: requestedTableId, ...slice }\n }, [document, requestedTableId])\n\n const isNoiseColumnId = useMemo(\n () =>\n (colId: string, col?: GristReplicaColumn): boolean =>\n isGristNoiseColumn(colId, col, {\n excludeId: true,\n excludeGristHelpers: true,\n excludeLoggingColumns: true,\n excludeManualSort: true,\n }),\n []\n )\n\n const sortColumnIds = useMemo(\n () => (colIds: string[], columns: Record<string, GristReplicaColumn>): string[] => {\n return [...colIds].sort((a, b) => {\n const la = (columns[a]?.label || a).toLowerCase()\n const lb = (columns[b]?.label || b).toLowerCase()\n if (la !== lb) return la.localeCompare(lb)\n return a.localeCompare(b)\n })\n },\n []\n )\n\n return { document, table, isNoiseColumnId, sortColumnIds }\n}\n","export type GristColumnLike = {\n formula?: string\n}\n\nexport type GristNoiseColumnsOptions = {\n excludeId?: boolean\n excludeGristHelpers?: boolean\n excludeLoggingColumns?: boolean\n /**\n * When `true`, treat Grist's `manualSort` column as noise (omit from filtered replicas).\n * Default `false` — `manualSort` is kept unless you opt in.\n */\n excludeManualSort?: boolean\n}\n\nconst NOISE_COLUMN_FORMULAS = new Set([\"now()\"])\n\nfunction normalizeFormulaForComparison(formula: string): string {\n return formula.trim().toLowerCase().replace(/\\s+/g, \"\")\n}\n\n/**\n * Grist-centric \"technical column\" detection used by document hooks and widgets.\n *\n * - `id` (when {@link GristNoiseColumnsOptions.excludeId} is true — default)\n * - `manualSort` (only when {@link GristNoiseColumnsOptions.excludeManualSort} is true)\n * - `gristHelper_*` (when `excludeGristHelpers` is true — default)\n * - trigger/logging formulas (`NOW()`, `user.*`) (when `excludeLoggingColumns` is true — default)\n */\nexport function isGristNoiseColumn(\n colId: string,\n col?: GristColumnLike,\n options?: GristNoiseColumnsOptions\n): boolean {\n const excludeId = options?.excludeId ?? true\n const excludeGristHelpers = options?.excludeGristHelpers ?? true\n const excludeLoggingColumns = options?.excludeLoggingColumns ?? true\n const excludeManualSort = options?.excludeManualSort ?? false\n\n if (excludeId && colId === \"id\") return true\n if (excludeManualSort && colId === \"manualSort\") return true\n if (excludeGristHelpers && colId.startsWith(\"gristHelper_\")) return true\n\n if (excludeLoggingColumns) {\n const formula = typeof col?.formula === \"string\" ? normalizeFormulaForComparison(col.formula) : \"\"\n if (formula && NOISE_COLUMN_FORMULAS.has(formula)) return true\n if (formula.startsWith(\"user.\")) return true\n }\n\n return false\n}\n"],"mappings":"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","names":["import_react","import_react","computeRowCount","manualSortKey","sortRowsByGristOrder","sortRowsByGristOrder","import_react","table"]}
|