@bubblelab/shared-schemas 0.1.4 → 0.1.5

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/dist/routes.js DELETED
@@ -1,978 +0,0 @@
1
- /**
2
- * @bubblelab/shared-schemas - API Schema Definitions
3
- *
4
- * This file contains all Zod schemas and TypeScript types for the NodeX API.
5
- *
6
- * IMPORTANT: All new API schemas should be written in this shared package to ensure
7
- * type safety and consistency between frontend and backend applications.
8
- *
9
- * ## Schema Organization
10
- *
11
- * ### Request Schemas (Input Validation)
12
- * - createBubbleFlowSchema - POST /bubble-flow
13
- * - executeBubbleFlowSchema - POST /:id/execute
14
- * - createCredentialSchema - POST /credentials
15
- * - updateBubbleFlowParametersSchema - PUT /bubble-flow/:id
16
- *
17
- * ### Response Schemas (Output Types)
18
- * - createBubbleFlowResponseSchema - POST /bubble-flow response
19
- * - executeBubbleFlowResponseSchema - POST /:id/execute response
20
- * - credentialResponseSchema - GET /credentials response
21
- * - createCredentialResponseSchema - POST /credentials response
22
- * - bubbleFlowDetailsResponseSchema - GET /bubble-flow/:id response
23
- * - listBubbleFlowsResponseSchema - GET /bubble-flow response
24
- * - webhookResponseSchema - POST /webhook/{userId}/{path} response
25
- * - errorResponseSchema - Error responses
26
- * - successMessageResponseSchema - Success responses
27
- *
28
- * ### TypeScript Types
29
- * All schemas have corresponding TypeScript types exported for use in both
30
- * frontend and backend applications.
31
- *
32
- * ## Usage Examples
33
- *
34
- * ### Backend (Validation)
35
- * ```typescript
36
- * import { createBubbleFlowSchema } from '@bubblelab/shared-schemas';
37
- *
38
- * // Validate request body
39
- * const validatedData = createBubbleFlowSchema.parse(requestBody);
40
- * ```
41
- *
42
- * ### Frontend (Type Safety)
43
- * ```typescript
44
- * import type { CreateBubbleFlowRequest, CreateBubbleFlowResponse } from '@bubblelab/shared-schemas';
45
- *
46
- * const createBubbleFlow = async (data: CreateBubbleFlowRequest): Promise<CreateBubbleFlowResponse> => {
47
- * // API call with full type safety
48
- * };
49
- * ```
50
- *
51
- * ## Adding New Schemas
52
- *
53
- * 1. Define the Zod schema with proper OpenAPI metadata
54
- * 2. Export the schema for validation
55
- * 3. Export the TypeScript type using `z.infer<typeof schemaName>`
56
- * 4. Update this documentation
57
- * 5. Rebuild the package: `pnpm build:core`
58
- */
59
- import { z } from 'zod';
60
- import { databaseMetadataSchema } from './database-definition-schema';
61
- import { CredentialType } from './types';
62
- import { BubbleParameterType, ParsedBubbleSchema, ParsedBubbleWithInfoSchema, } from './bubble-definition-schema';
63
- // ============================================================================
64
- // BUBBLEFLOW PARSING TYPES (Backend/Frontend Shared)
65
- // ============================================================================
66
- // ============================================================================
67
- // REQUEST SCHEMAS (Input Validation)
68
- // ============================================================================
69
- // POST /bubble-flow - Create new BubbleFlow schema
70
- export const createBubbleFlowSchema = z
71
- .object({
72
- name: z.string().min(1).max(100).openapi({
73
- description: 'Name of the BubbleFlow',
74
- example: 'My First BubbleFlow',
75
- }),
76
- description: z.string().optional().openapi({
77
- description: 'Optional description of what this BubbleFlow does',
78
- example: 'A flow that processes webhook data',
79
- }),
80
- prompt: z.string().optional().openapi({
81
- description: 'Optional prompt used to generate the flow',
82
- example: 'Create a flow that processes webhook data and sends notifications',
83
- }),
84
- code: z.string().min(1).openapi({
85
- description: 'TypeScript code that defines the BubbleFlow class',
86
- example: 'export class MyFlow extends BubbleFlow { ... }',
87
- }),
88
- eventType: z.string().min(1).openapi({
89
- description: 'Event type this BubbleFlow responds to',
90
- example: 'webhook/http',
91
- }),
92
- webhookPath: z
93
- .string()
94
- .min(1)
95
- .max(50)
96
- .regex(/^[a-zA-Z0-9-_]+$/)
97
- .optional()
98
- .openapi({
99
- description: 'Custom webhook path (auto-generated if not provided)',
100
- example: 'my-webhook',
101
- }),
102
- webhookActive: z.boolean().default(false).optional().openapi({
103
- description: 'Whether the webhook should be active immediately',
104
- example: true,
105
- }),
106
- })
107
- .openapi('CreateBubbleFlowRequest');
108
- // POST /:id/execute - Execute BubbleFlow schema
109
- export const executeBubbleFlowSchema = z
110
- .record(z.string(), z.unknown())
111
- .openapi('ExecuteBubbleFlowRequest');
112
- // POST /credentials - Create credential schema
113
- export const createCredentialSchema = z
114
- .object({
115
- credentialType: z.nativeEnum(CredentialType).openapi({
116
- description: 'Type of credential to store',
117
- example: CredentialType.OPENAI_CRED,
118
- }),
119
- value: z.string().min(1).openapi({
120
- description: 'The credential value (will be encrypted)',
121
- example: 'sk-1234567890abcdef',
122
- }),
123
- name: z.string().optional().openapi({
124
- description: 'Optional user-friendly name for the credential',
125
- example: 'My OpenAI Key',
126
- }),
127
- skipValidation: z.boolean().optional().openapi({
128
- description: 'Skip credential validation before storing (for testing/admin use)',
129
- example: false,
130
- }),
131
- credentialConfigurations: z
132
- .record(z.string(), z.unknown())
133
- .optional()
134
- .openapi({
135
- description: 'Optional configurations for credential validation (e.g., ignoreSSL for PostgreSQL)',
136
- example: { ignoreSSL: true },
137
- }),
138
- metadata: databaseMetadataSchema.optional().openapi({
139
- description: 'Optional metadata for the credential (e.g., database schema for DATABASE_CRED)',
140
- example: {
141
- tables: {
142
- users: {
143
- id: 'integer',
144
- email: 'character varying',
145
- created_at: 'timestamp with time zone',
146
- },
147
- },
148
- rules: [
149
- {
150
- id: 'rule-1',
151
- text: 'No direct DELETE on users table',
152
- enabled: true,
153
- createdAt: '2024-01-01T00:00:00Z',
154
- updatedAt: '2024-01-01T00:00:00Z',
155
- },
156
- ],
157
- },
158
- }),
159
- })
160
- .openapi('CreateCredentialRequest');
161
- // PUT /credentials/:id - Update credential schema
162
- export const updateCredentialSchema = z
163
- .object({
164
- value: z.string().optional().openapi({
165
- description: 'The credential value (will be encrypted). Leave empty to keep current value.',
166
- example: 'sk-1234567890abcdef',
167
- }),
168
- name: z.string().optional().openapi({
169
- description: 'Optional user-friendly name for the credential',
170
- example: 'My OpenAI Key',
171
- }),
172
- skipValidation: z.boolean().optional().openapi({
173
- description: 'Skip credential validation before storing (for testing/admin use)',
174
- example: false,
175
- }),
176
- credentialConfigurations: z
177
- .record(z.string(), z.unknown())
178
- .optional()
179
- .openapi({
180
- description: 'Optional configurations for credential validation (e.g., ignoreSSL for PostgreSQL)',
181
- example: { ignoreSSL: true },
182
- }),
183
- metadata: databaseMetadataSchema.optional().openapi({
184
- description: 'Optional metadata for the credential (e.g., database schema for DATABASE_CRED)',
185
- example: {
186
- tables: {
187
- users: {
188
- id: 'integer',
189
- email: 'character varying',
190
- created_at: 'timestamp with time zone',
191
- },
192
- },
193
- },
194
- }),
195
- })
196
- .openapi('UpdateCredentialRequest');
197
- // PUT /bubble-flow/:id - Update BubbleFlow parameters schema
198
- export const updateBubbleFlowParametersSchema = z
199
- .object({
200
- bubbleParameters: z.record(z.string(), z.union([ParsedBubbleWithInfoSchema, ParsedBubbleSchema])),
201
- })
202
- .openapi('UpdateBubbleFlowParametersRequest');
203
- // ============================================================================
204
- // RESPONSE SCHEMAS (Output Types)
205
- // ============================================================================
206
- // POST /bubble-flow - Create BubbleFlow response
207
- export const createBubbleFlowResponseSchema = z
208
- .object({
209
- id: z.number().openapi({
210
- description: 'ID of the created BubbleFlow',
211
- example: 123,
212
- }),
213
- message: z.string().openapi({
214
- description: 'Success message',
215
- example: 'BubbleFlow created successfully',
216
- }),
217
- inputSchema: z
218
- .record(z.string(), z.unknown())
219
- .optional()
220
- .openapi({
221
- description: 'Input schema',
222
- example: {
223
- name: 'string',
224
- age: 'number',
225
- },
226
- }),
227
- bubbleParameters: z.record(z.string(), ParsedBubbleWithInfoSchema).openapi({
228
- description: 'Parsed bubble parameters from the BubbleFlow code',
229
- }),
230
- requiredCredentials: z
231
- .record(z.string(), z.array(z.nativeEnum(CredentialType)))
232
- .optional()
233
- .openapi({
234
- description: 'Mapping of bubble names to their required credential types',
235
- example: {
236
- 'database-connection': [CredentialType.DATABASE_CRED],
237
- 'slack-notification': [CredentialType.SLACK_CRED],
238
- 'ai-analysis': [CredentialType.GOOGLE_GEMINI_CRED],
239
- },
240
- }),
241
- webhook: z
242
- .object({
243
- id: z.number().openapi({ description: 'Webhook ID', example: 456 }),
244
- url: z.string().openapi({
245
- description: 'Full webhook URL',
246
- example: 'http://localhost:3001/webhook/user123/my-webhook',
247
- }),
248
- path: z.string().openapi({
249
- description: 'Webhook path',
250
- example: 'my-webhook',
251
- }),
252
- active: z.boolean().openapi({
253
- description: 'Whether webhook is active',
254
- example: true,
255
- }),
256
- })
257
- .optional()
258
- .openapi({
259
- description: 'Webhook information (if webhook was created)',
260
- }),
261
- })
262
- .openapi('CreateBubbleFlowResponse');
263
- // POST /:id/execute - Execute BubbleFlow response
264
- export const executeBubbleFlowResponseSchema = z
265
- .object({
266
- executionId: z.number().openapi({
267
- description: 'ID of the execution record',
268
- example: 789,
269
- }),
270
- success: z.boolean().openapi({
271
- description: 'Whether the execution was successful',
272
- example: true,
273
- }),
274
- data: z
275
- .any()
276
- .optional()
277
- .openapi({
278
- description: 'Data returned by the BubbleFlow (if successful)',
279
- example: { result: 'processed successfully', count: 42 },
280
- }),
281
- error: z.string().optional().openapi({
282
- description: 'Error message (if execution failed)',
283
- example: 'Validation error in BubbleFlow',
284
- }),
285
- })
286
- .openapi('ExecuteBubbleFlowResponse');
287
- // GET /credentials - List credentials response
288
- export const credentialResponseSchema = z
289
- .object({
290
- id: z.number().openapi({ description: 'Credential ID' }),
291
- credentialType: z.string().openapi({ description: 'Type of credential' }),
292
- name: z.string().optional().openapi({ description: 'Credential name' }),
293
- metadata: databaseMetadataSchema
294
- .optional()
295
- .openapi({ description: 'Credential metadata' }),
296
- createdAt: z.string().openapi({ description: 'Creation timestamp' }),
297
- // OAuth-specific fields
298
- isOauth: z
299
- .boolean()
300
- .optional()
301
- .openapi({ description: 'Whether this is an OAuth credential' }),
302
- oauthProvider: z
303
- .string()
304
- .optional()
305
- .openapi({ description: 'OAuth provider name' }),
306
- oauthExpiresAt: z
307
- .string()
308
- .optional()
309
- .openapi({ description: 'OAuth token expiration timestamp' }),
310
- oauthScopes: z
311
- .array(z.string())
312
- .optional()
313
- .openapi({ description: 'OAuth scopes granted' }),
314
- oauthStatus: z
315
- .enum(['active', 'expired', 'needs_refresh'])
316
- .optional()
317
- .openapi({ description: 'OAuth token status' }),
318
- })
319
- .openapi('CredentialResponse');
320
- // POST /credentials - Create credential response
321
- export const createCredentialResponseSchema = z
322
- .object({
323
- id: z.number().openapi({ description: 'Credential ID' }),
324
- message: z.string().openapi({ description: 'Success message' }),
325
- })
326
- .openapi('CreateCredentialResponse');
327
- // PUT /credentials/:id - Update credential response
328
- export const updateCredentialResponseSchema = z
329
- .object({
330
- id: z.number().openapi({ description: 'Credential ID' }),
331
- message: z.string().openapi({ description: 'Success message' }),
332
- })
333
- .openapi('UpdateCredentialResponse');
334
- // General success message response (used by DELETE /credentials/:id, DELETE /bubble-flow/:id, PUT /bubble-flow/:id)
335
- export const successMessageResponseSchema = z
336
- .object({
337
- message: z.string().openapi({ description: 'Success message' }),
338
- })
339
- .openapi('SuccessMessageResponse');
340
- // GET /bubble-flow/:id - Get BubbleFlow details response
341
- export const bubbleFlowDetailsResponseSchema = z
342
- .object({
343
- id: z.number().openapi({ description: 'BubbleFlow ID' }),
344
- name: z.string().openapi({ description: 'BubbleFlow name' }),
345
- description: z.string().optional().openapi({ description: 'Description' }),
346
- prompt: z
347
- .string()
348
- .optional()
349
- .openapi({ description: 'Original prompt used to generate the flow' }),
350
- eventType: z.string().openapi({ description: 'Event type' }),
351
- code: z.string().openapi({ description: 'TypeScript source code' }),
352
- inputSchema: z
353
- .record(z.string(), z.unknown())
354
- .optional()
355
- .openapi({ description: 'Input schema' }),
356
- isActive: z
357
- .boolean()
358
- .openapi({ description: 'Whether the BubbleFlow is active' }),
359
- requiredCredentials: z
360
- .record(z.string(), z.array(z.nativeEnum(CredentialType)))
361
- .openapi({ description: 'Required credentials by bubble' }),
362
- displayedBubbleParameters: z
363
- .record(z.string(), z.object({
364
- variableName: z.string(),
365
- bubbleName: z.string(),
366
- className: z.string(),
367
- parameters: z.array(z.object({
368
- name: z.string(),
369
- value: z.unknown(),
370
- type: z.nativeEnum(BubbleParameterType),
371
- })),
372
- hasAwait: z.boolean(),
373
- hasActionCall: z.boolean(),
374
- }))
375
- .optional()
376
- .openapi({
377
- description: 'Displayed bubble parameters for visualization',
378
- }),
379
- bubbleParameters: z.record(z.string(), ParsedBubbleWithInfoSchema).openapi({
380
- description: 'Bubble parameters',
381
- }),
382
- createdAt: z.string().openapi({ description: 'Creation timestamp' }),
383
- updatedAt: z.string().openapi({ description: 'Update timestamp' }),
384
- webhook_url: z
385
- .string()
386
- .openapi({ description: 'Webhook URL for this bubble flow' }),
387
- })
388
- .openapi('BubbleFlowDetailsResponse');
389
- // Webhook execution response (used internally)
390
- export const webhookExecutionResponseSchema = z
391
- .object({
392
- executionId: z.number().openapi({ description: 'Execution ID' }),
393
- success: z.boolean().openapi({ description: 'Execution success' }),
394
- data: z.unknown().optional().openapi({ description: 'Result data' }),
395
- error: z.string().optional().openapi({ description: 'Error message' }),
396
- webhook: z
397
- .object({
398
- userId: z.string().openapi({ description: 'User ID' }),
399
- path: z.string().openapi({ description: 'Webhook path' }),
400
- triggeredAt: z.string().openapi({ description: 'Trigger timestamp' }),
401
- method: z.string().openapi({ description: 'HTTP method' }),
402
- })
403
- .openapi({ description: 'Webhook info' }),
404
- })
405
- .openapi('WebhookExecutionResponse');
406
- // POST /webhook/{userId}/{path} - Webhook response
407
- export const webhookResponseSchema = z
408
- .object({
409
- // Slack verification fields
410
- challenge: z
411
- .string()
412
- .optional()
413
- .openapi({ description: 'Slack URL verification challenge' }),
414
- // Execution fields
415
- executionId: z.number().optional().openapi({ description: 'Execution ID' }),
416
- success: z
417
- .boolean()
418
- .optional()
419
- .openapi({ description: 'Execution success' }),
420
- data: z
421
- .record(z.string(), z.unknown())
422
- .or(z.undefined())
423
- .optional()
424
- .openapi({ description: 'Result data' }),
425
- error: z.string().optional().openapi({ description: 'Error message' }),
426
- webhook: z
427
- .object({
428
- userId: z.string().openapi({ description: 'User ID' }),
429
- path: z.string().openapi({ description: 'Webhook path' }),
430
- triggeredAt: z.string().openapi({ description: 'Trigger timestamp' }),
431
- method: z.string().openapi({ description: 'HTTP method' }),
432
- })
433
- .optional()
434
- .openapi({ description: 'Webhook info' }),
435
- })
436
- .openapi('WebhookResponse');
437
- // Individual BubbleFlow list item schema
438
- export const bubbleFlowListItemSchema = z.object({
439
- id: z.number().openapi({ description: 'BubbleFlow ID' }),
440
- name: z.string().openapi({ description: 'BubbleFlow name' }),
441
- description: z.string().optional().openapi({ description: 'Description' }),
442
- eventType: z.string().openapi({ description: 'Event type' }),
443
- isActive: z
444
- .boolean()
445
- .openapi({ description: 'Whether the BubbleFlow is active' }),
446
- webhookExecutionCount: z
447
- .number()
448
- .openapi({ description: 'Webhook execution count' }),
449
- webhookFailureCount: z
450
- .number()
451
- .openapi({ description: 'Webhook failure count' }),
452
- createdAt: z.string().openapi({ description: 'Creation timestamp' }),
453
- updatedAt: z.string().openapi({ description: 'Update timestamp' }),
454
- });
455
- // GET /bubble-flow - List BubbleFlows response with user info
456
- export const bubbleFlowListResponseSchema = z.object({
457
- bubbleFlows: z.array(bubbleFlowListItemSchema).default([]),
458
- userMonthlyUsage: z
459
- .object({
460
- count: z.number().openapi({ description: 'Current monthly usage count' }),
461
- })
462
- .openapi({ description: 'User monthly usage information' }),
463
- });
464
- // Validation schemas
465
- export const validateBubbleFlowCodeSchema = z.object({
466
- code: z.string().min(1).openapi({
467
- description: 'TypeScript BubbleFlow code to validate',
468
- example: 'export class TestFlow extends BubbleFlow<"webhook/http"> { async handle() { return {}; } }',
469
- }),
470
- options: z
471
- .object({
472
- includeDetails: z.boolean().default(true).openapi({
473
- description: 'Include detailed bubble analysis',
474
- }),
475
- strictMode: z.boolean().default(true).openapi({
476
- description: 'Enable strict TypeScript validation',
477
- }),
478
- })
479
- .optional()
480
- .openapi({
481
- description: 'Validation options',
482
- }),
483
- flowId: z.number().positive().optional().openapi({
484
- description: 'Optional BubbleFlow ID to update with validation results if user owns the flow',
485
- example: 123,
486
- }),
487
- credentials: z
488
- .record(z.string(), z.record(z.string(), z.number()))
489
- .optional()
490
- .openapi({
491
- description: 'Optional credentials mapping: bubble name -> credential type -> credential ID',
492
- example: {
493
- 'slack-sender': {
494
- SLACK_CRED: 123,
495
- },
496
- 'ai-agent': {
497
- OPENAI_CRED: 456,
498
- },
499
- },
500
- }),
501
- });
502
- export const validateBubbleFlowCodeResponseSchema = z.object({
503
- valid: z.boolean().openapi({
504
- description: 'Whether the code is valid',
505
- }),
506
- errors: z.array(z.string()).optional().openapi({
507
- description: 'List of validation errors if any',
508
- }),
509
- bubbleCount: z.number().optional().openapi({
510
- description: 'Number of bubbles found in the code',
511
- }),
512
- inputSchema: z.record(z.string(), z.unknown()).openapi({
513
- description: 'Input schema',
514
- example: {
515
- name: 'string',
516
- age: 'number',
517
- },
518
- }),
519
- bubbles: z.record(z.string(), ParsedBubbleWithInfoSchema).optional().openapi({
520
- description: 'Record mapping bubble IDs to their detailed information',
521
- }),
522
- requiredCredentials: z
523
- .record(z.string(), z.array(z.string()))
524
- .optional()
525
- .openapi({
526
- description: 'Required credentials for the bubbles in the code',
527
- }),
528
- metadata: z
529
- .object({
530
- validatedAt: z.string().openapi({
531
- description: 'Timestamp when validation was performed',
532
- }),
533
- codeLength: z.number().openapi({
534
- description: 'Length of the code in characters',
535
- }),
536
- strictMode: z.boolean().openapi({
537
- description: 'Whether strict mode was used',
538
- }),
539
- flowUpdated: z.boolean().optional().openapi({
540
- description: 'Whether the BubbleFlow was updated with validation results',
541
- }),
542
- })
543
- .openapi({
544
- description: 'Validation metadata',
545
- }),
546
- success: z.boolean(),
547
- error: z.string(),
548
- });
549
- // BubbleFlow generation schemas
550
- export const generateBubbleFlowCodeSchema = z.object({
551
- prompt: z.string().min(1).openapi({
552
- description: 'Natural language description of the desired BubbleFlow',
553
- example: 'Create a flow that queries my database and sends results to Slack',
554
- }),
555
- });
556
- export const generateBubbleFlowCodeResponseSchema = z.object({
557
- generatedCode: z.string().openapi({
558
- description: 'The generated BubbleFlow TypeScript code',
559
- }),
560
- isValid: z.boolean().openapi({
561
- description: 'Whether the generated code is valid',
562
- }),
563
- success: z.boolean(),
564
- error: z.string(),
565
- bubbleParameters: z.record(z.string(), ParsedBubbleWithInfoSchema).openapi({
566
- description: 'Parsed bubble parameters from the generated code',
567
- }),
568
- requiredCredentials: z.record(z.string(), z.array(z.string())).openapi({
569
- description: 'Required credentials for the bubbles in the generated code',
570
- }),
571
- });
572
- // General error response (used by all routes)
573
- export const errorResponseSchema = z
574
- .object({
575
- error: z.string().openapi({
576
- description: 'Error message',
577
- example: 'Validation failed',
578
- }),
579
- details: z.string().optional().openapi({
580
- description: 'Additional error details',
581
- example: 'Invalid field: name is required',
582
- }),
583
- })
584
- .openapi('ErrorResponse');
585
- // ============================================================================
586
- // TYPESCRIPT TYPES (Derived from Schemas)
587
- // ============================================================================
588
- // BubbleFlow execution history item schema
589
- export const bubbleFlowExecutionSchema = z.object({
590
- id: z.number().openapi({ description: 'Execution ID' }),
591
- status: z
592
- .enum(['running', 'success', 'error'])
593
- .openapi({ description: 'Execution status' }),
594
- payload: z
595
- .record(z.string(), z.any())
596
- .openapi({ description: 'Execution payload' }),
597
- result: z.any().optional().openapi({ description: 'Execution result data' }),
598
- error: z
599
- .string()
600
- .optional()
601
- .openapi({ description: 'Error message if failed' }),
602
- startedAt: z.string().openapi({ description: 'Execution start timestamp' }),
603
- webhook_url: z.string().openapi({ description: 'Webhook URL' }),
604
- completedAt: z
605
- .string()
606
- .optional()
607
- .openapi({ description: 'Execution completion timestamp' }),
608
- });
609
- // GET /bubble-flow/:id/executions - List BubbleFlow executions response
610
- export const listBubbleFlowExecutionsResponseSchema = z
611
- .array(bubbleFlowExecutionSchema)
612
- .openapi('ListBubbleFlowExecutionsResponse');
613
- // ============================================================================
614
- // WEBHOOK SCHEMAS
615
- // ============================================================================
616
- // Slack URL verification schema
617
- export const slackUrlVerificationSchema = z.object({
618
- token: z.string(),
619
- challenge: z.string(),
620
- type: z.literal('url_verification'),
621
- });
622
- export const slackUrlVerificationResponseSchema = z
623
- .object({
624
- challenge: z
625
- .string()
626
- .openapi({ description: 'Slack URL verification challenge' }),
627
- })
628
- .openapi('SlackUrlVerificationResponse');
629
- // POST /bubbleflow-template/data-analyst - Generate template from description
630
- export const generateBubbleFlowTemplateSchema = z
631
- .object({
632
- name: z.string().min(1).max(100).openapi({
633
- description: 'Name for the workflow',
634
- example: 'Sam Dix Data Scientist Bot',
635
- }),
636
- description: z.string().min(10).max(500).openapi({
637
- description: 'Description of what the workflow should do',
638
- example: 'A Slack bot that helps analyze user engagement data and provides insights',
639
- }),
640
- roles: z.string().min(10).max(1000).openapi({
641
- description: "Detailed description of the bot's roles and responsibilities",
642
- example: 'Be prepared to answer any question on user engagement and come up with proactive insights...',
643
- }),
644
- useCase: z.literal('slack-data-scientist').openapi({
645
- description: 'The specific use case template to generate',
646
- example: 'slack-data-scientist',
647
- }),
648
- // Optional configuration parameters
649
- verbosity: z.enum(['1', '2', '3', '4', '5']).optional().openapi({
650
- description: 'Response verbosity level (1=concise, 5=comprehensive)',
651
- example: '3',
652
- }),
653
- technicality: z.enum(['1', '2', '3', '4', '5']).optional().openapi({
654
- description: 'Technical complexity level (1=plain English, 5=expert)',
655
- example: '2',
656
- }),
657
- includeQuery: z.boolean().optional().openapi({
658
- description: 'Include the SQL query in the response',
659
- example: true,
660
- }),
661
- includeExplanation: z.boolean().optional().openapi({
662
- description: 'Include query explanation in the response',
663
- example: true,
664
- }),
665
- maxQueries: z.number().optional().openapi({
666
- description: 'Maximum number of queries to run',
667
- example: 10,
668
- }),
669
- })
670
- .openapi('GenerateBubbleFlowTemplateRequest');
671
- // POST /bubbleflow-template/document-generation - Generate document processing template
672
- export const generateDocumentGenerationTemplateSchema = z
673
- .object({
674
- name: z.string().min(1).max(100).openapi({
675
- description: 'Name for the document processing workflow',
676
- example: 'Expense Report Generator',
677
- }),
678
- description: z
679
- .string()
680
- .max(500)
681
- .default('Document processing workflow')
682
- .openapi({
683
- description: 'Description of what the document processing workflow should do (optional)',
684
- example: 'Process receipts and invoices to generate structured expense reports',
685
- }),
686
- outputDescription: z.string().min(1).max(1000).openapi({
687
- description: 'Detailed description of the desired output format and data extraction',
688
- example: 'Extract expense tracking data with vendor name, transaction date, amount, category, and description',
689
- }),
690
- // Optional configuration parameters
691
- outputFormat: z.enum(['html', 'csv', 'json']).optional().openapi({
692
- description: 'Default output format for generated documents',
693
- example: 'html',
694
- }),
695
- conversionOptions: z
696
- .object({
697
- preserveStructure: z.boolean().optional().openapi({
698
- description: 'Preserve document structure during parsing',
699
- example: true,
700
- }),
701
- includeVisualDescriptions: z.boolean().optional().openapi({
702
- description: 'Include descriptions of visual elements',
703
- example: true,
704
- }),
705
- extractNumericalData: z.boolean().optional().openapi({
706
- description: 'Extract and process numerical data',
707
- example: true,
708
- }),
709
- combinePages: z.boolean().optional().openapi({
710
- description: 'Combine multiple pages into single output',
711
- example: true,
712
- }),
713
- })
714
- .optional(),
715
- imageOptions: z
716
- .object({
717
- format: z.enum(['png', 'jpg', 'jpeg']).optional().openapi({
718
- description: 'Image format for document conversion',
719
- example: 'png',
720
- }),
721
- quality: z.number().min(0.1).max(1.0).optional().openapi({
722
- description: 'Image quality (0.1 to 1.0)',
723
- example: 0.9,
724
- }),
725
- dpi: z.number().min(72).max(300).optional().openapi({
726
- description: 'Image DPI for conversion',
727
- example: 200,
728
- }),
729
- })
730
- .optional(),
731
- aiOptions: z
732
- .object({
733
- model: z.string().optional().openapi({
734
- description: 'AI model to use for processing',
735
- example: 'google/gemini-2.5-flash',
736
- }),
737
- temperature: z.number().min(0).max(2).optional().openapi({
738
- description: 'AI model temperature (0 to 2)',
739
- example: 0.2,
740
- }),
741
- maxTokens: z.number().min(1000).max(200000).optional().openapi({
742
- description: 'Maximum tokens for AI processing',
743
- example: 90000,
744
- }),
745
- jsonMode: z.boolean().optional().openapi({
746
- description: 'Enable JSON mode for structured output',
747
- example: false,
748
- }),
749
- })
750
- .optional(),
751
- metadata: z
752
- .record(z.string(), z.unknown())
753
- .optional()
754
- .openapi({
755
- description: 'Additional metadata for the workflow (e.g., outputDescription)',
756
- example: { outputDescription: 'Extract expense data from receipts' },
757
- }),
758
- })
759
- .openapi('GenerateDocumentGenerationTemplateRequest');
760
- // Response for template generation (extends the regular create response)
761
- export const bubbleFlowTemplateResponseSchema = z
762
- .object({
763
- id: z.number().openapi({
764
- description: 'ID of the created BubbleFlow template',
765
- example: 123,
766
- }),
767
- name: z.string().openapi({
768
- description: 'Name of the BubbleFlow',
769
- example: 'Sam Dix Data Scientist Bot',
770
- }),
771
- description: z.string().openapi({
772
- description: 'Description of the BubbleFlow',
773
- example: 'A Slack bot that helps analyze user engagement data',
774
- }),
775
- eventType: z.string().openapi({
776
- description: 'Event type this BubbleFlow responds to',
777
- example: 'slack/bot_mentioned',
778
- }),
779
- displayedBubbleParameters: z.record(z.string(), z.object({
780
- variableName: z.string(),
781
- bubbleName: z.string(),
782
- className: z.string(),
783
- parameters: z.array(z.object({
784
- name: z.string(),
785
- value: z.unknown(),
786
- type: z.nativeEnum(BubbleParameterType),
787
- })),
788
- hasAwait: z.boolean(),
789
- hasActionCall: z.boolean(),
790
- })),
791
- bubbleParameters: z
792
- .record(z.string(), z.object({
793
- variableName: z.string(),
794
- bubbleName: z.string(),
795
- className: z.string(),
796
- parameters: z.array(z.object({
797
- name: z.string(),
798
- value: z.unknown(),
799
- type: z.nativeEnum(BubbleParameterType),
800
- })),
801
- hasAwait: z.boolean(),
802
- hasActionCall: z.boolean(),
803
- }))
804
- .openapi({
805
- description: 'Parsed bubble parameters from the BubbleFlow code',
806
- }),
807
- requiredCredentials: z
808
- .record(z.string(), z.array(z.nativeEnum(CredentialType)))
809
- .optional()
810
- .openapi({
811
- description: 'Mapping of bubble names to their required credential types',
812
- example: {
813
- 'database-connection': [CredentialType.DATABASE_CRED],
814
- 'slack-notification': [CredentialType.SLACK_CRED],
815
- 'ai-analysis': [CredentialType.GOOGLE_GEMINI_CRED],
816
- },
817
- }),
818
- createdAt: z.string().openapi({
819
- description: 'ISO timestamp when the template was created',
820
- example: '2025-01-15T10:30:00.000Z',
821
- }),
822
- updatedAt: z.string().openapi({
823
- description: 'ISO timestamp when the template was last updated',
824
- example: '2025-01-15T10:30:00.000Z',
825
- }),
826
- webhook: z
827
- .object({
828
- id: z.number().openapi({ description: 'Webhook ID', example: 456 }),
829
- url: z.string().openapi({
830
- description: 'Full webhook URL',
831
- example: 'http://localhost:3001/webhook/user123/my-webhook',
832
- }),
833
- path: z.string().openapi({
834
- description: 'Webhook path',
835
- example: 'my-webhook',
836
- }),
837
- active: z.boolean().openapi({
838
- description: 'Whether webhook is active',
839
- example: true,
840
- }),
841
- })
842
- .optional()
843
- .openapi({
844
- description: 'Webhook information (if webhook was created)',
845
- }),
846
- })
847
- .openapi('BubbleFlowTemplateResponse');
848
- // Export TypeScript types
849
- // POST /bubble-flow/:id/test - Test workflow
850
- export const testBubbleFlowSchema = z
851
- .object({
852
- message: z.string().min(1).openapi({
853
- description: 'Test message to send to the workflow',
854
- example: 'What is our user engagement rate this month?',
855
- }),
856
- })
857
- .openapi('TestBubbleFlowRequest');
858
- export const testBubbleFlowResponseSchema = z
859
- .object({
860
- success: z.boolean().openapi({
861
- description: 'Whether the test execution was successful',
862
- example: true,
863
- }),
864
- response: z.string().openapi({
865
- description: 'Response from the workflow',
866
- example: 'Based on your query, I found 1,247 active users...',
867
- }),
868
- executionTime: z.number().openapi({
869
- description: 'Execution time in milliseconds',
870
- example: 1500,
871
- }),
872
- error: z.string().optional().openapi({
873
- description: 'Error message if test failed',
874
- example: 'Database connection failed',
875
- }),
876
- })
877
- .openapi('TestBubbleFlowResponse');
878
- // POST /bubble-flow/:id/activate - Activate workflow
879
- export const activateBubbleFlowResponseSchema = z
880
- .object({
881
- success: z.boolean().openapi({
882
- description: 'Whether the activation was successful',
883
- example: true,
884
- }),
885
- webhookUrl: z.string().openapi({
886
- description: 'Webhook URL for the activated workflow',
887
- example: 'https://api.nodex.dev/webhook/user123/workflow-123',
888
- }),
889
- message: z.string().openapi({
890
- description: 'Success message',
891
- example: 'Workflow activated successfully! Your Slack bot is now ready.',
892
- }),
893
- })
894
- .openapi('ActivateBubbleFlowResponse');
895
- // ============================================================================
896
- // SUBSCRIPTION SCHEMAS
897
- // ============================================================================
898
- // GET /subscription/status - Get user's subscription status
899
- export const subscriptionStatusResponseSchema = z
900
- .object({
901
- userId: z.string().openapi({
902
- description: 'User ID from Clerk',
903
- example: 'user_30Gbwrzto1VZvAHcGUm5NLQhpkp',
904
- }),
905
- plan: z.string().openapi({
906
- description: 'Current subscription plan',
907
- example: 'pro_plus',
908
- }),
909
- planDisplayName: z.string().openapi({
910
- description: 'Human-readable plan name',
911
- example: 'Pro Plus',
912
- }),
913
- features: z.array(z.string()).openapi({
914
- description: 'List of features available to the user',
915
- example: ['unlimited_usage', 'priority_support'],
916
- }),
917
- usage: z.object({
918
- current: z.number().openapi({
919
- description: 'Current monthly usage count',
920
- example: 42,
921
- }),
922
- limit: z.number().openapi({
923
- description: 'Monthly usage limit',
924
- example: 100,
925
- }),
926
- percentage: z.number().openapi({
927
- description: 'Usage percentage',
928
- example: 42,
929
- }),
930
- resetDate: z.string().openapi({
931
- description: 'ISO date when usage resets',
932
- example: '2025-02-01T00:00:00.000Z',
933
- }),
934
- }),
935
- isActive: z.boolean().openapi({
936
- description: 'Whether the subscription is active',
937
- example: true,
938
- }),
939
- })
940
- .openapi('SubscriptionStatusResponse');
941
- // ============================================================================
942
- // JOIN WAITLIST SCHEMAS
943
- // ============================================================================
944
- // POST /join-waitlist - Join waitlist request schema
945
- export const joinWaitlistSchema = z
946
- .object({
947
- name: z.string().min(1, 'Name is required').openapi({
948
- description: 'Full name of the user',
949
- example: 'John Doe',
950
- }),
951
- email: z.string().email('Valid email is required').openapi({
952
- description: 'Email address of the user',
953
- example: 'john.doe@example.com',
954
- }),
955
- database: z.string().min(1, 'Database selection is required').openapi({
956
- description: 'Database type the user wants to use',
957
- example: 'postgres',
958
- }),
959
- otherDatabase: z.string().optional().openapi({
960
- description: 'Other database type if "other" was selected',
961
- example: 'Redis',
962
- }),
963
- })
964
- .openapi('JoinWaitlistRequest');
965
- // POST /join-waitlist - Join waitlist response schema
966
- export const joinWaitlistResponseSchema = z
967
- .object({
968
- success: z.boolean().openapi({
969
- description: 'Whether the request was successful',
970
- example: true,
971
- }),
972
- message: z.string().openapi({
973
- description: 'Success message',
974
- example: 'Successfully joined the waitlist! Check your email for next steps.',
975
- }),
976
- })
977
- .openapi('JoinWaitlistResponse');
978
- //# sourceMappingURL=routes.js.map