@synnaxlabs/client 0.55.0 → 0.56.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/.turbo/turbo-build.log +10 -13
  2. package/dist/client.cjs +60 -36
  3. package/dist/client.js +6435 -4786
  4. package/dist/src/access/policy/client.d.ts +70 -80
  5. package/dist/src/access/policy/client.d.ts.map +1 -1
  6. package/dist/src/access/policy/types.gen.d.ts +18 -20
  7. package/dist/src/access/policy/types.gen.d.ts.map +1 -1
  8. package/dist/src/access/role/client.d.ts.map +1 -1
  9. package/dist/src/access/role/types.gen.d.ts +2 -2
  10. package/dist/src/actions/actions.d.ts +68 -0
  11. package/dist/src/actions/actions.d.ts.map +1 -0
  12. package/dist/src/actions/actions.spec.d.ts +2 -0
  13. package/dist/src/actions/actions.spec.d.ts.map +1 -0
  14. package/dist/src/actions/external.d.ts +2 -0
  15. package/dist/src/actions/external.d.ts.map +1 -0
  16. package/dist/src/actions/index.d.ts +2 -0
  17. package/dist/src/actions/index.d.ts.map +1 -0
  18. package/dist/src/arc/client.d.ts.map +1 -1
  19. package/dist/src/arc/compiler/types.gen.d.ts +1 -1
  20. package/dist/src/arc/compiler/types.gen.d.ts.map +1 -1
  21. package/dist/src/arc/graph/types.gen.d.ts +29 -29
  22. package/dist/src/arc/graph/types.gen.d.ts.map +1 -1
  23. package/dist/src/arc/ir/types.gen.d.ts +123 -123
  24. package/dist/src/arc/ir/types.gen.d.ts.map +1 -1
  25. package/dist/src/arc/module/types.gen.d.ts +45 -45
  26. package/dist/src/arc/program/types.gen.d.ts +45 -45
  27. package/dist/src/arc/types/types.gen.d.ts +11 -11
  28. package/dist/src/arc/types/types.gen.d.ts.map +1 -1
  29. package/dist/src/arc/types.gen.d.ts +99 -99
  30. package/dist/src/auth/auth.d.ts +3 -3
  31. package/dist/src/auth/auth.d.ts.map +1 -1
  32. package/dist/src/channel/client.d.ts +2 -2
  33. package/dist/src/channel/client.d.ts.map +1 -1
  34. package/dist/src/channel/retriever.d.ts +5 -8
  35. package/dist/src/channel/retriever.d.ts.map +1 -1
  36. package/dist/src/channel/types.gen.d.ts +3 -3
  37. package/dist/src/channel/writer.d.ts.map +1 -1
  38. package/dist/src/connection/checker.d.ts +1 -1
  39. package/dist/src/connection/checker.d.ts.map +1 -1
  40. package/dist/src/device/client.d.ts.map +1 -1
  41. package/dist/src/device/types.gen.d.ts +6 -8
  42. package/dist/src/device/types.gen.d.ts.map +1 -1
  43. package/dist/src/errors.d.ts +2 -0
  44. package/dist/src/errors.d.ts.map +1 -1
  45. package/dist/src/framer/adapter.d.ts.map +1 -1
  46. package/dist/src/framer/client.d.ts +2 -2
  47. package/dist/src/framer/codec.d.ts +9 -1
  48. package/dist/src/framer/codec.d.ts.map +1 -1
  49. package/dist/src/framer/deleter.d.ts.map +1 -1
  50. package/dist/src/framer/frame.d.ts +1 -1
  51. package/dist/src/framer/iterator.d.ts +84 -3
  52. package/dist/src/framer/iterator.d.ts.map +1 -1
  53. package/dist/src/framer/streamProxy.d.ts.map +1 -1
  54. package/dist/src/framer/streamer.d.ts +1 -3
  55. package/dist/src/framer/streamer.d.ts.map +1 -1
  56. package/dist/src/framer/types.gen.d.ts +18 -0
  57. package/dist/src/framer/types.gen.d.ts.map +1 -1
  58. package/dist/src/framer/writer.d.ts +8 -8
  59. package/dist/src/framer/writer.d.ts.map +1 -1
  60. package/dist/src/group/client.d.ts +1 -2
  61. package/dist/src/group/client.d.ts.map +1 -1
  62. package/dist/src/group/types.gen.d.ts +2 -2
  63. package/dist/src/index.d.ts +2 -1
  64. package/dist/src/index.d.ts.map +1 -1
  65. package/dist/src/label/client.d.ts +5 -8
  66. package/dist/src/label/client.d.ts.map +1 -1
  67. package/dist/src/lineplot/client.d.ts.map +1 -1
  68. package/dist/src/lineplot/types.gen.d.ts +2 -2
  69. package/dist/src/log/client.d.ts.map +1 -1
  70. package/dist/src/log/types.gen.d.ts +2 -2
  71. package/dist/src/ontology/client.d.ts +1 -3
  72. package/dist/src/ontology/client.d.ts.map +1 -1
  73. package/dist/src/ontology/payload.d.ts +12 -16
  74. package/dist/src/ontology/payload.d.ts.map +1 -1
  75. package/dist/src/ontology/types.gen.d.ts +1 -2
  76. package/dist/src/ontology/types.gen.d.ts.map +1 -1
  77. package/dist/src/ontology/writer.d.ts +5 -10
  78. package/dist/src/ontology/writer.d.ts.map +1 -1
  79. package/dist/src/rack/client.d.ts.map +1 -1
  80. package/dist/src/rack/types.gen.d.ts +3 -3
  81. package/dist/src/ranger/alias/client.d.ts.map +1 -1
  82. package/dist/src/ranger/client.d.ts.map +1 -1
  83. package/dist/src/ranger/kv/client.d.ts.map +1 -1
  84. package/dist/src/ranger/types.gen.d.ts +6 -6
  85. package/dist/src/ranger/types.gen.d.ts.map +1 -1
  86. package/dist/src/ranger/writer.d.ts +2 -3
  87. package/dist/src/ranger/writer.d.ts.map +1 -1
  88. package/dist/src/schematic/actions.d.ts +147 -0
  89. package/dist/src/schematic/actions.d.ts.map +1 -0
  90. package/dist/src/schematic/actions.gen.d.ts +484 -0
  91. package/dist/src/schematic/actions.gen.d.ts.map +1 -0
  92. package/dist/src/schematic/actions.spec.d.ts +2 -0
  93. package/dist/src/schematic/actions.spec.d.ts.map +1 -0
  94. package/dist/src/schematic/client.d.ts +53 -2
  95. package/dist/src/schematic/client.d.ts.map +1 -1
  96. package/dist/src/schematic/external.d.ts +2 -0
  97. package/dist/src/schematic/external.d.ts.map +1 -1
  98. package/dist/src/schematic/symbol/client.d.ts.map +1 -1
  99. package/dist/src/schematic/symbol/types.gen.d.ts +48 -58
  100. package/dist/src/schematic/symbol/types.gen.d.ts.map +1 -1
  101. package/dist/src/schematic/types.gen.d.ts +131 -5
  102. package/dist/src/schematic/types.gen.d.ts.map +1 -1
  103. package/dist/src/status/client.d.ts.map +1 -1
  104. package/dist/src/status/payload.d.ts +3 -3
  105. package/dist/src/table/actions.d.ts +156 -0
  106. package/dist/src/table/actions.d.ts.map +1 -0
  107. package/dist/src/table/actions.gen.d.ts +587 -0
  108. package/dist/src/table/actions.gen.d.ts.map +1 -0
  109. package/dist/src/table/client.d.ts +28 -2
  110. package/dist/src/table/client.d.ts.map +1 -1
  111. package/dist/src/table/external.d.ts +2 -0
  112. package/dist/src/table/external.d.ts.map +1 -1
  113. package/dist/src/table/types.gen.d.ts +71 -4
  114. package/dist/src/table/types.gen.d.ts.map +1 -1
  115. package/dist/src/task/client.d.ts.map +1 -1
  116. package/dist/src/task/types.gen.d.ts +7 -7
  117. package/dist/src/task/types.gen.d.ts.map +1 -1
  118. package/dist/src/user/client.d.ts +2 -2
  119. package/dist/src/user/client.d.ts.map +1 -1
  120. package/dist/src/user/types.gen.d.ts +2 -2
  121. package/dist/src/view/client.d.ts.map +1 -1
  122. package/dist/src/view/types.gen.d.ts +2 -2
  123. package/dist/src/workspace/client.d.ts.map +1 -1
  124. package/dist/src/workspace/types.gen.d.ts +3 -3
  125. package/dist/src/workspace/types.gen.d.ts.map +1 -1
  126. package/package.json +12 -11
  127. package/src/access/policy/client.ts +4 -7
  128. package/src/access/role/client.ts +6 -26
  129. package/src/actions/actions.spec.ts +229 -0
  130. package/src/actions/actions.ts +104 -0
  131. package/src/actions/external.ts +10 -0
  132. package/src/actions/index.ts +10 -0
  133. package/src/arc/client.ts +3 -7
  134. package/src/arc/compiler/types.gen.ts +2 -1
  135. package/src/arc/ir/types.gen.ts +2 -2
  136. package/src/arc/lsp.spec.ts +3 -7
  137. package/src/arc/types/types.gen.ts +3 -3
  138. package/src/auth/auth.spec.ts +12 -13
  139. package/src/auth/auth.ts +36 -34
  140. package/src/channel/batchRetriever.spec.ts +13 -4
  141. package/src/channel/client.ts +8 -6
  142. package/src/channel/retriever.ts +7 -16
  143. package/src/channel/writer.ts +4 -20
  144. package/src/connection/checker.ts +6 -6
  145. package/src/connection/connection.spec.ts +5 -8
  146. package/src/device/client.ts +5 -8
  147. package/src/device/types.gen.ts +4 -4
  148. package/src/errors.ts +9 -9
  149. package/src/framer/adapter.ts +2 -4
  150. package/src/framer/client.ts +1 -1
  151. package/src/framer/codec.spec.ts +53 -3
  152. package/src/framer/codec.ts +58 -25
  153. package/src/framer/deleter.ts +2 -8
  154. package/src/framer/iterator.ts +43 -40
  155. package/src/framer/streamProxy.ts +13 -13
  156. package/src/framer/streamer.spec.ts +12 -3
  157. package/src/framer/streamer.ts +7 -12
  158. package/src/framer/types.gen.ts +20 -0
  159. package/src/framer/writer.spec.ts +77 -0
  160. package/src/framer/writer.ts +51 -28
  161. package/src/group/client.ts +4 -7
  162. package/src/index.ts +3 -2
  163. package/src/label/client.ts +6 -16
  164. package/src/lineplot/client.ts +6 -21
  165. package/src/log/client.ts +6 -21
  166. package/src/ontology/client.ts +3 -4
  167. package/src/ontology/types.gen.ts +0 -1
  168. package/src/ontology/writer.ts +4 -7
  169. package/src/rack/client.ts +4 -7
  170. package/src/ranger/alias/client.ts +6 -11
  171. package/src/ranger/client.ts +3 -4
  172. package/src/ranger/kv/client.ts +5 -8
  173. package/src/ranger/writer.ts +4 -17
  174. package/src/schematic/access.spec.ts +6 -6
  175. package/src/schematic/actions.gen.ts +200 -0
  176. package/src/schematic/actions.spec.ts +699 -0
  177. package/src/schematic/actions.ts +168 -0
  178. package/src/schematic/client.ts +34 -30
  179. package/src/schematic/external.ts +2 -0
  180. package/src/schematic/schematic.spec.ts +233 -69
  181. package/src/schematic/symbol/client.ts +6 -11
  182. package/src/schematic/symbol/types.gen.ts +1 -10
  183. package/src/schematic/types.gen.ts +55 -6
  184. package/src/status/client.ts +4 -10
  185. package/src/table/access.spec.ts +0 -6
  186. package/src/table/actions.gen.ts +243 -0
  187. package/src/table/actions.ts +255 -0
  188. package/src/table/client.ts +21 -25
  189. package/src/table/external.ts +2 -0
  190. package/src/table/table.spec.ts +588 -43
  191. package/src/table/types.gen.ts +58 -5
  192. package/src/task/client.ts +7 -11
  193. package/src/task/types.gen.ts +8 -6
  194. package/src/user/client.ts +6 -11
  195. package/src/view/client.ts +4 -7
  196. package/src/workspace/client.ts +6 -16
  197. package/src/workspace/types.gen.ts +2 -1
