grist-widget-sdk 0.3.27 → 0.5.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +79 -208
  3. package/dist/app.cjs +1336 -4415
  4. package/dist/app.cjs.map +1 -1
  5. package/dist/app.d.cts +6 -103
  6. package/dist/app.d.ts +6 -103
  7. package/dist/app.js +5 -7
  8. package/dist/chunk-4ZGVKGDF.js +204 -0
  9. package/dist/chunk-4ZGVKGDF.js.map +1 -0
  10. package/dist/{chunk-6Y2IONGJ.js → chunk-LSALXIGM.js} +191 -20
  11. package/dist/chunk-LSALXIGM.js.map +1 -0
  12. package/dist/chunk-MAPAWVQC.js +1898 -0
  13. package/dist/chunk-MAPAWVQC.js.map +1 -0
  14. package/dist/{chunk-YQNMIL33.js → chunk-OXA2VITC.js} +532 -181
  15. package/dist/chunk-OXA2VITC.js.map +1 -0
  16. package/dist/define-widget-B1FIvI-h.d.cts +433 -0
  17. package/dist/define-widget-B9gEtJP0.d.ts +433 -0
  18. package/dist/emulator/testing.cjs +3341 -6512
  19. package/dist/emulator/testing.cjs.map +1 -1
  20. package/dist/emulator/testing.d.cts +29 -14
  21. package/dist/emulator/testing.d.ts +29 -14
  22. package/dist/emulator/testing.js +78 -72
  23. package/dist/emulator/testing.js.map +1 -1
  24. package/dist/emulator.cjs +63 -249
  25. package/dist/emulator.cjs.map +1 -1
  26. package/dist/emulator.d.cts +6 -8
  27. package/dist/emulator.d.ts +6 -8
  28. package/dist/emulator.js +5 -11
  29. package/dist/index.cjs +1442 -4862
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +81 -260
  32. package/dist/index.d.ts +81 -260
  33. package/dist/index.js +12 -158
  34. package/dist/mount-grist-widget-CkB-3iG_.d.ts +137 -0
  35. package/dist/mount-grist-widget-Dtelqao_.d.cts +137 -0
  36. package/dist/{inline-DpcT8tV9.d.ts → templates-CGmRIQBV.d.cts} +89 -35
  37. package/dist/{inline-C7DkvuET.d.cts → templates-Cq94qOcf.d.ts} +89 -35
  38. package/dist/{types-D3JxUCfL.d.cts → types-DBStn0Dk.d.cts} +2 -26
  39. package/dist/{types-D3JxUCfL.d.ts → types-DBStn0Dk.d.ts} +2 -26
  40. package/package.json +8 -37
  41. package/dist/advanced.cjs +0 -2799
  42. package/dist/advanced.cjs.map +0 -1
  43. package/dist/advanced.d.cts +0 -822
  44. package/dist/advanced.d.ts +0 -822
  45. package/dist/advanced.js +0 -872
  46. package/dist/advanced.js.map +0 -1
  47. package/dist/chunk-22U7WAY3.js +0 -463
  48. package/dist/chunk-22U7WAY3.js.map +0 -1
  49. package/dist/chunk-64SVRWW7.js +0 -758
  50. package/dist/chunk-64SVRWW7.js.map +0 -1
  51. package/dist/chunk-6Y2IONGJ.js.map +0 -1
  52. package/dist/chunk-B4AKVSWV.js +0 -2362
  53. package/dist/chunk-B4AKVSWV.js.map +0 -1
  54. package/dist/chunk-ELGVOHFD.js +0 -32
  55. package/dist/chunk-ELGVOHFD.js.map +0 -1
  56. package/dist/chunk-GTTD5HPO.js +0 -36
  57. package/dist/chunk-GTTD5HPO.js.map +0 -1
  58. package/dist/chunk-NO6FYX33.js +0 -2084
  59. package/dist/chunk-NO6FYX33.js.map +0 -1
  60. package/dist/chunk-OPTOYD2Y.js +0 -277
  61. package/dist/chunk-OPTOYD2Y.js.map +0 -1
  62. package/dist/chunk-PM3B4WYV.js +0 -12
  63. package/dist/chunk-PM3B4WYV.js.map +0 -1
  64. package/dist/chunk-REV5AUXD.js +0 -25
  65. package/dist/chunk-REV5AUXD.js.map +0 -1
  66. package/dist/chunk-YQNMIL33.js.map +0 -1
  67. package/dist/create-grist-emulator-BCqp1BF9.d.ts +0 -81
  68. package/dist/create-grist-emulator-DBM8OSIR.d.cts +0 -81
  69. package/dist/emulator/devtools.cjs +0 -1404
  70. package/dist/emulator/devtools.cjs.map +0 -1
  71. package/dist/emulator/devtools.d.cts +0 -48
  72. package/dist/emulator/devtools.d.ts +0 -48
  73. package/dist/emulator/devtools.js +0 -506
  74. package/dist/emulator/devtools.js.map +0 -1
  75. package/dist/emulator/transports.cjs +0 -1132
  76. package/dist/emulator/transports.cjs.map +0 -1
  77. package/dist/emulator/transports.d.cts +0 -38
  78. package/dist/emulator/transports.d.ts +0 -38
  79. package/dist/emulator/transports.js +0 -12
  80. package/dist/emulator/transports.js.map +0 -1
  81. package/dist/templates-8k2LKoO-.d.cts +0 -24
  82. package/dist/templates-DIwi_mvI.d.ts +0 -24
  83. package/dist/use-grist-reads-DUMvJgV7.d.ts +0 -480
  84. package/dist/use-grist-reads-DpjVuI0H.d.cts +0 -480
  85. package/dist/use-grist-types-DdOLEJXN.d.cts +0 -499
  86. package/dist/use-grist-types-kwxoFeub.d.ts +0 -499
  87. package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.cts +0 -43
  88. package/dist/use-grist-widget-options-from-context-CGOlQ5Vc.d.ts +0 -43
