@highstate/contract 0.19.1 → 0.20.0

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,9 +1,41 @@
1
1
  import { z } from 'zod';
2
2
  export { z } from 'zod';
3
+ import { sha256 } from '@noble/hashes/sha2.js';
3
4
  import { mapValues, pickBy, isNonNullish, uniqueBy } from 'remeda';
4
5
  import { parse } from 'yaml';
5
6
 
6
7
  // src/entity.ts
8
+ var cuidv2DefaultLength = 24;
9
+ function bufToBigInt(buf) {
10
+ const bits = 8n;
11
+ let value = 0n;
12
+ for (const byte of buf.values()) {
13
+ value = (value << bits) + BigInt(byte);
14
+ }
15
+ return value;
16
+ }
17
+ function hashCuid2(input) {
18
+ const bytes = new TextEncoder().encode(input);
19
+ const digest = sha256(bytes);
20
+ return bufToBigInt(digest).toString(36).slice(1);
21
+ }
22
+ function normalizeCuid2Prefix(prefix) {
23
+ if (prefix >= "a" && prefix <= "z") {
24
+ return prefix;
25
+ }
26
+ if (prefix >= "0" && prefix <= "9") {
27
+ const digit = prefix.charCodeAt(0) - "0".charCodeAt(0);
28
+ return String.fromCharCode("a".charCodeAt(0) + digit);
29
+ }
30
+ throw new Error(`Invalid CUID prefix character: ${prefix}`);
31
+ }
32
+ function cuidv2d(namespace, identity) {
33
+ const hashInput = `${namespace}:${identity}`;
34
+ const hashed = hashCuid2(hashInput);
35
+ const raw = hashed.slice(0, cuidv2DefaultLength);
36
+ const prefix = normalizeCuid2Prefix(raw[0]);
37
+ return `${prefix}${raw.slice(1)}`;
38
+ }
7
39
 
8
40
  // src/i18n.ts
9
41
  var knownAbbreviationsMap = /* @__PURE__ */ new Map();
@@ -28,6 +60,96 @@ function camelCaseToHumanReadable(text2) {
28
60
  return word.charAt(0).toUpperCase() + word.slice(1);
29
61
  }).join(" ");
30
62
  }
