@checkstack/catalog-common 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # @checkstack/catalog-common
2
2
 
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7a23261: ## TanStack Query Integration
8
+
9
+ Migrated all frontend components to use `usePluginClient` hook with TanStack Query integration, replacing the legacy `forPlugin()` pattern.
10
+
11
+ ### New Features
12
+
13
+ - **`usePluginClient` hook**: Provides type-safe access to plugin APIs with `.useQuery()` and `.useMutation()` methods
14
+ - **Automatic request deduplication**: Multiple components requesting the same data share a single network request
15
+ - **Built-in caching**: Configurable stale time and cache duration per query
16
+ - **Loading/error states**: TanStack Query provides `isLoading`, `error`, `isRefetching` states automatically
17
+ - **Background refetching**: Stale data is automatically refreshed when components mount
18
+
19
+ ### Contract Changes
20
+
21
+ All RPC contracts now require `operationType: "query"` or `operationType: "mutation"` metadata:
22
+
23
+ ```typescript
24
+ const getItems = proc()
25
+ .meta({ operationType: "query", access: [access.read] })
26
+ .output(z.array(itemSchema))
27
+ .query();
28
+
29
+ const createItem = proc()
30
+ .meta({ operationType: "mutation", access: [access.manage] })
31
+ .input(createItemSchema)
32
+ .output(itemSchema)
33
+ .mutation();
34
+ ```
35
+
36
+ ### Migration
37
+
38
+ ```typescript
39
+ // Before (forPlugin pattern)
40
+ const api = useApi(myPluginApiRef);
41
+ const [items, setItems] = useState<Item[]>([]);
42
+ useEffect(() => {
43
+ api.getItems().then(setItems);
44
+ }, [api]);
45
+
46
+ // After (usePluginClient pattern)
47
+ const client = usePluginClient(MyPluginApi);
48
+ const { data: items, isLoading } = client.getItems.useQuery({});
49
+ ```
50
+
51
+ ### Bug Fixes
52
+
53
+ - Fixed `rpc.test.ts` test setup for middleware type inference
54
+ - Fixed `SearchDialog` to use `setQuery` instead of deprecated `search` method
55
+ - Fixed null→undefined warnings in notification and queue frontends
56
+
57
+ ### Patch Changes
58
+
59
+ - Updated dependencies [7a23261]
60
+ - @checkstack/frontend-api@0.2.0
61
+ - @checkstack/common@0.3.0
62
+
3
63
  ## 1.1.0
4
64
 
5
65
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/catalog-common",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,16 +1,9 @@
1
- import { oc } from "@orpc/contract";
2
- import {
3
- createClientDefinition,
4
- type ProcedureMetadata,
5
- } from "@checkstack/common";
1
+ import { createClientDefinition, proc } from "@checkstack/common";
6
2
  import { pluginMetadata } from "./plugin-metadata";
7
3
  import { z } from "zod";
8
4
  import { SystemSchema, GroupSchema, ViewSchema } from "./types";
9
5
  import { catalogAccess } from "./access";
10
6
 
11
- // Base builder with full metadata support
12
- const _base = oc.$meta<ProcedureMetadata>({});
13
-
14
7
  // Input schemas that match the service layer expectations
