grist-widget-sdk 0.3.27 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/dist/app.cjs +1139 -4336
- package/dist/app.cjs.map +1 -1
- package/dist/app.d.cts +1 -3
- package/dist/app.d.ts +1 -3
- package/dist/app.js +3 -7
- package/dist/chunk-4ZGVKGDF.js +204 -0
- package/dist/chunk-4ZGVKGDF.js.map +1 -0
- package/dist/{chunk-YQNMIL33.js → chunk-B5ZZNLVS.js} +528 -181
- package/dist/chunk-B5ZZNLVS.js.map +1 -0
- package/dist/chunk-O7NY46QY.js +1830 -0
- package/dist/chunk-O7NY46QY.js.map +1 -0
- package/dist/{chunk-6Y2IONGJ.js → chunk-P6VTEKWO.js} +113 -14
- package/dist/chunk-P6VTEKWO.js.map +1 -0
- package/dist/emulator/testing.cjs +1504 -4822
- package/dist/emulator/testing.cjs.map +1 -1
- package/dist/emulator/testing.d.cts +3 -6
- package/dist/emulator/testing.d.ts +3 -6
- package/dist/emulator/testing.js +7 -20
- package/dist/emulator/testing.js.map +1 -1
- package/dist/emulator.cjs +59 -249
- package/dist/emulator.cjs.map +1 -1
- package/dist/emulator.d.cts +3 -5
- package/dist/emulator.d.ts +3 -5
- package/dist/emulator.js +5 -11
- package/dist/index.cjs +1373 -4859
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -260
- package/dist/index.d.ts +81 -260
- package/dist/index.js +8 -158
- package/dist/{inline-DpcT8tV9.d.ts → templates-CGmRIQBV.d.cts} +89 -35
- package/dist/{inline-C7DkvuET.d.cts → templates-Cq94qOcf.d.ts} +89 -35
- package/dist/{types-D3JxUCfL.d.cts → types-DBStn0Dk.d.cts} +2 -26
- package/dist/{types-D3JxUCfL.d.ts → types-DBStn0Dk.d.ts} +2 -26
- package/dist/use-grist-BK0eke9K.d.cts +358 -0
- package/dist/use-grist-C5DMZ3wU.d.ts +358 -0
- package/package.json +8 -37
- package/dist/advanced.cjs +0 -2799
- package/dist/advanced.cjs.map +0 -1
- package/dist/advanced.d.cts +0 -822
- package/dist/advanced.d.ts +0 -822
- package/dist/advanced.js +0 -872
- package/dist/advanced.js.map +0 -1
- package/dist/chunk-22U7WAY3.js +0 -463
- package/dist/chunk-22U7WAY3.js.map +0 -1
- package/dist/chunk-64SVRWW7.js +0 -758
- package/dist/chunk-64SVRWW7.js.map +0 -1
- package/dist/chunk-6Y2IONGJ.js.map +0 -1
- package/dist/chunk-B4AKVSWV.js +0 -2362
- package/dist/chunk-B4AKVSWV.js.map +0 -1
- package/dist/chunk-ELGVOHFD.js +0 -32
- package/dist/chunk-ELGVOHFD.js.map +0 -1
- package/dist/chunk-GTTD5HPO.js +0 -36
- package/dist/chunk-GTTD5HPO.js.map +0 -1
- package/dist/chunk-NO6FYX33.js +0 -2084
- package/dist/chunk-NO6FYX33.js.map +0 -1
- package/dist/chunk-OPTOYD2Y.js +0 -277
- package/dist/chunk-OPTOYD2Y.js.map +0 -1
- package/dist/chunk-PM3B4WYV.js +0 -12
- package/dist/chunk-PM3B4WYV.js.map +0 -1
- package/dist/chunk-REV5AUXD.js +0 -25
- package/dist/chunk-REV5AUXD.js.map +0 -1
- package/dist/chunk-YQNMIL33.js.map +0 -1
- package/dist/create-grist-emulator-BCqp1BF9.d.ts +0 -81
- package/dist/create-grist-emulator-DBM8OSIR.d.cts +0 -81
- package/dist/emulator/devtools.cjs +0 -1404
- package/dist/emulator/devtools.cjs.map +0 -1
- package/dist/emulator/devtools.d.cts +0 -48
- package/dist/emulator/devtools.d.ts +0 -48
- package/dist/emulator/devtools.js +0 -506
- package/dist/emulator/devtools.js.map +0 -1
- package/dist/emulator/transports.cjs +0 -1132
- package/dist/emulator/transports.cjs.map +0 -1
- package/dist/emulator/transports.d.cts +0 -38
- package/dist/emulator/transports.d.ts +0 -38
- package/dist/emulator/transports.js +0 -12
- package/dist/emulator/transports.js.map +0 -1
- package/dist/templates-8k2LKoO-.d.cts +0 -24
- package/dist/templates-DIwi_mvI.d.ts +0 -24
- package/dist/use-grist-reads-DUMvJgV7.d.ts +0 -480
- package/dist/use-grist-reads-DpjVuI0H.d.cts +0 -480
- package/dist/use-grist-types-DdOLEJXN.d.cts +0 -499
- package/dist/use-grist-types-kwxoFeub.d.ts +0 -499
- package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.cts +0 -43
- package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.ts +0 -43
package/dist/app.d.cts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ComponentType, ReactNode } from 'react';
|
|
3
3
|
import { UseGristOptions } from './index.cjs';
|
|
4
|
-
import './types-
|
|
5
|
-
import './use-grist-reads-DpjVuI0H.cjs';
|
|
6
|
-
import 'zod';
|
|
4
|
+
import './types-DBStn0Dk.cjs';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Where a deployed build is being served from.
|
package/dist/app.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ComponentType, ReactNode } from 'react';
|
|
3
3
|
import { UseGristOptions } from './index.js';
|
|
4
|
-
import './types-
|
|
5
|
-
import './use-grist-reads-DUMvJgV7.js';
|
|
6
|
-
import 'zod';
|
|
4
|
+
import './types-DBStn0Dk.js';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Where a deployed build is being served from.
|
package/dist/app.js
CHANGED
|
@@ -5,13 +5,9 @@ import {
|
|
|
5
5
|
parseDeployPath,
|
|
6
6
|
useReleasedVersions,
|
|
7
7
|
useTheme
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-GTTD5HPO.js";
|
|
12
|
-
import "./chunk-REV5AUXD.js";
|
|
13
|
-
import "./chunk-OPTOYD2Y.js";
|
|
14
|
-
import "./chunk-64SVRWW7.js";
|
|
8
|
+
} from "./chunk-P6VTEKWO.js";
|
|
9
|
+
import "./chunk-O7NY46QY.js";
|
|
10
|
+
import "./chunk-4ZGVKGDF.js";
|
|
15
11
|
export {
|
|
16
12
|
GristWidgetApp,
|
|
17
13
|
deployChannelLabel,
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// src/sdk/helpers/grist-value-codec.ts
|
|
2
|
+
var MARSHALLED_TAGS = /* @__PURE__ */ new Set(["E", "L", "D", "d", "R", "r", "P"]);
|
|
3
|
+
function isMarshalledTuple(value) {
|
|
4
|
+
return Array.isArray(value) && typeof value[0] === "string" && value[0].length <= 2 && MARSHALLED_TAGS.has(value[0]);
|
|
5
|
+
}
|
|
6
|
+
function coerceGristDocApiRefRowId(value) {
|
|
7
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
8
|
+
if (!Array.isArray(value) || value.length < 2) return void 0;
|
|
9
|
+
const tag = value[0];
|
|
10
|
+
if (tag === "R" && typeof value[2] === "number" && Number.isFinite(value[2])) return value[2];
|
|
11
|
+
if (tag === "r" && typeof value[1] === "number" && Number.isFinite(value[1])) return value[1];
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
function looksLikeAttachmentColumn(column) {
|
|
15
|
+
return column?.type === "Attachments";
|
|
16
|
+
}
|
|
17
|
+
function looksLikeChoiceListColumn(column) {
|
|
18
|
+
return column?.type === "ChoiceList";
|
|
19
|
+
}
|
|
20
|
+
function looksLikeRefListColumn(column) {
|
|
21
|
+
return typeof column?.type === "string" && column.type.startsWith("RefList:");
|
|
22
|
+
}
|
|
23
|
+
function looksLikeRefColumn(column) {
|
|
24
|
+
return typeof column?.type === "string" && column.type.startsWith("Ref:");
|
|
25
|
+
}
|
|
26
|
+
function looksLikeDateColumn(column) {
|
|
27
|
+
return column?.type === "Date";
|
|
28
|
+
}
|
|
29
|
+
function looksLikeDateTimeColumn(column) {
|
|
30
|
+
return typeof column?.type === "string" && column.type.startsWith("DateTime");
|
|
31
|
+
}
|
|
32
|
+
function decodeGristValue(value, column) {
|
|
33
|
+
if (value === null || value === void 0) return null;
|
|
34
|
+
if (isMarshalledTuple(value)) {
|
|
35
|
+
const tag = value[0];
|
|
36
|
+
switch (tag) {
|
|
37
|
+
case "E":
|
|
38
|
+
return {
|
|
39
|
+
__error: true,
|
|
40
|
+
type: typeof value[1] === "string" ? value[1] : "Error",
|
|
41
|
+
message: typeof value[2] === "string" ? value[2] : void 0,
|
|
42
|
+
traceback: typeof value[3] === "string" ? value[3] : void 0
|
|
43
|
+
};
|
|
44
|
+
case "L":
|
|
45
|
+
return value.slice(1).map((v) => decodeGristValue(v, void 0));
|
|
46
|
+
case "D":
|
|
47
|
+
if (typeof value[1] === "number") return new Date(value[1] * 1e3);
|
|
48
|
+
return null;
|
|
49
|
+
case "d":
|
|
50
|
+
if (typeof value[1] === "number") return new Date(value[1] * 1e3);
|
|
51
|
+
return null;
|
|
52
|
+
case "R":
|
|
53
|
+
return {
|
|
54
|
+
__ref: true,
|
|
55
|
+
tableId: typeof value[1] === "string" ? value[1] : void 0,
|
|
56
|
+
rowId: typeof value[2] === "number" ? value[2] : 0
|
|
57
|
+
};
|
|
58
|
+
case "r":
|
|
59
|
+
return { __ref: true, rowId: typeof value[1] === "number" ? value[1] : 0 };
|
|
60
|
+
case "P":
|
|
61
|
+
return null;
|
|
62
|
+
default:
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {
|
|
67
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value * 1e3);
|
|
68
|
+
}
|
|
69
|
+
if (looksLikeRefColumn(column) && typeof value === "number") {
|
|
70
|
+
return { __ref: true, rowId: value };
|
|
71
|
+
}
|
|
72
|
+
if ((looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) && Array.isArray(value)) {
|
|
73
|
+
return value.map((v) => decodeGristValue(v, void 0));
|
|
74
|
+
}
|
|
75
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
76
|
+
if (Array.isArray(value)) return value.map((v) => decodeGristValue(v, void 0));
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function isGristCellError(value) {
|
|
80
|
+
return Array.isArray(value) && value[0] === "E";
|
|
81
|
+
}
|
|
82
|
+
function encodeGristValue(value, column) {
|
|
83
|
+
if (value === null || value === void 0) return null;
|
|
84
|
+
if (looksLikeDateColumn(column) || looksLikeDateTimeColumn(column)) {
|
|
85
|
+
if (value instanceof Date) return Math.floor(value.getTime() / 1e3);
|
|
86
|
+
if (typeof value === "string") {
|
|
87
|
+
const parsed = Date.parse(value);
|
|
88
|
+
if (!Number.isNaN(parsed)) return Math.floor(parsed / 1e3);
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === "number") return Math.floor(value);
|
|
91
|
+
}
|
|
92
|
+
if (looksLikeRefColumn(column)) {
|
|
93
|
+
if (typeof value === "number") return value;
|
|
94
|
+
if (value && typeof value === "object" && "rowId" in value) {
|
|
95
|
+
return value.rowId;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (looksLikeRefListColumn(column) || looksLikeChoiceListColumn(column) || looksLikeAttachmentColumn(column)) {
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
const items = value.map((v) => {
|
|
101
|
+
if (v && typeof v === "object" && "rowId" in v) return v.rowId;
|
|
102
|
+
return v;
|
|
103
|
+
});
|
|
104
|
+
return ["L", ...items];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/sdk/helpers/grist-user-actions.ts
|
|
111
|
+
function gristUpdateRecordAction(tableId, rowId, patch) {
|
|
112
|
+
return ["UpdateRecord", tableId, rowId, patch];
|
|
113
|
+
}
|
|
114
|
+
function gristAddRecordAction(tableId, values) {
|
|
115
|
+
return ["AddRecord", tableId, null, values];
|
|
116
|
+
}
|
|
117
|
+
function gristRemoveRecordAction(tableId, rowId) {
|
|
118
|
+
return ["RemoveRecord", tableId, rowId];
|
|
119
|
+
}
|
|
120
|
+
function gristBulkUpdateRecordAction(tableId, rowIds, columnarPatch) {
|
|
121
|
+
return ["BulkUpdateRecord", tableId, rowIds, columnarPatch];
|
|
122
|
+
}
|
|
123
|
+
function gristBulkAddRecordAction(tableId, values, rowIds) {
|
|
124
|
+
const length = inferBulkLength(values);
|
|
125
|
+
const ids = rowIds ?? new Array(length).fill(null);
|
|
126
|
+
return ["BulkAddRecord", tableId, ids, values];
|
|
127
|
+
}
|
|
128
|
+
function gristBulkRemoveRecordAction(tableId, rowIds) {
|
|
129
|
+
return ["BulkRemoveRecord", tableId, rowIds];
|
|
130
|
+
}
|
|
131
|
+
function gristAddColumnAction(tableId, colId, colInfo) {
|
|
132
|
+
return ["AddColumn", tableId, colId, colInfo];
|
|
133
|
+
}
|
|
134
|
+
function gristAddVisibleColumnAction(tableId, colId, colInfo) {
|
|
135
|
+
return ["AddVisibleColumn", tableId, colId, colInfo];
|
|
136
|
+
}
|
|
137
|
+
function gristRenameColumnAction(tableId, colId, newColId) {
|
|
138
|
+
return ["RenameColumn", tableId, colId, newColId];
|
|
139
|
+
}
|
|
140
|
+
function gristModifyColumnAction(tableId, colId, colInfo) {
|
|
141
|
+
return ["ModifyColumn", tableId, colId, colInfo];
|
|
142
|
+
}
|
|
143
|
+
function gristRemoveColumnAction(tableId, colId) {
|
|
144
|
+
return ["RemoveColumn", tableId, colId];
|
|
145
|
+
}
|
|
146
|
+
function gristAddTableAction(tableId, tableInfo) {
|
|
147
|
+
return ["AddTable", tableId, tableInfo];
|
|
148
|
+
}
|
|
149
|
+
function inferBulkLength(values) {
|
|
150
|
+
for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length;
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/sdk/helpers/replica-normalize.ts
|
|
155
|
+
function normalizeReplicaTableInput(table) {
|
|
156
|
+
return { ...table, rows: table.rows ?? [] };
|
|
157
|
+
}
|
|
158
|
+
function normalizeReplicaDocumentInput(doc) {
|
|
159
|
+
return {
|
|
160
|
+
...doc,
|
|
161
|
+
tables: Object.fromEntries(
|
|
162
|
+
Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])
|
|
163
|
+
)
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function buildReplicaJsonPayload(doc, options) {
|
|
167
|
+
const limit = options.sampleRowLimit ?? 10;
|
|
168
|
+
const tables = Object.fromEntries(
|
|
169
|
+
Object.entries(doc.tables).map(([tid, t]) => {
|
|
170
|
+
if (options.includeRows === "none") {
|
|
171
|
+
const { rows: _r, ...rest } = t;
|
|
172
|
+
return [tid, rest];
|
|
173
|
+
}
|
|
174
|
+
if (options.includeRows === "samples") {
|
|
175
|
+
const r = t.rows ?? [];
|
|
176
|
+
return [tid, { ...t, rows: r.slice(0, limit) }];
|
|
177
|
+
}
|
|
178
|
+
return [tid, { ...t, rows: t.rows }];
|
|
179
|
+
})
|
|
180
|
+
);
|
|
181
|
+
return { ...doc, tables };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
coerceGristDocApiRefRowId,
|
|
186
|
+
decodeGristValue,
|
|
187
|
+
isGristCellError,
|
|
188
|
+
encodeGristValue,
|
|
189
|
+
normalizeReplicaDocumentInput,
|
|
190
|
+
buildReplicaJsonPayload,
|
|
191
|
+
gristUpdateRecordAction,
|
|
192
|
+
gristAddRecordAction,
|
|
193
|
+
gristRemoveRecordAction,
|
|
194
|
+
gristBulkUpdateRecordAction,
|
|
195
|
+
gristBulkAddRecordAction,
|
|
196
|
+
gristBulkRemoveRecordAction,
|
|
197
|
+
gristAddColumnAction,
|
|
198
|
+
gristAddVisibleColumnAction,
|
|
199
|
+
gristRenameColumnAction,
|
|
200
|
+
gristModifyColumnAction,
|
|
201
|
+
gristRemoveColumnAction,
|
|
202
|
+
gristAddTableAction
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=chunk-4ZGVKGDF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sdk/helpers/grist-value-codec.ts","../src/sdk/helpers/grist-user-actions.ts","../src/sdk/helpers/replica-normalize.ts"],"sourcesContent":["/**\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","/**\n * Grist `docApi.applyUserActions` payloads are arrays of user-action tuples.\n * @see https://support.getgrist.com/code/interfaces/grist_plugin_api.GristDocAPI/#applyuseractions\n */\n\nexport type GristUserActionTuple = unknown[]\n\n/** `[\"UpdateRecord\", tableId, rowId, { col: value, ... }]` */\nexport function gristUpdateRecordAction(\n tableId: string,\n rowId: number,\n patch: Record<string, unknown>\n): GristUserActionTuple {\n return [\"UpdateRecord\", tableId, rowId, patch]\n}\n\n/** `[\"AddRecord\", tableId, null, { col: value, ... }]` */\nexport function gristAddRecordAction(tableId: string, values: Record<string, unknown>): GristUserActionTuple {\n return [\"AddRecord\", tableId, null, values]\n}\n\n/** `[\"RemoveRecord\", tableId, rowId]` */\nexport function gristRemoveRecordAction(tableId: string, rowId: number): GristUserActionTuple {\n return [\"RemoveRecord\", tableId, rowId]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristBulkUpdateRecordAction(\n tableId: string,\n rowIds: number[],\n columnarPatch: Record<string, unknown[]>\n): GristUserActionTuple {\n return [\"BulkUpdateRecord\", tableId, rowIds, columnarPatch]\n}\n\n/**\n * `[\"BulkAddRecord\", tableId, rowIds | nullArray, { col: value[], ... }]`.\n * Pass `null` (or omit) for `rowIds` to let Grist allocate ids; in user-action\n * format Grist expects an array of nulls of the same length as the value arrays.\n */\nexport function gristBulkAddRecordAction(\n tableId: string,\n values: Record<string, unknown[]>,\n rowIds?: Array<number | null>\n): GristUserActionTuple {\n const length = inferBulkLength(values)\n const ids = rowIds ?? new Array<number | null>(length).fill(null)\n return [\"BulkAddRecord\", tableId, ids, values]\n}\n\n/** `[\"BulkRemoveRecord\", tableId, rowIds]` */\nexport function gristBulkRemoveRecordAction(tableId: string, rowIds: number[]): GristUserActionTuple {\n return [\"BulkRemoveRecord\", tableId, rowIds]\n}\n\n/** `[\"AddColumn\", tableId, colId, colInfo]` — `colInfo` shape depends on Grist version / column type. */\nexport function gristAddColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"AddVisibleColumn\", tableId, colId, colInfo]` — like `AddColumn` but also adds the column to the current view section. */\nexport function gristAddVisibleColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddVisibleColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RenameColumn\", tableId, colId, newColId]` */\nexport function gristRenameColumnAction(tableId: string, colId: string, newColId: string): GristUserActionTuple {\n return [\"RenameColumn\", tableId, colId, newColId]\n}\n\n/** `[\"ModifyColumn\", tableId, colId, colInfo]` */\nexport function gristModifyColumnAction(tableId: string, colId: string, colInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"ModifyColumn\", tableId, colId, colInfo]\n}\n\n/** `[\"RemoveColumn\", tableId, colId]` */\nexport function gristRemoveColumnAction(tableId: string, colId: string): GristUserActionTuple {\n return [\"RemoveColumn\", tableId, colId]\n}\n\n/** `[\"AddTable\", tableId, tableInfo]` */\nexport function gristAddTableAction(tableId: string, tableInfo: Record<string, unknown>): GristUserActionTuple {\n return [\"AddTable\", tableId, tableInfo]\n}\n\nfunction inferBulkLength(values: Record<string, unknown[]>): number {\n for (const arr of Object.values(values)) if (Array.isArray(arr)) return arr.length\n return 0\n}\n","import type { GristReplicaDocument, GristReplicaRow, GristReplicaTable } from \"../replica-document\"\n\n/**\n * Ensure `rows` is a concrete array for emulator / merge logic.\n * Call at host boundaries (`createDocument`, tests); JSON may still omit `rows` for schema-only.\n */\nexport function normalizeReplicaTableInput<T extends GristReplicaTable>(table: T): T & { rows: GristReplicaRow[] } {\n return { ...table, rows: table.rows ?? [] }\n}\n\n/** Apply {@link normalizeReplicaTableInput} to every table; shallow-copies the document shell. */\nexport function normalizeReplicaDocumentInput<T extends GristReplicaDocument>(doc: T): T {\n return {\n ...doc,\n tables: Object.fromEntries(\n Object.entries(doc.tables).map(([tableId, t]) => [tableId, normalizeReplicaTableInput(t)])\n ),\n } as T\n}\n\n/** How row arrays appear in serialized replica JSON from {@link buildReplicaJsonPayload}. */\nexport type ReplicaJsonIncludeRows = \"none\" | \"samples\" | \"full\"\n\n/**\n * Clone a replica document for JSON output: strip rows, cap to first N, or pass through.\n * Does not mutate the source document.\n */\nexport function buildReplicaJsonPayload(\n doc: GristReplicaDocument,\n options: { includeRows: ReplicaJsonIncludeRows; sampleRowLimit?: number }\n): GristReplicaDocument {\n const limit = options.sampleRowLimit ?? 10\n const tables = Object.fromEntries(\n Object.entries(doc.tables).map(([tid, t]) => {\n if (options.includeRows === \"none\") {\n const { rows: _r, ...rest } = t\n return [tid, rest]\n }\n if (options.includeRows === \"samples\") {\n const r = t.rows ?? []\n return [tid, { ...t, rows: r.slice(0, limit) }]\n }\n return [tid, { ...t, rows: t.rows }]\n })\n ) as GristReplicaDocument[\"tables\"]\n return { ...doc, tables }\n}\n"],"mappings":"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","names":[]}
|