@@ -7,7 +7,7 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
10
+ import { type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { array } from "@synnaxlabs/x";
12
12
  import { z } from "zod";
13
13
 
@@ -72,8 +72,7 @@ export class Client {
72
72
  async create(options: CreateArgs | CreateMultipleArgs): Promise<Symbol | Symbol[]> {
73
73
  const isMany = "symbols" in options;
74
74
  const symbols = isMany ? options.symbols : [options];
75
- const res = await sendRequired(
76
- this.client,
75
+ const res = await this.client.send(
77
76
  "/schematic/symbol/create",
78
77
  { symbols, parent: options.parent },
79
78
  createReqZ,
@@ -83,8 +82,7 @@ export class Client {
83
82
  }
84
83
 
85
84
  async rename(key: Key, name: string): Promise<void> {
86
- await sendRequired(
87
- this.client,
85
+ await this.client.send(
88
86
  "/schematic/symbol/rename",
89
87
  { key, name },
90
88
  renameReqZ,
@@ -96,8 +94,7 @@ export class Client {
96
94
  async retrieve(args: RetrieveMultipleParams): Promise<Symbol[]>;
97
95
  async retrieve(args: RetrieveArgs): Promise<Symbol | Symbol[]> {
98
96
  const isSingle = "key" in args;
99
- const res = await sendRequired(
100
- this.client,
97
+ const res = await this.client.send(
101
98
  "/schematic/symbol/retrieve",
102
99
  args,
103
100
  retrieveArgsZ,
@@ -108,8 +105,7 @@ export class Client {
108
105
  }
109
106
 
110
107
  async delete(keys: Key | Key[]): Promise<void> {
111
- await sendRequired(
112
- this.client,
108
+ await this.client.send(
113
109
  "/schematic/symbol/delete",
114
110
  { keys: array.toArray(keys) },
115
111
  deleteReqZ,
@@ -118,8 +114,7 @@ export class Client {
118
114
  }
119
115
 
120
116
  async retrieveGroup(): Promise<group.Group> {
121
- const res = await sendRequired(
122
- this.client,
117
+ const res = await this.client.send(
123
118
  "/schematic/symbol/retrieve-group",
124
119
  {},
125
120
  retrieveGroupReqZ,
@@ -43,15 +43,6 @@ export const handleZ = z.object({
43
43
  });
44
44
  export interface Handle extends z.infer<typeof handleZ> {}
45
45
 
46
- /** Viewport is the camera state for viewing or previewing a symbol. */
47
- export const viewportZ = z.object({
48
- /** zoom is the zoom level where 1.0 equals 100%. */
49
- zoom: z.number().default(1),
50
- /** position is the (x, y) pan offset. */
51
- position: spatial.xyZ,
52
- });
53
- export interface Viewport extends z.infer<typeof viewportZ> {}
54
-
55
46
  export const keyZ = z.uuid();
56
47
  export type Key = z.infer<typeof keyZ>;
57
48
 
@@ -84,7 +75,7 @@ export const specZ = z.object({
84
75
  /** scaleStroke indicates whether stroke width scales with the symbol size. */
85
76
  scaleStroke: z.boolean().default(false),
86
77
  /** previewViewport is an optional viewport configuration for symbol preview rendering. */
87
- previewViewport: viewportZ.optional(),
78
+ previewViewport: spatial.viewportZ.optional(),
88
79
  });
89
80
  export interface Spec extends z.infer<typeof specZ> {}
90
81
 
@@ -9,14 +9,58 @@
9
9
 
10
10
  // Code generated by Oracle. DO NOT EDIT.
11
11
 
12
- import { caseconv, record } from "@synnaxlabs/x";
12
+ import { array, caseconv, record, spatial, zod } from "@synnaxlabs/x";
13
13
  import { z } from "zod";
14
14
 
15
15
  import { ontology } from "@/ontology";
16
16
 
17
+ /** Node is a diagram node representing a symbol in the schematic. */
18
+ export const nodeZ = z.object({
19
+ /** key is the unique node identifier within the schematic. */
20
+ key: z.string(),
21
+ /** position is the top-left position of the node. */
22
+ position: spatial.xyZ,
23
+ /**
24
+ * zIndex is the stacking order of the node within the schematic. Higher
25
+ * values render above lower values. Set by the user via
26
+ * send-to-back / bring-to-front actions.
27
+ */
28
+ zIndex: zod.int16.optional(),
29
+ /**
30
+ * measured is the rendered pixel size of the node. Populated by the
31
+ * renderer after the node is mounted and used to keep diagram
32
+ * measurements consistent across re-renders.
33
+ */
34
+ measured: spatial.dimensionsZ.optional(),
35
+ });
36
+ export interface Node extends z.infer<typeof nodeZ> {}
37
+
38
+ /**
39
+ * Handle is a reference to a specific connection point on a specific node.
40
+ * For schematics, param is the symbol handle key (e.g. inlet, outlet).
41
+ */
42
+ export const handleZ = z.object({
43
+ /** node is the node identifier. */
44
+ node: z.string(),
45
+ /** param is the connection point identifier on the node. */
46
+ param: z.string(),
47
+ });
48
+ export interface Handle extends z.infer<typeof handleZ> {}
49
+
17
50
  export const keyZ = z.uuid();
18
51
  export type Key = z.infer<typeof keyZ>;
19
52
 
53
+ /** Edge is a connection between two nodes in the schematic. */
54
+ export const edgeZ = z.object({
55
+ /** key is the unique edge identifier within the schematic. */
56
+ key: z.string(),
57
+ /** source is the source endpoint of the edge. */
58
+ source: handleZ,
59
+ /** target is the target endpoint of the edge. */
60
+ target: handleZ,
61
+ });
62
+ export interface Edge extends z.infer<typeof edgeZ> {}
63
+
20
64
  /**
21
65
  * Schematic is a visual diagram editor component for drawing system schematics,
22
66
  * control flows, and process diagrams. Schematics support interactive
@@ -27,13 +71,18 @@ export const schematicZ = z.object({
27
71
  key: keyZ,
28
72
  /** name is a human-readable name for the schematic. */
29
73
  name: z.string(),
30
- /**
31
- * data is the schematic content including symbols, connections, and layout
32
- * configuration.
33
- */
34
- data: caseconv.preserveCase(record.nullishToEmpty()),
35
74
  /** snapshot indicates whether this schematic represents a saved snapshot state. */
36
75
  snapshot: z.boolean(),
76
+ /** nodes contains all diagram nodes in the schematic. */
77
+ nodes: array.nullishToEmpty(nodeZ),
78
+ /** edges contains all connections between nodes. */
79
+ edges: array.nullishToEmpty(edgeZ),
80
+ /**
81
+ * configs contains per-element configuration keyed by node or edge key. The
82
+ * shape of each value is determined by the element's variant; the
83
+ * wire format intentionally stores it as an opaque record.
84
+ */
85
+ configs: caseconv.preserveCase(record.nullishToEmpty(z.string(), record.unknownZ())),
37
86
  });
38
87
  export interface Schematic extends z.infer<typeof schematicZ> {}
39
88
 
@@ -7,7 +7,7 @@
7
7
  // License, use of this software will be governed by the Apache License, Version 2.0,
8
8
  // included in the file licenses/APL.txt.
9
9
 
10
- import { sendRequired, type UnaryClient } from "@synnaxlabs/freighter";
10
+ import { type UnaryClient } from "@synnaxlabs/freighter";
11
11
  import { array } from "@synnaxlabs/x";
12
12
  import z from "zod";
13
13
 
@@ -74,8 +74,7 @@ export class Client {
74
74
  args: RetrieveArgs & { detailsSchema?: DetailsSchema },
75
75
  ): Promise<Status<DetailsSchema> | Status<DetailsSchema>[]> {
76
76
  const isSingle = "key" in args;
77
- const res = await sendRequired(
78
- this.client,
77
+ const res = await this.client.send(
79
78
  "/status/retrieve",
80
79
  args,
81
80
  retrieveArgsZ,
@@ -97,11 +96,7 @@ export class Client {
97
96
  opts: SetOptions & { detailsSchema?: DetailsSchema } = {},
98
97
  ): Promise<Status<DetailsSchema> | Status<DetailsSchema>[]> {
99
98
  const isMany = Array.isArray(statuses);
100
- const res = await sendRequired<
101
- ReturnType<typeof setReqZ<DetailsSchema>>,
102
- ReturnType<typeof setResZ<DetailsSchema>>
103
- >(
104
- this.client,
99
+ const res = await this.client.send(
105
100
  "/status/set",
106
101
  {
107
102
  statuses: array.toArray(statuses),
@@ -115,8 +110,7 @@ export class Client {
115
110
  }
116
111
 
117
112
  async delete(keys: Key | Key[]): Promise<void> {
118
- await sendRequired<typeof deleteReqZ, typeof emptyResZ>(
119
- this.client,
113
+ await this.client.send(
120
114
  "/status/delete",
121
115
  { keys: array.toArray(keys) },
122
116
  deleteReqZ,
@@ -30,7 +30,6 @@ describe("table", () => {
30
30
  });
31
31
  const randomTable = await client.tables.create(ws.key, {
32
32
  name: "test",
33
- data: {},
34
33
  });
35
34
  await expect(
36
35
  userClient.tables.retrieve({ key: randomTable.key }),
@@ -49,7 +48,6 @@ describe("table", () => {
49
48
  });
50
49
  const randomTable = await client.tables.create(ws.key, {
51
50
  name: "test",
52
- data: {},
53
51
  });
54
52
  const retrieved = await userClient.tables.retrieve({
55
53
  key: randomTable.key,
@@ -70,7 +68,6 @@ describe("table", () => {
70
68
  });
71
69
  await userClient.tables.create(ws.key, {
72
70
  name: "test",
73
- data: {},
74
71
  });
75
72
  });
76
73
 
@@ -87,7 +84,6 @@ describe("table", () => {
87
84
  await expect(
88
85
  userClient.tables.create(ws.key, {
89
86
  name: "test",
90
- data: {},
91
87
  }),
92
88
  ).rejects.toThrow(AuthError);
93
89
  });
@@ -104,7 +100,6 @@ describe("table", () => {
104
100
  });
105
101
  const randomTable = await client.tables.create(ws.key, {
106
102
  name: "test",
107
- data: {},
108
103
  });
109
104
  await userClient.tables.delete(randomTable.key);
110
105
  await expect(
@@ -124,7 +119,6 @@ describe("table", () => {
124
119
  });
125
120
  const randomTable = await client.tables.create(ws.key, {
126
121
  name: "test",
127
- data: {},
128
122
  });
129
123
  await expect(userClient.tables.delete(randomTable.key)).rejects.toThrow(
130
124
  AuthError,
@@ -0,0 +1,243 @@
1
+ // Copyright 2026 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ // Code generated by Oracle. DO NOT EDIT.
11
+ import { array } from "@synnaxlabs/x";
12
+ import { type Draft } from "immer";
13
+ import { z } from "zod";
14
+
15
+ import { actions } from "@/actions";
16
+ import { cellTemplateZ, cellZ, keyZ, type Table } from "@/table/types.gen";
17
+
18
+ /** Rename renames the table. */
19
+ export const renamePayloadZ = z.object({
20
+ name: z.string(),
21
+ });
22
+
23
+ export type RenamePayload = z.infer<typeof renamePayloadZ>;
24
+
25
+ /**
26
+ * AddRow inserts a row at the given index. Three flows:
27
+ *
28
+ * 1. User gesture with cell_template against a non-empty table:
29
+ * replicate the template once per existing column.
30
+ * 2. User gesture with cell_template against a fully-empty table:
31
+ * seed a 1x1 grid (one template replica plus one default-sized
32
+ * column).
33
+ * 3. Undo replay of RemoveRow (cell_template is null, cells is
34
+ * non-empty): use cells as-is. If the original RemoveRow had
35
+ * stripped the table down to no columns, the explicit cells
36
+ * trigger the same column-bootstrap as flow 2.
37
+ *
38
+ * Derived replica keys come from the template's key with the last
39
+ * four hex digits replaced by the column index. Out-of-range
40
+ * indices clamp to the end.
41
+ */
42
+ export const addRowPayloadZ = z.object({
43
+ index: z.uint32(),
44
+ size: z.number(),
45
+ cells: array.nullishToEmpty(cellZ),
46
+ cellTemplate: cellZ.optional(),
47
+ });
48
+
49
+ export type AddRowPayload = z.infer<typeof addRowPayloadZ>;
50
+
51
+ /**
52
+ * RemoveRow removes the row at the given index. All cells referenced by the
53
+ * removed row are also dropped from the cells map. No-op if the
54
+ * index is out of range.
55
+ */
56
+ export const removeRowPayloadZ = z.object({
57
+ index: z.uint32(),
58
+ });
59
+
60
+ export type RemoveRowPayload = z.infer<typeof removeRowPayloadZ>;
61
+
62
+ /**
63
+ * AddCol inserts a column at the given index. Three flows:
64
+ *
65
+ * 1. User gesture with cell_template against a non-empty table:
66
+ * replicate the template once per existing row.
67
+ * 2. User gesture with cell_template against a fully-empty table:
68
+ * seed a 1x1 grid (one template replica plus one default-sized
69
+ * row).
70
+ * 3. Undo replay of RemoveCol (cell_template is null, cells is
71
+ * non-empty): use cells as-is. If the original RemoveCol had
72
+ * stripped the table down to no rows, the explicit cells
73
+ * trigger the same row-bootstrap as flow 2.
74
+ *
75
+ * Derived replica keys come from the template's key with the last
76
+ * four hex digits replaced by the row index. Cells whose row
77
+ * index exceeds the row count are added to the cells map but not
78
+ * referenced by any row. Out-of-range indices clamp to the end of
79
+ * every row's cells list.
80
+ */
81
+ export const addColPayloadZ = z.object({
82
+ index: z.uint32(),
83
+ size: z.number(),
84
+ cells: array.nullishToEmpty(cellZ),
85
+ cellTemplate: cellZ.optional(),
86
+ });
87
+
88
+ export type AddColPayload = z.infer<typeof addColPayloadZ>;
89
+
90
+ /**
91
+ * RemoveCol removes the column at the given index. All cells in that column
92
+ * (across every row) are dropped from the cells map. No-op if the
93
+ * index is out of range.
94
+ */
95
+ export const removeColPayloadZ = z.object({
96
+ index: z.uint32(),
97
+ });
98
+
99
+ export type RemoveColPayload = z.infer<typeof removeColPayloadZ>;
100
+
101
+ /** ResizeRow resizes the row at the given index. No-op if the index is out of range. */
102
+ export const resizeRowPayloadZ = z.object({
103
+ index: z.uint32(),
104
+ size: z.number(),
105
+ });
106
+
107
+ export type ResizeRowPayload = z.infer<typeof resizeRowPayloadZ>;
108
+
109
+ /** ResizeCol resizes the column at the given index. No-op if the index is out of range. */
110
+ export const resizeColPayloadZ = z.object({
111
+ index: z.uint32(),
112
+ size: z.number(),
113
+ });
114
+
115
+ export type ResizeColPayload = z.infer<typeof resizeColPayloadZ>;
116
+
117
+ /**
118
+ * SetCell replaces the cell at cell.key with the provided value. No-op if
119
+ * no cell with that key exists in the table.
120
+ */
121
+ export const setCellPayloadZ = z.object({
122
+ cell: cellZ,
123
+ });
124
+
125
+ export type SetCellPayload = z.infer<typeof setCellPayloadZ>;
126
+
127
+ /**
128
+ * EraseCells erases the cells whose keys are in cells. Any row whose every
129
+ * cell is in the selection is removed entirely; same for columns.
130
+ * Cells that survive that row/column removal have their variant
131
+ * and props replaced with the template's, keeping their original
132
+ * keys. Cells in the selection whose keys are not in the table's
133
+ * cells map are silently skipped.
134
+ */
135
+ export const eraseCellsPayloadZ = z.object({
136
+ cells: array.nullishToEmpty(z.string()),
137
+ template: cellTemplateZ,
138
+ });
139
+
140
+ export type EraseCellsPayload = z.infer<typeof eraseCellsPayloadZ>;
141
+
142
+ export const actionZ = z.discriminatedUnion("type", [
143
+ z.object({ type: z.literal("rename"), rename: renamePayloadZ }),
144
+ z.object({ type: z.literal("add_row"), addRow: addRowPayloadZ }),
145
+ z.object({ type: z.literal("remove_row"), removeRow: removeRowPayloadZ }),
146
+ z.object({ type: z.literal("add_col"), addCol: addColPayloadZ }),
147
+ z.object({ type: z.literal("remove_col"), removeCol: removeColPayloadZ }),
148
+ z.object({ type: z.literal("resize_row"), resizeRow: resizeRowPayloadZ }),
149
+ z.object({ type: z.literal("resize_col"), resizeCol: resizeColPayloadZ }),
150
+ z.object({ type: z.literal("set_cell"), setCell: setCellPayloadZ }),
151
+ z.object({ type: z.literal("erase_cells"), eraseCells: eraseCellsPayloadZ }),
152
+ ]);
153
+
154
+ export type Action = z.infer<typeof actionZ>;
155
+
156
+ export const rename = (payload: RenamePayload): Action => ({
157
+ type: "rename",
158
+ rename: payload,
159
+ });
160
+
161
+ export const addRow = (payload: AddRowPayload): Action => ({
162
+ type: "add_row",
163
+ addRow: payload,
164
+ });
165
+
166
+ export const removeRow = (payload: RemoveRowPayload): Action => ({
167
+ type: "remove_row",
168
+ removeRow: payload,
169
+ });
170
+
171
+ export const addCol = (payload: AddColPayload): Action => ({
172
+ type: "add_col",
173
+ addCol: payload,
174
+ });
175
+
176
+ export const removeCol = (payload: RemoveColPayload): Action => ({
177
+ type: "remove_col",
178
+ removeCol: payload,
179
+ });
180
+
181
+ export const resizeRow = (payload: ResizeRowPayload): Action => ({
182
+ type: "resize_row",
183
+ resizeRow: payload,
184
+ });
185
+
186
+ export const resizeCol = (payload: ResizeColPayload): Action => ({
187
+ type: "resize_col",
188
+ resizeCol: payload,
189
+ });
190
+
191
+ export const setCell = (payload: SetCellPayload): Action => ({
192
+ type: "set_cell",
193
+ setCell: payload,
194
+ });
195
+
196
+ export const eraseCells = (payload: EraseCellsPayload): Action => ({
197
+ type: "erase_cells",
198
+ eraseCells: payload,
199
+ });
200
+
201
+ export type HandlerResult = actions.HandlerResult<Action>;
202
+
203
+ export type ReduceAllResult = actions.ReduceAllResult<Table, Action>;
204
+
205
+ export interface Handlers {
206
+ rename: (state: Draft<Table>, payload: RenamePayload) => HandlerResult;
207
+ addRow: (state: Draft<Table>, payload: AddRowPayload) => HandlerResult;
208
+ removeRow: (state: Draft<Table>, payload: RemoveRowPayload) => HandlerResult;
209
+ addCol: (state: Draft<Table>, payload: AddColPayload) => HandlerResult;
210
+ removeCol: (state: Draft<Table>, payload: RemoveColPayload) => HandlerResult;
211
+ resizeRow: (state: Draft<Table>, payload: ResizeRowPayload) => HandlerResult;
212
+ resizeCol: (state: Draft<Table>, payload: ResizeColPayload) => HandlerResult;
213
+ setCell: (state: Draft<Table>, payload: SetCellPayload) => HandlerResult;
214
+ eraseCells: (state: Draft<Table>, payload: EraseCellsPayload) => HandlerResult;
215
+ }
216
+
217
+ export const createReduceAll = (handlers: Handlers) =>
218
+ actions.createReduceAll<Table, Action>((state, action) => {
219
+ switch (action.type) {
220
+ case "rename":
221
+ return handlers.rename(state, action.rename);
222
+ case "add_row":
223
+ return handlers.addRow(state, action.addRow);
224
+ case "remove_row":
225
+ return handlers.removeRow(state, action.removeRow);
226
+ case "add_col":
227
+ return handlers.addCol(state, action.addCol);
228
+ case "remove_col":
229
+ return handlers.removeCol(state, action.removeCol);
230
+ case "resize_row":
231
+ return handlers.resizeRow(state, action.resizeRow);
232
+ case "resize_col":
233
+ return handlers.resizeCol(state, action.resizeCol);
234
+ case "set_cell":
235
+ return handlers.setCell(state, action.setCell);
236
+ case "erase_cells":
237
+ return handlers.eraseCells(state, action.eraseCells);
238
+ }
239
+ });
240
+
241
+ export const scopedActionZ = actions.scopedZ(keyZ, actionZ);
242
+
243
+ export const dispatchReqZ = actions.dispatchReqZ(keyZ, actionZ);