15
8
  const CreateSystemInputSchema = z.object({
16
9
  name: z.string(),
@@ -23,9 +16,9 @@ const UpdateSystemInputSchema = z.object({
23
16
  id: z.string(),
24
17
  data: z.object({
25
18
  name: z.string().optional(),
26
- description: z.string().nullable().optional(), // Allow nullable for updates
19
+ description: z.string().nullable().optional(),
27
20
  owner: z.string().nullable().optional(),
28
- metadata: z.record(z.string(), z.unknown()).nullable().optional(), // Allow nullable
21
+ metadata: z.record(z.string(), z.unknown()).nullable().optional(),
29
22
  }),
30
23
  });
31
24
 
@@ -38,7 +31,7 @@ const UpdateGroupInputSchema = z.object({
38
31
  id: z.string(),
39
32
  data: z.object({
40
33
  name: z.string().optional(),
41
- metadata: z.record(z.string(), z.unknown()).nullable().optional(), // Allow nullable
34
+ metadata: z.record(z.string(), z.unknown()).nullable().optional(),
42
35
  }),
43
36
  });
44
37
 
@@ -54,62 +47,62 @@ export const catalogContract = {
54
47
  // ENTITY READ ENDPOINTS (userType: "public" - accessible by anyone with access)
55
48
  // ==========================================================================
56
49
 
57
- getEntities: _base
58
- .meta({
59
- userType: "public",
60
- access: [catalogAccess.system.read],
61
- })
62
- .output(
63
- z.object({
64
- systems: z.array(SystemSchema),
65
- groups: z.array(GroupSchema),
66
- })
67
- ),
68
-
69
- getSystems: _base
70
- .meta({
71
- userType: "public",
72
- access: [catalogAccess.system.read],
73
- })
74
- .output(z.object({ systems: z.array(SystemSchema) })),
75
-
76
- getSystem: _base
77
- .meta({
78
- userType: "public",
79
- access: [catalogAccess.system.read],
50
+ getEntities: proc({
51
+ operationType: "query",
52
+ userType: "public",
53
+ access: [catalogAccess.system.read],
54
+ }).output(
55
+ z.object({
56
+ systems: z.array(SystemSchema),
57
+ groups: z.array(GroupSchema),
80
58
  })
59
+ ),
60
+
61
+ getSystems: proc({
62
+ operationType: "query",
63
+ userType: "public",
64
+ access: [catalogAccess.system.read],
65
+ }).output(z.object({ systems: z.array(SystemSchema) })),
66
+
67
+ getSystem: proc({
68
+ operationType: "query",
69
+ userType: "public",
70
+ access: [catalogAccess.system.read],
71
+ })
81
72
  .input(z.object({ systemId: z.string() }))
82
73
  .output(SystemSchema.nullable()),
83
74
 
84
- getGroups: _base
85
- .meta({ userType: "public", access: [catalogAccess.group.read] })
86
- .output(z.array(GroupSchema)),
75
+ getGroups: proc({
76
+ operationType: "query",
77
+ userType: "public",
78
+ access: [catalogAccess.group.read],
79
+ }).output(z.array(GroupSchema)),
87
80
 
88
81
  // ==========================================================================
89
82
  // SYSTEM MANAGEMENT (userType: "authenticated" with manage access)
90
83
  // ==========================================================================
91
84
 
92
- createSystem: _base
93
- .meta({
94
- userType: "authenticated",
95
- access: [catalogAccess.system.manage],
96
- })
85
+ createSystem: proc({
86
+ operationType: "mutation",
87
+ userType: "authenticated",
88
+ access: [catalogAccess.system.manage],
89
+ })
97
90
  .input(CreateSystemInputSchema)
98
91
  .output(SystemSchema),
99
92
 
100
- updateSystem: _base
101
- .meta({
102
- userType: "authenticated",
103
- access: [catalogAccess.system.manage],
104
- })
93
+ updateSystem: proc({
94
+ operationType: "mutation",
95
+ userType: "authenticated",
96
+ access: [catalogAccess.system.manage],
97
+ })
105
98
  .input(UpdateSystemInputSchema)
106
99
  .output(SystemSchema),
107
100
 
108
- deleteSystem: _base
109
- .meta({
110
- userType: "authenticated",
111
- access: [catalogAccess.system.manage],
112
- })
101
+ deleteSystem: proc({
102
+ operationType: "mutation",
103
+ userType: "authenticated",
104
+ access: [catalogAccess.system.manage],
105
+ })
113
106
  .input(z.string())
114
107
  .output(z.object({ success: z.boolean() })),
115
108
 
@@ -117,27 +110,27 @@ export const catalogContract = {
117
110
  // GROUP MANAGEMENT (userType: "authenticated" with manage access)
118
111
  // ==========================================================================
119
112
 
120
- createGroup: _base
121
- .meta({
122
- userType: "authenticated",
123
- access: [catalogAccess.group.manage],
124
- })
113
+ createGroup: proc({
114
+ operationType: "mutation",
115
+ userType: "authenticated",
116
+ access: [catalogAccess.group.manage],
117
+ })
125
118
  .input(CreateGroupInputSchema)
126
119
  .output(GroupSchema),
127
120
 
128
- updateGroup: _base
129
- .meta({
130
- userType: "authenticated",
131
- access: [catalogAccess.group.manage],
132
- })
121
+ updateGroup: proc({
122
+ operationType: "mutation",
123
+ userType: "authenticated",
124
+ access: [catalogAccess.group.manage],
125
+ })
133
126
  .input(UpdateGroupInputSchema)
134
127
  .output(GroupSchema),
135
128
 
136
- deleteGroup: _base
137
- .meta({
138
- userType: "authenticated",
139
- access: [catalogAccess.group.manage],
140
- })
129
+ deleteGroup: proc({
130
+ operationType: "mutation",
131
+ userType: "authenticated",
132
+ access: [catalogAccess.group.manage],
133
+ })
141
134
  .input(z.string())
142
135
  .output(z.object({ success: z.boolean() })),
143
136
 
@@ -145,11 +138,11 @@ export const catalogContract = {
145
138
  // SYSTEM-GROUP RELATIONSHIPS (userType: "authenticated" with manage access)
146
139
  // ==========================================================================
147
140
 
148
- addSystemToGroup: _base
149
- .meta({
150
- userType: "authenticated",
151
- access: [catalogAccess.system.manage],
152
- })
141
+ addSystemToGroup: proc({
142
+ operationType: "mutation",
143
+ userType: "authenticated",
144
+ access: [catalogAccess.system.manage],
145
+ })
153
146
  .input(
154
147
  z.object({
155
148
  groupId: z.string(),
@@ -158,11 +151,11 @@ export const catalogContract = {
158
151
  )
159
152
  .output(z.object({ success: z.boolean() })),
160
153
 
161
- removeSystemFromGroup: _base
162
- .meta({
163
- userType: "authenticated",
164
- access: [catalogAccess.system.manage],
165
- })
154
+ removeSystemFromGroup: proc({
155
+ operationType: "mutation",
156
+ userType: "authenticated",
157
+ access: [catalogAccess.system.manage],
158
+ })
166
159
  .input(
167
160
  z.object({
168
161
  groupId: z.string(),
@@ -175,12 +168,17 @@ export const catalogContract = {
175
168
  // VIEW MANAGEMENT (userType: "user")
176
169
  // ==========================================================================
177
170
 
178
- getViews: _base
179
- .meta({ userType: "user", access: [catalogAccess.view.read] })
180
- .output(z.array(ViewSchema)),
181
-
182
- createView: _base
183
- .meta({ userType: "user", access: [catalogAccess.view.manage] })
171
+ getViews: proc({
172
+ operationType: "query",
173
+ userType: "user",
174
+ access: [catalogAccess.view.read],
175
+ }).output(z.array(ViewSchema)),
176
+
177
+ createView: proc({
178
+ operationType: "mutation",
179
+ userType: "user",
180
+ access: [catalogAccess.view.manage],
181
+ })
184
182
  .input(CreateViewInputSchema)
185
183
  .output(ViewSchema),
186
184
 
@@ -197,18 +195,19 @@ export const catalogContract = {
197
195
  * deduplicated so users subscribed to both the system AND its groups
198
196
  * receive only one notification.
199
197
  */
200
- notifySystemSubscribers: _base
201
- .meta({ userType: "service" })
198
+ notifySystemSubscribers: proc({
199
+ operationType: "mutation",
200
+ userType: "service",
201
+ access: [], // Service-to-service, no access rules needed
202
+ })
202
203
  .input(
203
204
  z.object({
204
205
  systemId: z
205
206
  .string()
206
207
  .describe("The system ID to notify subscribers for"),
207
208
  title: z.string().describe("Notification title"),
208
- /** Notification body in markdown format */
209
209
  body: z.string().describe("Notification body (supports markdown)"),
210
210
  importance: z.enum(["info", "warning", "critical"]).optional(),
211
- /** Primary action button */
212
211
  action: z
213
212
  .object({
214
213
  label: z.string(),