@stigmer/react 3.11.1-dev.20260812192248 → 3.12.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 (273) hide show
  1. package/activity/useRecentActivity.d.ts +3 -2
  2. package/activity/useRecentActivity.d.ts.map +1 -1
  3. package/activity/useRecentActivity.js +3 -2
  4. package/activity/useRecentActivity.js.map +1 -1
  5. package/agent/AgentDetailView.d.ts +2 -12
  6. package/agent/AgentDetailView.d.ts.map +1 -1
  7. package/agent/AgentDetailView.js +10 -42
  8. package/agent/AgentDetailView.js.map +1 -1
  9. package/agent/internal/agentToInput.d.ts.map +1 -1
  10. package/agent/internal/agentToInput.js +0 -8
  11. package/agent/internal/agentToInput.js.map +1 -1
  12. package/dependency-graph/DependencyTreeNode.d.ts.map +1 -1
  13. package/dependency-graph/DependencyTreeNode.js +1 -7
  14. package/dependency-graph/DependencyTreeNode.js.map +1 -1
  15. package/dependency-graph/types.d.ts +8 -20
  16. package/dependency-graph/types.d.ts.map +1 -1
  17. package/dependency-graph/useDependencyGraph.d.ts.map +1 -1
  18. package/dependency-graph/useDependencyGraph.js +2 -20
  19. package/dependency-graph/useDependencyGraph.js.map +1 -1
  20. package/execution/useCreateAgentExecution.d.ts +3 -2
  21. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  22. package/execution/useCreateAgentExecution.js.map +1 -1
  23. package/index.d.ts +0 -2
  24. package/index.d.ts.map +1 -1
  25. package/index.js +0 -6
  26. package/index.js.map +1 -1
  27. package/internal/isUnimplemented.d.ts +17 -0
  28. package/internal/isUnimplemented.d.ts.map +1 -0
  29. package/internal/isUnimplemented.js +26 -0
  30. package/internal/isUnimplemented.js.map +1 -0
  31. package/library/useExportResource.d.ts +3 -4
  32. package/library/useExportResource.d.ts.map +1 -1
  33. package/library/useExportResource.js +1 -1
  34. package/library/useExportResource.js.map +1 -1
  35. package/manifest/EditResourceYamlDialog.d.ts.map +1 -1
  36. package/manifest/EditResourceYamlDialog.js.map +1 -1
  37. package/mcp-server/McpServerConnectDialog.js +7 -3
  38. package/mcp-server/McpServerConnectDialog.js.map +1 -1
  39. package/mcp-server/useMcpServerCredentials.d.ts +38 -10
  40. package/mcp-server/useMcpServerCredentials.d.ts.map +1 -1
  41. package/mcp-server/useMcpServerCredentials.js +50 -7
  42. package/mcp-server/useMcpServerCredentials.js.map +1 -1
  43. package/mcp-server/useOrgOAuthApp.d.ts +22 -0
  44. package/mcp-server/useOrgOAuthApp.d.ts.map +1 -1
  45. package/mcp-server/useOrgOAuthApp.js +39 -7
  46. package/mcp-server/useOrgOAuthApp.js.map +1 -1
  47. package/package.json +4 -4
  48. package/session/useSessionConversation.d.ts +4 -2
  49. package/session/useSessionConversation.d.ts.map +1 -1
  50. package/session/useSessionConversation.js.map +1 -1
  51. package/skill/useSkillVersions.d.ts.map +1 -1
  52. package/skill/useSkillVersions.js +1 -9
  53. package/skill/useSkillVersions.js.map +1 -1
  54. package/src/activity/useRecentActivity.ts +3 -2
  55. package/src/agent/AgentDetailView.tsx +6 -130
  56. package/src/agent/internal/__tests__/agentToInput.test.ts +2 -11
  57. package/src/agent/internal/agentToInput.ts +0 -11
  58. package/src/dependency-graph/DependencyTreeNode.tsx +1 -7
  59. package/src/dependency-graph/__tests__/useDependencyGraph.test.ts +18 -34
  60. package/src/dependency-graph/types.ts +8 -20
  61. package/src/dependency-graph/useDependencyGraph.ts +2 -22
  62. package/src/execution/useCreateAgentExecution.ts +3 -2
  63. package/src/index.ts +0 -82
  64. package/src/internal/isUnimplemented.ts +26 -0
  65. package/src/library/useExportResource.ts +3 -4
  66. package/src/manifest/EditResourceYamlDialog.tsx +1 -2
  67. package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +2 -2
  68. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +9 -9
  69. package/src/mcp-server/McpServerConnectDialog.tsx +29 -11
  70. package/src/mcp-server/__tests__/VendorApprovalBlocked.surfaces.test.tsx +103 -5
  71. package/src/mcp-server/__tests__/byoaEditionDegradation.test.tsx +323 -0
  72. package/src/mcp-server/__tests__/useMcpServerCredentials.test.tsx +306 -0
  73. package/src/mcp-server/useMcpServerCredentials.ts +87 -19
  74. package/src/mcp-server/useOrgOAuthApp.ts +54 -8
  75. package/src/session/useSessionConversation.ts +4 -2
  76. package/src/skill/useSkillVersions.ts +1 -11
  77. package/src/workflow/WorkflowCanvasEditor.tsx +37 -7
  78. package/src/workflow/WorkflowExecutionGraph.tsx +26 -1
  79. package/src/workflow/WorkflowExecutionViewer.tsx +27 -13
  80. package/src/workflow/WorkflowNode.tsx +5 -2
  81. package/src/workflow/WorkflowRunDialog.tsx +28 -1
  82. package/src/workflow/__tests__/WorkflowExecutionViewer.reconciliation.test.tsx +48 -1
  83. package/src/workflow/__tests__/WorkflowNode.test.tsx +93 -0
  84. package/src/workflow/__tests__/WorkflowRunDialog.test.tsx +127 -0
  85. package/src/workflow/__tests__/graph-history.test.ts +103 -0
  86. package/src/workflow/__tests__/overview-graph.test.ts +17 -0
  87. package/src/workflow/__tests__/useCanvasKeyboardShortcuts.undo.test.ts +115 -0
  88. package/src/workflow/__tests__/useWorkflowCanvas.undo.test.tsx +133 -0
  89. package/src/workflow/instance/CreateWorkflowInstanceDialog.tsx +16 -7
  90. package/src/workflow/instance/useDeleteWorkflowInstance.ts +9 -4
  91. package/src/workflow/layout/registry-dimensions.ts +2 -5
  92. package/src/workflow/node-shell/NodeShell.tsx +4 -0
  93. package/src/workflow/task-type-visual-registry.ts +5 -3
  94. package/src/workflow/useCanvasKeyboardShortcuts.ts +33 -3
  95. package/src/workflow/useGraphHistory.ts +22 -41
  96. package/src/workflow/useWorkflowCanvas.ts +12 -10
  97. package/src/workflow/useWorkflowSave.ts +2 -15
  98. package/src/workflow/workflow-graph-conversions.ts +25 -3
  99. package/styles.css +1 -1
  100. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  101. package/workflow/WorkflowCanvasEditor.d.ts.map +1 -1
  102. package/workflow/WorkflowCanvasEditor.js +31 -6
  103. package/workflow/WorkflowCanvasEditor.js.map +1 -1
  104. package/workflow/WorkflowExecutionGraph.d.ts.map +1 -1
  105. package/workflow/WorkflowExecutionGraph.js +27 -1
  106. package/workflow/WorkflowExecutionGraph.js.map +1 -1
  107. package/workflow/WorkflowExecutionViewer.d.ts.map +1 -1
  108. package/workflow/WorkflowExecutionViewer.js +26 -12
  109. package/workflow/WorkflowExecutionViewer.js.map +1 -1
  110. package/workflow/WorkflowNode.d.ts.map +1 -1
  111. package/workflow/WorkflowNode.js +2 -2
  112. package/workflow/WorkflowNode.js.map +1 -1
  113. package/workflow/WorkflowRunDialog.d.ts +11 -1
  114. package/workflow/WorkflowRunDialog.d.ts.map +1 -1
  115. package/workflow/WorkflowRunDialog.js +16 -2
  116. package/workflow/WorkflowRunDialog.js.map +1 -1
  117. package/workflow/instance/CreateWorkflowInstanceDialog.d.ts.map +1 -1
  118. package/workflow/instance/CreateWorkflowInstanceDialog.js +10 -2
  119. package/workflow/instance/CreateWorkflowInstanceDialog.js.map +1 -1
  120. package/workflow/instance/useDeleteWorkflowInstance.d.ts +9 -4
  121. package/workflow/instance/useDeleteWorkflowInstance.d.ts.map +1 -1
  122. package/workflow/instance/useDeleteWorkflowInstance.js +4 -2
  123. package/workflow/instance/useDeleteWorkflowInstance.js.map +1 -1
  124. package/workflow/layout/registry-dimensions.d.ts.map +1 -1
  125. package/workflow/layout/registry-dimensions.js +2 -5
  126. package/workflow/layout/registry-dimensions.js.map +1 -1
  127. package/workflow/node-shell/NodeShell.js +1 -1
  128. package/workflow/node-shell/NodeShell.js.map +1 -1
  129. package/workflow/task-type-visual-registry.d.ts.map +1 -1
  130. package/workflow/task-type-visual-registry.js +5 -3
  131. package/workflow/task-type-visual-registry.js.map +1 -1
  132. package/workflow/useCanvasKeyboardShortcuts.d.ts +15 -4
  133. package/workflow/useCanvasKeyboardShortcuts.d.ts.map +1 -1
  134. package/workflow/useCanvasKeyboardShortcuts.js +25 -4
  135. package/workflow/useCanvasKeyboardShortcuts.js.map +1 -1
  136. package/workflow/useGraphHistory.d.ts +16 -9
  137. package/workflow/useGraphHistory.d.ts.map +1 -1
  138. package/workflow/useGraphHistory.js +19 -33
  139. package/workflow/useGraphHistory.js.map +1 -1
  140. package/workflow/useWorkflowCanvas.d.ts +1 -3
  141. package/workflow/useWorkflowCanvas.d.ts.map +1 -1
  142. package/workflow/useWorkflowCanvas.js +15 -9
  143. package/workflow/useWorkflowCanvas.js.map +1 -1
  144. package/workflow/useWorkflowSave.d.ts.map +1 -1
  145. package/workflow/useWorkflowSave.js +2 -15
  146. package/workflow/useWorkflowSave.js.map +1 -1
  147. package/workflow/workflow-graph-conversions.d.ts +19 -1
  148. package/workflow/workflow-graph-conversions.d.ts.map +1 -1
  149. package/workflow/workflow-graph-conversions.js +17 -3
  150. package/workflow/workflow-graph-conversions.js.map +1 -1
  151. package/datastore/CollectionRecordsBrowser.d.ts +0 -34
  152. package/datastore/CollectionRecordsBrowser.d.ts.map +0 -1
  153. package/datastore/CollectionRecordsBrowser.js +0 -226
  154. package/datastore/CollectionRecordsBrowser.js.map +0 -1
  155. package/datastore/CollectionSchemaView.d.ts +0 -29
  156. package/datastore/CollectionSchemaView.d.ts.map +0 -1
  157. package/datastore/CollectionSchemaView.js +0 -93
  158. package/datastore/CollectionSchemaView.js.map +0 -1
  159. package/datastore/DatastoreDetailView.d.ts +0 -44
  160. package/datastore/DatastoreDetailView.d.ts.map +0 -1
  161. package/datastore/DatastoreDetailView.js +0 -76
  162. package/datastore/DatastoreDetailView.js.map +0 -1
  163. package/datastore/DatastoreSyncReport.d.ts +0 -19
  164. package/datastore/DatastoreSyncReport.d.ts.map +0 -1
  165. package/datastore/DatastoreSyncReport.js +0 -45
  166. package/datastore/DatastoreSyncReport.js.map +0 -1
  167. package/datastore/DeleteDatastoreDialog.d.ts +0 -35
  168. package/datastore/DeleteDatastoreDialog.d.ts.map +0 -1
  169. package/datastore/DeleteDatastoreDialog.js +0 -90
  170. package/datastore/DeleteDatastoreDialog.js.map +0 -1
  171. package/datastore/FieldValueControl.d.ts +0 -55
  172. package/datastore/FieldValueControl.d.ts.map +0 -1
  173. package/datastore/FieldValueControl.js +0 -138
  174. package/datastore/FieldValueControl.js.map +0 -1
  175. package/datastore/RecordFilterBuilder.d.ts +0 -37
  176. package/datastore/RecordFilterBuilder.d.ts.map +0 -1
  177. package/datastore/RecordFilterBuilder.js +0 -122
  178. package/datastore/RecordFilterBuilder.js.map +0 -1
  179. package/datastore/RecordFormPanel.d.ts +0 -45
  180. package/datastore/RecordFormPanel.d.ts.map +0 -1
  181. package/datastore/RecordFormPanel.js +0 -215
  182. package/datastore/RecordFormPanel.js.map +0 -1
  183. package/datastore/index.d.ts +0 -43
  184. package/datastore/index.d.ts.map +0 -1
  185. package/datastore/index.js +0 -22
  186. package/datastore/index.js.map +0 -1
  187. package/datastore/recordFilter.d.ts +0 -62
  188. package/datastore/recordFilter.d.ts.map +0 -1
  189. package/datastore/recordFilter.js +0 -104
  190. package/datastore/recordFilter.js.map +0 -1
  191. package/datastore/recordValues.d.ts +0 -85
  192. package/datastore/recordValues.d.ts.map +0 -1
  193. package/datastore/recordValues.js +0 -282
  194. package/datastore/recordValues.js.map +0 -1
  195. package/datastore/useDatastore.d.ts +0 -39
  196. package/datastore/useDatastore.d.ts.map +0 -1
  197. package/datastore/useDatastore.js +0 -44
  198. package/datastore/useDatastore.js.map +0 -1
  199. package/datastore/useDatastoreCount.d.ts +0 -50
  200. package/datastore/useDatastoreCount.d.ts.map +0 -1
  201. package/datastore/useDatastoreCount.js +0 -27
  202. package/datastore/useDatastoreCount.js.map +0 -1
  203. package/datastore/useDatastoreDescription.d.ts +0 -54
  204. package/datastore/useDatastoreDescription.d.ts.map +0 -1
  205. package/datastore/useDatastoreDescription.js +0 -50
  206. package/datastore/useDatastoreDescription.js.map +0 -1
  207. package/datastore/useDatastoreList.d.ts +0 -57
  208. package/datastore/useDatastoreList.d.ts.map +0 -1
  209. package/datastore/useDatastoreList.js +0 -29
  210. package/datastore/useDatastoreList.js.map +0 -1
  211. package/datastore/useDatastoreSearch.d.ts +0 -19
  212. package/datastore/useDatastoreSearch.d.ts.map +0 -1
  213. package/datastore/useDatastoreSearch.js +0 -22
  214. package/datastore/useDatastoreSearch.js.map +0 -1
  215. package/datastore/useDeleteDatastore.d.ts +0 -53
  216. package/datastore/useDeleteDatastore.d.ts.map +0 -1
  217. package/datastore/useDeleteDatastore.js +0 -40
  218. package/datastore/useDeleteDatastore.js.map +0 -1
  219. package/datastore/useDeleteRecord.d.ts +0 -34
  220. package/datastore/useDeleteRecord.d.ts.map +0 -1
  221. package/datastore/useDeleteRecord.js +0 -43
  222. package/datastore/useDeleteRecord.js.map +0 -1
  223. package/datastore/useInsertRecord.d.ts +0 -50
  224. package/datastore/useInsertRecord.d.ts.map +0 -1
  225. package/datastore/useInsertRecord.js +0 -55
  226. package/datastore/useInsertRecord.js.map +0 -1
  227. package/datastore/useRecordCollection.d.ts +0 -104
  228. package/datastore/useRecordCollection.d.ts.map +0 -1
  229. package/datastore/useRecordCollection.js +0 -136
  230. package/datastore/useRecordCollection.js.map +0 -1
  231. package/datastore/useRecordList.d.ts +0 -66
  232. package/datastore/useRecordList.d.ts.map +0 -1
  233. package/datastore/useRecordList.js +0 -58
  234. package/datastore/useRecordList.js.map +0 -1
  235. package/datastore/useUpdateRecord.d.ts +0 -52
  236. package/datastore/useUpdateRecord.d.ts.map +0 -1
  237. package/datastore/useUpdateRecord.js +0 -55
  238. package/datastore/useUpdateRecord.js.map +0 -1
  239. package/src/agent/__tests__/AgentDetailView.datastores.test.tsx +0 -166
  240. package/src/datastore/CollectionRecordsBrowser.tsx +0 -571
  241. package/src/datastore/CollectionSchemaView.tsx +0 -247
  242. package/src/datastore/DatastoreDetailView.tsx +0 -201
  243. package/src/datastore/DatastoreSyncReport.tsx +0 -105
  244. package/src/datastore/DeleteDatastoreDialog.tsx +0 -202
  245. package/src/datastore/FieldValueControl.tsx +0 -289
  246. package/src/datastore/RecordFilterBuilder.tsx +0 -422
  247. package/src/datastore/RecordFormPanel.tsx +0 -432
  248. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +0 -245
  249. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +0 -133
  250. package/src/datastore/__tests__/FieldValueControl.test.tsx +0 -160
  251. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +0 -155
  252. package/src/datastore/__tests__/RecordFormPanel.test.tsx +0 -227
  253. package/src/datastore/__tests__/recordFilter.test.ts +0 -169
  254. package/src/datastore/__tests__/recordMutations.test.tsx +0 -195
  255. package/src/datastore/__tests__/recordValues.test.ts +0 -359
  256. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +0 -142
  257. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +0 -143
  258. package/src/datastore/__tests__/useRecordCollection.test.tsx +0 -250
  259. package/src/datastore/__tests__/useRecordList.test.tsx +0 -85
  260. package/src/datastore/index.ts +0 -111
  261. package/src/datastore/recordFilter.ts +0 -154
  262. package/src/datastore/recordValues.ts +0 -327
  263. package/src/datastore/useDatastore.ts +0 -67
  264. package/src/datastore/useDatastoreCount.ts +0 -69
  265. package/src/datastore/useDatastoreDescription.ts +0 -90
  266. package/src/datastore/useDatastoreList.ts +0 -79
  267. package/src/datastore/useDatastoreSearch.ts +0 -39
  268. package/src/datastore/useDeleteDatastore.ts +0 -87
  269. package/src/datastore/useDeleteRecord.ts +0 -77
  270. package/src/datastore/useInsertRecord.ts +0 -92
  271. package/src/datastore/useRecordCollection.ts +0 -256
  272. package/src/datastore/useRecordList.ts +0 -131
  273. package/src/datastore/useUpdateRecord.ts +0 -95
