@highstate/contract 0.9.16 → 0.9.18

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/index.js CHANGED
@@ -1,13 +1,274 @@
1
- // src/instance.ts
2
- import { Type } from "@sinclair/typebox";
3
- var boundaryInput = Symbol("boundaryInput");
1
+ import z5, { z } from 'zod';
2
+ export { z } from 'zod';
3
+ import { mapValues, pickBy, isNonNullish } from 'remeda';
4
+ import { Ajv } from 'ajv';
5
+
6
+ // src/entity.ts
7
+ var userObjectMetaSchema = z.object({
8
+ /**
9
+ * Human-readable name of the object.
10
+ *
11
+ * Used in UI components for better user experience.
12
+ */
13
+ title: z.string().optional(),
14
+ /**
15
+ * The title used globally for the object.
16
+ *
17
+ * For example, the title of an instance secret is "Password" which is okay
18
+ * to display in the instance secret list, but when the secret is displayed in a
19
+ * global secret list the name should be more descriptive, like "Proxmox Password".
20
+ */
21
+ globalTitle: z.string().optional(),
22
+ /**
23
+ * Description of the object.
24
+ *
25
+ * Provides additional context for users and developers.
26
+ */
27
+ description: z.string().optional(),
28
+ /**
29
+ * The color of the object.
30
+ *
31
+ * Used in UI components to visually distinguish objects.
32
+ */
33
+ color: z.string().optional(),
34
+ /**
35
+ * Primary icon identifier.
36
+ *
37
+ * Should reference a iconify icon name, like "mdi:server" or "gg:remote".
38
+ */
39
+ icon: z.string().optional(),
40
+ /**
41
+ * The color of the primary icon.
42
+ */
43
+ iconColor: z.string().optional(),
44
+ /**
45
+ * The secondary icon identifier.
46
+ *
47
+ * Used to provide additional context or actions related to the object.
48
+ *
49
+ * Should reference a iconify icon name, like "mdi:edit" or "mdi:delete".
50
+ */
51
+ secondaryIcon: z.string().optional(),
52
+ /**
53
+ * The color of the secondary icon.
54
+ */
55
+ secondaryIconColor: z.string().optional()
56
+ });
57
+ var objectMetaSchema = userObjectMetaSchema.extend({
58
+ /**
59
+ * Creation timestamp in milliseconds.
60
+ *
61
+ * Managed automatically by the system.
62
+ */
63
+ createdAt: z.number().optional(),
64
+ /**
65
+ * Last update timestamp in milliseconds.
66
+ *
67
+ * Managed automatically by the system.
68
+ */
69
+ updatedAt: z.number().optional(),
70
+ /**
71
+ * The optional version of the document to support optimistic concurrency control.
72
+ *
73
+ * Managed automatically by the system.
74
+ */
75
+ version: z.number().optional()
76
+ });
77
+ var genericNameSchema = z.string().regex(/^[a-z][a-z0-9-_.]+$/).min(2).max(64);
78
+ var fieldNameSchema = z.string().regex(/^[a-z][a-zA-Z0-9]+$/).min(2).max(64);
79
+
80
+ // src/i18n.ts
81
+ var knownAbbreviationsMap = /* @__PURE__ */ new Map();
82
+ function registerKnownAbbreviations(abbreviations) {
83
+ for (const abbr of abbreviations) {
84
+ const lower = abbr.toLowerCase();
85
+ if (!knownAbbreviationsMap.has(lower)) {
86
+ knownAbbreviationsMap.set(lower, abbr);
87
+ }
88
+ }
89
+ }
90
+ function camelCaseToHumanReadable(text2) {
91
+ const words = text2.split(/(?=[A-Z])|_|-|\./);
92
+ return words.map((word) => {
93
+ const lower = word.toLowerCase();
94
+ if (knownAbbreviationsMap.has(lower)) {
95
+ return knownAbbreviationsMap.get(lower);
96
+ }
97
+ return word.charAt(0).toUpperCase() + word.slice(1);
98
+ }).join(" ");
99
+ }
100
+
101
+ // src/entity.ts
102
+ var entityModelSchema = z.object({
103
+ /**
104
+ * The static type of the entity.
105
+ */
106
+ type: z.string(),
107
+ /**
108
+ * The JSON schema of the entity value.
109
+ */
110
+ schema: z.custom(),
111
+ /**
112
+ * The extra metadata of the entity.
113
+ */
114
+ meta: objectMetaSchema.required({ title: true }).pick({
115
+ title: true,
116
+ description: true,
117
+ color: true,
118
+ icon: true,
119
+ iconColor: true
120
+ }),
121
+ /**
122
+ * The CRC32 of the entity definition.
123
+ */
124
+ definitionHash: z.number()
125
+ });
126
+ function defineEntity(options) {
127
+ if (!options.type) {
128
+ throw new Error("Entity type is required");
129
+ }
130
+ if (!options.schema) {
131
+ throw new Error("Entity schema is required");
132
+ }
133
+ try {
134
+ return {
135
+ type: options.type,
136
+ schema: options.schema,
137
+ model: {
138
+ type: options.type,
139
+ schema: z.toJSONSchema(options.schema, { target: "draft-7" }),
140
+ meta: {
141
+ ...options.meta,
142
+ title: options.meta?.title ?? camelCaseToHumanReadable(options.type)
143
+ },
144
+ // will be calculated by the library loader
145
+ definitionHash: null
146
+ }
147
+ };
148
+ } catch (error) {
149
+ throw new Error(`Failed to define entity "${options.type}"`, { cause: error });
150
+ }
151
+ }
152
+ function isEntity(value) {
153
+ return typeof value === "object" && value !== null && "model" in value;
154
+ }
155
+ var positionSchema = z.object({
156
+ x: z.number(),
157
+ y: z.number()
158
+ });
159
+ var instanceIdSchema = z.templateLiteral([genericNameSchema, ":", genericNameSchema]);
160
+ var instanceInputSchema = z.object({
161
+ instanceId: instanceIdSchema,
162
+ output: z.string()
163
+ });
164
+ var hubInputSchema = z.object({
165
+ hubId: z.string()
166
+ });
167
+ var instanceModelPatchSchema = z.object({
168
+ /**
169
+ * The static arguments passed to the instance.
170
+ */
171
+ args: z.record(z.string(), z.unknown()).optional(),
172
+ /**
173
+ * The direct instances passed as inputs to the instance.
174
+ */
175
+ inputs: z.record(z.string(), z.array(instanceInputSchema)).optional(),
176
+ /**
177
+ * The resolved unit inputs for the instance.
178
+ *
179
+ * Only for computed composite instances.
180
+ */
181
+ hubInputs: z.record(z.string(), z.array(hubInputSchema)).optional(),
182
+ /**
183
+ * The inputs injected to the instance from the hubs.
184
+ *
185
+ * While `hubInputs` allows to pass hubs to distinct inputs,
186
+ * `injectionInputs` allows to pass hubs to the instance as a whole filling all inputs with matching types.
187
+ *
188
+ * Only for designer-first instances.
189
+ */
190
+ injectionInputs: z.array(hubInputSchema).optional(),
191
+ /**
192
+ * The position of the instance on the canvas.
193
+ *
194
+ * Only for designer-first instances.
195
+ */
196
+ position: positionSchema.optional()
197
+ });
198
+ var instanceModelSchema = z.object({
199
+ /**
200
+ * The id of the instance unique within the project.
201
+ *
202
+ * The format is `${instanceType}:${instanceName}`.
203
+ */
204
+ id: instanceIdSchema,
205
+ /**
206
+ * The type of the instance.
207
+ */
208
+ type: genericNameSchema,
209
+ /**
210
+ * The name of the instance.
211
+ *
212
+ * Must be unique within instances of the same type in the project.
213
+ */
214
+ name: genericNameSchema,
215
+ ...instanceModelPatchSchema.shape,
216
+ /**
217
+ * The id of the top level parent instance.
218
+ *
219
+ * Only for child instances of the composite instances.
220
+ */
221
+ resolvedInputs: z.record(z.string(), z.array(instanceInputSchema)).optional(),
222
+ /**
223
+ * The position of the instance on the canvas.
224
+ *
225
+ * Only for designer-first instances.
226
+ */
227
+ parentId: z.string().optional(),
228
+ /**
229
+ * The direct instance outputs returned by the instance as outputs.
230
+ *
231
+ * Only for computed composite instances.
232
+ */
233
+ outputs: z.record(z.string(), z.array(instanceInputSchema)).optional(),
234
+ /**
235
+ * The resolved unit outputs for the instance.
236
+ *
237
+ * Only for computed composite instances.
238
+ */
239
+ resolvedOutputs: z.record(z.string(), z.array(instanceInputSchema)).optional()
240
+ });
241
+ var hubModelPatchSchema = z.object({
242
+ /**
243
+ * The position of the hub on the canvas.
244
+ */
245
+ position: positionSchema.optional(),
246
+ /**
247
+ * The inputs of the hub.
248
+ */
249
+ inputs: z.array(instanceInputSchema).optional(),
250
+ /**
251
+ * The inputs injected to the hub from the hubs.
252
+ *
253
+ * While `inputs` allows to pass hubs to distinct inputs,
254
+ * `injectionInputs` allows to pass hubs to the hub as a whole filling all inputs with matching types.
255
+ */
256
+ injectionInputs: z.array(hubInputSchema).optional()
257
+ });
258
+ var hubModelSchema = z.object({
259
+ /**
260
+ * The id of the hub unique within the project.
261
+ */
262
+ id: z.nanoid(),
263
+ ...hubModelPatchSchema.shape
264
+ });
4
265
  function getInstanceId(instanceType, instanceName) {
5
266
  return `${instanceType}:${instanceName}`;
6
267
  }
