skedyul 0.1.30 → 0.1.32

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/config.d.ts CHANGED
@@ -128,6 +128,58 @@ export interface WorkflowDefinition {
128
128
  /** Actions in this workflow */
129
129
  actions: WorkflowAction[];
130
130
  }
131
+ /**
132
+ * Supported data types for internal model fields.
133
+ * Matches the DataType enum in the database.
134
+ */
135
+ export type InternalFieldDataType = 'TEXT' | 'LONG_TEXT' | 'NUMBER' | 'BOOLEAN' | 'DATE' | 'DATETIME' | 'EMAIL' | 'URL' | 'PHONE' | 'SELECT' | 'MULTI_SELECT' | 'JSON';
136
+ /**
137
+ * Definition of a field within an internal model.
138
+ * This is a normalized format that can be reused for standard models.
139
+ */
140
+ export interface InternalFieldDefinition {
141
+ /** Unique handle for the field (e.g., 'phone', 'forwarding_phone_number') */
142
+ handle: string;
143
+ /** Human-readable label */
144
+ label: string;
145
+ /** Data type of the field */
146
+ type: InternalFieldDataType;
147
+ /** Optional metafield definition handle for validation/normalization */
148
+ definitionHandle?: string;
149
+ /** Whether this field is required */
150
+ required?: boolean;
151
+ /** Whether values must be unique across instances */
152
+ unique?: boolean;
153
+ /** Whether this is a system field (managed by app logic) */
154
+ system?: boolean;
155
+ /** Whether this field is a list (array of values) */
156
+ isList?: boolean;
157
+ /** Default value for the field */
158
+ defaultValue?: {
159
+ value: unknown;
160
+ };
161
+ /** Description/help text */
162
+ description?: string;
163
+ }
164
+ /**
165
+ * Definition of an internal model owned by an app.
166
+ * Internal models are created and managed by the app, not by users.
167
+ * Data is stored in the standard Model/Field/Instance tables.
168
+ */
169
+ export interface InternalModelDefinition {
170
+ /** Unique handle for the model (e.g., 'dedicated_phone_number') */
171
+ handle: string;
172
+ /** Human-readable singular name */
173
+ name: string;
174
+ /** Human-readable plural name */
175
+ namePlural: string;
176
+ /** Template for generating instance labels (e.g., '{{phone}}') */
177
+ labelTemplate: string;
178
+ /** Description of the model */
179
+ description?: string;
180
+ /** Fields in this model */
181
+ fields: InternalFieldDefinition[];
182
+ }
131
183
  export type ComputeLayerType = 'serverless' | 'dedicated';
132
184
  export interface SkedyulConfig {
133
185
  /** App name */
@@ -188,6 +240,28 @@ export interface SkedyulConfig {
188
240
  * Can reference channels via channelHandle.
189
241
  */
190
242
  workflows?: WorkflowDefinition[];
243
+ /**
244
+ * Internal models owned by this app.
245
+ * These models are created and managed by the app, not by users.
246
+ * Data is stored in the standard Model/Field/Instance tables but
247
+ * linked to the AppVersion for ownership tracking.
248
+ *
249
+ * @example
250
+ * ```typescript
251
+ * internalModels: [
252
+ * {
253
+ * handle: 'dedicated_phone_number',
254
+ * name: 'Dedicated Phone Number',
255
+ * namePlural: 'Dedicated Phone Numbers',
256
+ * labelTemplate: '{{phone}}',
257
+ * fields: [
258
+ * { handle: 'phone', label: 'Phone Number', type: 'TEXT', required: true, unique: true },
259
+ * ],
260
+ * },
261
+ * ]
262
+ * ```
263
+ */
264
+ internalModels?: InternalModelDefinition[];
191
265
  }
192
266
  /**
193
267
  * Serializable snapshot of SkedyulConfig for database storage.
@@ -220,6 +294,8 @@ export interface SerializableSkedyulConfig {
220
294
  communicationChannels?: CommunicationChannelDefinition[];
221
295
  /** Workflows this app provides */
222
296
  workflows?: WorkflowDefinition[];
297
+ /** Internal models owned by this app */
298
+ internalModels?: InternalModelDefinition[];
223
299
  }