@@ -1,169 +0,0 @@
1
- // Tests for the records-specific filter model — typed 1:1 against
2
- // RecordConditionOp, structurally unable to express anything
3
- // findRecords cannot serve (DD-008 invariant 2).
4
-
5
- import { describe, expect, it } from "vitest";
6
- import { create } from "@bufbuild/protobuf";
7
- import {
8
- CollectionDeclarationSchema,
9
- FieldType,
10
- } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/spec_pb";
11
- import { RecordConditionOp } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
12
- import {
13
- buildRecordFilter,
14
- filterableFields,
15
- formatConditionChip,
16
- isConditionComplete,
17
- } from "../recordFilter.js";
18
-
19
- const COLLECTION = create(CollectionDeclarationSchema, {
20
- name: "bookings",
21
- fields: [
22
- { name: "slot_date", type: FieldType.date, required: true },
23
- { name: "status", type: FieldType.string, enumValues: ["confirmed", "cancelled"] },
24
- { name: "notes", type: FieldType.json },
25
- ],
26
- });
27
-
28
- describe("filterableFields", () => {
29
- it("offers declared filterable fields plus the filterable system fields", () => {
30
- const names = filterableFields(COLLECTION).map((f) => f.name);
31
- expect(names).toEqual(["slot_date", "status", "id", "created_at", "updated_at"]);
32
- });
33
-
34
- it("excludes json fields — not filterable", () => {
35
- const names = filterableFields(COLLECTION).map((f) => f.name);
36
- expect(names).not.toContain("notes");
37
- });
38
-
39
- it("system fields carry the server's operator sets", () => {
40
- const fields = filterableFields(COLLECTION);
41
- const id = fields.find((f) => f.name === "id")!;
42
- expect(id.operators).toEqual([RecordConditionOp.eq, RecordConditionOp.is_in]);
43
- const createdAt = fields.find((f) => f.name === "created_at")!;
44
- expect(createdAt.operators).toEqual([
45
- RecordConditionOp.gt,
46
- RecordConditionOp.gte,
47
- RecordConditionOp.lt,
48
- RecordConditionOp.lte,
49
- ]);
50
- });
51
-
52
- it("required fields get no null tests; optional ones do", () => {
53
- const fields = filterableFields(COLLECTION);
54
- const slotDate = fields.find((f) => f.name === "slot_date")!;
55
- expect(slotDate.operators).not.toContain(RecordConditionOp.is_null);
56
- const status = fields.find((f) => f.name === "status")!;
57
- expect(status.operators).toContain(RecordConditionOp.is_null);
58
- });
59
-
60
- it("narrows to the caller's readable fields; system fields stay offered", () => {
61
- // A field-restricted read grant: the server refuses conditions on
62
- // unreadable fields, so the builder must not offer them.
63
- const names = filterableFields(COLLECTION, ["status"]).map((f) => f.name);
64
- expect(names).toEqual(["status", "id", "created_at", "updated_at"]);
65
- });
66
-
67
- it("empty readable_fields means unrestricted (the proto contract)", () => {
68
- expect(filterableFields(COLLECTION, []).map((f) => f.name)).toEqual(
69
- filterableFields(COLLECTION).map((f) => f.name),
70
- );
71
- });
72
- });
73
-
74
- describe("isConditionComplete", () => {
75
- it("value-less operators are complete without a value", () => {
76
- expect(
77
- isConditionComplete({ field: "status", op: RecordConditionOp.is_null }),
78
- ).toBe(true);
79
- });
80
-
81
- it("scalar operators need a value", () => {
82
- expect(isConditionComplete({ field: "status", op: RecordConditionOp.eq })).toBe(false);
83
- expect(
84
- isConditionComplete({ field: "status", op: RecordConditionOp.eq, value: "confirmed" }),
85
- ).toBe(true);
86
- });
87
-
88
- it("list operators need at least one value", () => {
89
- expect(
90
- isConditionComplete({ field: "status", op: RecordConditionOp.is_in, values: [] }),
91
- ).toBe(false);
92
- expect(
93
- isConditionComplete({
94
- field: "status",
95
- op: RecordConditionOp.is_in,
96
- values: ["confirmed"],
97
- }),
98
- ).toBe(true);
99
- });
100
-
101
- it("an unspecified operator is never complete", () => {
102
- expect(
103
- isConditionComplete({
104
- field: "status",
105
- op: RecordConditionOp.record_condition_op_unspecified,
106
- value: "x",
107
- }),
108
- ).toBe(false);
109
- });
110
- });
111
-
112
- describe("buildRecordFilter", () => {
113
- it("returns undefined for no complete conditions (absent filter, not empty)", () => {
114
- expect(buildRecordFilter([])).toBeUndefined();
115
- expect(
116
- buildRecordFilter([{ field: "status", op: RecordConditionOp.eq }]),
117
- ).toBeUndefined();
118
- });
119
-
120
- it("builds proto conditions with scalar values", () => {
121
- const filter = buildRecordFilter([
122
- { field: "status", op: RecordConditionOp.eq, value: "confirmed" },
123
- ])!;
124
- expect(filter.conditions).toHaveLength(1);
125
- expect(filter.conditions[0].field).toBe("status");
126
- expect(filter.conditions[0].op).toBe(RecordConditionOp.eq);
127
- expect(filter.conditions[0].value?.kind).toEqual({
128
- case: "stringValue",
129
- value: "confirmed",
130
- });
131
- });
132
-
133
- it("builds list values for is_in", () => {
134
- const filter = buildRecordFilter([
135
- {
136
- field: "status",
137
- op: RecordConditionOp.is_in,
138
- values: ["confirmed", "cancelled"],
139
- },
140
- ])!;
141
- expect(filter.conditions[0].values).toHaveLength(2);
142
- });
143
-
144
- it("leaves the value unset for null tests", () => {
145
- const filter = buildRecordFilter([
146
- { field: "status", op: RecordConditionOp.not_null },
147
- ])!;
148
- expect(filter.conditions[0].value).toBeUndefined();
149
- expect(filter.conditions[0].values).toHaveLength(0);
150
- });
151
- });
152
-
153
- describe("formatConditionChip", () => {
154
- it("formats scalar, list, and value-less conditions", () => {
155
- expect(
156
- formatConditionChip({ field: "status", op: RecordConditionOp.eq, value: "confirmed" }),
157
- ).toBe("status = confirmed");
158
- expect(
159
- formatConditionChip({
160
- field: "status",
161
- op: RecordConditionOp.not_in,
162
- values: ["a", "b"],
163
- }),
164
- ).toBe("status not in [a, b]");
165
- expect(formatConditionChip({ field: "notes", op: RecordConditionOp.is_null })).toBe(
166
- "notes is empty",
167
- );
168
- });
169
- });
@@ -1,195 +0,0 @@
1
- // Tests for the three record mutation hooks and the guarded datastore
2
- // delete. Mutations are imperative: the promise carries the result, the
3
- // hook carries isPending/error, and errors preserve the server's
4
- // relayable message byte-for-byte.
5
-
6
- import { describe, it, expect, vi, beforeEach } from "vitest";
7
- import { renderHook, act } from "@testing-library/react";
8
- import type { ReactNode } from "react";
9
- import { create } from "@bufbuild/protobuf";
10
- import { RecordEnvelopeSchema } from "@stigmer/protos/ai/stigmer/agentic/datastore/v1/record_io_pb";
11
- import { StigmerContext } from "../../context";
12
- import { useInsertRecord } from "../useInsertRecord";
13
- import { useUpdateRecord } from "../useUpdateRecord";
14
- import { useDeleteRecord } from "../useDeleteRecord";
15
- import { useDeleteDatastore } from "../useDeleteDatastore";
16
-
17
- function wrapper(client: unknown) {
18
- return function Wrapper({ children }: { children: ReactNode }) {
19
- return (
20
- <StigmerContext.Provider value={client as never}>
21
- {children}
22
- </StigmerContext.Provider>
23
- );
24
- };
25
- }
26
-
27
- const SCOPE = { org: "acme", datastore: "clinic", collection: "bookings" } as const;
28
-
29
- describe("useInsertRecord", () => {
30
- beforeEach(() => vi.restoreAllMocks());
31
-
32
- it("inserts and resolves with the server-stamped envelope", async () => {
33
- const stamped = create(RecordEnvelopeSchema, { id: "dsr_new" });
34
- const insertRecord = vi.fn().mockResolvedValue(stamped);
35
- const client = { datastore: { insertRecord } } as never;
36
-
37
- const { result } = renderHook(() => useInsertRecord(), { wrapper: wrapper(client) });
38
-
39
- let returned: unknown;
40
- await act(async () => {
41
- returned = await result.current.insertRecord({
42
- ...SCOPE,
43
- record: { slot_date: "2026-07-22", slot_time: "09:30:00" },
44
- });
45
- });
46
-
47
- expect(returned).toBe(stamped);
48
- expect(insertRecord).toHaveBeenCalledWith(
49
- expect.objectContaining({
50
- org: "acme",
51
- datastore: "clinic",
52
- collection: "bookings",
53
- partition: "",
54
- record: { slot_date: "2026-07-22", slot_time: "09:30:00" },
55
- }),
56
- );
57
- expect(result.current.error).toBeNull();
58
- expect(result.current.isInserting).toBe(false);
59
- });
60
-
61
- it("threads the partition (DD-010)", async () => {
62
- const insertRecord = vi.fn().mockResolvedValue(create(RecordEnvelopeSchema, {}));
63
- const client = { datastore: { insertRecord } } as never;
64
- const { result } = renderHook(() => useInsertRecord(), { wrapper: wrapper(client) });
65
-
66
- await act(async () => {
67
- await result.current.insertRecord({ ...SCOPE, partition: "dr-alt", record: {} });
68
- });
69
-
70
- expect(insertRecord).toHaveBeenCalledWith(
71
- expect.objectContaining({ partition: "dr-alt" }),
72
- );
73
- });
74
-
75
- it("preserves the constraint violation's message verbatim and rethrows", async () => {
76
- const violation = new Error("that slot is already booked");
77
- const client = {
78
- datastore: { insertRecord: vi.fn().mockRejectedValue(violation) },
79
- } as never;
80
- const { result } = renderHook(() => useInsertRecord(), { wrapper: wrapper(client) });
81
-
82
- await act(async () => {
83
- await expect(
84
- result.current.insertRecord({ ...SCOPE, record: {} }),
85
- ).rejects.toThrow("that slot is already booked");
86
- });
87
-
88
- expect(result.current.error?.message).toBe("that slot is already booked");
89
-
90
- act(() => result.current.clearError());
91
- expect(result.current.error).toBeNull();
92
- });
93
- });
94
-
95
- describe("useUpdateRecord", () => {
96
- beforeEach(() => vi.restoreAllMocks());
97
-
98
- it("submits the partial-merge payload including explicit nulls", async () => {
99
- const updateRecord = vi.fn().mockResolvedValue(create(RecordEnvelopeSchema, {}));
100
- const client = { datastore: { updateRecord } } as never;
101
- const { result } = renderHook(() => useUpdateRecord(), { wrapper: wrapper(client) });
102
-
103
- await act(async () => {
104
- await result.current.updateRecord({
105
- ...SCOPE,
106
- id: "dsr_1",
107
- fields: { patient_phone: "+15550100", notes: null },
108
- });
109
- });
110
-
111
- expect(updateRecord).toHaveBeenCalledWith(
112
- expect.objectContaining({
113
- id: "dsr_1",
114
- // Tri-state: dirty value + explicit clear travel; untouched
115
- // fields are absent from the payload entirely.
116
- fields: { patient_phone: "+15550100", notes: null },
117
- }),
118
- );
119
- });
120
-
121
- it("surfaces update denials verbatim", async () => {
122
- const denial = new Error("you are not allowed to update records in bookings");
123
- const client = {
124
- datastore: { updateRecord: vi.fn().mockRejectedValue(denial) },
125
- } as never;
126
- const { result } = renderHook(() => useUpdateRecord(), { wrapper: wrapper(client) });
127
-
128
- await act(async () => {
129
- await expect(
130
- result.current.updateRecord({ ...SCOPE, id: "dsr_1", fields: {} }),
131
- ).rejects.toThrow();
132
- });
133
-
134
- expect(result.current.error?.message).toBe(
135
- "you are not allowed to update records in bookings",
136
- );
137
- });
138
- });
139
-
140
- describe("useDeleteRecord", () => {
141
- beforeEach(() => vi.restoreAllMocks());
142
-
143
- it("deletes by id and resolves with the final envelope", async () => {
144
- const last = create(RecordEnvelopeSchema, { id: "dsr_1" });
145
- const deleteRecord = vi.fn().mockResolvedValue(last);
146
- const client = { datastore: { deleteRecord } } as never;
147
- const { result } = renderHook(() => useDeleteRecord(), { wrapper: wrapper(client) });
148
-
149
- let returned: unknown;
150
- await act(async () => {
151
- returned = await result.current.deleteRecord({ ...SCOPE, id: "dsr_1" });
152
- });
153
-
154
- expect(returned).toBe(last);
155
- expect(deleteRecord).toHaveBeenCalledWith(
156
- expect.objectContaining({ id: "dsr_1", collection: "bookings" }),
157
- );
158
- });
159
- });
160
-
161
- describe("useDeleteDatastore", () => {
162
- beforeEach(() => vi.restoreAllMocks());
163
-
164
- it("passes the force acknowledgment through", async () => {
165
- const deleted = { metadata: { id: "dst_1" } };
166
- const del = vi.fn().mockResolvedValue(deleted);
167
- const client = { datastore: { delete: del } } as never;
168
- const { result } = renderHook(() => useDeleteDatastore(), { wrapper: wrapper(client) });
169
-
170
- await act(async () => {
171
- await result.current.deleteDatastore({ resourceId: "dst_1", force: true });
172
- });
173
-
174
- expect(del).toHaveBeenCalledWith({ resourceId: "dst_1", force: true });
175
- });
176
-
177
- it("surfaces guard refusals verbatim — the server stays authoritative", async () => {
178
- const guard = new Error(
179
- 'datastore "clinic" holds 214 records across 2 collections; pass force to acknowledge their destruction',
180
- );
181
- const client = {
182
- datastore: { delete: vi.fn().mockRejectedValue(guard) },
183
- } as never;
184
- const { result } = renderHook(() => useDeleteDatastore(), { wrapper: wrapper(client) });
185
-
186
- await act(async () => {
187
- await expect(
188
- result.current.deleteDatastore({ resourceId: "dst_1" }),
189
- ).rejects.toThrow();
190
- });
191
-
192
- expect(result.current.error?.message).toBe(guard.message);
193
- expect(result.current.isDeleting).toBe(false);
194
- });
195
- });