7
268
  function parseInstanceId(instanceId) {
8
269
  const parts = instanceId.split(":");
9
270
  if (parts.length !== 2) {
10
- throw new Error(`Invalid instance key: ${instanceId}`);
271
+ throw new Error(`Invalid instance ID: ${instanceId}`);
11
272
  }
12
273
  return parts;
13
274
  }
@@ -40,52 +301,51 @@ function findRequiredInputs(inputs, names) {
40
301
  }
41
302
  var HighstateSignature = /* @__PURE__ */ ((HighstateSignature2) => {
42
303
  HighstateSignature2["Artifact"] = "d55c63ac-3174-4756-808f-f778e99af0d1";
304
+ HighstateSignature2["Secret"] = "56ebf97b-57de-4985-8c86-bc1bc5871e6e";
305
+ HighstateSignature2["Yaml"] = "c857cac5-caa6-4421-b82c-e561fbce6367";
43
306
  return HighstateSignature2;
44
307
  })(HighstateSignature || {});
45
- var fileMetaSchema = Type.Object({
46
- name: Type.String(),
47
- contentType: Type.Optional(Type.String()),
48
- size: Type.Optional(Type.Number()),
49
- mode: Type.Optional(Type.Number()),
50
- isBinary: Type.Optional(Type.Boolean())
308
+ var yamlValueSchema = z.object({
309
+ ["c857cac5-caa6-4421-b82c-e561fbce6367" /* Yaml */]: z.literal(true),
310
+ value: z.string()
311
+ });
312
+ var fileMetaSchema = z.object({
313
+ name: z.string(),
314
+ contentType: z.string().optional(),
315
+ size: z.number().optional(),
316
+ mode: z.number().optional(),
317
+ isBinary: z.boolean().optional()
51
318
  });
52
- var unitObjectMetaSchema = Type.Object({
53
- displayName: Type.Optional(Type.String()),
54
- description: Type.Optional(Type.String()),
55
- primaryIcon: Type.Optional(Type.String())
319
+ var unitObjectMetaSchema = z.object({
320
+ displayName: z.string().optional(),
321
+ description: z.string().optional(),
322
+ primaryIcon: z.string().optional()
56
323
  });
57
- var unitArtifactSchema = Type.Object({
58
- hash: Type.String(),
59
- meta: Type.Optional(unitObjectMetaSchema)
324
+ var unitSecretSchema = z.object({
325
+ ["56ebf97b-57de-4985-8c86-bc1bc5871e6e" /* Secret */]: z.literal(true),
326
+ id: z.uuidv7(),
327
+ value: z.unknown()
60
328
  });
61
- var fileContentSchema = Type.Union([
62
- Type.Object({
63
- type: Type.Literal("embedded"),
64
- value: Type.String()
329
+ var unitArtifactSchema = z.object({
330
+ ["d55c63ac-3174-4756-808f-f778e99af0d1" /* Artifact */]: z.literal(true),
331
+ hash: z.string(),
332
+ meta: unitObjectMetaSchema.optional()
333
+ });
334
+ var fileContentSchema = z.union([
335
+ z.object({
336
+ type: z.literal("embedded"),
337
+ value: z.string()
65
338
  }),
66
- Type.Object({
67
- type: Type.Literal("artifact"),
68
- ["d55c63ac-3174-4756-808f-f778e99af0d1" /* Artifact */]: unitArtifactSchema
339
+ z.object({
340
+ type: z.literal("artifact"),
341
+ ...unitArtifactSchema.shape
69
342
  })
70
343
  ]);
71
- var fileSchema = Type.Object({
344
+ var fileSchema = z.object({
72
345
  meta: fileMetaSchema,
73
346
  content: fileContentSchema
74
347
  });
75
348
 
76
- // src/evaluation.ts
77
- import { mapValues as mapValues3 } from "remeda";
78
-
79
- // src/unit.ts
80
- import { mapValues as mapValues2 } from "remeda";
81
-
82
- // src/component.ts
83
- import {
84
- OptionalKind
85
- } from "@sinclair/typebox";
86
- import { isNonNullish, mapValues, pickBy } from "remeda";
87
- import { Ajv } from "ajv";
88
-
89
349
  // src/utils.ts
90
350
  function text(strings, ...values) {
91
351
  const stringValues = values.map(String);
@@ -113,40 +373,194 @@ function bytesToHumanReadable(bytes) {
113
373
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
114
374
  return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + " " + sizes[i];
115
375
  }
116
-
117
- // src/i18n.ts
118
- var knownAbbreviationsMap = /* @__PURE__ */ new Map();
119
- function registerKnownAbbreviations(abbreviations) {
120
- for (const abbr of abbreviations) {
121
- const lower = abbr.toLowerCase();
122
- if (!knownAbbreviationsMap.has(lower)) {
123
- knownAbbreviationsMap.set(lower, abbr);
376
+ function formatInstancePath(instance) {
377
+ let result = instance.id;
378
+ while (instance.parentId) {
379
+ const parent = runtimeInstances.get(instance.parentId)?.instance;
380
+ if (!parent) {
381
+ break;
124
382
  }
383
+ result = `${parent.id} -> ${result}`;
384
+ instance = parent;
125
385
  }
386
+ return result;
126
387
  }
127
- function camelCaseToHumanReadable(text2) {
128
- const words = text2.split(/(?=[A-Z])|_|\./);
129
- return words.map((word) => {
130
- const lower = word.toLowerCase();
131
- if (knownAbbreviationsMap.has(lower)) {
132
- return knownAbbreviationsMap.get(lower);
388
+ var InstanceNameConflictError = class extends Error {
389
+ constructor(instanceId, firstPath, secondPath) {
390
+ super(
391
+ `Multiple instances produced with the same instance ID "${instanceId}":
392
+ 1. ${firstPath}
393
+ 2. ${secondPath}`
394
+ );
395
+ this.instanceId = instanceId;
396
+ this.firstPath = firstPath;
397
+ this.secondPath = secondPath;
398
+ this.name = "InstanceNameConflictError";
399
+ }
400
+ };
401
+ var currentInstance = null;
402
+ var runtimeInstances = /* @__PURE__ */ new Map();
403
+ function resetEvaluation() {
404
+ runtimeInstances.clear();
405
+ currentInstance = null;
406
+ }
407
+ function getRuntimeInstances() {
408
+ return Array.from(runtimeInstances.values());
409
+ }
410
+ function registerInstance(component, instance, fn) {
411
+ if (runtimeInstances.has(instance.id)) {
412
+ const existing = runtimeInstances.get(instance.id);
413
+ throw new InstanceNameConflictError(
414
+ instance.id,
415
+ formatInstancePath(existing.instance),
416
+ formatInstancePath(instance)
417
+ );
418
+ }
419
+ runtimeInstances.set(instance.id, { instance, component });
420
+ let previousParentInstance = null;
421
+ if (currentInstance) {
422
+ instance.parentId = currentInstance.id;
423
+ }
424
+ if (!isUnitModel(component.model)) {
425
+ previousParentInstance = currentInstance;
426
+ currentInstance = instance;
427
+ }
428
+ try {
429
+ const outputs = fn();
430
+ instance.resolvedOutputs = outputs;
431
+ instance.outputs = mapValues(
432
+ outputs ?? {},
433
+ (outputs2) => outputs2.map((output) => output[boundaryInput] ?? output)
434
+ );
435
+ return mapValues(
436
+ outputs,
437
+ (outputs2, outputKey) => outputs2.map((output) => ({
438
+ ...output,
439
+ [boundaryInput]: { instanceId: instance.id, output: outputKey }
440
+ }))
441
+ );
442
+ } finally {
443
+ if (previousParentInstance) {
444
+ currentInstance = previousParentInstance;
133
445
  }
134
- return word.charAt(0).toUpperCase() + word.slice(1);
135
- }).join(" ");
446
+ }
136
447
  }
137
448
 
138
449
  // src/component.ts
450
+ var boundaryInput = Symbol("boundaryInput");
139
451
  var ajv = new Ajv({ strict: false });
452
+ var validationEnabled = true;
453
+ function setValidationEnabled(enabled) {
454
+ validationEnabled = enabled;
455
+ }
456
+ var componentArgumentSchema = z.object({
457
+ /**
458
+ * The JSON schema of the argument value.
459
+ */
460
+ schema: z.custom(),
461
+ /**
462
+ * Whether the argument is required.
463
+ */
464
+ required: z.boolean(),
465
+ /**
466
+ * The extra metadata of the argument.
467
+ */
468
+ meta: objectMetaSchema.required({ title: true }).pick({
469
+ title: true,
470
+ globalTitle: true,
471
+ description: true,
472
+ color: true,
473
+ icon: true,
474
+ iconColor: true
475
+ })
476
+ });
477
+ function isSchemaOptional(schema) {
478
+ return schema.safeParse(void 0).success;
479
+ }
480
+ var componentInputSchema = z.object({
481
+ /**
482
+ * The type of the input.
483
+ */
484
+ type: genericNameSchema,
485
+ /**
486
+ * Whether the input is required.
487
+ */
488
+ required: z.boolean(),
489
+ /**
490
+ * Whether the input can have multiple values.
491
+ */
492
+ multiple: z.boolean(),
493
+ /**
494
+ * The extra metadata of the input.
495
+ */
496
+ meta: objectMetaSchema.required({ title: true }).pick({
497
+ title: true,
498
+ description: true
499
+ })
500
+ });
501
+ var componentModelSchema = z.object({
502
+ /**
503
+ * The type of the component.
504
+ */
505
+ type: genericNameSchema,
506
+ /**
507
+ * The record of the argument schemas.
508
+ */
509
+ args: z.record(fieldNameSchema, componentArgumentSchema),
510
+ /**
511
+ * The record of the input schemas.
512
+ */
513
+ inputs: z.record(fieldNameSchema, componentInputSchema),
514
+ /**
515
+ * The record of the output schemas.
516
+ */
517
+ outputs: z.record(fieldNameSchema, componentInputSchema),
518
+ /**
519
+ * The extra metadata of the component.
520
+ */
521
+ meta: objectMetaSchema.required({ title: true }).pick({
522
+ title: true,
523
+ description: true,
524
+ color: true,
525
+ icon: true,
526
+ iconColor: true,
527
+ secondaryIcon: true,
528
+ secondaryIconColor: true
529
+ }).extend({
530
+ /**
531
+ * The category of the component.
532
+ *
533
+ * Used to group components in the UI.
534
+ */
535
+ category: z.string().optional(),
536
+ /**
537
+ * The default name prefix for the component instances.
538
+ *
539
+ * Used to generate default names for the instances.
540
+ */
541
+ defaultNamePrefix: z.string().optional()
542
+ }),
543
+ /**
544
+ * The CRC32 of the component definition.
545
+ */
546
+ definitionHash: z.number()
547
+ });
140
548
  var originalCreate = Symbol("originalCreate");
141
549
  function defineComponent(options) {
550
+ if (!options.type) {
551
+ throw new Error("Component type is required");
552
+ }
553
+ if (!options.create) {
554
+ throw new Error("Component create function is required");
555
+ }
142
556
  function create(params) {
143
557
  const { name, args, inputs } = params;
144
- const id = `${options.type}:${name}`;
558
+ const instanceId = getInstanceId(options.type, name);
145
559
  const flatInputs = mapValues(pickBy(inputs ?? {}, isNonNullish), (inputs2) => [inputs2].flat(2));
146
560
  return registerInstance(
147
- create.model,
561
+ create,
148
562
  {
149
- id,
563
+ id: instanceId,
150
564
  type: options.type,
151
565
  name,
152
566
  args: args ?? {},
@@ -154,18 +568,23 @@ function defineComponent(options) {
154
568
  resolvedInputs: flatInputs
155
569
  },
156
570
  () => {
157
- const markedInputs = mapValues(flatInputs, (inputs2, key) => {
571
+ const componentInputs = create.model.inputs;
572
+ const markedInputs = mapValues(componentInputs, (componentInput, key) => {
573
+ const inputs2 = flatInputs[key];
574
+ if (!inputs2 || inputs2.length === 0) {
575
+ return create.model.inputs[key].multiple ? [{ instanceId, output: key }] : { instanceId, output: key };
576
+ }
158
577
  const result = inputs2.map((input) => ({
159
578
  ...input,
160
- [boundaryInput]: { instanceId: id, output: key }
579
+ [boundaryInput]: { instanceId, output: key }
161
580
  }));
162
581
  return create.model.inputs?.[key]?.multiple === false ? result[0] : result;
163
582
  });
164
583
  const outputs = options.create({
165
- id,
584
+ id: instanceId,
166
585
  name,
167
586
  args: validateArgsAndFillDefaults(
168
- id,
587
+ instanceId,
169
588
  create.model,
170
589
  args ? { ...args } : {}
171
590
  ),
@@ -175,20 +594,26 @@ function defineComponent(options) {
175
594
  }
176
595
  );
177
596
  }
178
- create.entities = /* @__PURE__ */ new Map();
179
- const mapInput = createInputMapper(create.entities);
180
- create.model = {
181
- type: options.type,
182
- args: mapValues(options.args ?? {}, mapArgument),
183
- inputs: mapValues(options.inputs ?? {}, mapInput),
184
- outputs: mapValues(options.outputs ?? {}, mapInput),
185
- meta: {
186
- ...options.meta,
187
- displayName: options.meta?.displayName ?? camelCaseToHumanReadable(options.type)
188
- }
189
- };
190
- create[originalCreate] = options.create;
191
- return create;
597
+ try {
598
+ create.entities = /* @__PURE__ */ new Map();
599
+ const mapInput = createInputMapper(create.entities);
600
+ create.model = {
601
+ type: options.type,
602
+ args: mapValues(options.args ?? {}, mapArgument),
603
+ inputs: mapValues(options.inputs ?? {}, mapInput),
604
+ outputs: mapValues(options.outputs ?? {}, mapInput),
605
+ meta: {
606
+ ...options.meta,
607
+ title: options.meta?.title ?? camelCaseToHumanReadable(options.type)
608
+ },
609
+ definitionHash: null
610
+ // will be calculated by library loader
611
+ };
612
+ create[originalCreate] = options.create;
613
+ return create;
614
+ } catch (error) {
615
+ throw new Error(`Failed to define component "${options.type}"`, { cause: error });
616
+ }
192
617
  }
193
618
  function isComponent(value) {
194
619
  return typeof value === "function" && "model" in value;
@@ -196,19 +621,19 @@ function isComponent(value) {
196
621
  function mapArgument(value, key) {
197
622
  if ("schema" in value) {
198
623
  return {
199
- schema: value.schema,
200
- required: value.required ?? (!value.schema[OptionalKind] && value.schema.default === void 0),
624
+ schema: z.toJSONSchema(value.schema, { target: "draft-7" }),
625
+ required: value.required ?? !isSchemaOptional(value.schema),
201
626
  meta: {
202
- displayName: value.meta?.displayName ?? camelCaseToHumanReadable(key),
203
- description: value.meta?.description
627
+ ...value.meta,
628
+ title: value.meta?.title ?? camelCaseToHumanReadable(key)
204
629
  }
205
630
  };
206
631
  }
207
632
  return {
208
- schema: value,
209
- required: !value[OptionalKind] && value.default === void 0,
633
+ schema: z.toJSONSchema(value, { target: "draft-7" }),
634
+ required: !isSchemaOptional(value),
210
635
  meta: {
211
- displayName: camelCaseToHumanReadable(key)
636
+ title: camelCaseToHumanReadable(key)
212
637
  }
213
638
  };
214
639
  }
@@ -224,9 +649,8 @@ function createInputMapper(entities) {
224
649
  required: value.required ?? true,
225
650
  multiple: value.multiple ?? false,
226
651
  meta: {
227
- displayName: value.displayName ?? camelCaseToHumanReadable(key),
228
- description: value.description,
229
- color: value.color
652
+ ...value.meta,
653
+ title: value.meta?.title ?? camelCaseToHumanReadable(key)
230
654
  }
231
655
  };
232
656
  }
@@ -236,7 +660,7 @@ function createInputMapper(entities) {
236
660
  required: true,
237
661
  multiple: false,
238
662
  meta: {
239
- displayName: camelCaseToHumanReadable(key)
663
+ title: camelCaseToHumanReadable(key)
240
664
  }
241
665
  };
242
666
  };
@@ -245,18 +669,21 @@ function validateArgsAndFillDefaults(instanceId, model, args) {
245
669
  for (const [key, argModel] of Object.entries(model.args)) {
246
670
  let value = args[key];
247
671
  if (!value) {
248
- if (argModel.required) {
672
+ if (argModel.required && validationEnabled) {
249
673
  throw new Error(`Missing required argument "${key}" for instance "${instanceId}"`);
250
674
  }
251
675
  value = argModel.schema.default;
252
676
  args[key] = value;
253
677
  }
254
- if (value && !ajv.validate(argModel.schema, value)) {
678
+ if (validationEnabled && value && !ajv.validate(argModel.schema, value)) {
255
679
  throw new Error(`Invalid argument "${key}" for instance "${instanceId}": ${ajv.errorsText()}`);
256
680
  }
257
681
  }
258
682
  return args;
259
683
  }
684
+ function isUnitModel(model) {
685
+ return "source" in model;
686
+ }
260
687
  function $args(args) {
261
688
  return args;
262
689
  }
@@ -268,10 +695,20 @@ function $outputs(outputs) {
268
695
  }
269
696
 
270
697
  // src/unit.ts
271
- function isUnitModel(model) {
272
- return "source" in model;
273
- }
698
+ var componentSecretSchema = componentArgumentSchema.extend({
699
+ /**
700
+ * The secret cannot be modified by the user, but can be modified by the unit.
701
+ */
702
+ readonly: z5.boolean(),
703
+ /**
704
+ * The secret value is computed by the unit and should not be passed to it when invoked.
705
+ */
706
+ computed: z5.boolean()
707
+ });
274
708
  function defineUnit(options) {
709
+ if (!options.source) {
710
+ throw new Error("Unit source is required");
711
+ }
275
712
  const component = defineComponent({
276
713
  ...options,
277
714
  create({ id }) {
@@ -288,116 +725,27 @@ function defineUnit(options) {
288
725
  }
289
726
  });
290
727
  component.model.source = options.source ?? {};
291
- component.model.secrets = mapValues2(options.secrets ?? {}, mapArgument);
728
+ component.model.secrets = mapValues(options.secrets ?? {}, mapSecret);
292
729
  return component;
293
730
  }
294
731
  function $secrets(secrets) {
295
732
  return secrets;
296
733
  }
297
-
298
- // src/evaluation.ts
299
- var compositeInstances = /* @__PURE__ */ new Map();
300
- var currentCompositeInstance = null;
301
- function resetEvaluation() {
302
- compositeInstances.clear();
303
- currentCompositeInstance = null;
304
- }
305
- function getCompositeInstances() {
306
- return Array.from(compositeInstances.values());
307
- }
308
- function registerInstance(component, instance, fn) {
309
- let previousParentInstance = null;
310
- if (currentCompositeInstance) {
311
- instance.parentId = currentCompositeInstance.instance.id;
312
- currentCompositeInstance.children.push(instance);
313
- }
314
- if (!isUnitModel(component)) {
315
- previousParentInstance = currentCompositeInstance;
316
- currentCompositeInstance = { instance, children: [] };
317
- compositeInstances.set(currentCompositeInstance.instance.id, currentCompositeInstance);
318
- }
319
- try {
320
- const outputs = fn();
321
- instance.resolvedOutputs = outputs;
322
- instance.outputs = mapValues3(
323
- outputs ?? {},
324
- (outputs2) => outputs2.map((output) => output[boundaryInput] ?? output)
325
- );
326
- return mapValues3(
327
- outputs,
328
- (outputs2, outputKey) => outputs2.map((output) => ({
329
- ...output,
330
- [boundaryInput]: { instanceId: instance.id, output: outputKey }
331
- }))
332
- );
333
- } finally {
334
- if (previousParentInstance) {
335
- currentCompositeInstance = previousParentInstance;
336
- }
734
+ function mapSecret(value, key) {
735
+ if ("schema" in value) {
736
+ return {
737
+ ...mapArgument(value, key),
738
+ readonly: value.readonly ?? false,
739
+ computed: value.computed ?? false
740
+ };
337
741
  }
338
- }
339
-
340
- // src/entity.ts
341
- function defineEntity(options) {
342
742
  return {
343
- meta: {},
344
- ...options
743
+ ...mapArgument(value, key),
744
+ readonly: false,
745
+ computed: false
345
746
  };
346
747
  }
347
- function isEntity(value) {
348
- return typeof value === "object" && value !== null && "type" in value && "schema" in value && "meta" in value;
349
- }
350
748
 
351
- // src/types.ts
352
- import "@sinclair/typebox";
353
-
354
- // src/index.ts
355
- export * from "@sinclair/typebox";
356
- import {
357
- Type as BaseType
358
- } from "@sinclair/typebox";
359
- function StringEnum(values) {
360
- return Type2.Union(values.map((value) => Type2.Literal(value)));
361
- }
362
- function Default(schema, defaultValue) {
363
- return { ...schema, default: defaultValue };
364
- }
365
- var Type2 = {
366
- ...BaseType,
367
- StringEnum,
368
- Default
369
- };
370
- export {
371
- $args,
372
- $inputs,
373
- $outputs,
374
- $secrets,
375
- HighstateSignature,
376
- Type2 as Type,
377
- bytesToHumanReadable,
378
- camelCaseToHumanReadable,
379
- defineComponent,
380
- defineEntity,
381
- defineUnit,
382
- fileContentSchema,
383
- fileMetaSchema,
384
- fileSchema,
385
- findInput,
386
- findInputs,
387
- findRequiredInput,
388
- findRequiredInputs,
389
- getCompositeInstances,
390
- getInstanceId,
391
- isComponent,
392
- isEntity,
393
- isUnitModel,
394
- originalCreate,
395
- parseInstanceId,
396
- registerKnownAbbreviations,
397
- resetEvaluation,
398
- text,
399
- trimIndentation,
400
- unitArtifactSchema,
401
- unitObjectMetaSchema
402
- };
749
+ export { $args, $inputs, $outputs, $secrets, HighstateSignature, InstanceNameConflictError, bytesToHumanReadable, camelCaseToHumanReadable, componentArgumentSchema, componentInputSchema, componentModelSchema, componentSecretSchema, defineComponent, defineEntity, defineUnit, entityModelSchema, fieldNameSchema, fileContentSchema, fileMetaSchema, fileSchema, findInput, findInputs, findRequiredInput, findRequiredInputs, genericNameSchema, getInstanceId, getRuntimeInstances, hubInputSchema, hubModelPatchSchema, hubModelSchema, instanceIdSchema, instanceInputSchema, instanceModelPatchSchema, instanceModelSchema, isComponent, isEntity, isUnitModel, objectMetaSchema, originalCreate, parseInstanceId, positionSchema, registerKnownAbbreviations, resetEvaluation, setValidationEnabled, text, trimIndentation, unitArtifactSchema, unitObjectMetaSchema, unitSecretSchema, userObjectMetaSchema, yamlValueSchema };
750
+ //# sourceMappingURL=index.js.map
403
751
  //# sourceMappingURL=index.js.map