@decocms/bindings 1.0.1-alpha.19 → 1.0.1-alpha.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/bindings",
3
- "version": "1.0.1-alpha.19",
3
+ "version": "1.0.1-alpha.21",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "check": "tsc --noEmit",
package/src/index.ts CHANGED
@@ -25,6 +25,8 @@ export {
25
25
  export {
26
26
  CloudEventSchema,
27
27
  type CloudEvent,
28
+ EventResultSchema,
29
+ type EventResult,
28
30
  OnEventsInputSchema,
29
31
  type OnEventsInput,
30
32
  OnEventsOutputSchema,
@@ -56,6 +58,14 @@ export {
56
58
  type EventAckInput,
57
59
  EventAckOutputSchema,
58
60
  type EventAckOutput,
61
+ SubscriptionItemSchema,
62
+ type SubscriptionItem,
63
+ SubscriptionDetailSchema,
64
+ type SubscriptionDetail,
65
+ EventSyncSubscriptionsInputSchema,
66
+ type EventSyncSubscriptionsInput,
67
+ EventSyncSubscriptionsOutputSchema,
68
+ type EventSyncSubscriptionsOutput,
59
69
  EVENT_BUS_BINDING,
60
70
  EventBusBinding,
61
71
  type EventBusBindingClient,
@@ -45,22 +45,30 @@ const ComparisonExpressionSchema = z.object({
45
45
  });
46
46
 
47
47
  /**
48
- * Where expression schema for filtering
49
- * Supports TanStack DB predicate push-down patterns
48
+ * Where expression type for filtering
49
+ * Recursive to allow nested logical operators
50
50
  */
51
- export const WhereExpressionSchema = z.union([
52
- ComparisonExpressionSchema,
53
- z.object({
54
- operator: z.enum(["and", "or", "not"]),
55
- conditions: z.array(ComparisonExpressionSchema),
56
- }),
57
- ]);
51
+ export type WhereExpression =
52
+ | z.infer<typeof ComparisonExpressionSchema>
53
+ | {
54
+ operator: "and" | "or" | "not";
55
+ conditions: WhereExpression[];
56
+ };
58
57
 
59
58
  /**
60
- * Where expression type for filtering
61
- * Derived from WhereExpressionSchema
59
+ * Where expression schema for filtering
60
+ * Supports TanStack DB predicate push-down patterns
61
+ * Recursive to allow nested logical operators
62
62
  */
63
- export type WhereExpression = z.infer<typeof WhereExpressionSchema>;
63
+ export const WhereExpressionSchema: z.ZodType<WhereExpression> = z.lazy(() =>
64
+ z.union([
65
+ ComparisonExpressionSchema,
66
+ z.object({
67
+ operator: z.enum(["and", "or", "not"]),
68
+ conditions: z.array(WhereExpressionSchema),
69
+ }),
70
+ ]),
71
+ );
64
72
 
65
73
  /**
66
74
  * Order by expression for sorting
@@ -159,6 +159,119 @@ export const EventSubscribeOutputSchema = z.object({
159
159
 
160
160
  export type EventSubscribeOutput = z.infer<typeof EventSubscribeOutputSchema>;
161
161
 
162
+ // ============================================================================
163
+ // Sync Subscriptions Schemas
164
+ // ============================================================================
165
+
166
+ /**
167
+ * Subscription item schema for sync operations
168
+ */
169
+ export const SubscriptionItemSchema = z.object({
170
+ /** Event type pattern to match */
171
+ eventType: z.string().min(1).max(255).describe("Event type to subscribe to"),
172
+
173
+ /** Optional: Only receive events from this publisher connection */
174
+ publisher: z
175
+ .string()
176
+ .optional()
177
+ .describe("Filter events by publisher connection ID"),
178
+
179
+ /** Optional: JSONPath filter expression on event data */
180
+ filter: z
181
+ .string()
182
+ .max(1000)
183
+ .optional()
184
+ .describe("JSONPath filter expression on event data"),
185
+ });
186
+
187
+ export type SubscriptionItem = z.infer<typeof SubscriptionItemSchema>;
188
+
189
+ /**
190
+ * Subscription detail schema (returned in responses)
191
+ */
192
+ export const SubscriptionDetailSchema = z.object({
193
+ /** Subscription ID */
194
+ id: z.string().describe("Subscription ID"),
195
+
196
+ /** Subscriber connection ID */
197
+ connectionId: z.string().describe("Subscriber connection ID"),
198
+
199
+ /** Event type pattern */
200
+ eventType: z.string().describe("Event type pattern"),
201
+
202
+ /** Publisher connection filter */
203
+ publisher: z.string().nullable().describe("Publisher connection filter"),
204
+
205
+ /** JSONPath filter */
206
+ filter: z.string().nullable().describe("JSONPath filter expression"),
207
+
208
+ /** Whether subscription is enabled */
209
+ enabled: z.boolean().describe("Whether subscription is enabled"),
210
+
211
+ /** Created timestamp */
212
+ createdAt: z.union([z.string(), z.date()]).describe("Created timestamp"),
213
+
214
+ /** Updated timestamp */
215
+ updatedAt: z.union([z.string(), z.date()]).describe("Updated timestamp"),
216
+ });
217
+
218
+ export type SubscriptionDetail = z.infer<typeof SubscriptionDetailSchema>;
219
+
220
+ /**
221
+ * EVENT_SYNC_SUBSCRIPTIONS Input Schema
222
+ *
223
+ * Input for syncing subscriptions to a desired state.
224
+ * The system will create new, delete removed, and update changed subscriptions.
225
+ * Subscriptions are identified by (eventType, publisher) - only one subscription
226
+ * per combination is allowed.
227
+ */
228
+ export const EventSyncSubscriptionsInputSchema = z.object({
229
+ /** Desired subscriptions - system will create/update/delete to match */
230
+ subscriptions: z
231
+ .array(SubscriptionItemSchema)
232
+ .describe(
233
+ "Desired subscriptions - system will create/update/delete to match",
234
+ ),
235
+ });
236
+
237
+ export type EventSyncSubscriptionsInput = z.infer<
238
+ typeof EventSyncSubscriptionsInputSchema
239
+ >;
240
+
241
+ /**
242
+ * EVENT_SYNC_SUBSCRIPTIONS Output Schema
243
+ */
244
+ export const EventSyncSubscriptionsOutputSchema = z.object({
245
+ /** Number of new subscriptions created */
246
+ created: z.number().int().min(0).describe("Number of subscriptions created"),
247
+
248
+ /** Number of subscriptions with filter updated */
249
+ updated: z
250
+ .number()
251
+ .int()
252
+ .min(0)
253
+ .describe("Number of subscriptions with filter updated"),
254
+
255
+ /** Number of old subscriptions removed */
256
+ deleted: z.number().int().min(0).describe("Number of subscriptions removed"),
257
+
258
+ /** Number of subscriptions unchanged */
259
+ unchanged: z
260
+ .number()
261
+ .int()
262
+ .min(0)
263
+ .describe("Number of subscriptions unchanged"),
264
+
265
+ /** Current subscriptions after sync */
266
+ subscriptions: z
267
+ .array(SubscriptionDetailSchema)
268
+ .describe("Current subscriptions after sync"),
269
+ });
270
+
271
+ export type EventSyncSubscriptionsOutput = z.infer<
272
+ typeof EventSyncSubscriptionsOutputSchema
273
+ >;
274
+
162
275
  // ============================================================================
163
276
  // Unsubscribe Schemas
164
277
  // ============================================================================
@@ -259,7 +372,7 @@ export type EventAckOutput = z.infer<typeof EventAckOutputSchema>;
259
372
  * Event Bus Binding
260
373
  *
261
374
  * Defines the interface for interacting with an event bus.
262
- * Implementations must provide PUBLISH, SUBSCRIBE, UNSUBSCRIBE, CANCEL, and ACK tools.
375
+ * Implementations must provide PUBLISH, SUBSCRIBE, UNSUBSCRIBE, CANCEL, ACK, and SYNC_SUBSCRIPTIONS tools.
263
376
  *
264
377
  * Required tools:
265
378
  * - EVENT_PUBLISH: Publish an event (supports one-time, scheduled, and recurring via cron)
@@ -267,6 +380,7 @@ export type EventAckOutput = z.infer<typeof EventAckOutputSchema>;
267
380
  * - EVENT_UNSUBSCRIBE: Remove a subscription
268
381
  * - EVENT_CANCEL: Cancel a recurring event (stops future deliveries)
269
382
  * - EVENT_ACK: Acknowledge event delivery (for async processing with retryAfter)
383
+ * - EVENT_SYNC_SUBSCRIPTIONS: Sync subscriptions to desired state
270
384
  */
271
385
  export const EVENT_BUS_BINDING = [
272
386
  {
@@ -294,6 +408,11 @@ export const EVENT_BUS_BINDING = [
294
408
  inputSchema: EventAckInputSchema,
295
409
  outputSchema: EventAckOutputSchema,
296
410
  },
411
+ {
412
+ name: "EVENT_SYNC_SUBSCRIPTIONS" as const,
413
+ inputSchema: EventSyncSubscriptionsInputSchema,
414
+ outputSchema: EventSyncSubscriptionsOutputSchema,
415
+ },
297
416
  ] satisfies ToolBinder[];
298
417
 
299
418
  /**
@@ -104,24 +104,81 @@ export const OnEventsInputSchema = z.object({
104
104
  */
105
105
  export type OnEventsInput = z.infer<typeof OnEventsInputSchema>;
106
106
 
107
+ /**
108
+ * Per-event result schema
109
+ * Allows granular control over each event in a batch
110
+ *
111
+ * Three modes:
112
+ * - `{ success: true }` - Event processed successfully
113
+ * - `{ success: false, error: "..." }` - Event failed permanently
114
+ * - `{ retryAfter: 60000 }` - Retry later (success not yet determined)
115
+ */
116
+ export const EventResultSchema = z.object({
117
+ /** Whether this specific event was processed successfully */
118
+ success: z
119
+ .boolean()
120
+ .optional()
121
+ .describe("Whether this event was processed successfully"),
122
+
123
+ /** Error message if success=false */
124
+ error: z.string().optional().describe("Error message for this event"),
125
+
126
+ /**
127
+ * Request re-delivery of this event after this many milliseconds.
128
+ * Does not count toward max retry attempts.
129
+ * When present without success, indicates the event should be retried.
130
+ */
131
+ retryAfter: z
132
+ .number()
133
+ .int()
134
+ .positive()
135
+ .optional()
136
+ .describe("Re-deliver this event after this many ms"),
137
+ });
138
+
139
+ /**
140
+ * Per-event result type
141
+ */
142
+ export type EventResult = z.infer<typeof EventResultSchema>;
143
+
107
144
  /**
108
145
  * ON_EVENTS Output Schema
109
146
  *
110
- * Returns success status. If success=true, all events in the batch
111
- * are considered delivered and will be marked as such by the event bus.
147
+ * Two modes of operation:
148
+ *
149
+ * 1. **Batch mode** (backward compatible): Use `success`, `error`, `retryAfter`
150
+ * to apply the same result to all events in the batch.
112
151
  *
113
- * Alternatively, return retryAfter (ms) to request re-delivery after a delay.
114
- * Events with retryAfter stay pending until explicitly ACKed via EVENT_ACK.
115
- * This enables async processing patterns where the subscriber needs time to process.
152
+ * 2. **Per-event mode**: Use `results` to specify individual outcomes for each event.
153
+ * Keys are event IDs, values are per-event results.
154
+ * Events not in `results` will use the batch-level fields as fallback.
155
+ *
156
+ * @example
157
+ * // Batch mode - all events succeeded
158
+ * { success: true }
159
+ *
160
+ * @example
161
+ * // Per-event mode - mixed results
162
+ * {
163
+ * results: {
164
+ * "event-1": { success: true },
165
+ * "event-2": { success: false, error: "Validation failed" },
166
+ * "event-3": { retryAfter: 60000 }
167
+ * }
168
+ * }
116
169
  */
117
170
  export const OnEventsOutputSchema = z.object({
118
- /** Whether all events were successfully processed */
171
+ /** Batch-level success (applies to events not in `results`) */
119
172
  success: z
120
173
  .boolean()
121
- .describe("True if all events were successfully processed"),
174
+ .optional()
175
+ .describe("Batch success - applies to events not in results"),
122
176
 
123
- /** Optional error message if success=false */
124
- error: z.string().optional().describe("Error message if processing failed"),
177
+ /** Batch-level error message */
178
+ error: z
179
+ .string()
180
+ .optional()
181
+ .describe("Batch error message - applies to events not in results"),
125
182
 
126
183
  /** Optional count of successfully processed events */
127
184
  processedCount: z
@@ -132,18 +189,24 @@ export const OnEventsOutputSchema = z.object({
132
189
  .describe("Number of events successfully processed"),
133
190
 
134
191
  /**
135
- * Request re-delivery after this many milliseconds.
136
- * Events remain pending until explicitly ACKed via EVENT_ACK.
137
- * Does not count toward max retry attempts.
192
+ * Batch-level re-delivery request (applies to events not in `results`)
138
193
  */
139
194
  retryAfter: z
140
195
  .number()
141
196
  .int()
142
197
  .positive()
143
198
  .optional()
144
- .describe(
145
- "Request re-delivery after this many ms. Call EVENT_ACK to mark delivered.",
146
- ),
199
+ .describe("Batch retryAfter - applies to events not in results"),
200
+
201
+ /**
202
+ * Per-event results, keyed by event ID.
203
+ * Allows different handling for each event in the batch.
204
+ * Events not specified here use batch-level fields as fallback.
205
+ */
206
+ results: z
207
+ .record(z.string(), EventResultSchema)
208
+ .optional()
209
+ .describe("Per-event results keyed by event ID"),
147
210
  });
148
211
 
149
212
  /**