@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,186 @@
1
+ import { parse as parseYAML } from "yaml";
2
+ import { z } from "zod";
3
+ /**
4
+ * IntegrationSpec — the shape of nova-integration.yaml
5
+ * Generated by `nova integrations build` from a defineIntegration() call.
6
+ */
7
+ const IntegrationSchemaSpecSchema = z.object({
8
+ slug: z.string(),
9
+ name: z.string(),
10
+ type: z.enum(['request', 'response', 'entity', 'webhook_payload', 'configuration']),
11
+ description: z.string().optional(),
12
+ schema: z.union([z.string(), z.record(z.string(), z.unknown())]),
13
+ version: z.string().optional(),
14
+ fieldCount: z.number().optional(),
15
+ });
16
+ const IntegrationEventSpecSchema = z.object({
17
+ slug: z.string(),
18
+ name: z.string(),
19
+ direction: z.enum(['inbound', 'outbound', 'bidirectional']),
20
+ description: z.string().optional(),
21
+ category: z.string().optional(),
22
+ severity: z.enum(['info', 'warning', 'error', 'critical']).optional(),
23
+ payloadSchema: z.string().optional(),
24
+ });
25
+ const IntegrationFunctionSpecSchema = z.object({
26
+ slug: z.string(),
27
+ name: z.string(),
28
+ httpMethod: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),
29
+ endpointPath: z.string(),
30
+ description: z.string().optional(),
31
+ requestSchema: z.string().optional(),
32
+ responseSchema: z.string().optional(),
33
+ requiredScopes: z.array(z.string()).optional(),
34
+ category: z.string().optional(),
35
+ });
36
+ // Capability schemas (shared with worker spec)
37
+ const WebhookCapabilitySchema = z.object({
38
+ type: z.literal('webhook'),
39
+ eventTypes: z.array(z.string()),
40
+ source: z.string(),
41
+ endpoint: z.string().optional(),
42
+ headers: z.record(z.string(), z.string()).optional(),
43
+ authentication: z.object({
44
+ type: z.enum(['bearer', 'basic', 'api_key', 'signature']),
45
+ config: z.record(z.string(), z.unknown()).optional(),
46
+ }).optional(),
47
+ });
48
+ const ScheduledCapabilitySchema = z.object({
49
+ type: z.literal('scheduled'),
50
+ cron: z.string(),
51
+ timezone: z.string().optional(),
52
+ description: z.string().optional(),
53
+ });
54
+ const QueueCapabilitySchema = z.object({
55
+ type: z.literal('queue'),
56
+ topics: z.array(z.string()),
57
+ queueName: z.string().optional(),
58
+ consumerGroup: z.string().optional(),
59
+ });
60
+ const StreamCapabilitySchema = z.object({
61
+ type: z.literal('stream'),
62
+ streamName: z.string(),
63
+ eventTypes: z.array(z.string()).optional(),
64
+ consumerGroup: z.string().optional(),
65
+ });
66
+ const CapabilitySchema = z.discriminatedUnion('type', [
67
+ WebhookCapabilitySchema,
68
+ ScheduledCapabilitySchema,
69
+ QueueCapabilitySchema,
70
+ StreamCapabilitySchema,
71
+ ]);
72
+ export const IntegrationSpecSchema = z.object({
73
+ apiVersion: z.string(),
74
+ kind: z.literal('Integration'),
75
+ metadata: z.object({
76
+ slug: z.string(),
77
+ name: z.string(),
78
+ displayName: z.string().optional(),
79
+ description: z.string().optional(),
80
+ category: z.string().optional(),
81
+ icon: z.string().optional(),
82
+ tags: z.array(z.string()).optional(),
83
+ logoUrl: z.string().optional(),
84
+ color: z.string().optional(),
85
+ }),
86
+ spec: z.object({
87
+ type: z.enum(['oidc', 'oauth2', 'api_key']),
88
+ endpoints: z.object({
89
+ authorization: z.string().optional(),
90
+ token: z.string().optional(),
91
+ userinfo: z.string().optional(),
92
+ revocation: z.string().optional(),
93
+ jwks: z.string().optional(),
94
+ baseUrl: z.string().optional(),
95
+ }).optional(),
96
+ scopes: z.array(z.string()).optional(),
97
+ runtime: z.object({
98
+ type: z.string(),
99
+ image: z.string(),
100
+ queue: z.string(),
101
+ port: z.number().optional(),
102
+ command: z.array(z.string()),
103
+ resources: z.object({
104
+ cpu: z.string(),
105
+ memory: z.string(),
106
+ }),
107
+ envSpec: z.array(z.object({
108
+ name: z.string(),
109
+ value: z.string().optional(),
110
+ secret: z.boolean().optional(),
111
+ default: z.string().optional(),
112
+ })).optional(),
113
+ }),
114
+ actions: z.array(z.object({
115
+ name: z.string(),
116
+ displayName: z.string().optional(),
117
+ description: z.string().optional(),
118
+ async: z.boolean().optional(),
119
+ input: z.unknown().optional(),
120
+ output: z.unknown().optional(),
121
+ schema: z.object({
122
+ input: z.string(),
123
+ output: z.string(),
124
+ }).optional(),
125
+ fga: z.object({
126
+ resourceType: z.string(),
127
+ relation: z.string(),
128
+ }).optional(),
129
+ capabilities: z.array(CapabilitySchema).optional(),
130
+ })),
131
+ capabilities: z.array(CapabilitySchema).optional(),
132
+ // Integration-specific config sections
133
+ schemas: z.array(IntegrationSchemaSpecSchema).optional(),
134
+ events: z.array(IntegrationEventSpecSchema).optional(),
135
+ functions: z.array(IntegrationFunctionSpecSchema).optional(),
136
+ }),
137
+ build: z.object({
138
+ dockerfile: z.string(),
139
+ context: z.string(),
140
+ }).optional(),
141
+ ui: z.object({
142
+ category: z.string().optional(),
143
+ color: z.string().optional(),
144
+ }).optional(),
145
+ fga: z.object({
146
+ types: z.array(z.object({
147
+ name: z.string(),
148
+ relations: z.record(z.string(), z.union([
149
+ z.array(z.string()),
150
+ z.object({
151
+ computedUserset: z.object({
152
+ object: z.string(),
153
+ relation: z.string(),
154
+ }),
155
+ }),
156
+ ])),
157
+ })),
158
+ }).optional(),
159
+ });
160
+ /**
161
+ * Parse nova-integration.yaml content and validate against the IntegrationSpec schema.
162
+ * @param yamlContent String contents of a nova-integration.yaml specification
163
+ * @returns Parsed IntegrationSpec object
164
+ * @throws Error with validation details if parsing or validation fail
165
+ */
166
+ export function parseIntegrationSpec(yamlContent) {
167
+ let parsed;
168
+ try {
169
+ parsed = parseYAML(yamlContent);
170
+ }
171
+ catch (e) {
172
+ throw new Error(`Failed to parse YAML content: ${e.message}`);
173
+ }
174
+ try {
175
+ return IntegrationSpecSchema.parse(parsed);
176
+ }
177
+ catch (e) {
178
+ if (e instanceof z.ZodError) {
179
+ const details = e.issues
180
+ .map((issue) => `Path '${issue.path.join(".")}': ${issue.message}`)
181
+ .join("; ");
182
+ throw new Error(`nova-integration.yaml validation error(s): ${details}`);
183
+ }
184
+ throw e;
185
+ }
186
+ }
@@ -29,11 +29,54 @@ export declare const WorkerDefSchema: z.ZodObject<{
29
29
  method: z.ZodOptional<z.ZodEnum<{
30
30
  GET: "GET";
31
31
  POST: "POST";
32
- PUT: "PUT";
33
- DELETE: "DELETE";
34
32
  PATCH: "PATCH";
33
+ DELETE: "DELETE";
34
+ PUT: "PUT";
35
35
  }>>;
36
36
  path: z.ZodOptional<z.ZodString>;
37
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
38
+ category: z.ZodOptional<z.ZodString>;
39
+ description: z.ZodOptional<z.ZodString>;
40
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
41
+ in: z.ZodEnum<{
42
+ body: "body";
43
+ path: "path";
44
+ query: "query";
45
+ header: "header";
46
+ }>;
47
+ uiType: z.ZodOptional<z.ZodEnum<{
48
+ number: "number";
49
+ boolean: "boolean";
50
+ date: "date";
51
+ text: "text";
52
+ uuid: "uuid";
53
+ json: "json";
54
+ textarea: "textarea";
55
+ integer: "integer";
56
+ datetime: "datetime";
57
+ select: "select";
58
+ multiselect: "multiselect";
59
+ password: "password";
60
+ email: "email";
61
+ url: "url";
62
+ hidden: "hidden";
63
+ }>>;
64
+ label: z.ZodOptional<z.ZodString>;
65
+ description: z.ZodOptional<z.ZodString>;
66
+ placeholder: z.ZodOptional<z.ZodString>;
67
+ required: z.ZodOptional<z.ZodBoolean>;
68
+ defaultValue: z.ZodOptional<z.ZodAny>;
69
+ options: z.ZodOptional<z.ZodArray<z.ZodObject<{
70
+ label: z.ZodString;
71
+ value: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>;
72
+ }, z.core.$strip>>>;
73
+ min: z.ZodOptional<z.ZodNumber>;
74
+ max: z.ZodOptional<z.ZodNumber>;
75
+ step: z.ZodOptional<z.ZodNumber>;
76
+ pattern: z.ZodOptional<z.ZodString>;
77
+ order: z.ZodOptional<z.ZodNumber>;
78
+ group: z.ZodOptional<z.ZodString>;
79
+ }, z.core.$strip>>>;
37
80
  fga: z.ZodOptional<z.ZodObject<{
38
81
  resourceType: z.ZodString;
39
82
  relation: z.ZodString;
@@ -26,6 +26,34 @@ export const WorkerDefSchema = z.object({
26
26
  // NEW: HTTP routing support for oRPC
27
27
  method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).optional(),
28
28
  path: z.string().optional(),
29
+ // Integration function metadata
30
+ scopes: z.array(z.string()).optional(),
31
+ category: z.string().optional(),
32
+ description: z.string().optional(),
33
+ // Per-field parameter metadata (path/query/body/header + UI type hints)
34
+ params: z.record(z.string(), z.object({
35
+ in: z.enum(['path', 'query', 'body', 'header']),
36
+ uiType: z.enum([
37
+ 'text', 'textarea', 'number', 'integer', 'boolean',
38
+ 'date', 'datetime', 'select', 'multiselect',
39
+ 'password', 'email', 'url', 'uuid', 'json', 'hidden',
40
+ ]).optional(),
41
+ label: z.string().optional(),
42
+ description: z.string().optional(),
43
+ placeholder: z.string().optional(),
44
+ required: z.boolean().optional(),
45
+ defaultValue: z.any().optional(),
46
+ options: z.array(z.object({
47
+ label: z.string(),
48
+ value: z.union([z.string(), z.number(), z.boolean()]),
49
+ })).optional(),
50
+ min: z.number().optional(),
51
+ max: z.number().optional(),
52
+ step: z.number().optional(),
53
+ pattern: z.string().optional(),
54
+ order: z.number().optional(),
55
+ group: z.string().optional(),
56
+ })).optional(),
29
57
  // Optional per-action OpenFGA hints: resource type, relation, ID key, and optional policy caveat
30
58
  fga: z.object({
31
59
  resourceType: z.string(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newhomestar/sdk",
3
- "version": "0.5.2",
3
+ "version": "0.6.5",
4
4
  "description": "Type-safe SDK for building Nova pipelines (workers & functions)",
5
5
  "homepage": "https://github.com/newhomestar/nova-node-sdk#readme",
6
6
  "bugs": {
@@ -35,6 +35,7 @@
35
35
  "body-parser": "^1.20.2",
36
36
  "dotenv": "^16.4.3",
37
37
  "express": "^4.18.2",
38
+ "express-oauth2-jwt-bearer": "^1.7.4",
38
39
  "yaml": "^2.7.1",
39
40
  "zod": "^4.0.5"
40
41
  },