@newhomestar/sdk 0.5.2 → 0.6.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.
@@ -0,0 +1,398 @@
1
+ import { z, type ZodTypeAny } from "zod";
2
+ /** Where the parameter is sent in the HTTP request */
3
+ export type ParamIn = 'path' | 'query' | 'body' | 'header';
4
+ /** UI input widget type hint for the admin dashboard form builder */
5
+ export type ParamUiType = 'text' | 'textarea' | 'number' | 'integer' | 'boolean' | 'date' | 'datetime' | 'select' | 'multiselect' | 'password' | 'email' | 'url' | 'uuid' | 'json' | 'hidden';
6
+ /**
7
+ * Per-field metadata for action input parameters.
8
+ *
9
+ * Tells the platform where each field goes in the HTTP request (path, query,
10
+ * body, header) and what UI widget the admin dashboard should render.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * params: {
15
+ * id: { in: "path", uiType: "text", label: "Worker ID", required: true },
16
+ * asOfDate: { in: "query", uiType: "date", label: "As-of Date", placeholder: "YYYY-MM-DD" },
17
+ * syncType: { in: "body", uiType: "select", label: "Sync Type", options: [
18
+ * { label: "Full", value: "full" },
19
+ * { label: "Incremental", value: "incremental" },
20
+ * ]},
21
+ * }
22
+ * ```
23
+ */
24
+ export interface ParamMeta {
25
+ /** Where this parameter is sent: path, query, body, or header */
26
+ in: ParamIn;
27
+ /** UI widget type hint — tells the admin dashboard what input to render */
28
+ uiType?: ParamUiType;
29
+ /** Human-readable label (overrides the field name) */
30
+ label?: string;
31
+ /** Help text / description shown below the input */
32
+ description?: string;
33
+ /** Placeholder text for the input */
34
+ placeholder?: string;
35
+ /** Whether this field is required (overrides Zod's optional/required) */
36
+ required?: boolean;
37
+ /** Default value shown in the UI */
38
+ defaultValue?: unknown;
39
+ /** Options for select/multiselect UI types */
40
+ options?: Array<{
41
+ label: string;
42
+ value: string | number | boolean;
43
+ }>;
44
+ /** Minimum value (for number/integer) or min length (for string) */
45
+ min?: number;
46
+ /** Maximum value (for number/integer) or max length (for string) */
47
+ max?: number;
48
+ /** Step increment for number inputs (e.g., 1, 0.01) */
49
+ step?: number;
50
+ /** Regex pattern for frontend validation */
51
+ pattern?: string;
52
+ /** Display order (lower = higher priority, default = declaration order) */
53
+ order?: number;
54
+ /** Group name for visual grouping in the form (e.g., "Identity", "Options") */
55
+ group?: string;
56
+ }
57
+ export type SchemaType = 'request' | 'response' | 'entity' | 'webhook_payload' | 'configuration';
58
+ export interface IntegrationSchemaDef<T extends ZodTypeAny = ZodTypeAny> {
59
+ /** Human-readable name for this schema */
60
+ name: string;
61
+ /** Unique slug within this integration (snake_case) */
62
+ slug: string;
63
+ /** Optional description */
64
+ description?: string;
65
+ /** Classification of this schema */
66
+ schemaType: SchemaType;
67
+ /** Zod schema — converted to JSON Schema during `nova integrations build` */
68
+ schema: T;
69
+ /** Developer-controlled version string (e.g., "1.0.0") */
70
+ version?: string;
71
+ /** Direct Zod reference for use in actions/events (lean API) */
72
+ shape?: T;
73
+ }
74
+ /**
75
+ * **Verbose** helper — define a schema with all metadata explicitly.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const WorkerProfile = integrationSchema({
80
+ * name: "Worker Profile",
81
+ * slug: "worker_profile",
82
+ * schemaType: "entity",
83
+ * schema: z.object({ workerId: z.string() }),
84
+ * });
85
+ * ```
86
+ */
87
+ export declare function integrationSchema<T extends ZodTypeAny>(cfg: {
88
+ name: string;
89
+ slug: string;
90
+ description?: string;
91
+ schemaType: SchemaType;
92
+ schema: T;
93
+ version?: string;
94
+ }): IntegrationSchemaDef<T>;
95
+ /**
96
+ * **Lean** helper — slug and name are inferred from the key in `schemas: {}`.
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * const User = schema("entity", z.object({
101
+ * id: z.string(),
102
+ * email: z.string().email(),
103
+ * }));
104
+ *
105
+ * // In defineIntegration:
106
+ * schemas: { user: User }
107
+ * // → slug: "user", name: "User", schemaType: "entity"
108
+ * ```
109
+ */
110
+ export declare function schema<T extends ZodTypeAny>(schemaType: SchemaType, zodSchema: T, opts?: {
111
+ version?: string;
112
+ description?: string;
113
+ }): IntegrationSchemaDef<T>;
114
+ export interface IntegrationEventDef {
115
+ /** Unique event slug within this integration (dot-notation, e.g. "worker.hire") */
116
+ slug: string;
117
+ /** Human-readable name */
118
+ name: string;
119
+ /** Direction of the event relative to the platform */
120
+ direction: 'inbound' | 'outbound' | 'bidirectional';
121
+ /** Optional description of the event */
122
+ description?: string;
123
+ /** Event category for grouping (e.g., "lifecycle", "payroll") */
124
+ category?: string;
125
+ /** Severity/importance level */
126
+ severity?: 'info' | 'warning' | 'error' | 'critical';
127
+ /** Reference to a schema slug that defines the event payload shape */
128
+ payloadSchema?: string;
129
+ }
130
+ /**
131
+ * **Verbose** helper — define an event with all metadata explicitly.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * const workerHire = integrationEvent({
136
+ * slug: "worker.hire",
137
+ * name: "Worker Hired",
138
+ * direction: "inbound",
139
+ * category: "lifecycle",
140
+ * severity: "info",
141
+ * payloadSchema: "new_hire_payload",
142
+ * });
143
+ * ```
144
+ */
145
+ export declare function integrationEvent(cfg: IntegrationEventDef): IntegrationEventDef;
146
+ /**
147
+ * **Lean** helper — slug and name inferred from key in `events: {}`.
148
+ * Payload can reference a `schema()` result directly (type-safe, no strings).
149
+ *
150
+ * @example
151
+ * ```ts
152
+ * const User = schema("entity", z.object({ id: z.string() }));
153
+ *
154
+ * // In defineIntegration:
155
+ * events: {
156
+ * user_synced: event("outbound", { payload: User }),
157
+ * sync_failed: event("outbound", { severity: "error" }),
158
+ * }
159
+ * ```
160
+ */
161
+ export declare function event(direction: IntegrationEventDef['direction'], opts?: {
162
+ payload?: IntegrationSchemaDef | ZodTypeAny;
163
+ severity?: IntegrationEventDef['severity'];
164
+ category?: string;
165
+ description?: string;
166
+ }): IntegrationEventDef;
167
+ export interface IntegrationFunctionDef {
168
+ /** Unique function slug within this integration (snake_case) */
169
+ slug: string;
170
+ /** Human-readable name */
171
+ name: string;
172
+ /** HTTP method for the external API call */
173
+ httpMethod: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
174
+ /** Endpoint path template (e.g., "/hr/v2/workers/{workerId}") */
175
+ endpointPath: string;
176
+ /** Description of what this function does */
177
+ description?: string;
178
+ /** Reference to a schema slug that defines the request body shape */
179
+ requestSchema?: string;
180
+ /** Reference to a schema slug that defines the response body shape */
181
+ responseSchema?: string;
182
+ /** OAuth scopes required to call this function */
183
+ requiredScopes?: string[];
184
+ /** Function category for grouping (e.g., "workers", "payroll") */
185
+ category?: string;
186
+ /** Capabilities metadata (e.g., "webhook", "scheduled", "queue") — can be simple strings or structured objects */
187
+ capabilities?: (string | Record<string, unknown>)[];
188
+ }
189
+ /**
190
+ * Helper to define an integration function (API endpoint).
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * const listWorkers = integrationFunction({
195
+ * slug: "list_workers",
196
+ * name: "List Workers",
197
+ * httpMethod: "GET",
198
+ * endpointPath: "/hr/v2/workers",
199
+ * responseSchema: "worker_profile",
200
+ * requiredScopes: ["api"],
201
+ * category: "workers",
202
+ * });
203
+ * ```
204
+ */
205
+ export declare function integrationFunction(cfg: IntegrationFunctionDef): IntegrationFunctionDef;
206
+ /**
207
+ * Full integration definition — the single source of truth.
208
+ *
209
+ * Integrations are containerized services (like workers) that also carry
210
+ * structured configuration: schemas, events, and functions. When pushed
211
+ * via `nova integrations push`, the container image is deployed and the
212
+ * config is synced to the platform database.
213
+ */
214
+ export interface IntegrationDef {
215
+ /** Unique integration slug (snake_case, e.g. "adp_workforce_now") */
216
+ slug: string;
217
+ /** Human-readable name */
218
+ name: string;
219
+ /** Short description */
220
+ description?: string;
221
+ /** Integration authentication type */
222
+ integrationType: 'oidc' | 'oauth2' | 'api_key';
223
+ /** Category for grouping (e.g., "hr", "crm", "finance") */
224
+ category?: string;
225
+ /** Logo URL for the admin dashboard */
226
+ logoUrl?: string;
227
+ /** Brand color hex code */
228
+ color?: string;
229
+ /** OAuth2/OIDC authorization endpoint */
230
+ authorizationEndpoint?: string;
231
+ /** OAuth2/OIDC token endpoint */
232
+ tokenEndpoint?: string;
233
+ /** OIDC userinfo endpoint */
234
+ userinfoEndpoint?: string;
235
+ /** OAuth2 token revocation endpoint */
236
+ revocationEndpoint?: string;
237
+ /** OIDC JWKS URI */
238
+ jwksUri?: string;
239
+ /** Base URL for API calls */
240
+ baseUrl?: string;
241
+ /** OAuth scopes to request */
242
+ scopes?: string[];
243
+ /** PGMQ queue name for async message processing */
244
+ queue: string;
245
+ /** Display name (used in admin dashboard and nova-integration.yaml) */
246
+ displayName?: string;
247
+ /** Icon URL */
248
+ icon?: string;
249
+ /** Tags for discovery/filtering */
250
+ tags?: string[];
251
+ /** UI metadata */
252
+ ui?: {
253
+ category?: string;
254
+ color?: string;
255
+ };
256
+ /** Resource limits for the container */
257
+ resources?: {
258
+ cpu: string;
259
+ memory: string;
260
+ };
261
+ /** Environment variable spec for deployment */
262
+ envSpec?: Array<{
263
+ name: string;
264
+ secret: boolean;
265
+ default?: string;
266
+ }>;
267
+ /** Map of action definitions — same as workers */
268
+ actions: Record<string, any>;
269
+ /** Schema definitions — Zod schemas converted to JSON Schema on build */
270
+ schemas: Record<string, IntegrationSchemaDef>;
271
+ /** Event definitions — describe inbound/outbound events */
272
+ events: Record<string, IntegrationEventDef>;
273
+ /** Function definitions — describe external API endpoints */
274
+ functions: Record<string, IntegrationFunctionDef>;
275
+ }
276
+ export declare const IntegrationDefSchema: z.ZodObject<{
277
+ slug: z.ZodString;
278
+ name: z.ZodString;
279
+ description: z.ZodOptional<z.ZodString>;
280
+ integrationType: z.ZodEnum<{
281
+ api_key: "api_key";
282
+ oidc: "oidc";
283
+ oauth2: "oauth2";
284
+ }>;
285
+ category: z.ZodOptional<z.ZodString>;
286
+ logoUrl: z.ZodOptional<z.ZodString>;
287
+ color: z.ZodOptional<z.ZodString>;
288
+ authorizationEndpoint: z.ZodOptional<z.ZodString>;
289
+ tokenEndpoint: z.ZodOptional<z.ZodString>;
290
+ userinfoEndpoint: z.ZodOptional<z.ZodString>;
291
+ revocationEndpoint: z.ZodOptional<z.ZodString>;
292
+ jwksUri: z.ZodOptional<z.ZodString>;
293
+ baseUrl: z.ZodOptional<z.ZodString>;
294
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
295
+ queue: z.ZodString;
296
+ displayName: z.ZodOptional<z.ZodString>;
297
+ icon: z.ZodOptional<z.ZodString>;
298
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
299
+ ui: z.ZodOptional<z.ZodObject<{
300
+ category: z.ZodOptional<z.ZodString>;
301
+ color: z.ZodOptional<z.ZodString>;
302
+ }, z.core.$strip>>;
303
+ resources: z.ZodOptional<z.ZodObject<{
304
+ cpu: z.ZodString;
305
+ memory: z.ZodString;
306
+ }, z.core.$strip>>;
307
+ envSpec: z.ZodOptional<z.ZodArray<z.ZodObject<{
308
+ name: z.ZodString;
309
+ secret: z.ZodBoolean;
310
+ default: z.ZodOptional<z.ZodString>;
311
+ }, z.core.$strip>>>;
312
+ actions: z.ZodRecord<z.ZodString, z.ZodAny>;
313
+ schemas: z.ZodRecord<z.ZodString, z.ZodObject<{
314
+ name: z.ZodString;
315
+ slug: z.ZodString;
316
+ description: z.ZodOptional<z.ZodString>;
317
+ schemaType: z.ZodEnum<{
318
+ response: "response";
319
+ request: "request";
320
+ entity: "entity";
321
+ webhook_payload: "webhook_payload";
322
+ configuration: "configuration";
323
+ }>;
324
+ schema: z.ZodAny;
325
+ version: z.ZodOptional<z.ZodString>;
326
+ }, z.core.$strip>>;
327
+ events: z.ZodRecord<z.ZodString, z.ZodObject<{
328
+ slug: z.ZodString;
329
+ name: z.ZodString;
330
+ direction: z.ZodEnum<{
331
+ inbound: "inbound";
332
+ outbound: "outbound";
333
+ bidirectional: "bidirectional";
334
+ }>;
335
+ description: z.ZodOptional<z.ZodString>;
336
+ category: z.ZodOptional<z.ZodString>;
337
+ severity: z.ZodOptional<z.ZodEnum<{
338
+ error: "error";
339
+ info: "info";
340
+ warning: "warning";
341
+ critical: "critical";
342
+ }>>;
343
+ payloadSchema: z.ZodOptional<z.ZodString>;
344
+ }, z.core.$strip>>;
345
+ functions: z.ZodRecord<z.ZodString, z.ZodObject<{
346
+ slug: z.ZodString;
347
+ name: z.ZodString;
348
+ httpMethod: z.ZodEnum<{
349
+ GET: "GET";
350
+ POST: "POST";
351
+ PATCH: "PATCH";
352
+ DELETE: "DELETE";
353
+ PUT: "PUT";
354
+ }>;
355
+ endpointPath: z.ZodString;
356
+ description: z.ZodOptional<z.ZodString>;
357
+ requestSchema: z.ZodOptional<z.ZodString>;
358
+ responseSchema: z.ZodOptional<z.ZodString>;
359
+ requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
360
+ category: z.ZodOptional<z.ZodString>;
361
+ capabilities: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>>;
362
+ }, z.core.$strip>>;
363
+ }, z.core.$strip>;
364
+ /**
365
+ * Result of validating an integration definition before build/push.
366
+ * Errors block the operation; warnings are printed but non-blocking.
367
+ */
368
+ export interface ValidationResult {
369
+ /** True if no errors were found (warnings are allowed) */
370
+ valid: boolean;
371
+ /** Blocking issues that must be fixed before build/push */
372
+ errors: string[];
373
+ /** Non-blocking recommendations */
374
+ warnings: string[];
375
+ }
376
+ /**
377
+ * Validate an integration definition before build or push.
378
+ *
379
+ * Performs conditional validation based on `integrationType`:
380
+ * - **Always required**: slug, name, queue, baseUrl, ≥1 action
381
+ * - **OAuth2/OIDC required**: authorizationEndpoint, tokenEndpoint
382
+ * - **OIDC warned**: jwksUri, userinfoEndpoint
383
+ * - **Warnings**: no schemas, no scopes, non-HTTPS URLs, no health action
384
+ *
385
+ * Called automatically during `nova integrations build` and `nova integrations push`.
386
+ *
387
+ * @example
388
+ * ```ts
389
+ * const result = validateIntegration(myIntegration);
390
+ * if (!result.valid) {
391
+ * result.errors.forEach(e => console.error(`❌ ${e}`));
392
+ * process.exit(1);
393
+ * }
394
+ * result.warnings.forEach(w => console.warn(`⚠️ ${w}`));
395
+ * ```
396
+ */
397
+ export declare function validateIntegration(def: IntegrationDef): ValidationResult;
398
+ export declare function defineIntegration<T extends IntegrationDef>(def: T): T;