package/dist/app.d.cts CHANGED
@@ -1,104 +1,7 @@
1
- import * as react from 'react';
2
- import { ComponentType, ReactNode } from 'react';
3
- import { UseGristOptions } from './index.cjs';
4
- import './types-D3JxUCfL.cjs';
5
- import './use-grist-reads-DpjVuI0H.cjs';
6
- import 'zod';
7
-
8
- /**
9
- * Where a deployed build is being served from.
10
- *
11
- * A widget's deploy pipeline publishes the same build at its root and at
12
- * `/latest/`, a preview at `/dev/`, and each release at `/v<version>/`, all
13
- * under one base path (e.g. `/my-widget/` on GitHub Pages). Opened outside
14
- * Grist, the page tells them apart from `window.location.pathname` alone.
15
- */
16
- type DeployChannel = {
17
- kind: "latest";
18
- } | {
19
- kind: "dev";
20
- } | {
21
- kind: "version";
22
- version: string;
23
- };
24
- type DeployPath = {
25
- channel: DeployChannel;
26
- /**
27
- * The path the channels live under, always ending in `/`: the current
28
- * path without its channel segment. `"/my-widget/v1.2.0/"` gives
29
- * `"/my-widget/"`.
30
- */
31
- basePath: string;
32
- };
33
- /**
34
- * Parse a pathname into its deploy channel and base path. A path without a
35
- * channel segment (the deployed root, or a local dev server) is `latest`:
36
- * the deploy places the latest release at the root too.
37
- */
38
- declare function parseDeployPath(pathname: string): DeployPath;
39
- /** `"latest"`, `"dev"` or `"v1.2.0"`. */
40
- declare function deployChannelLabel(channel: DeployChannel): string;
41
-
42
- type GristWidgetAppProps = {
43
- /** The widget. A `React.lazy()` component works too: its code then loads only inside Grist. */
44
- App: ComponentType;
45
- /** The widget's `GRIST_OPTIONS`: access level, columns, and so on. */
46
- options: UseGristOptions;
47
- /**
48
- * Whether this is the local dev server. Pass `import.meta.env.DEV`.
49
- * Outside Grist it picks the local-dev page over the release page.
50
- */
51
- dev?: boolean;
52
- /**
53
- * Wraps the widget inside Grist, under {@link GristBoundary}. The default
54
- * lists what needs the user's attention (column mapping, access level,
55
- * failed writes) above the widget; `null` renders the widget alone.
56
- */
57
- Alerts?: ComponentType<{
58
- children: ReactNode;
59
- }> | null;
60
- /** Shown outside Grist on the local dev server. Defaults to a page pointing at `pnpm test` and the `dev` loop. */
61
- LocalDevPage?: ComponentType;
62
- /**
63
- * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`).
64
- * Defaults to a page linking every channel and version, with the URL to
65
- * paste into Grist.
66
- */
67
- ReleasePage?: ComponentType<{
68
- channel: DeployChannel;
69
- }>;
70
- };
71
- type MountGristWidgetConfig = GristWidgetAppProps & {
72
- /** The element to render into, or its CSS selector. Defaults to `#root`. */
73
- root?: Element | string;
74
- };
75
- type MountedGristWidget = {
76
- unmount: () => void;
77
- };
78
- /**
79
- * Render a widget into the page: everything `src/main.tsx` used to wire by
80
- * hand.
81
- *
82
- * ```tsx
83
- * import { mountGristWidget } from "grist-widget-sdk/app"
84
- * import "./index.css"
85
- * import App, { GRIST_OPTIONS } from "./App"
86
- *
87
- * mountGristWidget({ App, options: GRIST_OPTIONS, dev: import.meta.env.DEV })
88
- * ```
89
- *
90
- * Inside Grist, the widget renders in {@link GristWidgetProvider} and
91
- * {@link GristBoundary}, which gates on its mapped columns when it declares
92
- * any, and follows Grist's light/dark theme. Outside Grist, where there is
93
- * nothing to connect to, the page shows `LocalDevPage` on the dev server and
94
- * `ReleasePage` on a deployed URL.
95
- */
96
- declare function mountGristWidget(config: MountGristWidgetConfig): MountedGristWidget;
97
- /**
98
- * The tree {@link mountGristWidget} renders, as a component: for a test, or
99
- * for a page that manages its own React root.
100
- */
101
- declare function GristWidgetApp({ App, options, dev, Alerts, LocalDevPage, ReleasePage, }: GristWidgetAppProps): react.JSX.Element;
1
+ export { D as DeployChannel, a as DeployPath, G as GristWidgetApp, b as GristWidgetAppProps, c as GristWidgetEntry, M as MountGristWidgetConfig, d as MountedGristWidget, e as deployChannelLabel, f as entryProps, m as mountGristWidget, p as parseDeployPath } from './mount-grist-widget-Dtelqao_.cjs';
2
+ import 'react';
3
+ import './define-widget-B1FIvI-h.cjs';
4
+ import './types-DBStn0Dk.cjs';
102
5
 