224
300
  /**
225
301
  * Define a Skedyul app configuration with full type safety.
package/dist/config.js CHANGED
@@ -247,6 +247,48 @@ function validateConfig(config) {
247
247
  }
248
248
  }
249
249
  }
250
+ // Validate internalModels
251
+ if (config.internalModels) {
252
+ const validDataTypes = [
253
+ 'TEXT', 'LONG_TEXT', 'NUMBER', 'BOOLEAN', 'DATE', 'DATETIME',
254
+ 'EMAIL', 'URL', 'PHONE', 'SELECT', 'MULTI_SELECT', 'JSON',
255
+ ];
256
+ for (let i = 0; i < config.internalModels.length; i++) {
257
+ const model = config.internalModels[i];
258
+ if (!model.handle) {
259
+ errors.push(`internalModels[${i}]: Missing required field 'handle'`);
260
+ }
261
+ if (!model.name) {
262
+ errors.push(`internalModels[${i}]: Missing required field 'name'`);
263
+ }
264
+ if (!model.namePlural) {
265
+ errors.push(`internalModels[${i}]: Missing required field 'namePlural'`);
266
+ }
267
+ if (!model.labelTemplate) {
268
+ errors.push(`internalModels[${i}]: Missing required field 'labelTemplate'`);
269
+ }
270
+ if (!model.fields || model.fields.length === 0) {
271
+ errors.push(`internalModels[${i}]: Must have at least one field`);
272
+ }
273
+ else {
274
+ for (let j = 0; j < model.fields.length; j++) {
275
+ const field = model.fields[j];
276
+ if (!field.handle) {
277
+ errors.push(`internalModels[${i}].fields[${j}]: Missing required field 'handle'`);
278
+ }
279
+ if (!field.label) {
280
+ errors.push(`internalModels[${i}].fields[${j}]: Missing required field 'label'`);
281
+ }
282
+ if (!field.type) {
283
+ errors.push(`internalModels[${i}].fields[${j}]: Missing required field 'type'`);
284
+ }
285
+ else if (!validDataTypes.includes(field.type)) {
286
+ errors.push(`internalModels[${i}].fields[${j}]: Invalid type '${field.type}'`);
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
250
292
  return { valid: errors.length === 0, errors };
251
293
  }
252
294
  /**
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './types';
2
+ export * from './schemas';
2
3
  export { server } from './server';
3
4
  export { workplace, communicationChannel, configure, getConfig } from './core/client';
4
5
  export { defineConfig, loadConfig, validateConfig, getRequiredInstallEnvKeys, getAllEnvKeys, CONFIG_FILE_NAMES, } from './config';
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.CONFIG_FILE_NAMES = exports.getAllEnvKeys = exports.getRequiredInstallEnvKeys = exports.validateConfig = exports.loadConfig = exports.defineConfig = exports.getConfig = exports.configure = exports.communicationChannel = exports.workplace = exports.server = void 0;
18
18
  __exportStar(require("./types"), exports);
19
+ __exportStar(require("./schemas"), exports);
19
20
  var server_1 = require("./server");
20
21
  Object.defineProperty(exports, "server", { enumerable: true, get: function () { return server_1.server; } });
21
22
  var client_1 = require("./core/client");
@@ -0,0 +1,446 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Schema for environment variable visibility
4
+ */
5
+ export declare const EnvVisibilitySchema: z.ZodEnum<{
6
+ visible: "visible";
7
+ encrypted: "encrypted";
8
+ }>;
9
+ /**
10
+ * Schema for a single environment variable definition.
11
+ */
12
+ export declare const EnvVariableDefinitionSchema: z.ZodObject<{
13
+ label: z.ZodString;
14
+ required: z.ZodOptional<z.ZodBoolean>;
15
+ visibility: z.ZodOptional<z.ZodEnum<{
16
+ visible: "visible";
17
+ encrypted: "encrypted";
18
+ }>>;
19
+ default: z.ZodOptional<z.ZodString>;
20
+ description: z.ZodOptional<z.ZodString>;
21
+ placeholder: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>;
23
+ /**
24
+ * Schema for a collection of environment variable definitions.
25
+ */
26
+ export declare const EnvSchemaSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
27
+ label: z.ZodString;
28
+ required: z.ZodOptional<z.ZodBoolean>;
29
+ visibility: z.ZodOptional<z.ZodEnum<{
30
+ visible: "visible";
31
+ encrypted: "encrypted";
32
+ }>>;
33
+ default: z.ZodOptional<z.ZodString>;
34
+ description: z.ZodOptional<z.ZodString>;
35
+ placeholder: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>>;
37
+ /**
38
+ * Schema for app model definition.
39
+ */
40
+ export declare const AppModelDefinitionSchema: z.ZodObject<{
41
+ entityHandle: z.ZodString;
42
+ label: z.ZodString;
43
+ description: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strip>;
45
+ /**
46
+ * Schema for install configuration.
47
+ */
48
+ export declare const InstallConfigSchema: z.ZodObject<{
49
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
50
+ label: z.ZodString;
51
+ required: z.ZodOptional<z.ZodBoolean>;
52
+ visibility: z.ZodOptional<z.ZodEnum<{
53
+ visible: "visible";
54
+ encrypted: "encrypted";
55
+ }>>;
56
+ default: z.ZodOptional<z.ZodString>;
57
+ description: z.ZodOptional<z.ZodString>;
58
+ placeholder: z.ZodOptional<z.ZodString>;
59
+ }, z.core.$strip>>>;
60
+ appModels: z.ZodOptional<z.ZodArray<z.ZodObject<{
61
+ entityHandle: z.ZodString;
62
+ label: z.ZodString;
63
+ description: z.ZodOptional<z.ZodString>;
64
+ }, z.core.$strip>>>;
65
+ }, z.core.$strip>;
66
+ /**
67
+ * Schema for app field visibility.
68
+ */
69
+ export declare const AppFieldVisibilitySchema: z.ZodObject<{
70
+ data: z.ZodOptional<z.ZodBoolean>;
71
+ list: z.ZodOptional<z.ZodBoolean>;
72
+ filters: z.ZodOptional<z.ZodBoolean>;
73
+ }, z.core.$strip>;
74
+ /**
75
+ * Schema for app field definition (communication channels).
76
+ */
77
+ export declare const AppFieldDefinitionSchema: z.ZodObject<{
78
+ label: z.ZodString;
79
+ fieldHandle: z.ZodString;
80
+ entityHandle: z.ZodString;
81
+ definitionHandle: z.ZodString;
82
+ required: z.ZodOptional<z.ZodBoolean>;
83
+ system: z.ZodOptional<z.ZodBoolean>;
84
+ unique: z.ZodOptional<z.ZodBoolean>;
85
+ defaultValue: z.ZodOptional<z.ZodObject<{
86
+ value: z.ZodUnknown;
87
+ }, z.core.$strip>>;
88
+ visibility: z.ZodOptional<z.ZodObject<{
89
+ data: z.ZodOptional<z.ZodBoolean>;
90
+ list: z.ZodOptional<z.ZodBoolean>;
91
+ filters: z.ZodOptional<z.ZodBoolean>;
92
+ }, z.core.$strip>>;
93
+ }, z.core.$strip>;
94
+ /**
95
+ * Schema for channel tool bindings.
96
+ */
97
+ export declare const ChannelToolBindingsSchema: z.ZodObject<{
98
+ send_message: z.ZodString;
99
+ }, z.core.$strip>;
100
+ /**
101
+ * Schema for channel identifier type.
102
+ */
103
+ export declare const ChannelIdentifierTypeSchema: z.ZodEnum<{
104
+ DEDICATED_PHONE: "DEDICATED_PHONE";
105
+ TEXT: "TEXT";
106
+ EMAIL: "EMAIL";
107
+ }>;
108
+ /**
109
+ * Schema for channel identifier value.
110
+ */
111
+ export declare const ChannelIdentifierValueSchema: z.ZodObject<{
112
+ type: z.ZodEnum<{
113
+ DEDICATED_PHONE: "DEDICATED_PHONE";
114
+ TEXT: "TEXT";
115
+ EMAIL: "EMAIL";
116
+ }>;
117
+ definitionHandle: z.ZodString;
118
+ }, z.core.$strip>;
119
+ /**
120
+ * Schema for communication channel definition.
121
+ */
122
+ export declare const CommunicationChannelDefinitionSchema: z.ZodObject<{
123
+ handle: z.ZodString;
124
+ name: z.ZodString;
125
+ icon: z.ZodOptional<z.ZodString>;
126
+ tools: z.ZodObject<{
127
+ send_message: z.ZodString;
128
+ }, z.core.$strip>;
129
+ identifierValue: z.ZodObject<{
130
+ type: z.ZodEnum<{
131
+ DEDICATED_PHONE: "DEDICATED_PHONE";
132
+ TEXT: "TEXT";
133
+ EMAIL: "EMAIL";
134
+ }>;
135
+ definitionHandle: z.ZodString;
136
+ }, z.core.$strip>;
137
+ appFields: z.ZodOptional<z.ZodArray<z.ZodObject<{
138
+ label: z.ZodString;
139
+ fieldHandle: z.ZodString;
140
+ entityHandle: z.ZodString;
141
+ definitionHandle: z.ZodString;
142
+ required: z.ZodOptional<z.ZodBoolean>;
143
+ system: z.ZodOptional<z.ZodBoolean>;
144
+ unique: z.ZodOptional<z.ZodBoolean>;
145
+ defaultValue: z.ZodOptional<z.ZodObject<{
146
+ value: z.ZodUnknown;
147
+ }, z.core.$strip>>;
148
+ visibility: z.ZodOptional<z.ZodObject<{
149
+ data: z.ZodOptional<z.ZodBoolean>;
150
+ list: z.ZodOptional<z.ZodBoolean>;
151
+ filters: z.ZodOptional<z.ZodBoolean>;
152
+ }, z.core.$strip>>;
153
+ }, z.core.$strip>>>;
154
+ settings: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
155
+ }, z.core.$strip>;
156
+ /**
157
+ * Schema for workflow action input.
158
+ */
159
+ export declare const WorkflowActionInputSchema: z.ZodObject<{
160
+ key: z.ZodString;
161
+ label: z.ZodString;
162
+ fieldRef: z.ZodOptional<z.ZodObject<{
163
+ fieldHandle: z.ZodString;
164
+ entityHandle: z.ZodString;
165
+ }, z.core.$strip>>;
166
+ template: z.ZodOptional<z.ZodString>;
167
+ }, z.core.$strip>;
168
+ /**
169
+ * Schema for workflow action.
170
+ */
171
+ export declare const WorkflowActionSchema: z.ZodObject<{
172
+ label: z.ZodString;
173
+ handle: z.ZodString;
174
+ batch: z.ZodOptional<z.ZodBoolean>;
175
+ entityHandle: z.ZodOptional<z.ZodString>;
176
+ inputs: z.ZodOptional<z.ZodArray<z.ZodObject<{
177
+ key: z.ZodString;
178
+ label: z.ZodString;
179
+ fieldRef: z.ZodOptional<z.ZodObject<{
180
+ fieldHandle: z.ZodString;
181
+ entityHandle: z.ZodString;
182
+ }, z.core.$strip>>;
183
+ template: z.ZodOptional<z.ZodString>;
184
+ }, z.core.$strip>>>;
185
+ }, z.core.$strip>;
186
+ /**
187
+ * Schema for workflow definition.
188
+ */
189
+ export declare const WorkflowDefinitionSchema: z.ZodObject<{
190
+ path: z.ZodString;
191
+ label: z.ZodOptional<z.ZodString>;
192
+ handle: z.ZodOptional<z.ZodString>;
193
+ channelHandle: z.ZodOptional<z.ZodString>;
194
+ actions: z.ZodArray<z.ZodObject<{
195
+ label: z.ZodString;
196
+ handle: z.ZodString;
197
+ batch: z.ZodOptional<z.ZodBoolean>;
198
+ entityHandle: z.ZodOptional<z.ZodString>;
199
+ inputs: z.ZodOptional<z.ZodArray<z.ZodObject<{
200
+ key: z.ZodString;
201
+ label: z.ZodString;
202
+ fieldRef: z.ZodOptional<z.ZodObject<{
203
+ fieldHandle: z.ZodString;
204
+ entityHandle: z.ZodString;
205
+ }, z.core.$strip>>;
206
+ template: z.ZodOptional<z.ZodString>;
207
+ }, z.core.$strip>>>;
208
+ }, z.core.$strip>>;
209
+ }, z.core.$strip>;
210
+ /**
211
+ * Schema for compute layer type.
212
+ */
213
+ export declare const ComputeLayerTypeSchema: z.ZodEnum<{
214
+ dedicated: "dedicated";
215
+ serverless: "serverless";
216
+ }>;
217
+ /**
218
+ * Schema for internal field data types.
219
+ */
220
+ export declare const InternalFieldDataTypeSchema: z.ZodEnum<{
221
+ TEXT: "TEXT";
222
+ EMAIL: "EMAIL";
223
+ LONG_TEXT: "LONG_TEXT";
224
+ NUMBER: "NUMBER";
225
+ BOOLEAN: "BOOLEAN";
226
+ DATE: "DATE";
227
+ DATETIME: "DATETIME";
228
+ URL: "URL";
229
+ PHONE: "PHONE";
230
+ SELECT: "SELECT";
231
+ MULTI_SELECT: "MULTI_SELECT";
232
+ JSON: "JSON";
233
+ }>;
234
+ /**
235
+ * Schema for a field within an internal model.
236
+ */
237
+ export declare const InternalFieldDefinitionSchema: z.ZodObject<{
238
+ handle: z.ZodString;
239
+ label: z.ZodString;
240
+ type: z.ZodEnum<{
241
+ TEXT: "TEXT";
242
+ EMAIL: "EMAIL";
243
+ LONG_TEXT: "LONG_TEXT";
244
+ NUMBER: "NUMBER";
245
+ BOOLEAN: "BOOLEAN";
246
+ DATE: "DATE";
247
+ DATETIME: "DATETIME";
248
+ URL: "URL";
249
+ PHONE: "PHONE";
250
+ SELECT: "SELECT";
251
+ MULTI_SELECT: "MULTI_SELECT";
252
+ JSON: "JSON";
253
+ }>;
254
+ definitionHandle: z.ZodOptional<z.ZodString>;
255
+ required: z.ZodOptional<z.ZodBoolean>;
256
+ unique: z.ZodOptional<z.ZodBoolean>;
257
+ system: z.ZodOptional<z.ZodBoolean>;
258
+ isList: z.ZodOptional<z.ZodBoolean>;
259
+ defaultValue: z.ZodOptional<z.ZodObject<{
260
+ value: z.ZodUnknown;
261
+ }, z.core.$strip>>;
262
+ description: z.ZodOptional<z.ZodString>;
263
+ }, z.core.$strip>;
264
+ /**
265
+ * Schema for an internal model definition.
266
+ */
267
+ export declare const InternalModelDefinitionSchema: z.ZodObject<{
268
+ handle: z.ZodString;
269
+ name: z.ZodString;
270
+ namePlural: z.ZodString;
271
+ labelTemplate: z.ZodString;
272
+ description: z.ZodOptional<z.ZodString>;
273
+ fields: z.ZodArray<z.ZodObject<{
274
+ handle: z.ZodString;
275
+ label: z.ZodString;
276
+ type: z.ZodEnum<{
277
+ TEXT: "TEXT";
278
+ EMAIL: "EMAIL";
279
+ LONG_TEXT: "LONG_TEXT";
280
+ NUMBER: "NUMBER";
281
+ BOOLEAN: "BOOLEAN";
282
+ DATE: "DATE";
283
+ DATETIME: "DATETIME";
284
+ URL: "URL";
285
+ PHONE: "PHONE";
286
+ SELECT: "SELECT";
287
+ MULTI_SELECT: "MULTI_SELECT";
288
+ JSON: "JSON";
289
+ }>;
290
+ definitionHandle: z.ZodOptional<z.ZodString>;
291
+ required: z.ZodOptional<z.ZodBoolean>;
292
+ unique: z.ZodOptional<z.ZodBoolean>;
293
+ system: z.ZodOptional<z.ZodBoolean>;
294
+ isList: z.ZodOptional<z.ZodBoolean>;
295
+ defaultValue: z.ZodOptional<z.ZodObject<{
296
+ value: z.ZodUnknown;
297
+ }, z.core.$strip>>;
298
+ description: z.ZodOptional<z.ZodString>;
299
+ }, z.core.$strip>>;
300
+ }, z.core.$strip>;
301
+ /**
302
+ * Schema for the full skedyul.config.ts stored on an Executable.
303
+ * This is the single source of truth for all app configuration.
304
+ *
305
+ * Note: tools and webhooks are stored as null/unknown since they are
306
+ * dynamic imports that cannot be serialized. Use SerializableSkedyulConfigSchema
307
+ * for database storage which uses ToolMetadata[] and WebhookMetadata[] instead.
308
+ */
309
+ export declare const SkedyulConfigSchema: z.ZodObject<{
310
+ name: z.ZodString;
311
+ version: z.ZodOptional<z.ZodString>;
312
+ description: z.ZodOptional<z.ZodString>;
313
+ computeLayer: z.ZodOptional<z.ZodEnum<{
314
+ dedicated: "dedicated";
315
+ serverless: "serverless";
316
+ }>>;
317
+ tools: z.ZodOptional<z.ZodUnknown>;
318
+ webhooks: z.ZodOptional<z.ZodUnknown>;
319
+ workflowsPath: z.ZodOptional<z.ZodString>;
320
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
321
+ label: z.ZodString;
322
+ required: z.ZodOptional<z.ZodBoolean>;
323
+ visibility: z.ZodOptional<z.ZodEnum<{
324
+ visible: "visible";
325
+ encrypted: "encrypted";
326
+ }>>;
327
+ default: z.ZodOptional<z.ZodString>;
328
+ description: z.ZodOptional<z.ZodString>;
329
+ placeholder: z.ZodOptional<z.ZodString>;
330
+ }, z.core.$strip>>>;
331
+ install: z.ZodOptional<z.ZodObject<{
332
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
333
+ label: z.ZodString;
334
+ required: z.ZodOptional<z.ZodBoolean>;
335
+ visibility: z.ZodOptional<z.ZodEnum<{
336
+ visible: "visible";
337
+ encrypted: "encrypted";
338
+ }>>;
339
+ default: z.ZodOptional<z.ZodString>;
340
+ description: z.ZodOptional<z.ZodString>;
341
+ placeholder: z.ZodOptional<z.ZodString>;
342
+ }, z.core.$strip>>>;
343
+ appModels: z.ZodOptional<z.ZodArray<z.ZodObject<{
344
+ entityHandle: z.ZodString;
345
+ label: z.ZodString;
346
+ description: z.ZodOptional<z.ZodString>;
347
+ }, z.core.$strip>>>;
348
+ }, z.core.$strip>>;
349
+ communicationChannels: z.ZodOptional<z.ZodArray<z.ZodObject<{
350
+ handle: z.ZodString;
351
+ name: z.ZodString;
352
+ icon: z.ZodOptional<z.ZodString>;
353
+ tools: z.ZodObject<{
354
+ send_message: z.ZodString;
355
+ }, z.core.$strip>;
356
+ identifierValue: z.ZodObject<{
357
+ type: z.ZodEnum<{
358
+ DEDICATED_PHONE: "DEDICATED_PHONE";
359
+ TEXT: "TEXT";
360
+ EMAIL: "EMAIL";
361
+ }>;
362
+ definitionHandle: z.ZodString;
363
+ }, z.core.$strip>;
364
+ appFields: z.ZodOptional<z.ZodArray<z.ZodObject<{
365
+ label: z.ZodString;
366
+ fieldHandle: z.ZodString;
367
+ entityHandle: z.ZodString;
368
+ definitionHandle: z.ZodString;
369
+ required: z.ZodOptional<z.ZodBoolean>;
370
+ system: z.ZodOptional<z.ZodBoolean>;
371
+ unique: z.ZodOptional<z.ZodBoolean>;
372
+ defaultValue: z.ZodOptional<z.ZodObject<{
373
+ value: z.ZodUnknown;
374
+ }, z.core.$strip>>;
375
+ visibility: z.ZodOptional<z.ZodObject<{
376
+ data: z.ZodOptional<z.ZodBoolean>;
377
+ list: z.ZodOptional<z.ZodBoolean>;
378
+ filters: z.ZodOptional<z.ZodBoolean>;
379
+ }, z.core.$strip>>;
380
+ }, z.core.$strip>>>;
381
+ settings: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
382
+ }, z.core.$strip>>>;
383
+ workflows: z.ZodOptional<z.ZodArray<z.ZodObject<{
384
+ path: z.ZodString;
385
+ label: z.ZodOptional<z.ZodString>;
386
+ handle: z.ZodOptional<z.ZodString>;
387
+ channelHandle: z.ZodOptional<z.ZodString>;
388
+ actions: z.ZodArray<z.ZodObject<{
389
+ label: z.ZodString;
390
+ handle: z.ZodString;
391
+ batch: z.ZodOptional<z.ZodBoolean>;
392
+ entityHandle: z.ZodOptional<z.ZodString>;
393
+ inputs: z.ZodOptional<z.ZodArray<z.ZodObject<{
394
+ key: z.ZodString;
395
+ label: z.ZodString;
396
+ fieldRef: z.ZodOptional<z.ZodObject<{
397
+ fieldHandle: z.ZodString;
398
+ entityHandle: z.ZodString;
399
+ }, z.core.$strip>>;
400
+ template: z.ZodOptional<z.ZodString>;
401
+ }, z.core.$strip>>>;
402
+ }, z.core.$strip>>;
403
+ }, z.core.$strip>>>;
404
+ internalModels: z.ZodOptional<z.ZodArray<z.ZodObject<{
405
+ handle: z.ZodString;
406
+ name: z.ZodString;
407
+ namePlural: z.ZodString;
408
+ labelTemplate: z.ZodString;
409
+ description: z.ZodOptional<z.ZodString>;
410
+ fields: z.ZodArray<z.ZodObject<{
411
+ handle: z.ZodString;
412
+ label: z.ZodString;
413
+ type: z.ZodEnum<{
414
+ TEXT: "TEXT";
415
+ EMAIL: "EMAIL";
416
+ LONG_TEXT: "LONG_TEXT";
417
+ NUMBER: "NUMBER";
418
+ BOOLEAN: "BOOLEAN";
419
+ DATE: "DATE";
420
+ DATETIME: "DATETIME";
421
+ URL: "URL";
422
+ PHONE: "PHONE";
423
+ SELECT: "SELECT";
424
+ MULTI_SELECT: "MULTI_SELECT";
425
+ JSON: "JSON";
426
+ }>;
427
+ definitionHandle: z.ZodOptional<z.ZodString>;
428
+ required: z.ZodOptional<z.ZodBoolean>;
429
+ unique: z.ZodOptional<z.ZodBoolean>;
430
+ system: z.ZodOptional<z.ZodBoolean>;
431
+ isList: z.ZodOptional<z.ZodBoolean>;
432
+ defaultValue: z.ZodOptional<z.ZodObject<{
433
+ value: z.ZodUnknown;
434
+ }, z.core.$strip>>;
435
+ description: z.ZodOptional<z.ZodString>;
436
+ }, z.core.$strip>>;
437
+ }, z.core.$strip>>>;
438
+ }, z.core.$strip>;
439
+ /**
440
+ * Inferred type from SkedyulConfigSchema for runtime-validated configs.
441
+ */
442
+ export type ParsedSkedyulConfig = z.infer<typeof SkedyulConfigSchema>;
443
+ /**
444
+ * Safely parse a skedyul config, returning null if invalid.
445
+ */
446
+ export declare function safeParseConfig(data: unknown): ParsedSkedyulConfig | null;
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SkedyulConfigSchema = exports.InternalModelDefinitionSchema = exports.InternalFieldDefinitionSchema = exports.InternalFieldDataTypeSchema = exports.ComputeLayerTypeSchema = exports.WorkflowDefinitionSchema = exports.WorkflowActionSchema = exports.WorkflowActionInputSchema = exports.CommunicationChannelDefinitionSchema = exports.ChannelIdentifierValueSchema = exports.ChannelIdentifierTypeSchema = exports.ChannelToolBindingsSchema = exports.AppFieldDefinitionSchema = exports.AppFieldVisibilitySchema = exports.InstallConfigSchema = exports.AppModelDefinitionSchema = exports.EnvSchemaSchema = exports.EnvVariableDefinitionSchema = exports.EnvVisibilitySchema = void 0;
4
+ exports.safeParseConfig = safeParseConfig;
5
+ const zod_1 = require("zod");
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Zod Schemas for SkedyulConfig
8
+ // These schemas are used for runtime validation of config files.
9
+ // TypeScript types in config.ts should match these schemas.
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ /**
12
+ * Schema for environment variable visibility
13
+ */
14
+ exports.EnvVisibilitySchema = zod_1.z.enum(['visible', 'encrypted']);
15
+ /**
16
+ * Schema for a single environment variable definition.
17
+ */
18
+ exports.EnvVariableDefinitionSchema = zod_1.z.object({
19
+ label: zod_1.z.string(),
20
+ required: zod_1.z.boolean().optional(),
21
+ visibility: exports.EnvVisibilitySchema.optional(),
22
+ default: zod_1.z.string().optional(),
23
+ description: zod_1.z.string().optional(),
24
+ placeholder: zod_1.z.string().optional(),
25
+ });
26
+ /**
27
+ * Schema for a collection of environment variable definitions.
28
+ */
29
+ exports.EnvSchemaSchema = zod_1.z.record(zod_1.z.string(), exports.EnvVariableDefinitionSchema);
30
+ /**
31
+ * Schema for app model definition.
32
+ */
33
+ exports.AppModelDefinitionSchema = zod_1.z.object({
34
+ entityHandle: zod_1.z.string(),
35
+ label: zod_1.z.string(),
36
+ description: zod_1.z.string().optional(),
37
+ });
38
+ /**
39
+ * Schema for install configuration.
40
+ */
41
+ exports.InstallConfigSchema = zod_1.z.object({
42
+ env: exports.EnvSchemaSchema.optional(),
43
+ appModels: zod_1.z.array(exports.AppModelDefinitionSchema).optional(),
44
+ });
45
+ /**
46
+ * Schema for app field visibility.
47
+ */
48
+ exports.AppFieldVisibilitySchema = zod_1.z.object({
49
+ data: zod_1.z.boolean().optional(),
50
+ list: zod_1.z.boolean().optional(),
51
+ filters: zod_1.z.boolean().optional(),
52
+ });
53
+ /**
54
+ * Schema for app field definition (communication channels).
55
+ */
56
+ exports.AppFieldDefinitionSchema = zod_1.z.object({
57
+ label: zod_1.z.string(),
58
+ fieldHandle: zod_1.z.string(),
59
+ entityHandle: zod_1.z.string(),
60
+ definitionHandle: zod_1.z.string(),
61
+ required: zod_1.z.boolean().optional(),
62
+ system: zod_1.z.boolean().optional(),
63
+ unique: zod_1.z.boolean().optional(),
64
+ defaultValue: zod_1.z.object({ value: zod_1.z.unknown() }).optional(),
65
+ visibility: exports.AppFieldVisibilitySchema.optional(),
66
+ });
67
+ /**
68
+ * Schema for channel tool bindings.
69
+ */
70
+ exports.ChannelToolBindingsSchema = zod_1.z.object({
71
+ send_message: zod_1.z.string(),
72
+ });
73
+ /**
74
+ * Schema for channel identifier type.
75
+ */
76
+ exports.ChannelIdentifierTypeSchema = zod_1.z.enum([
77
+ 'DEDICATED_PHONE',
78
+ 'TEXT',
79
+ 'EMAIL',
80
+ ]);
81
+ /**
82
+ * Schema for channel identifier value.
83
+ */
84
+ exports.ChannelIdentifierValueSchema = zod_1.z.object({
85
+ type: exports.ChannelIdentifierTypeSchema,
86
+ definitionHandle: zod_1.z.string(),
87
+ });
88
+ /**
89
+ * Schema for communication channel definition.
90
+ */
91
+ exports.CommunicationChannelDefinitionSchema = zod_1.z.object({
92
+ handle: zod_1.z.string(),
93
+ name: zod_1.z.string(),
94
+ icon: zod_1.z.string().optional(),
95
+ tools: exports.ChannelToolBindingsSchema,
96
+ identifierValue: exports.ChannelIdentifierValueSchema,
97
+ appFields: zod_1.z.array(exports.AppFieldDefinitionSchema).optional(),
98
+ settings: zod_1.z.array(zod_1.z.unknown()).optional(),
99
+ });
100
+ /**
101
+ * Schema for workflow action input.
102
+ */
103
+ exports.WorkflowActionInputSchema = zod_1.z.object({
104
+ key: zod_1.z.string(),
105
+ label: zod_1.z.string(),
106
+ fieldRef: zod_1.z
107
+ .object({
108
+ fieldHandle: zod_1.z.string(),
109
+ entityHandle: zod_1.z.string(),
110
+ })
111
+ .optional(),
112
+ template: zod_1.z.string().optional(),
113
+ });
114
+ /**
115
+ * Schema for workflow action.
116
+ */
117
+ exports.WorkflowActionSchema = zod_1.z.object({
118
+ label: zod_1.z.string(),
119
+ handle: zod_1.z.string(),
120
+ batch: zod_1.z.boolean().optional(),
121
+ entityHandle: zod_1.z.string().optional(),
122
+ inputs: zod_1.z.array(exports.WorkflowActionInputSchema).optional(),
123
+ });
124
+ /**
125
+ * Schema for workflow definition.
126
+ */
127
+ exports.WorkflowDefinitionSchema = zod_1.z.object({
128
+ /** Path to external YAML workflow file (relative to config) */
129
+ path: zod_1.z.string(),
130
+ /** Human-readable label (optional when path is provided, inferred from YAML) */
131
+ label: zod_1.z.string().optional(),
132
+ /** Workflow handle/key (optional when path is provided, inferred from YAML) */
133
+ handle: zod_1.z.string().optional(),
134
+ /** Channel handle (optional) */
135
+ channelHandle: zod_1.z.string().optional(),
136
+ /** Actions in this workflow */
137
+ actions: zod_1.z.array(exports.WorkflowActionSchema),
138
+ });
139
+ /**
140
+ * Schema for compute layer type.
141
+ */
142
+ exports.ComputeLayerTypeSchema = zod_1.z.enum(['serverless', 'dedicated']);
143
+ // ─────────────────────────────────────────────────────────────────────────────
144
+ // Internal Model Schemas (App-owned models)
145
+ // ─────────────────────────────────────────────────────────────────────────────
146
+ /**
147
+ * Schema for internal field data types.
148
+ */
149
+ exports.InternalFieldDataTypeSchema = zod_1.z.enum([
150
+ 'TEXT',
151
+ 'LONG_TEXT',
152
+ 'NUMBER',
153
+ 'BOOLEAN',
154
+ 'DATE',
155
+ 'DATETIME',
156
+ 'EMAIL',
157
+ 'URL',
158
+ 'PHONE',
159
+ 'SELECT',
160
+ 'MULTI_SELECT',
161
+ 'JSON',
162
+ ]);
163
+ /**
164
+ * Schema for a field within an internal model.
165
+ */
166
+ exports.InternalFieldDefinitionSchema = zod_1.z.object({
167
+ handle: zod_1.z.string(),
168
+ label: zod_1.z.string(),
169
+ type: exports.InternalFieldDataTypeSchema,
170
+ definitionHandle: zod_1.z.string().optional(),
171
+ required: zod_1.z.boolean().optional(),
172
+ unique: zod_1.z.boolean().optional(),
173
+ system: zod_1.z.boolean().optional(),
174
+ isList: zod_1.z.boolean().optional(),
175
+ defaultValue: zod_1.z.object({ value: zod_1.z.unknown() }).optional(),
176
+ description: zod_1.z.string().optional(),
177
+ });
178
+ /**
179
+ * Schema for an internal model definition.
180
+ */
181
+ exports.InternalModelDefinitionSchema = zod_1.z.object({
182
+ handle: zod_1.z.string(),
183
+ name: zod_1.z.string(),
184
+ namePlural: zod_1.z.string(),
185
+ labelTemplate: zod_1.z.string(),
186
+ description: zod_1.z.string().optional(),
187
+ fields: zod_1.z.array(exports.InternalFieldDefinitionSchema),
188
+ });
189
+ /**
190
+ * Schema for the full skedyul.config.ts stored on an Executable.
191
+ * This is the single source of truth for all app configuration.
192
+ *
193
+ * Note: tools and webhooks are stored as null/unknown since they are
194
+ * dynamic imports that cannot be serialized. Use SerializableSkedyulConfigSchema
195
+ * for database storage which uses ToolMetadata[] and WebhookMetadata[] instead.
196
+ */
197
+ exports.SkedyulConfigSchema = zod_1.z.object({
198
+ name: zod_1.z.string(),
199
+ version: zod_1.z.string().optional(),
200
+ description: zod_1.z.string().optional(),
201
+ computeLayer: exports.ComputeLayerTypeSchema.optional(),
202
+ // Dynamic imports become null after transpilation
203
+ tools: zod_1.z.unknown().optional(),
204
+ webhooks: zod_1.z.unknown().optional(),
205
+ workflowsPath: zod_1.z.string().optional(),
206
+ env: exports.EnvSchemaSchema.optional(),
207
+ install: exports.InstallConfigSchema.optional(),
208
+ communicationChannels: zod_1.z.array(exports.CommunicationChannelDefinitionSchema).optional(),
209
+ workflows: zod_1.z.array(exports.WorkflowDefinitionSchema).optional(),
210
+ internalModels: zod_1.z.array(exports.InternalModelDefinitionSchema).optional(),
211
+ });
212
+ /**
213
+ * Safely parse a skedyul config, returning null if invalid.
214
+ */
215
+ function safeParseConfig(data) {
216
+ const result = exports.SkedyulConfigSchema.safeParse(data);
217
+ return result.success ? result.data : null;
218
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",