@stigmer/react 3.11.1-dev.20260812192248 → 3.12.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 (168) 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/index.d.ts +0 -2
  21. package/index.d.ts.map +1 -1
  22. package/index.js +0 -6
  23. package/index.js.map +1 -1
  24. package/library/useExportResource.d.ts +3 -4
  25. package/library/useExportResource.d.ts.map +1 -1
  26. package/library/useExportResource.js +1 -1
  27. package/library/useExportResource.js.map +1 -1
  28. package/manifest/EditResourceYamlDialog.d.ts.map +1 -1
  29. package/manifest/EditResourceYamlDialog.js.map +1 -1
  30. package/package.json +4 -4
  31. package/src/activity/useRecentActivity.ts +3 -2
  32. package/src/agent/AgentDetailView.tsx +6 -130
  33. package/src/agent/internal/__tests__/agentToInput.test.ts +2 -11
  34. package/src/agent/internal/agentToInput.ts +0 -11
  35. package/src/dependency-graph/DependencyTreeNode.tsx +1 -7
  36. package/src/dependency-graph/__tests__/useDependencyGraph.test.ts +18 -34
  37. package/src/dependency-graph/types.ts +8 -20
  38. package/src/dependency-graph/useDependencyGraph.ts +2 -22
  39. package/src/index.ts +0 -82
  40. package/src/library/useExportResource.ts +3 -4
  41. package/src/manifest/EditResourceYamlDialog.tsx +1 -2
  42. package/src/manifest/__tests__/ApplyManifestDialog.test.tsx +2 -2
  43. package/src/manifest/__tests__/EditResourceYamlDialog.test.tsx +9 -9
  44. package/styles.css +1 -1
  45. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  46. package/datastore/CollectionRecordsBrowser.d.ts +0 -34
  47. package/datastore/CollectionRecordsBrowser.d.ts.map +0 -1
  48. package/datastore/CollectionRecordsBrowser.js +0 -226
  49. package/datastore/CollectionRecordsBrowser.js.map +0 -1
  50. package/datastore/CollectionSchemaView.d.ts +0 -29
  51. package/datastore/CollectionSchemaView.d.ts.map +0 -1
  52. package/datastore/CollectionSchemaView.js +0 -93
  53. package/datastore/CollectionSchemaView.js.map +0 -1
  54. package/datastore/DatastoreDetailView.d.ts +0 -44
  55. package/datastore/DatastoreDetailView.d.ts.map +0 -1
  56. package/datastore/DatastoreDetailView.js +0 -76
  57. package/datastore/DatastoreDetailView.js.map +0 -1
  58. package/datastore/DatastoreSyncReport.d.ts +0 -19
  59. package/datastore/DatastoreSyncReport.d.ts.map +0 -1
  60. package/datastore/DatastoreSyncReport.js +0 -45
  61. package/datastore/DatastoreSyncReport.js.map +0 -1
  62. package/datastore/DeleteDatastoreDialog.d.ts +0 -35
  63. package/datastore/DeleteDatastoreDialog.d.ts.map +0 -1
  64. package/datastore/DeleteDatastoreDialog.js +0 -90
  65. package/datastore/DeleteDatastoreDialog.js.map +0 -1
  66. package/datastore/FieldValueControl.d.ts +0 -55
  67. package/datastore/FieldValueControl.d.ts.map +0 -1
  68. package/datastore/FieldValueControl.js +0 -138
  69. package/datastore/FieldValueControl.js.map +0 -1
  70. package/datastore/RecordFilterBuilder.d.ts +0 -37
  71. package/datastore/RecordFilterBuilder.d.ts.map +0 -1
  72. package/datastore/RecordFilterBuilder.js +0 -122
  73. package/datastore/RecordFilterBuilder.js.map +0 -1
  74. package/datastore/RecordFormPanel.d.ts +0 -45
  75. package/datastore/RecordFormPanel.d.ts.map +0 -1
  76. package/datastore/RecordFormPanel.js +0 -215
  77. package/datastore/RecordFormPanel.js.map +0 -1
  78. package/datastore/index.d.ts +0 -43
  79. package/datastore/index.d.ts.map +0 -1
  80. package/datastore/index.js +0 -22
  81. package/datastore/index.js.map +0 -1
  82. package/datastore/recordFilter.d.ts +0 -62
  83. package/datastore/recordFilter.d.ts.map +0 -1
  84. package/datastore/recordFilter.js +0 -104
  85. package/datastore/recordFilter.js.map +0 -1
  86. package/datastore/recordValues.d.ts +0 -85
  87. package/datastore/recordValues.d.ts.map +0 -1
  88. package/datastore/recordValues.js +0 -282
  89. package/datastore/recordValues.js.map +0 -1
  90. package/datastore/useDatastore.d.ts +0 -39
  91. package/datastore/useDatastore.d.ts.map +0 -1
  92. package/datastore/useDatastore.js +0 -44
  93. package/datastore/useDatastore.js.map +0 -1
  94. package/datastore/useDatastoreCount.d.ts +0 -50
  95. package/datastore/useDatastoreCount.d.ts.map +0 -1
  96. package/datastore/useDatastoreCount.js +0 -27
  97. package/datastore/useDatastoreCount.js.map +0 -1
  98. package/datastore/useDatastoreDescription.d.ts +0 -54
  99. package/datastore/useDatastoreDescription.d.ts.map +0 -1
  100. package/datastore/useDatastoreDescription.js +0 -50
  101. package/datastore/useDatastoreDescription.js.map +0 -1
  102. package/datastore/useDatastoreList.d.ts +0 -57
  103. package/datastore/useDatastoreList.d.ts.map +0 -1
  104. package/datastore/useDatastoreList.js +0 -29
  105. package/datastore/useDatastoreList.js.map +0 -1
  106. package/datastore/useDatastoreSearch.d.ts +0 -19
  107. package/datastore/useDatastoreSearch.d.ts.map +0 -1
  108. package/datastore/useDatastoreSearch.js +0 -22
  109. package/datastore/useDatastoreSearch.js.map +0 -1
  110. package/datastore/useDeleteDatastore.d.ts +0 -53
  111. package/datastore/useDeleteDatastore.d.ts.map +0 -1
  112. package/datastore/useDeleteDatastore.js +0 -40
  113. package/datastore/useDeleteDatastore.js.map +0 -1
  114. package/datastore/useDeleteRecord.d.ts +0 -34
  115. package/datastore/useDeleteRecord.d.ts.map +0 -1
  116. package/datastore/useDeleteRecord.js +0 -43
  117. package/datastore/useDeleteRecord.js.map +0 -1
  118. package/datastore/useInsertRecord.d.ts +0 -50
  119. package/datastore/useInsertRecord.d.ts.map +0 -1
  120. package/datastore/useInsertRecord.js +0 -55
  121. package/datastore/useInsertRecord.js.map +0 -1
  122. package/datastore/useRecordCollection.d.ts +0 -104
  123. package/datastore/useRecordCollection.d.ts.map +0 -1
  124. package/datastore/useRecordCollection.js +0 -136
  125. package/datastore/useRecordCollection.js.map +0 -1
  126. package/datastore/useRecordList.d.ts +0 -66
  127. package/datastore/useRecordList.d.ts.map +0 -1
  128. package/datastore/useRecordList.js +0 -58
  129. package/datastore/useRecordList.js.map +0 -1
  130. package/datastore/useUpdateRecord.d.ts +0 -52
  131. package/datastore/useUpdateRecord.d.ts.map +0 -1
  132. package/datastore/useUpdateRecord.js +0 -55
  133. package/datastore/useUpdateRecord.js.map +0 -1
  134. package/src/agent/__tests__/AgentDetailView.datastores.test.tsx +0 -166
  135. package/src/datastore/CollectionRecordsBrowser.tsx +0 -571
  136. package/src/datastore/CollectionSchemaView.tsx +0 -247
  137. package/src/datastore/DatastoreDetailView.tsx +0 -201
  138. package/src/datastore/DatastoreSyncReport.tsx +0 -105
  139. package/src/datastore/DeleteDatastoreDialog.tsx +0 -202
  140. package/src/datastore/FieldValueControl.tsx +0 -289
  141. package/src/datastore/RecordFilterBuilder.tsx +0 -422
  142. package/src/datastore/RecordFormPanel.tsx +0 -432
  143. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +0 -245
  144. package/src/datastore/__tests__/DeleteDatastoreDialog.test.tsx +0 -133
  145. package/src/datastore/__tests__/FieldValueControl.test.tsx +0 -160
  146. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +0 -155
  147. package/src/datastore/__tests__/RecordFormPanel.test.tsx +0 -227
  148. package/src/datastore/__tests__/recordFilter.test.ts +0 -169
  149. package/src/datastore/__tests__/recordMutations.test.tsx +0 -195
  150. package/src/datastore/__tests__/recordValues.test.ts +0 -359
  151. package/src/datastore/__tests__/schemaAndSyncViews.test.tsx +0 -142
  152. package/src/datastore/__tests__/useDatastoreDescription.test.tsx +0 -143
  153. package/src/datastore/__tests__/useRecordCollection.test.tsx +0 -250
  154. package/src/datastore/__tests__/useRecordList.test.tsx +0 -85
  155. package/src/datastore/index.ts +0 -111
  156. package/src/datastore/recordFilter.ts +0 -154
  157. package/src/datastore/recordValues.ts +0 -327
  158. package/src/datastore/useDatastore.ts +0 -67
  159. package/src/datastore/useDatastoreCount.ts +0 -69
  160. package/src/datastore/useDatastoreDescription.ts +0 -90
  161. package/src/datastore/useDatastoreList.ts +0 -79
  162. package/src/datastore/useDatastoreSearch.ts +0 -39
  163. package/src/datastore/useDeleteDatastore.ts +0 -87
  164. package/src/datastore/useDeleteRecord.ts +0 -77
  165. package/src/datastore/useInsertRecord.ts +0 -92
  166. package/src/datastore/useRecordCollection.ts +0 -256
  167. package/src/datastore/useRecordList.ts +0 -131
  168. 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
- });