103
6
  type WidgetTheme = "light" | "dark" | "system";
104
7
  type ResolvedWidgetTheme = "light" | "dark";
@@ -143,5 +46,5 @@ type UseReleasedVersionsResult = {
143
46
  */
144
47
  declare function useReleasedVersions(pathname?: string): UseReleasedVersionsResult;
145
48
 
146
- export { GristWidgetApp, deployChannelLabel, mountGristWidget, parseDeployPath, useReleasedVersions, useTheme };
147
- export type { DeployChannel, DeployPath, GristWidgetAppProps, MountGristWidgetConfig, MountedGristWidget, ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
49
+ export { useReleasedVersions, useTheme };
50
+ export type { ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
package/dist/app.d.ts CHANGED
@@ -1,104 +1,7 @@
1
- import * as react from 'react';
2
- import { ComponentType, ReactNode } from 'react';
3
- import { UseGristOptions } from './index.js';
4
- import './types-D3JxUCfL.js';
5
- import './use-grist-reads-DUMvJgV7.js';
6
- import 'zod';
7
-
8
- /**
9
- * Where a deployed build is being served from.
10
- *
11
- * A widget's deploy pipeline publishes the same build at its root and at
12
- * `/latest/`, a preview at `/dev/`, and each release at `/v<version>/`, all
13
- * under one base path (e.g. `/my-widget/` on GitHub Pages). Opened outside
14
- * Grist, the page tells them apart from `window.location.pathname` alone.
15
- */
16
- type DeployChannel = {
17
- kind: "latest";
18
- } | {
19
- kind: "dev";
20
- } | {
21
- kind: "version";
22
- version: string;
23
- };
24
- type DeployPath = {
25
- channel: DeployChannel;
26
- /**
27
- * The path the channels live under, always ending in `/`: the current
28
- * path without its channel segment. `"/my-widget/v1.2.0/"` gives
29
- * `"/my-widget/"`.
30
- */
31
- basePath: string;
32
- };
33
- /**
34
- * Parse a pathname into its deploy channel and base path. A path without a
35
- * channel segment (the deployed root, or a local dev server) is `latest`:
36
- * the deploy places the latest release at the root too.
37
- */
38
- declare function parseDeployPath(pathname: string): DeployPath;
39
- /** `"latest"`, `"dev"` or `"v1.2.0"`. */
40
- declare function deployChannelLabel(channel: DeployChannel): string;
41
-
42
- type GristWidgetAppProps = {
43
- /** The widget. A `React.lazy()` component works too: its code then loads only inside Grist. */
44
- App: ComponentType;
45
- /** The widget's `GRIST_OPTIONS`: access level, columns, and so on. */
46
- options: UseGristOptions;
47
- /**
48
- * Whether this is the local dev server. Pass `import.meta.env.DEV`.
49
- * Outside Grist it picks the local-dev page over the release page.
50
- */
51
- dev?: boolean;
52
- /**
53
- * Wraps the widget inside Grist, under {@link GristBoundary}. The default
54
- * lists what needs the user's attention (column mapping, access level,
55
- * failed writes) above the widget; `null` renders the widget alone.
56
- */
57
- Alerts?: ComponentType<{
58
- children: ReactNode;
59
- }> | null;
60
- /** Shown outside Grist on the local dev server. Defaults to a page pointing at `pnpm test` and the `dev` loop. */
61
- LocalDevPage?: ComponentType;
62
- /**
63
- * Shown outside Grist on a deployed URL (`/latest/`, `/dev/`, `/v<version>/`).
64
- * Defaults to a page linking every channel and version, with the URL to
65
- * paste into Grist.
66
- */
67
- ReleasePage?: ComponentType<{
68
- channel: DeployChannel;
69
- }>;
70
- };
71
- type MountGristWidgetConfig = GristWidgetAppProps & {
72
- /** The element to render into, or its CSS selector. Defaults to `#root`. */
73
- root?: Element | string;
74
- };
75
- type MountedGristWidget = {
76
- unmount: () => void;
77
- };
78
- /**
79
- * Render a widget into the page: everything `src/main.tsx` used to wire by
80
- * hand.
81
- *
82
- * ```tsx
83
- * import { mountGristWidget } from "grist-widget-sdk/app"
84
- * import "./index.css"
85
- * import App, { GRIST_OPTIONS } from "./App"
86
- *
87
- * mountGristWidget({ App, options: GRIST_OPTIONS, dev: import.meta.env.DEV })
88
- * ```
89
- *
90
- * Inside Grist, the widget renders in {@link GristWidgetProvider} and
91
- * {@link GristBoundary}, which gates on its mapped columns when it declares
92
- * any, and follows Grist's light/dark theme. Outside Grist, where there is
93
- * nothing to connect to, the page shows `LocalDevPage` on the dev server and
94
- * `ReleasePage` on a deployed URL.
95
- */
96
- declare function mountGristWidget(config: MountGristWidgetConfig): MountedGristWidget;
97
- /**
98
- * The tree {@link mountGristWidget} renders, as a component: for a test, or
99
- * for a page that manages its own React root.
100
- */
101
- declare function GristWidgetApp({ App, options, dev, Alerts, LocalDevPage, ReleasePage, }: GristWidgetAppProps): react.JSX.Element;
1
+ export { D as DeployChannel, a as DeployPath, G as GristWidgetApp, b as GristWidgetAppProps, c as GristWidgetEntry, M as MountGristWidgetConfig, d as MountedGristWidget, e as deployChannelLabel, f as entryProps, m as mountGristWidget, p as parseDeployPath } from './mount-grist-widget-CkB-3iG_.js';
2
+ import 'react';
3
+ import './define-widget-B9gEtJP0.js';
4
+ import './types-DBStn0Dk.js';
102
5
 
103
6
  type WidgetTheme = "light" | "dark" | "system";
104
7
  type ResolvedWidgetTheme = "light" | "dark";
@@ -143,5 +46,5 @@ type UseReleasedVersionsResult = {
143
46
  */
144
47
  declare function useReleasedVersions(pathname?: string): UseReleasedVersionsResult;
145
48
 
146
- export { GristWidgetApp, deployChannelLabel, mountGristWidget, parseDeployPath, useReleasedVersions, useTheme };
147
- export type { DeployChannel, DeployPath, GristWidgetAppProps, MountGristWidgetConfig, MountedGristWidget, ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
49
+ export { useReleasedVersions, useTheme };
50
+ export type { ReleasedVersion, ResolvedWidgetTheme, UseReleasedVersionsResult, UseThemeResult, WidgetTheme };
package/dist/app.js CHANGED
@@ -1,20 +1,18 @@
1
1
  import {
2
2
  GristWidgetApp,
3
3
  deployChannelLabel,
4
+ entryProps,
4
5
  mountGristWidget,
5
6
  parseDeployPath,
6
7
  useReleasedVersions,
7
8
  useTheme
8
- } from "./chunk-6Y2IONGJ.js";
9
- import "./chunk-B4AKVSWV.js";
10
- import "./chunk-NO6FYX33.js";
11
- import "./chunk-GTTD5HPO.js";
12
- import "./chunk-REV5AUXD.js";
13
- import "./chunk-OPTOYD2Y.js";
14
- import "./chunk-64SVRWW7.js";
9
+ } from "./chunk-LSALXIGM.js";
10
+ import "./chunk-MAPAWVQC.js";
11
+ import "./chunk-4ZGVKGDF.js";
15
12
  export {
16
13
  GristWidgetApp,
17
14
  deployChannelLabel,
15
+ entryProps,
18
16
  mountGristWidget,
19
17
  parseDeployPath,
20
18
  useReleasedVersions,
@@ -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":[]}