63
+
64
+ // src/json-schema.ts
65
+ function isRecord(value) {
66
+ return typeof value === "object" && value !== null && !Array.isArray(value);
67
+ }
68
+ function fixJsonSchema(schema) {
69
+ if (!isRecord(schema)) {
70
+ return schema;
71
+ }
72
+ const allOf = schema.allOf;
73
+ if (Array.isArray(allOf) && allOf.length > 0) {
74
+ const objectSchemas = [];
75
+ const otherSchemas = [];
76
+ for (const item of allOf) {
77
+ if (isRecord(item) && item.type === "object") {
78
+ objectSchemas.push(item);
79
+ continue;
80
+ }
81
+ otherSchemas.push(item);
82
+ }
83
+ if (objectSchemas.length > 1) {
84
+ const required = /* @__PURE__ */ new Set();
85
+ const properties = {};
86
+ let additionalProperties;
87
+ for (const objectSchema of objectSchemas) {
88
+ const objectRequired = objectSchema.required;
89
+ if (Array.isArray(objectRequired)) {
90
+ for (const key of objectRequired) {
91
+ if (typeof key === "string") {
92
+ required.add(key);
93
+ }
94
+ }
95
+ }
96
+ const objectProperties = objectSchema.properties;
97
+ if (isRecord(objectProperties)) {
98
+ for (const [key, value] of Object.entries(objectProperties)) {
99
+ const existing = properties[key];
100
+ if (existing === void 0) {
101
+ properties[key] = value;
102
+ continue;
103
+ }
104
+ properties[key] = { allOf: [existing, value] };
105
+ }
106
+ }
107
+ if ("additionalProperties" in objectSchema) {
108
+ if (additionalProperties === void 0) {
109
+ additionalProperties = objectSchema.additionalProperties;
110
+ } else if (additionalProperties !== objectSchema.additionalProperties) {
111
+ additionalProperties = false;
112
+ }
113
+ }
114
+ }
115
+ const mergedObjectSchema = {
116
+ type: "object",
117
+ properties,
118
+ ...required.size > 0 ? { required: Array.from(required) } : {},
119
+ ...additionalProperties !== void 0 ? { additionalProperties } : { additionalProperties: false }
120
+ };
121
+ const merged = otherSchemas.length === 0 ? mergedObjectSchema : {
122
+ ...schema,
123
+ allOf: [mergedObjectSchema, ...otherSchemas]
124
+ };
125
+ return fixJsonSchema(merged);
126
+ }
127
+ }
128
+ const next = { ...schema };
129
+ if (Array.isArray(next.allOf)) {
130
+ next.allOf = next.allOf.map(fixJsonSchema);
131
+ }
132
+ if (Array.isArray(next.anyOf)) {
133
+ next.anyOf = next.anyOf.map(fixJsonSchema);
134
+ }
135
+ if (Array.isArray(next.oneOf)) {
136
+ next.oneOf = next.oneOf.map(fixJsonSchema);
137
+ }
138
+ if (isRecord(next.properties)) {
139
+ next.properties = Object.fromEntries(
140
+ Object.entries(next.properties).map(([key, value]) => [key, fixJsonSchema(value)])
141
+ );
142
+ }
143
+ if (isRecord(next.items)) {
144
+ next.items = fixJsonSchema(next.items);
145
+ } else if (Array.isArray(next.items)) {
146
+ next.items = next.items.map(fixJsonSchema);
147
+ }
148
+ if (isRecord(next.additionalProperties)) {
149
+ next.additionalProperties = fixJsonSchema(next.additionalProperties);
150
+ }
151
+ return next;
152
+ }
31
153
  var objectMetaSchema = z.object({
32
154
  /**
33
155
  * Human-readable name of the object.
@@ -220,7 +342,11 @@ var entityModelSchema = z.object({
220
342
  definitionHash: z.number()
221
343
  });
222
344
  function isEntityIncludeRef(value) {
223
- return typeof value === "object" && value !== null && "entity" in value;
345
+ if (typeof value !== "object" || value === null || !("entity" in value)) {
346
+ return false;
347
+ }
348
+ const entity = value.entity;
349
+ return typeof entity === "function" || isEntity(entity);
224
350
  }
225
351
  function defineEntity(options) {
226
352
  try {
@@ -231,35 +357,34 @@ function defineEntity(options) {
231
357
  if (!options.schema) {
232
358
  throw new Error("Entity schema is required");
233
359
  }
234
- const includedEntities = Object.entries(options.includes ?? {}).map(([field, entityRef]) => {
235
- if (isEntityIncludeRef(entityRef)) {
236
- return {
237
- entity: entityRef.entity,
238
- inclusion: {
239
- type: entityRef.entity.type,
240
- required: entityRef.required ?? true,
241
- multiple: entityRef.multiple ?? false,
242
- field
360
+ const includeRefs = Object.entries(options.includes ?? {}).map(
361
+ ([field, entityRef]) => {
362
+ if (isEntityIncludeRef(entityRef)) {
363
+ const required = entityRef.required ?? true;
364
+ const multiple = entityRef.multiple ?? false;
365
+ let getEntity2;
366
+ if (typeof entityRef.entity === "function") {
367
+ const entity = entityRef.entity;
368
+ getEntity2 = entity;
369
+ } else {
370
+ const entity = entityRef.entity;
371
+ getEntity2 = () => entity;
243
372
  }
244
- };
245
- }
246
- return {
247
- entity: entityRef,
248
- inclusion: {
249
- type: entityRef.type,
250
- required: true,
251
- multiple: false,
252
- field
373
+ return { field, required, multiple, getEntity: getEntity2 };
253
374
  }
254
- };
255
- });
256
- const inclusionShape = includedEntities.reduce(
257
- (shape, { entity, inclusion }) => {
258
- if (inclusion.multiple) {
259
- shape[inclusion.field] = inclusion.required ? entity.schema.array() : entity.schema.array().optional();
375
+ const getEntity = () => entityRef;
376
+ return { field, required: true, multiple: false, getEntity };
377
+ }
378
+ );
379
+ const inclusionShape = includeRefs.reduce(
380
+ (shape, includeRef) => {
381
+ let schema = z.lazy(() => includeRef.getEntity().schema);
382
+ if (includeRef.multiple) {
383
+ schema = includeRef.required ? schema.array().min(1) : schema.array().default([]);
260
384
  } else {
261
- shape[inclusion.field] = inclusion.required ? entity.schema : entity.schema.optional();
385
+ schema = includeRef.required ? schema : schema.optional();
262
386
  }
387
+ shape[includeRef.field] = schema;
263
388
  return shape;
264
389
  },
265
390
  {}
@@ -268,20 +393,26 @@ function defineEntity(options) {
268
393
  (schema, entity) => z.intersection(schema, entity.schema),
269
394
  options.schema
270
395
  );
271
- if (includedEntities.length > 0) {
396
+ if (includeRefs.length > 0) {
272
397
  finalSchema = z.intersection(finalSchema, z.object(inclusionShape));
273
398
  }
274
- const directInclusions = includedEntities.map(({ inclusion }) => inclusion);
399
+ finalSchema = z.intersection(finalSchema, entityWithMetaSchema);
400
+ const directInclusions = () => includeRefs.map((includeRef) => ({
401
+ type: includeRef.getEntity().type,
402
+ required: includeRef.required,
403
+ multiple: includeRef.multiple,
404
+ field: includeRef.field
405
+ }));
275
406
  const directExtensions = Object.values(options.extends ?? {}).map((entity) => entity.type);
276
- const inclusions = Object.values(options.extends ?? {}).reduce(
277
- (incs, entity) => {
407
+ const getInclusions = () => {
408
+ const incs = [...directInclusions()];
409
+ for (const entity of Object.values(options.extends ?? {})) {
278
410
  if (entity.model.inclusions) {
279
411
  incs.push(...entity.model.inclusions);
280
412
  }
281
- return incs;
282
- },
283
- [...directInclusions]
284
- );
413
+ }
414
+ return incs;
415
+ };
285
416
  const extensions = Object.values(options.extends ?? {}).reduce((exts, entity) => {
286
417
  exts.push(...entity.model.extensions ?? [], entity.type);
287
418
  return exts;
@@ -295,11 +426,21 @@ function defineEntity(options) {
295
426
  type: options.type,
296
427
  extensions: extensions.length > 0 ? extensions : void 0,
297
428
  directExtensions: directExtensions.length > 0 ? directExtensions : void 0,
298
- inclusions: inclusions.length > 0 ? inclusions : void 0,
299
- directInclusions: directInclusions.length > 0 ? directInclusions : void 0,
429
+ get inclusions() {
430
+ const incs = getInclusions();
431
+ return incs.length > 0 ? incs : void 0;
432
+ },
433
+ get directInclusions() {
434
+ const incs = directInclusions();
435
+ return incs.length > 0 ? incs : void 0;
436
+ },
300
437
  get schema() {
301
438
  if (!_schema) {
302
- _schema = z.toJSONSchema(finalSchema, { target: "draft-7", unrepresentable: "any" });
439
+ const rawSchema = z.toJSONSchema(finalSchema, {
440
+ target: "draft-7",
441
+ unrepresentable: "any"
442
+ });
443
+ _schema = fixJsonSchema(rawSchema);
303
444
  }
304
445
  return _schema;
305
446
  },
@@ -328,8 +469,51 @@ function isAssignableTo(entity, target) {
328
469
  }
329
470
  return entity.inclusions?.some((implementation) => implementation.type === target) ?? false;
330
471
  }
331
- var boundaryInput = Symbol("boundaryInput");
332
- var boundaryInputs = Symbol("boundaryInputs");
472
+ var entityMetaSchema = z.object({
473
+ /**
474
+ * The type of the entity.
475
+ */
476
+ type: versionedNameSchema,
477
+ /**
478
+ * The globally unique identity of the entity.
479
+ *
480
+ * Anonymous entities are forbidden.
481
+ */
482
+ identity: z.string(),
483
+ /**
484
+ * The IDs of the entities to reference by this entity.
485
+ * Must already exist in the system (or be at least defined by this unit).
486
+ */
487
+ references: z.record(z.string(), z.string().array()).optional(),
488
+ ...objectMetaSchema.pick({
489
+ title: true,
490
+ description: true,
491
+ icon: true,
492
+ iconColor: true
493
+ }).shape
494
+ });
495
+ var entityWithMetaSchema = z.object({
496
+ $meta: entityMetaSchema
497
+ });
498
+ var entityIdCache = /* @__PURE__ */ new WeakMap();
499
+ var entityIdNamespace = "3cd37048-7c50-43a9-a2b9-ff7ff2b5ee79";
500
+ function getEntityId(entity) {
501
+ if (!entity.$meta) {
502
+ throw new Error("Entity $meta is required to generate an entity id");
503
+ }
504
+ const existingId = entityIdCache.get(entity);
505
+ if (existingId) {
506
+ return existingId;
507
+ }
508
+ const { type, identity } = entity.$meta;
509
+ const id = cuidv2d(entityIdNamespace, `${type}:${identity}`);
510
+ entityIdCache.set(entity, id);
511
+ return id;
512
+ }
513
+ var boundaryInput = /* @__PURE__ */ Symbol("boundaryInput");
514
+ function isStableInstanceInput(value) {
515
+ return typeof value === "object" && value !== null && "instanceId" in value && "output" in value && typeof value.instanceId === "string" && typeof value.output === "string";
516
+ }
333
517
  function formatInstancePath(instance) {
334
518
  let result = instance.id;
335
519
  while (instance.parentId) {
@@ -383,19 +567,41 @@ function registerInstance(component, instance, fn) {
383
567
  currentInstance = instance;
384
568
  }
385
569
  try {
386
- const outputs = fn();
387
- instance.resolvedOutputs = outputs;
388
- instance.outputs = mapValues(
570
+ const rawOutputs = fn();
571
+ const outputs = mapValues(rawOutputs ?? {}, (outputGroup) => {
572
+ return [outputGroup].flat(2).filter(Boolean);
573
+ });
574
+ const toStableInputs = (outputGroup, useBoundaryFallback) => {
575
+ return outputGroup.map((output) => useBoundaryFallback ? output[boundaryInput] : output).filter(isStableInstanceInput).map((output) => {
576
+ return output.path ? {
577
+ instanceId: output.instanceId,
578
+ output: output.output,
579
+ path: output.path
580
+ } : {
581
+ instanceId: output.instanceId,
582
+ output: output.output
583
+ };
584
+ });
585
+ };
586
+ instance.resolvedOutputs = mapValues(
389
587
  outputs ?? {},
390
- (outputs2) => outputs2.map((output) => output[boundaryInput] ?? output)
391
- );
392
- return mapValues(
393
- outputs,
394
- (outputs2, outputKey) => outputs2.map((output) => ({
395
- ...output,
396
- [boundaryInput]: { instanceId: instance.id, output: outputKey }
397
- }))
588
+ (outputGroup) => toStableInputs(outputGroup, false)
398
589
  );
590
+ instance.outputs = mapValues(outputs ?? {}, (outputGroup) => toStableInputs(outputGroup, true));
591
+ return mapValues(rawOutputs, (rawOutputGroup, outputKey) => {
592
+ const outputRefs = (outputs[outputKey] ?? []).map((output) => {
593
+ if (output.provided) {
594
+ output[boundaryInput] = { instanceId: instance.id, output: outputKey };
595
+ }
596
+ return output;
597
+ });
598
+ if (component.model.outputs[outputKey]?.multiple) {
599
+ const multipleOutput = Array.isArray(rawOutputGroup) ? rawOutputGroup : outputRefs;
600
+ multipleOutput[boundaryInput] ??= { instanceId: instance.id, output: outputKey };
601
+ return multipleOutput;
602
+ }
603
+ return rawOutputGroup ?? outputRefs[0];
604
+ });
399
605
  } finally {
400
606
  if (previousParentInstance) {
401
607
  currentInstance = previousParentInstance;
@@ -403,8 +609,147 @@ function registerInstance(component, instance, fn) {
403
609
  }
404
610
  }
405
611
 
612
+ // src/instance-input.ts
613
+ function appendInputPath(currentPath, segment) {
614
+ return currentPath ? `${currentPath}.${segment}` : segment;
615
+ }
616
+ function createRuntimeInputAccessor(input, boundary) {
617
+ const accessorCache = input.provided ? void 0 : /* @__PURE__ */ new Map();
618
+ let currentBoundary = boundary;
619
+ return new Proxy(input, {
620
+ get(target, property, receiver) {
621
+ const runtimeTarget = target;
622
+ if (property === boundaryInput) {
623
+ return currentBoundary;
624
+ }
625
+ if (typeof property !== "string") {
626
+ return Reflect.get(target, property, receiver);
627
+ }
628
+ if (property in target) {
629
+ return Reflect.get(target, property, receiver);
630
+ }
631
+ if (property === "instanceId" || property === "output" || property === "path") {
632
+ return Reflect.get(target, property, receiver);
633
+ }
634
+ if (runtimeTarget.provided) {
635
+ return Reflect.get(runtimeTarget, property, receiver);
636
+ }
637
+ const cached = accessorCache?.get(property);
638
+ if (cached) {
639
+ return cached;
640
+ }
641
+ const nested = createNonProvidedInput(boundary, appendInputPath(runtimeTarget.path, property));
642
+ accessorCache?.set(property, nested);
643
+ return nested;
644
+ },
645
+ set(target, property, value, receiver) {
646
+ if (property === boundaryInput) {
647
+ currentBoundary = value;
648
+ return true;
649
+ }
650
+ return Reflect.set(target, property, value, receiver);
651
+ }
652
+ });
653
+ }
654
+ function createInput(input, options = {}) {
655
+ if (!("provided" in input)) {
656
+ const boundary2 = options.boundary ?? input;
657
+ const normalizedInput = {
658
+ provided: true,
659
+ instanceId: input.instanceId,
660
+ output: input.output,
661
+ ...input.path ? { path: input.path } : {},
662
+ [boundaryInput]: boundary2
663
+ };
664
+ return createRuntimeInputAccessor(normalizedInput, boundary2);
665
+ }
666
+ if (!input.provided) {
667
+ const boundary2 = options.boundary ?? input[boundaryInput];
668
+ if (!boundary2) {
669
+ throw new Error("Cannot create non-provided input without boundary metadata");
670
+ }
671
+ return createNonProvidedInput(boundary2, input.path);
672
+ }
673
+ const boundary = options.boundary ?? input[boundaryInput];
674
+ if (!boundary) {
675
+ throw new Error("Cannot create provided input without boundary metadata");
676
+ }
677
+ return createRuntimeInputAccessor(input, boundary);
678
+ }
679
+ function createNonProvidedInput(boundary, path) {
680
+ const target = {
681
+ provided: false,
682
+ ...path ? { path } : {},
683
+ [boundaryInput]: boundary
684
+ };
685
+ return createRuntimeInputAccessor(target, boundary);
686
+ }
687
+ function createMultipleInputAccessor(inputs, boundary) {
688
+ const arrayInputs = [...inputs];
689
+ arrayInputs[boundaryInput] = boundary;
690
+ return new Proxy(arrayInputs, {
691
+ get(target, property, receiver) {
692
+ if (typeof property !== "string") {
693
+ return Reflect.get(target, property, receiver);
694
+ }
695
+ if (property === "length" || property === "map" || property === "filter" || property === "path" || property in target) {
696
+ return Reflect.get(target, property, receiver);
697
+ }
698
+ const unfolded = target.flatMap((input) => {
699
+ if (!input.provided) {
700
+ return [];
701
+ }
702
+ const selected = input[property];
703
+ if (selected === void 0 || selected === null) {
704
+ return [];
705
+ }
706
+ if (Array.isArray(selected)) {
707
+ return selected;
708
+ }
709
+ return [selected];
710
+ });
711
+ return createMultipleInputAccessor(unfolded, boundary);
712
+ }
713
+ });
714
+ }
715
+ function createDeepOutputAccessor(output) {
716
+ const normalizedOutput = createInput(output);
717
+ if (!normalizedOutput.provided) {
718
+ return normalizedOutput;
719
+ }
720
+ const accessorCache = /* @__PURE__ */ new Map();
721
+ return new Proxy(normalizedOutput, {
722
+ get(target, property, receiver) {
723
+ if (typeof property !== "string") {
724
+ return Reflect.get(target, property, receiver);
725
+ }
726
+ if (property === "provided" || property === "instanceId" || property === "output" || property === "path") {
727
+ return Reflect.get(target, property, receiver);
728
+ }
729
+ if (property in target) {
730
+ return Reflect.get(target, property, receiver);
731
+ }
732
+ const cached = accessorCache.get(property);
733
+ if (cached !== void 0) {
734
+ return cached;
735
+ }
736
+ const providedTarget = target;
737
+ const nextInput = createInput(
738
+ {
739
+ ...providedTarget,
740
+ path: appendInputPath(providedTarget.path, property)
741
+ },
742
+ { boundary: providedTarget[boundaryInput] }
743
+ );
744
+ const resolved = createDeepOutputAccessor(nextInput);
745
+ accessorCache.set(property, resolved);
746
+ return resolved;
747
+ }
748
+ });
749
+ }
750
+
406
751
  // src/component.ts
407
- var runtimeSchema = Symbol("runtimeSchema");
752
+ var runtimeSchema = /* @__PURE__ */ Symbol("runtimeSchema");
408
753
  var validationEnabled = true;
409
754
  function setValidationEnabled(enabled) {
410
755
  validationEnabled = enabled;
@@ -442,6 +787,12 @@ var componentInputSchema = z.object({
442
787
  * The type of the entity passed through the input.
443
788
  */
444
789
  type: versionedNameSchema,
790
+ /**
791
+ * The input name this output type is derived from.
792
+ *
793
+ * If set, the output uses the referenced input as its fallback type source.
794
+ */
795
+ fromInput: fieldNameSchema.optional(),
445
796
  /**
446
797
  * Whether the input is required.
447
798
  */
@@ -509,8 +860,8 @@ var componentModelSchema = z.object({
509
860
  */
510
861
  definitionHash: z.number()
511
862
  });
512
- var originalCreate = Symbol("originalCreate");
513
- var kind = Symbol("kind");
863
+ var originalCreate = /* @__PURE__ */ Symbol("originalCreate");
864
+ var kind = /* @__PURE__ */ Symbol("kind");
514
865
  function defineComponent(options) {
515
866
  try {
516
867
  componentModelSchema.shape.type.parse(options.type);
@@ -522,12 +873,13 @@ function defineComponent(options) {
522
873
  }
523
874
  const entities = /* @__PURE__ */ new Map();
524
875
  const mapInput = createInputMapper(entities);
876
+ const mapOutput = createOutputMapper(options.inputs, entities);
525
877
  const model = {
526
878
  type: options.type,
527
879
  kind: options[kind] ?? "composite",
528
880
  args: mapValues(options.args ?? {}, mapArgument),
529
881
  inputs: mapValues(options.inputs ?? {}, mapInput),
530
- outputs: mapValues(options.outputs ?? {}, mapInput),
882
+ outputs: mapValues(options.outputs ?? {}, mapOutput),
531
883
  meta: {
532
884
  ...options.meta,
533
885
  title: options.meta?.title || camelCaseToHumanReadable(parseVersionedName(options.type)[0]),
@@ -541,27 +893,28 @@ function defineComponent(options) {
541
893
  const instanceId = getInstanceId(options.type, name);
542
894
  const flatInputs = {};
543
895
  const tracedInputs = {};
896
+ const runtimeInputKey = (input) => {
897
+ if (input.provided) {
898
+ return inputKey(input);
899
+ }
900
+ return `missing:${input[boundaryInput].instanceId}:${input[boundaryInput].output}`;
901
+ };
544
902
  for (const [key, inputGroup] of Object.entries(inputs ?? {})) {
903
+ if (!(key in model.inputs)) {
904
+ continue;
905
+ }
545
906
  if (!inputGroup) {
546
907
  continue;
547
908
  }
548
909
  if (!Array.isArray(inputGroup)) {
549
- if (inputGroup[boundaryInput]) {
550
- tracedInputs[key] = [inputGroup[boundaryInput]];
551
- }
552
- flatInputs[key] = [inputGroup];
910
+ const normalizedInput = normalizeIncomingInput(inputGroup, key);
911
+ tracedInputs[key] = [normalizedInput[boundaryInput]];
912
+ flatInputs[key] = [normalizedInput];
553
913
  continue;
554
914
  }
555
- const group = [...inputGroup[boundaryInputs] ?? []];
556
- const inputs2 = [];
557
- for (const item of inputGroup.flat(1)) {
558
- if (item[boundaryInput]) {
559
- group.push(item[boundaryInput]);
560
- }
561
- inputs2.push(item);
562
- }
915
+ const { group, inputs: inputs2 } = normalizeIncomingInputGroup(inputGroup, key);
563
916
  tracedInputs[key] = uniqueBy(group, inputKey);
564
- flatInputs[key] = uniqueBy(inputs2, inputKey);
917
+ flatInputs[key] = uniqueBy(inputs2, runtimeInputKey);
565
918
  }
566
919
  return registerInstance(
567
920
  create,
@@ -572,23 +925,34 @@ function defineComponent(options) {
572
925
  name,
573
926
  args,
574
927
  inputs: tracedInputs,
575
- resolvedInputs: mapValues(
576
- flatInputs,
577
- (inputs2) => inputs2.filter((input) => !("provided" in input && input.provided === false))
578
- )
928
+ resolvedInputs: mapValues(flatInputs, (inputs2) => {
929
+ return inputs2.filter((input) => input.provided).map((input) => ({
930
+ instanceId: input.instanceId,
931
+ output: input.output,
932
+ ...input.path ? { path: input.path } : {}
933
+ }));
934
+ })
579
935
  },
580
936
  () => {
581
937
  const markedInputs = mapValues(model.inputs, (componentInput, key) => {
582
938
  if (!componentInput.multiple) {
583
939
  const input = flatInputs[key]?.[0];
584
- if (input) {
585
- return { ...input, [boundaryInput]: { instanceId, output: key } };
940
+ if (input?.provided) {
941
+ return createDeepOutputAccessor({
942
+ ...input,
943
+ [boundaryInput]: { instanceId, output: key }
944
+ });
586
945
  }
587
- return { provided: false, [boundaryInput]: { instanceId, output: key } };
946
+ return createNonProvidedInput({ instanceId, output: key });
588
947
  }
589
- const inputs2 = flatInputs[key] ?? [];
590
- inputs2[boundaryInputs] = [{ instanceId, output: key }];
591
- return inputs2;
948
+ const inputs2 = (flatInputs[key] ?? []).filter(isProvidedRuntimeInput).map(
949
+ (input) => createDeepOutputAccessor({
950
+ ...input,
951
+ [boundaryInput]: { instanceId, output: key }
952
+ })
953
+ );
954
+ const multipleBoundary = { instanceId, output: key };
955
+ return createMultipleInputAccessor(inputs2, multipleBoundary);
592
956
  });
593
957
  const outputs = options.create({
594
958
  id: instanceId,
@@ -596,9 +960,51 @@ function defineComponent(options) {
596
960
  args: processArgs(instanceId, create.model, args),
597
961
  inputs: markedInputs
598
962
  }) ?? {};
599
- return mapValues(pickBy(outputs, isNonNullish), (outputs2) => [outputs2].flat(2));
963
+ const normalizedOutputs = normalizeCreateOutputs(outputs, model, instanceId);
964
+ return withDeepOutputAccessors(normalizedOutputs, model, instanceId);
600
965
  }
601
966
  );
967
+ function normalizeIncomingInput(input, inputName) {
968
+ if (isStableInstanceInput2(input)) {
969
+ return createInput(input);
970
+ }
971
+ const runtimeInput = input;
972
+ if (runtimeInput.provided) {
973
+ const inputBoundary = runtimeInput[boundaryInput] ?? {
974
+ instanceId: runtimeInput.instanceId,
975
+ output: runtimeInput.output,
976
+ ...runtimeInput.path ? { path: runtimeInput.path } : {}
977
+ };
978
+ return createInput(runtimeInput, { boundary: inputBoundary });
979
+ }
980
+ return createNonProvidedInput(
981
+ runtimeInput[boundaryInput] ?? { instanceId, output: inputName }
982
+ );
983
+ }
984
+ function normalizeIncomingInputGroup(inputGroup, inputName) {
985
+ const group = [];
986
+ const inputs2 = [];
987
+ const visit = (value) => {
988
+ if (Array.isArray(value)) {
989
+ const arrayBoundary = value[boundaryInput];
990
+ if (arrayBoundary) {
991
+ group.push(arrayBoundary);
992
+ }
993
+ for (const item of value) {
994
+ if (!item) {
995
+ continue;
996
+ }
997
+ visit(item);
998
+ }
999
+ return;
1000
+ }
1001
+ const normalizedInput = normalizeIncomingInput(value, inputName);
1002
+ group.push(normalizedInput[boundaryInput]);
1003
+ inputs2.push(normalizedInput);
1004
+ };
1005
+ visit(inputGroup);
1006
+ return { group, inputs: inputs2 };
1007
+ }
602
1008
  }
603
1009
  try {
604
1010
  create.entities = entities;
@@ -629,6 +1035,86 @@ function processArgs(instanceId, model, args) {
629
1035
  }
630
1036
  return validatedArgs;
631
1037
  }
1038
+ function withDeepOutputAccessors(outputs, model, instanceId) {
1039
+ return mapValues(outputs, (outputGroup, outputName) => {
1040
+ const outputSpec = model.outputs[outputName];
1041
+ if (!outputSpec) {
1042
+ return outputGroup[0];
1043
+ }
1044
+ const normalizedOutputs = outputGroup.map((output) => createDeepOutputAccessor(output));
1045
+ if (outputSpec.multiple) {
1046
+ return createMultipleInputAccessor(normalizedOutputs, {
1047
+ instanceId,
1048
+ output: outputName
1049
+ });
1050
+ }
1051
+ return normalizedOutputs[0];
1052
+ });
1053
+ }
1054
+ function isProvidedRuntimeInput(input) {
1055
+ return input.provided;
1056
+ }
1057
+ function normalizeCreateOutputGroup(outputGroup, instanceId, outputName) {
1058
+ return [outputGroup].flat(2).filter(isNonNullish).map((output) => {
1059
+ if (isStableInstanceInput2(output)) {
1060
+ return createInput(output);
1061
+ }
1062
+ const runtimeOutput = output;
1063
+ if (runtimeOutput.provided) {
1064
+ const stableBoundary = runtimeOutput[boundaryInput] ?? {
1065
+ instanceId: runtimeOutput.instanceId,
1066
+ output: runtimeOutput.output,
1067
+ ...runtimeOutput.path ? { path: runtimeOutput.path } : {}
1068
+ };
1069
+ return createInput(runtimeOutput, { boundary: stableBoundary });
1070
+ }
1071
+ return createNonProvidedInput(
1072
+ runtimeOutput[boundaryInput] ?? { instanceId, output: outputName }
1073
+ );
1074
+ });
1075
+ }
1076
+ function normalizeCreateOutputs(outputs, model, instanceId) {
1077
+ const normalizedOutputs = {};
1078
+ for (const [outputName, outputSpec] of Object.entries(model.outputs)) {
1079
+ const outputGroup = outputs[outputName];
1080
+ if (!isNonNullish(outputGroup)) {
1081
+ if (model.kind === "unit") {
1082
+ throw new Error(`Unit output "${outputName}" in instance "${instanceId}" must be provided`);
1083
+ }
1084
+ normalizedOutputs[outputName] = outputSpec.multiple ? [] : [createNonProvidedInput({ instanceId, output: outputName })];
1085
+ continue;
1086
+ }
1087
+ const normalizedGroup = normalizeCreateOutputGroup(outputGroup, instanceId, outputName);
1088
+ if (outputSpec.multiple && normalizedGroup.some((output) => !output.provided)) {
1089
+ throw new Error(
1090
+ `Multiple output "${outputName}" in instance "${instanceId}" cannot contain non-provided items`
1091
+ );
1092
+ }
1093
+ if (model.kind === "unit") {
1094
+ if (normalizedGroup.length === 0 || normalizedGroup.some((output) => !output.provided)) {
1095
+ throw new Error(`Unit output "${outputName}" in instance "${instanceId}" must be provided`);
1096
+ }
1097
+ }
1098
+ normalizedOutputs[outputName] = outputSpec.multiple || normalizedGroup.length > 0 ? normalizedGroup : [createNonProvidedInput({ instanceId, output: outputName })];
1099
+ }
1100
+ for (const [outputName, outputGroup] of Object.entries(pickBy(outputs, isNonNullish))) {
1101
+ if (!(outputName in model.outputs) || outputName in normalizedOutputs) {
1102
+ continue;
1103
+ }
1104
+ normalizedOutputs[outputName] = normalizeCreateOutputGroup(outputGroup, instanceId, outputName);
1105
+ }
1106
+ return normalizedOutputs;
1107
+ }
1108
+ function isStableInstanceInput2(value) {
1109
+ if (!value || typeof value !== "object") {
1110
+ return false;
1111
+ }
1112
+ if ("provided" in value) {
1113
+ return false;
1114
+ }
1115
+ const input = value;
1116
+ return typeof input.instanceId === "string" && typeof input.output === "string";
1117
+ }
632
1118
  function isComponent(value) {
633
1119
  return typeof value === "function" && "model" in value;
634
1120
  }
@@ -688,6 +1174,33 @@ function createInputMapper(entities) {
688
1174
  };
689
1175
  };
690
1176
  }
1177
+ function isFromInputOutputOptions(value) {
1178
+ return typeof value === "object" && value !== null && "fromInput" in value;
1179
+ }
1180
+ function createOutputMapper(inputs, entities) {
1181
+ const mapInput = createInputMapper(entities);
1182
+ return (value, key) => {
1183
+ if (!isFromInputOutputOptions(value)) {
1184
+ return mapInput(value, key);
1185
+ }
1186
+ const sourceInput = inputs?.[value.fromInput];
1187
+ if (!sourceInput) {
1188
+ throw new Error(
1189
+ `Output "${key}" references missing input "${value.fromInput}" via fromInput.`
1190
+ );
1191
+ }
1192
+ const mappedInput = mapInput(sourceInput, value.fromInput);
1193
+ return {
1194
+ ...mappedInput,
1195
+ fromInput: value.fromInput,
1196
+ meta: {
1197
+ ...mappedInput.meta,
1198
+ ...value.meta,
1199
+ title: value.meta?.title || camelCaseToHumanReadable(key)
1200
+ }
1201
+ };
1202
+ };
1203
+ }
691
1204
  function getInstanceId(instanceType, instanceName) {
692
1205
  return `${instanceType}:${instanceName}`;
693
1206
  }
@@ -697,6 +1210,17 @@ function toFullComponentArgumentOptions(args) {
697
1210
  function toFullComponentInputOptions(inputs) {
698
1211
  return mapValues(inputs, (input) => "entity" in input ? input : { entity: input });
699
1212
  }
1213
+ function toFullComponentOutputOptions(outputs) {
1214
+ return mapValues(outputs, (output) => {
1215
+ if (typeof output !== "object" || output === null) {
1216
+ return { entity: output };
1217
+ }
1218
+ if ("entity" in output || "fromInput" in output) {
1219
+ return output;
1220
+ }
1221
+ return { entity: output };
1222
+ });
1223
+ }
700
1224
  function $args(args) {
701
1225
  return toFullComponentArgumentOptions(args);
702
1226
  }
@@ -704,7 +1228,7 @@ function $inputs(inputs) {
704
1228
  return toFullComponentInputOptions(inputs);
705
1229
  }
706
1230
  function $outputs(outputs) {
707
- return toFullComponentInputOptions(outputs);
1231
+ return toFullComponentOutputOptions(outputs);
708
1232
  }
709
1233
  function $addArgumentDescription(argument, description) {
710
1234
  if ("schema" in argument) {
@@ -743,7 +1267,7 @@ function $addInputDescription(input, description) {
743
1267
 
744
1268
  // src/instance.ts
745
1269
  function inputKey(input) {
746
- return `${input.instanceId}:${input.output}`;
1270
+ return input.path ? `${input.instanceId}:${input.output}:${input.path}` : `${input.instanceId}:${input.output}`;
747
1271
  }
748
1272
  var positionSchema = z.object({
749
1273
  x: z.number(),
@@ -752,7 +1276,8 @@ var positionSchema = z.object({
752
1276
  var instanceIdSchema = z.templateLiteral([versionedNameSchema, ":", genericNameSchema]);
753
1277
  var instanceInputSchema = z.object({
754
1278
  instanceId: instanceIdSchema,
755
- output: z.string()
1279
+ output: z.string(),
1280
+ path: z.string().optional()
756
1281
  });
757
1282
  var hubInputSchema = z.object({
758
1283
  hubId: z.string()
@@ -868,53 +1393,38 @@ function parseInstanceId(instanceId) {
868
1393
  }
869
1394
  return parts;
870
1395
  }
871
- function findInput(inputs, name) {
872
- const matchedInputs = inputs.filter(
873
- (input) => parseInstanceId(input.instanceId)[1] === name || input.instanceId === name
874
- );
875
- if (matchedInputs.length === 0) {
876
- return null;
877
- }
878
- if (matchedInputs.length > 1) {
1396
+ function selectInput(inputs, name) {
1397
+ const groupBoundary = inputs[boundaryInput] ?? inputs[0]?.[boundaryInput];
1398
+ if (inputs.length === 0 && !groupBoundary) {
879
1399
  throw new Error(
880
- `Multiple inputs found for "${name}": ${matchedInputs.map((input) => input.instanceId).join(", ")}. Specify the full instance id to disambiguate.`
1400
+ `Cannot select input "${name}": empty input group has no boundary metadata to build a missing input reference.`
881
1401
  );
882
1402
  }
883
- return matchedInputs[0];
884
- }
885
- function findRequiredInput(inputs, name) {
886
- const input = findInput(inputs, name);
887
- if (input === null) {
888
- throw new Error(`Required input "${name}" not found.`);
1403
+ const input = inputs.find(
1404
+ (input2) => input2.provided && (input2.instanceId === name || parseInstanceId(input2.instanceId)[1] === name)
1405
+ );
1406
+ if (!input || !input.provided) {
1407
+ const fallbackBoundary = groupBoundary ?? inputs.find((input2) => Boolean(input2[boundaryInput]))?.[boundaryInput] ?? inputs[0]?.[boundaryInput];
1408
+ if (!fallbackBoundary) {
1409
+ throw new Error(
1410
+ `Cannot select input "${name}": input group has no boundary metadata to build a missing input reference.`
1411
+ );
1412
+ }
1413
+ return createNonProvidedInput(fallbackBoundary);
889
1414
  }
890
- return input;
891
- }
892
- function findInputs(inputs, names) {
893
- return names.map((name) => findInput(inputs, name)).filter(Boolean);
894
- }
895
- function findRequiredInputs(inputs, names) {
896
- return names.map((name) => findRequiredInput(inputs, name));
1415
+ const boundary = groupBoundary ?? input[boundaryInput];
1416
+ return createInput(input, { boundary });
897
1417
  }
898
1418
  var HighstateSignature = /* @__PURE__ */ ((HighstateSignature2) => {
899
1419
  HighstateSignature2["Artifact"] = "d55c63ac-3174-4756-808f-f778e99af0d1";
900
1420
  HighstateSignature2["Yaml"] = "c857cac5-caa6-4421-b82c-e561fbce6367";
901
- HighstateSignature2["Id"] = "348d020e-0d9e-4ae7-9415-b91af99f5339";
902
- HighstateSignature2["Ref"] = "6d7f9da0-9cb6-496d-b72e-cf85ee4d9cf8";
1421
+ HighstateSignature2["Secret"] = "240e5789-6ae4-4b22-b9d8-87169e8b4bab";
903
1422
  return HighstateSignature2;
904
1423
  })(HighstateSignature || {});
905
1424
  var yamlValueSchema = z.object({
906
1425
  ["c857cac5-caa6-4421-b82c-e561fbce6367" /* Yaml */]: z.literal(true),
907
1426
  value: z.string()
908
1427
  });
909
- var objectWithIdSchema = z.object({
910
- ["348d020e-0d9e-4ae7-9415-b91af99f5339" /* Id */]: z.literal(true),
911
- id: z.number(),
912
- value: z.unknown()
913
- });
914
- var objectRefSchema = z.object({
915
- ["6d7f9da0-9cb6-496d-b72e-cf85ee4d9cf8" /* Ref */]: z.literal(true),
916
- id: z.number()
917
- });
918
1428
  var fileMetaSchema = z.object({
919
1429
  name: z.string(),
920
1430
  contentType: z.string().optional(),
@@ -946,6 +1456,19 @@ var instanceStatusFieldSchema = z.object({
946
1456
  complementaryTo: z.string().optional(),
947
1457
  value: instanceStatusFieldValueSchema.optional()
948
1458
  });
1459
+ function secretSchema(schema) {
1460
+ const secretType = z.object({
1461
+ ["240e5789-6ae4-4b22-b9d8-87169e8b4bab" /* Secret */]: z.literal(true),
1462
+ value: schema
1463
+ });
1464
+ return z.codec(z.union([secretType, schema]), secretType, {
1465
+ decode: (value) => typeof value === "object" && value !== null && "240e5789-6ae4-4b22-b9d8-87169e8b4bab" /* Secret */ in value ? value : { ["240e5789-6ae4-4b22-b9d8-87169e8b4bab" /* Secret */]: true, value },
1466
+ encode: (value) => value
1467
+ });
1468
+ }
1469
+ function isSecret(value) {
1470
+ return typeof value === "object" && value !== null && "240e5789-6ae4-4b22-b9d8-87169e8b4bab" /* Secret */ in value;
1471
+ }
949
1472
  var componentSecretSchema = componentArgumentSchema.extend({
950
1473
  /**
951
1474
  * The secret cannot be modified by the user, but can be modified by the unit.
@@ -991,12 +1514,15 @@ function defineUnit(options) {
991
1514
  create({ id }) {
992
1515
  const outputs = {};
993
1516
  for (const key in options.outputs ?? {}) {
994
- outputs[key] = [
995
- {
1517
+ outputs[key] = {
1518
+ provided: true,
1519
+ instanceId: id,
1520
+ output: key,
1521
+ [boundaryInput]: {
996
1522
  instanceId: id,
997
1523
  output: key
998
1524
  }
999
- ];
1525
+ };
1000
1526
  }
1001
1527
  return outputs;
1002
1528
  }
@@ -1058,18 +1584,31 @@ var triggerInvocationSchema = z.object({
1058
1584
  });
1059
1585
 
1060
1586
  // src/pulumi.ts
1061
- var unitInputReference = z.object({
1062
- ...instanceInputSchema.shape,
1587
+ var unitInputSourceSchema = z.object({
1588
+ ...instanceInputSchema.shape
1589
+ });
1590
+ var unitInputValueSchema = z.object({
1063
1591
  /**
1064
- * The resolved inclusion needed to extract the input value.
1592
+ * Inline resolved value passed to the unit.
1593
+ *
1594
+ * The backend is responsible for resolving the correct entity snapshot value
1595
+ * and applying any inclusion transformations.
1065
1596
  */
1066
- inclusion: entityInclusionSchema.optional()
1597
+ value: z.unknown(),
1598
+ /**
1599
+ * Optional provenance of the value.
1600
+ */
1601
+ source: unitInputSourceSchema.optional()
1067
1602
  });
1068
1603
  var unitConfigSchema = z.object({
1069
1604
  /**
1070
1605
  * The ID of the instance.
1071
1606
  */
1072
1607
  instanceId: z.string(),
1608
+ /**
1609
+ * The state ID of the instance.
1610
+ */
1611
+ stateId: z.string(),
1073
1612
  /**
1074
1613
  * The record of argument values for the unit.
1075
1614
  */
@@ -1077,19 +1616,17 @@ var unitConfigSchema = z.object({
1077
1616
  /**
1078
1617
  * The record of input references for the unit.
1079
1618
  */
1080
- inputs: z.record(z.string(), unitInputReference.array()),
1619
+ inputs: z.record(z.string(), unitInputValueSchema.array()),
1081
1620
  /**
1082
1621
  * The list of triggers that have been invoked for this unit.
1083
1622
  */
1084
1623
  invokedTriggers: triggerInvocationSchema.array(),
1085
1624
  /**
1086
- * The list of secret names that exists and provided to the unit.
1087
- */
1088
- secretNames: z.string().array(),
1089
- /**
1090
- * The map of instance ID to state ID in order to resolve instance references.
1625
+ * The record of secret values provided to the unit.
1626
+ *
1627
+ * It is stored in Pulumi stack config as a secret.
1091
1628
  */
1092
- stateIdMap: z.record(instanceIdSchema, z.string()),
1629
+ secretValues: z.record(z.string(), z.unknown()),
1093
1630
  /**
1094
1631
  * The base path for imports.
1095
1632
  * Used to resolve dynamic dependencies in strict environments (like in pnpm node_modules isolation).
@@ -1112,10 +1649,9 @@ function parseArgumentValue(value) {
1112
1649
  }
1113
1650
  var HighstateConfigKey = /* @__PURE__ */ ((HighstateConfigKey2) => {
1114
1651
  HighstateConfigKey2["Config"] = "highstate";
1115
- HighstateConfigKey2["Secrets"] = "highstate.secrets";
1116
1652
  return HighstateConfigKey2;
1117
1653
  })(HighstateConfigKey || {});
1118
- var unitArtifactId = Symbol("unitArtifactId");
1654
+ var unitArtifactId = /* @__PURE__ */ Symbol("unitArtifactId");
1119
1655
  var unitArtifactSchema = z.object({
1120
1656
  ["d55c63ac-3174-4756-808f-f778e99af0d1" /* Artifact */]: z.literal(true),
1121
1657
  // only for internal use
@@ -1139,6 +1675,21 @@ var fileContentSchema = z.union([
1139
1675
  */
1140
1676
  value: z.string()
1141
1677
  }),
1678
+ z.object({
1679
+ type: z.literal("embedded-secret"),
1680
+ /**
1681
+ * Whether the content is binary or not.
1682
+ *
1683
+ * If true, the `value` will be a base64 encoded string.
1684
+ */
1685
+ isBinary: z.boolean().optional(),
1686
+ /**
1687
+ * The content of the file wrapped as a Highstate secret.
1688
+ *
1689
+ * If `isBinary` is true, this will be a base64 encoded string.
1690
+ */
1691
+ value: secretSchema(z.string())
1692
+ }),
1142
1693
  z.object({
1143
1694
  type: z.literal("artifact"),
1144
1695
  ...unitArtifactSchema.shape
@@ -1236,301 +1787,6 @@ var workerRunOptionsSchema = z.object({
1236
1787
  */
1237
1788
  apiKey: z.string()
1238
1789
  });
1239
- function compact(value) {
1240
- const counts = /* @__PURE__ */ new WeakMap();
1241
- const cyclic = /* @__PURE__ */ new WeakSet();
1242
- const expanded = /* @__PURE__ */ new WeakSet();
1243
- const inStack = /* @__PURE__ */ new WeakSet();
1244
- const stack = [];
1245
- function countIdentities(current) {
1246
- if (current === null || typeof current !== "object") {
1247
- return;
1248
- }
1249
- counts.set(current, (counts.get(current) ?? 0) + 1);
1250
- if (inStack.has(current)) {
1251
- cyclic.add(current);
1252
- for (const entry of stack) {
1253
- cyclic.add(entry);
1254
- }
1255
- return;
1256
- }
1257
- if (expanded.has(current)) {
1258
- return;
1259
- }
1260
- expanded.add(current);
1261
- inStack.add(current);
1262
- stack.push(current);
1263
- if (Array.isArray(current)) {
1264
- try {
1265
- for (const item of current) {
1266
- countIdentities(item);
1267
- }
1268
- return;
1269
- } finally {
1270
- stack.pop();
1271
- inStack.delete(current);
1272
- }
1273
- }
1274
- try {
1275
- for (const entryValue of Object.values(current)) {
1276
- countIdentities(entryValue);
1277
- }
1278
- } finally {
1279
- stack.pop();
1280
- inStack.delete(current);
1281
- }
1282
- }
1283
- countIdentities(value);
1284
- const ids = /* @__PURE__ */ new WeakMap();
1285
- const definitionSites = /* @__PURE__ */ new WeakMap();
1286
- let nextId = 1;
1287
- function ensureId(current) {
1288
- const existing = ids.get(current);
1289
- if (existing !== void 0) {
1290
- return existing;
1291
- }
1292
- const allocated = nextId;
1293
- nextId += 1;
1294
- ids.set(current, allocated);
1295
- return allocated;
1296
- }
1297
- function assignDefinitionSitesBfs(root) {
1298
- if (root === null || typeof root !== "object") {
1299
- return;
1300
- }
1301
- const queue = [];
1302
- const expandedQueue = /* @__PURE__ */ new WeakSet();
1303
- if (Array.isArray(root)) {
1304
- for (let index = 0; index < root.length; index += 1) {
1305
- queue.push({ parent: root, key: index, value: root[index] });
1306
- }
1307
- } else {
1308
- for (const [key, entryValue] of Object.entries(root)) {
1309
- queue.push({ parent: root, key, value: entryValue });
1310
- }
1311
- }
1312
- while (queue.length > 0) {
1313
- const current = queue.shift();
1314
- if (current === void 0) {
1315
- continue;
1316
- }
1317
- if (current.value === null || typeof current.value !== "object") {
1318
- continue;
1319
- }
1320
- const occurrences = counts.get(current.value) ?? 0;
1321
- if (occurrences > 1 && definitionSites.get(current.value) === void 0) {
1322
- definitionSites.set(current.value, { parent: current.parent, key: current.key });
1323
- ensureId(current.value);
1324
- }
1325
- if (expandedQueue.has(current.value)) {
1326
- continue;
1327
- }
1328
- expandedQueue.add(current.value);
1329
- if (Array.isArray(current.value)) {
1330
- for (let index = 0; index < current.value.length; index += 1) {
1331
- queue.push({ parent: current.value, key: index, value: current.value[index] });
1332
- }
1333
- continue;
1334
- }
1335
- for (const [key, entryValue] of Object.entries(current.value)) {
1336
- queue.push({ parent: current.value, key, value: entryValue });
1337
- }
1338
- }
1339
- }
1340
- assignDefinitionSitesBfs(value);
1341
- const emitted = /* @__PURE__ */ new WeakSet();
1342
- function buildTreeChildren(current, rootOfIdValue) {
1343
- if (Array.isArray(current)) {
1344
- return current.map((item) => buildTree(item, rootOfIdValue));
1345
- }
1346
- return mapValues(current, (entryValue) => buildTree(entryValue, rootOfIdValue));
1347
- }
1348
- function buildTree(current, rootOfIdValue) {
1349
- if (current === null || typeof current !== "object") {
1350
- return current;
1351
- }
1352
- if (rootOfIdValue !== void 0 && emitted.has(current)) {
1353
- const id = ids.get(current);
1354
- if (id === void 0) {
1355
- throw new Error("Compaction invariant violation: missing id for repeated object");
1356
- }
1357
- return {
1358
- ["6d7f9da0-9cb6-496d-b72e-cf85ee4d9cf8" /* Ref */]: true,
1359
- id
1360
- };
1361
- }
1362
- if (rootOfIdValue !== void 0 && cyclic.has(current) && !emitted.has(current)) {
1363
- const id = ensureId(current);
1364
- emitted.add(current);
1365
- return {
1366
- ["348d020e-0d9e-4ae7-9415-b91af99f5339" /* Id */]: true,
1367
- id,
1368
- value: buildTreeChildren(current, current)
1369
- };
1370
- }
1371
- return buildTreeChildren(current, rootOfIdValue);
1372
- }
1373
- function buildAt(parent, key, current) {
1374
- if (current === null || typeof current !== "object") {
1375
- return current;
1376
- }
1377
- const occurrences = counts.get(current) ?? 0;
1378
- if (occurrences <= 1) {
1379
- if (Array.isArray(current)) {
1380
- return current.map((item, index) => buildAt(current, index, item));
1381
- }
1382
- return mapValues(current, (entryValue, entryKey) => buildAt(current, entryKey, entryValue));
1383
- }
1384
- const site = definitionSites.get(current);
1385
- const shouldDefineHere = site?.parent === parent && site.key === key;
1386
- const id = ids.get(current);
1387
- if (id === void 0) {
1388
- throw new Error("Compaction invariant violation: missing id for repeated object");
1389
- }
1390
- if (!shouldDefineHere || emitted.has(current)) {
1391
- return {
1392
- ["6d7f9da0-9cb6-496d-b72e-cf85ee4d9cf8" /* Ref */]: true,
1393
- id
1394
- };
1395
- }
1396
- emitted.add(current);
1397
- return {
1398
- ["348d020e-0d9e-4ae7-9415-b91af99f5339" /* Id */]: true,
1399
- id,
1400
- value: buildTreeChildren(current, current)
1401
- };
1402
- }
1403
- if (value === null || typeof value !== "object") {
1404
- return value;
1405
- }
1406
- const topLevelOccurrences = counts.get(value) ?? 0;
1407
- if (topLevelOccurrences > 1) {
1408
- const id = ensureId(value);
1409
- emitted.add(value);
1410
- return {
1411
- ["348d020e-0d9e-4ae7-9415-b91af99f5339" /* Id */]: true,
1412
- id,
1413
- value: buildTreeChildren(value, value)
1414
- };
1415
- }
1416
- if (Array.isArray(value)) {
1417
- return value.map((item, index) => buildAt(value, index, item));
1418
- }
1419
- return mapValues(
1420
- value,
1421
- (entryValue, entryKey) => buildAt(value, entryKey, entryValue)
1422
- );
1423
- }
1424
- function decompact(value) {
1425
- const rawValuesById = /* @__PURE__ */ new Map();
1426
- const placeholdersById = /* @__PURE__ */ new Map();
1427
- function collect(current, visited) {
1428
- const result = objectWithIdSchema.safeParse(current);
1429
- if (result.success) {
1430
- const { id } = result.data;
1431
- if (rawValuesById.has(id)) {
1432
- throw new Error(`Duplicate compacted id ${id}`);
1433
- }
1434
- rawValuesById.set(id, result.data.value);
1435
- collect(result.data.value, visited);
1436
- return;
1437
- }
1438
- if (current === null || current === void 0 || typeof current !== "object") {
1439
- return;
1440
- }
1441
- if (visited.has(current)) {
1442
- return;
1443
- }
1444
- visited.add(current);
1445
- if (Array.isArray(current)) {
1446
- for (const item of current) {
1447
- collect(item, visited);
1448
- }
1449
- return;
1450
- }
1451
- for (const entryValue of Object.values(current)) {
1452
- collect(entryValue, visited);
1453
- }
1454
- }
1455
- function ensurePlaceholder(id) {
1456
- const existing = placeholdersById.get(id);
1457
- if (existing !== void 0) {
1458
- return existing;
1459
- }
1460
- const raw = rawValuesById.get(id);
1461
- if (raw === void 0) {
1462
- throw new Error(`Unresolved compacted ref id ${id}`);
1463
- }
1464
- let placeholder;
1465
- if (raw !== null && typeof raw === "object") {
1466
- placeholder = Array.isArray(raw) ? [] : {};
1467
- } else {
1468
- placeholder = raw;
1469
- }
1470
- placeholdersById.set(id, placeholder);
1471
- return placeholder;
1472
- }
1473
- function resolve(current) {
1474
- const refResult = objectRefSchema.safeParse(current);
1475
- if (refResult.success) {
1476
- return ensurePlaceholder(refResult.data.id);
1477
- }
1478
- const withIdResult = objectWithIdSchema.safeParse(current);
1479
- if (withIdResult.success) {
1480
- return ensurePlaceholder(withIdResult.data.id);
1481
- }
1482
- if (current === null || current === void 0 || typeof current !== "object") {
1483
- return current;
1484
- }
1485
- if (Array.isArray(current)) {
1486
- return current.map((item) => resolve(item));
1487
- }
1488
- return mapValues(current, (entryValue) => resolve(entryValue));
1489
- }
1490
- function fillPlaceholder(id, visitedIds2) {
1491
- if (visitedIds2.has(id)) {
1492
- return;
1493
- }
1494
- visitedIds2.add(id);
1495
- const raw = rawValuesById.get(id);
1496
- if (raw === void 0) {
1497
- throw new Error(`Unresolved compacted ref id ${id}`);
1498
- }
1499
- const placeholder = ensurePlaceholder(id);
1500
- if (placeholder === null || typeof placeholder !== "object") {
1501
- return;
1502
- }
1503
- if (raw === null || typeof raw !== "object") {
1504
- throw new Error(`Compaction invariant violation: id ${id} points to non-object value`);
1505
- }
1506
- const resolved = resolve(raw);
1507
- if (Array.isArray(placeholder)) {
1508
- if (!Array.isArray(resolved)) {
1509
- throw new Error(`Compaction invariant violation: id ${id} array placeholder mismatch`);
1510
- }
1511
- placeholder.length = 0;
1512
- for (const item of resolved) {
1513
- placeholder.push(item);
1514
- }
1515
- return;
1516
- }
1517
- if (Array.isArray(resolved) || resolved === null || typeof resolved !== "object") {
1518
- throw new Error(`Compaction invariant violation: id ${id} object placeholder mismatch`);
1519
- }
1520
- for (const [key, entryValue] of Object.entries(resolved)) {
1521
- placeholder[key] = entryValue;
1522
- }
1523
- }
1524
- collect(value, /* @__PURE__ */ new WeakSet());
1525
- for (const id of rawValuesById.keys()) {
1526
- ensurePlaceholder(id);
1527
- }
1528
- const visitedIds = /* @__PURE__ */ new Set();
1529
- for (const id of rawValuesById.keys()) {
1530
- fillPlaceholder(id, visitedIds);
1531
- }
1532
- return resolve(value);
1533
- }
1534
1790
  function text(strings, ...values) {
1535
1791
  const stringValues = values.map(String);
1536
1792
  let result = "";
@@ -1573,6 +1829,6 @@ function stripNullish(obj) {
1573
1829
  return pickBy(obj, isNonNullish);
1574
1830
  }
1575
1831
 
1576
- export { $addArgumentDescription, $addInputDescription, $args, $inputs, $outputs, $secrets, HighstateConfigKey, HighstateSignature, InstanceNameConflictError, WellKnownInstanceCustomStatus, bytesToHumanReadable, camelCaseToHumanReadable, check, clearKnownAbbreviations, commonObjectMetaSchema, compact, componentArgumentSchema, componentInputSchema, componentModelSchema, componentSecretSchema, decompact, defineComponent, defineEntity, defineUnit, entityModelSchema, fieldNameSchema, fileContentSchema, fileMetaSchema, fileSchema, findInput, findInputs, findRequiredInput, findRequiredInputs, genericNameSchema, getInstanceId, getOrCreate, getRuntimeInstances, globalCommonObjectMetaSchema, hubInputSchema, hubModelPatchSchema, hubModelSchema, inputKey, instanceIdSchema, instanceInputSchema, instanceModelPatchSchema, instanceModelSchema, instanceStatusFieldSchema, instanceStatusFieldValueSchema, isAssignableTo, isComponent, isEntity, isUnitModel, objectMetaSchema, objectRefSchema, objectWithIdSchema, originalCreate, pageBlockSchema, parseArgumentValue, parseInstanceId, parseVersionedName, positionSchema, registerKnownAbbreviations, resetEvaluation, runtimeSchema, serviceAccountMetaSchema, setValidationEnabled, stripNullish, terminalSpecSchema, text, timestampsSchema, triggerInvocationSchema, triggerSpecSchema, trimIndentation, unitArtifactId, unitArtifactSchema, unitConfigSchema, unitInputReference, unitModelSchema, unitPageSchema, unitSourceSchema, unitTerminalSchema, unitTriggerSchema, unitWorkerSchema, versionedNameSchema, workerRunOptionsSchema, yamlValueSchema };
1832
+ export { $addArgumentDescription, $addInputDescription, $args, $inputs, $outputs, $secrets, HighstateConfigKey, HighstateSignature, InstanceNameConflictError, WellKnownInstanceCustomStatus, bytesToHumanReadable, camelCaseToHumanReadable, check, clearKnownAbbreviations, commonObjectMetaSchema, componentArgumentSchema, componentInputSchema, componentModelSchema, componentSecretSchema, createInput, createNonProvidedInput, cuidv2d, defineComponent, defineEntity, defineUnit, entityModelSchema, fieldNameSchema, fileContentSchema, fileMetaSchema, fileSchema, genericNameSchema, getEntityId, getInstanceId, getOrCreate, getRuntimeInstances, globalCommonObjectMetaSchema, hubInputSchema, hubModelPatchSchema, hubModelSchema, inputKey, instanceIdSchema, instanceInputSchema, instanceModelPatchSchema, instanceModelSchema, instanceStatusFieldSchema, instanceStatusFieldValueSchema, isAssignableTo, isComponent, isEntity, isSecret, isUnitModel, objectMetaSchema, originalCreate, pageBlockSchema, parseArgumentValue, parseInstanceId, parseVersionedName, positionSchema, registerKnownAbbreviations, resetEvaluation, runtimeSchema, secretSchema, selectInput, serviceAccountMetaSchema, setValidationEnabled, stripNullish, terminalSpecSchema, text, timestampsSchema, triggerInvocationSchema, triggerSpecSchema, trimIndentation, unitArtifactId, unitArtifactSchema, unitConfigSchema, unitInputSourceSchema, unitInputValueSchema, unitModelSchema, unitPageSchema, unitSourceSchema, unitTerminalSchema, unitTriggerSchema, unitWorkerSchema, versionedNameSchema, workerRunOptionsSchema, yamlValueSchema };
1577
1833
  //# sourceMappingURL=index.js.map
1578
1834
  //# sourceMappingURL=index.js.map