@highstate/contract 0.9.15 → 0.9.16

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "sourceHashes": {
3
- "./dist/index.js": "5651f5e32c7a58ef4eae22b8a7c4ca37b001d5265e6b5a597b769c434e05d77f"
3
+ "./dist/index.js": "8c046a05a4ab42bf93b5b7c82f018ee26601c24a7f464bfb0c2d02c7b1357b3c"
4
4
  }
5
5
  }
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/instance.ts
2
+ import { Type } from "@sinclair/typebox";
2
3
  var boundaryInput = Symbol("boundaryInput");
3
4
  function getInstanceId(instanceType, instanceName) {
4
5
  return `${instanceType}:${instanceName}`;
@@ -37,6 +38,40 @@ function findInputs(inputs, names) {
37
38
  function findRequiredInputs(inputs, names) {
38
39
  return names.map((name) => findRequiredInput(inputs, name));
39
40
  }
41
+ var HighstateSignature = /* @__PURE__ */ ((HighstateSignature2) => {
42
+ HighstateSignature2["Artifact"] = "d55c63ac-3174-4756-808f-f778e99af0d1";
43
+ return HighstateSignature2;
44
+ })(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())
51
+ });
52
+ var unitObjectMetaSchema = Type.Object({
53
+ displayName: Type.Optional(Type.String()),
54
+ description: Type.Optional(Type.String()),
55
+ primaryIcon: Type.Optional(Type.String())
56
+ });
57
+ var unitArtifactSchema = Type.Object({
58
+ hash: Type.String(),
59
+ meta: Type.Optional(unitObjectMetaSchema)
60
+ });
61
+ var fileContentSchema = Type.Union([
62
+ Type.Object({
63
+ type: Type.Literal("embedded"),
64
+ value: Type.String()
65
+ }),
66
+ Type.Object({
67
+ type: Type.Literal("artifact"),
68
+ ["d55c63ac-3174-4756-808f-f778e99af0d1" /* Artifact */]: unitArtifactSchema
69
+ })
70
+ ]);
71
+ var fileSchema = Type.Object({
72
+ meta: fileMetaSchema,
73
+ content: fileContentSchema
74
+ });
40
75
 
41
76
  // src/evaluation.ts
42
77
  import { mapValues as mapValues3 } from "remeda";
@@ -79,6 +114,27 @@ function bytesToHumanReadable(bytes) {
79
114
  return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + " " + sizes[i];
80
115
  }
81
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);
124
+ }
125
+ }
126
+ }
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);
133
+ }
134
+ return word.charAt(0).toUpperCase() + word.slice(1);
135
+ }).join(" ");
136
+ }
137
+
82
138
  // src/component.ts
83
139
  var ajv = new Ajv({ strict: false });
84
140
  var originalCreate = Symbol("originalCreate");
@@ -126,7 +182,10 @@ function defineComponent(options) {
126
182
  args: mapValues(options.args ?? {}, mapArgument),
127
183
  inputs: mapValues(options.inputs ?? {}, mapInput),
128
184
  outputs: mapValues(options.outputs ?? {}, mapInput),
129
- meta: options.meta ?? {}
185
+ meta: {
186
+ ...options.meta,
187
+ displayName: options.meta?.displayName ?? camelCaseToHumanReadable(options.type)
188
+ }
130
189
  };
131
190
  create[originalCreate] = options.create;
132
191
  return create;
@@ -134,26 +193,30 @@ function defineComponent(options) {
134
193
  function isComponent(value) {
135
194
  return typeof value === "function" && "model" in value;
136
195
  }
137
- function mapArgument(value) {
196
+ function mapArgument(value, key) {
138
197
  if ("schema" in value) {
139
198
  return {
140
199
  schema: value.schema,
141
200
  required: value.required ?? (!value.schema[OptionalKind] && value.schema.default === void 0),
142
201
  meta: {
143
- displayName: value.displayName,
144
- description: value.description,
145
- color: value.color
202
+ displayName: value.meta?.displayName ?? camelCaseToHumanReadable(key),
203
+ description: value.meta?.description
146
204
  }
147
205
  };
148
206
  }
149
207
  return {
150
208
  schema: value,
151
209
  required: !value[OptionalKind] && value.default === void 0,
152
- meta: {}
210
+ meta: {
211
+ displayName: camelCaseToHumanReadable(key)
212
+ }
153
213
  };
154
214
  }
155
215
  function createInputMapper(entities) {
156
- return (value) => {
216
+ return (value, key) => {
217
+ if (!value) {
218
+ throw new Error(`Input/output "${key}" is undefined in the component model.`);
219
+ }
157
220
  if ("entity" in value) {
158
221
  entities.set(value.entity.type, value.entity);
159
222
  return {
@@ -161,7 +224,7 @@ function createInputMapper(entities) {
161
224
  required: value.required ?? true,
162
225
  multiple: value.multiple ?? false,
163
226
  meta: {
164
- displayName: value.displayName,
227
+ displayName: value.displayName ?? camelCaseToHumanReadable(key),
165
228
  description: value.description,
166
229
  color: value.color
167
230
  }
@@ -172,7 +235,9 @@ function createInputMapper(entities) {
172
235
  type: value.type,
173
236
  required: true,
174
237
  multiple: false,
175
- meta: {}
238
+ meta: {
239
+ displayName: camelCaseToHumanReadable(key)
240
+ }
176
241
  };
177
242
  };
178
243
  }
@@ -192,6 +257,15 @@ function validateArgsAndFillDefaults(instanceId, model, args) {
192
257
  }
193
258
  return args;
194
259
  }
260
+ function $args(args) {
261
+ return args;
262
+ }
263
+ function $inputs(inputs) {
264
+ return inputs;
265
+ }
266
+ function $outputs(outputs) {
267
+ return outputs;
268
+ }
195
269
 
196
270
  // src/unit.ts
197
271
  function isUnitModel(model) {
@@ -217,6 +291,9 @@ function defineUnit(options) {
217
291
  component.model.secrets = mapValues2(options.secrets ?? {}, mapArgument);
218
292
  return component;
219
293
  }
294
+ function $secrets(secrets) {
295
+ return secrets;
296
+ }
220
297
 
221
298
  // src/evaluation.ts
222
299
  var compositeInstances = /* @__PURE__ */ new Map();
@@ -280,22 +357,31 @@ import {
280
357
  Type as BaseType
281
358
  } from "@sinclair/typebox";
282
359
  function StringEnum(values) {
283
- return Type.Union(values.map((value) => Type.Literal(value)));
360
+ return Type2.Union(values.map((value) => Type2.Literal(value)));
284
361
  }
285
362
  function Default(schema, defaultValue) {
286
363
  return { ...schema, default: defaultValue };
287
364
  }
288
- var Type = {
365
+ var Type2 = {
289
366
  ...BaseType,
290
367
  StringEnum,
291
368
  Default
292
369
  };
293
370
  export {
294
- Type,
371
+ $args,
372
+ $inputs,
373
+ $outputs,
374
+ $secrets,
375
+ HighstateSignature,
376
+ Type2 as Type,
295
377
  bytesToHumanReadable,
378
+ camelCaseToHumanReadable,
296
379
  defineComponent,
297
380
  defineEntity,
298
381
  defineUnit,
382
+ fileContentSchema,
383
+ fileMetaSchema,
384
+ fileSchema,
299
385
  findInput,
300
386
  findInputs,
301
387
  findRequiredInput,
@@ -307,8 +393,11 @@ export {
307
393
  isUnitModel,
308
394
  originalCreate,
309
395
  parseInstanceId,
396
+ registerKnownAbbreviations,
310
397
  resetEvaluation,
311
398
  text,
312
- trimIndentation
399
+ trimIndentation,
400
+ unitArtifactSchema,
401
+ unitObjectMetaSchema
313
402
  };
314
403
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/instance.ts","../src/evaluation.ts","../src/unit.ts","../src/component.ts","../src/utils.ts","../src/entity.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["declare const type: unique symbol\n\nexport type InstanceInput<TType extends string = string> = {\n [type]?: TType\n [boundaryInput]?: InstanceInput\n instanceId: string\n output: string\n}\n\nexport const boundaryInput = Symbol(\"boundaryInput\")\n\nexport type HubInput = {\n hubId: string\n}\n\nexport type Position = {\n x: number\n y: number\n}\n\nexport type InstanceModel = {\n /**\n * The id of the instance unique within the project.\n *\n * The format is `${instanceType}:${instanceName}`.\n */\n id: string\n\n /**\n * The type of the instance.\n */\n type: string\n\n /**\n * The name of the instance.\n *\n * Must be unique within instances of the same type in the project.\n */\n name: string\n\n /**\n * The static arguments passed to the instance.\n */\n args?: Record<string, unknown>\n\n /**\n * The direct instances passed as inputs to the instance.\n */\n inputs?: Record<string, InstanceInput[]>\n\n /**\n * The resolved unit inputs for the instance.\n *\n * Only for computed composite instances.\n */\n resolvedInputs?: Record<string, InstanceInput[]>\n\n /**\n * The inputs passed to the instance from the hubs.\n *\n * Only for designer-first instances.\n */\n hubInputs?: Record<string, HubInput[]>\n\n /**\n * The inputs injected to the instance from the hubs.\n *\n * While `hubInputs` allows to pass hubs to distinct inputs,\n * `injectionInputs` allows to pass hubs to the instance as a whole filling all inputs with matching types.\n *\n * Only for designer-first instances.\n */\n injectionInputs?: HubInput[]\n\n /**\n * The position of the instance on the canvas.\n *\n * Only for designer-first instances.\n */\n position?: Position\n\n /**\n * The id of the top level parent instance.\n *\n * Only for child instances of the composite instances.\n */\n parentId?: string\n\n /**\n * The direct instance inputs and same-level children outputs returned by the instance as outputs.\n *\n * Only for computed composite instances.\n */\n outputs?: Record<string, InstanceInput[]>\n\n /**\n * The resolved unit outputs for the instance.\n *\n * Only for computed composite instances.\n */\n resolvedOutputs?: Record<string, InstanceInput[]>\n}\n\n/**\n * Formats the instance id from the instance type and instance name.\n *\n * @param instanceType The type of the instance.\n * @param instanceName The name of the instance.\n *\n * @returns The formatted instance id.\n */\nexport function getInstanceId(instanceType: string, instanceName: string): string {\n return `${instanceType}:${instanceName}`\n}\n\n/**\n * Parses the instance id into the instance type and instance name.\n *\n * @param instanceId The instance id to parse.\n *\n * @returns The instance type and instance name.\n */\nexport function parseInstanceId(instanceId: string): [instanceType: string, instanceName: string] {\n const parts = instanceId.split(\":\")\n\n if (parts.length !== 2) {\n throw new Error(`Invalid instance key: ${instanceId}`)\n }\n\n return parts as [string, string]\n}\n\nexport function findInput<T extends string>(\n inputs: InstanceInput<T>[],\n name: string,\n): InstanceInput<T> | null {\n const matchedInputs = inputs.filter(\n input => parseInstanceId(input.instanceId)[1] === name || input.instanceId === name,\n )\n\n if (matchedInputs.length === 0) {\n return null\n }\n\n if (matchedInputs.length > 1) {\n throw new Error(\n `Multiple inputs found for \"${name}\": ${matchedInputs.map(input => input.instanceId).join(\", \")}. Specify the full instance id to disambiguate.`,\n )\n }\n\n return matchedInputs[0]\n}\n\nexport function findRequiredInput<T extends string>(\n inputs: InstanceInput<T>[],\n name: string,\n): InstanceInput<T> {\n const input = findInput(inputs, name)\n\n if (input === null) {\n throw new Error(`Required input \"${name}\" not found.`)\n }\n\n return input\n}\n\nexport function findInputs<T extends string>(\n inputs: InstanceInput<T>[],\n names: string[],\n): InstanceInput<T>[] {\n return names.map(name => findInput(inputs, name)).filter(Boolean) as InstanceInput<T>[]\n}\n\nexport function findRequiredInputs<T extends string>(\n inputs: InstanceInput<T>[],\n names: string[],\n): InstanceInput<T>[] {\n return names.map(name => findRequiredInput(inputs, name))\n}\n","import type { ComponentModel } from \"./component\"\nimport { mapValues } from \"remeda\"\nimport { boundaryInput, type InstanceInput, type InstanceModel } from \"./instance\"\nimport { isUnitModel } from \"./unit\"\n\nexport type CompositeInstance = {\n instance: InstanceModel\n children: InstanceModel[]\n}\n\nconst compositeInstances: Map<string, CompositeInstance> = new Map()\nlet currentCompositeInstance: CompositeInstance | null = null\n\nexport function resetEvaluation(): void {\n compositeInstances.clear()\n currentCompositeInstance = null\n}\n\nexport function getCompositeInstances(): CompositeInstance[] {\n return Array.from(compositeInstances.values())\n}\n\nexport function registerInstance<T>(\n component: ComponentModel,\n instance: InstanceModel,\n fn: () => T,\n): T {\n let previousParentInstance: CompositeInstance | null = null\n\n if (currentCompositeInstance) {\n instance.parentId = currentCompositeInstance.instance.id\n currentCompositeInstance.children.push(instance)\n }\n\n if (!isUnitModel(component)) {\n previousParentInstance = currentCompositeInstance\n currentCompositeInstance = { instance, children: [] }\n compositeInstances.set(currentCompositeInstance.instance.id, currentCompositeInstance)\n }\n\n try {\n const outputs = fn() as Record<string, InstanceInput[]>\n\n instance.resolvedOutputs = outputs\n instance.outputs = mapValues(outputs ?? {}, outputs =>\n outputs.map(output => output[boundaryInput] ?? output),\n )\n\n // mark all outputs with the boundary input of the instance\n return mapValues(outputs, (outputs, outputKey) =>\n outputs.map(output => ({\n ...output,\n [boundaryInput]: { instanceId: instance.id, output: outputKey },\n })),\n ) as T\n } finally {\n if (previousParentInstance) {\n currentCompositeInstance = previousParentInstance\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\nimport type { ArgumentValue } from \"./types\"\nimport type { InstanceInput } from \"./instance\"\nimport { mapValues } from \"remeda\"\nimport {\n type ComponentArgumentSpec,\n type Component,\n type ComponentArgument,\n type ComponentArgumentOptions,\n type ComponentInputOptions,\n type ComponentInputOptionsMapToSpecMap,\n type ComponentInputSpec,\n type ComponentModel,\n type ComponentOptions,\n defineComponent,\n mapArgument,\n type ComponentArgumentOptionsMapToSpecMap,\n} from \"./component\"\n\ntype UnitOptions<\n TArgs extends Record<string, ComponentArgumentOptions>,\n TInputs extends Record<string, ComponentInputOptions>,\n TOutputs extends Record<string, ComponentInputOptions>,\n TSecrets extends Record<string, ComponentArgumentOptions>,\n> = Omit<ComponentOptions<TArgs, TInputs, TOutputs>, \"create\"> & {\n source: UnitSource\n\n secrets?: TSecrets\n}\n\nexport type UnitSource = {\n package: string\n path?: string\n version?: string\n}\n\nexport type UnitModel = ComponentModel & {\n /**\n * The source of the unit.\n */\n source: UnitSource\n\n /**\n * The record of the secret argument schemas.\n */\n secrets: Record<string, ComponentArgument>\n}\n\nexport type Unit<\n TArgs extends Record<string, ComponentArgumentSpec> = Record<string, never>,\n TInputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n TSecrets extends Record<string, ArgumentValue> = Record<string, never>,\n> = Component<TArgs, TInputs, TOutputs> & {\n __secrets: TSecrets\n\n model: UnitModel\n}\n\nexport function isUnitModel(model: ComponentModel): model is UnitModel {\n return \"source\" in model\n}\n\nexport function defineUnit<\n TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>,\n TInputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n TSecrets extends Record<string, ComponentArgumentOptions> = Record<string, never>,\n>(\n options: UnitOptions<TArgs, TInputs, TOutputs, TSecrets>,\n // @ts-expect-error typescript bug\n): Unit<\n ComponentArgumentOptionsMapToSpecMap<TArgs>,\n ComponentInputOptionsMapToSpecMap<TInputs>,\n ComponentInputOptionsMapToSpecMap<TOutputs>,\n ComponentArgumentOptionsMapToSpecMap<TSecrets>\n> {\n const component = defineComponent<TArgs, TInputs, TOutputs>({\n ...options,\n\n create({ id }) {\n const outputs: Record<string, InstanceInput[]> = {}\n for (const key in options.outputs ?? {}) {\n outputs[key] = [\n {\n instanceId: id,\n output: key,\n },\n ]\n }\n\n return outputs as any\n },\n }) as any\n\n component.model.source = options.source ?? {}\n component.model.secrets = mapValues(options.secrets ?? {}, mapArgument)\n\n return component\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n\nimport type { Entity } from \"./entity\"\nimport type { ArgumentValue, ArgumentValueSchema, Meta } from \"./types\"\nimport {\n type Static,\n type TObject,\n type TOptional,\n type TSchema,\n OptionalKind,\n} from \"@sinclair/typebox\"\nimport { isNonNullish, mapValues, pickBy } from \"remeda\"\nimport { Ajv } from \"ajv\"\nimport { boundaryInput, type InstanceInput } from \"./instance\"\nimport { type OptionalUndefinedFields, type OptionalEmptyRecords } from \"./utils\"\nimport { registerInstance } from \"./evaluation\"\n\nconst ajv = new Ajv({ strict: false })\n\n// Argument\nexport type ComponentArgument = {\n schema: ArgumentValueSchema\n required: boolean\n meta: Meta\n}\n\ntype ComponentArgumentFullOptions = Meta & {\n schema: ArgumentValueSchema\n required?: boolean\n}\n\nexport type ComponentArgumentOptions = ArgumentValueSchema | ComponentArgumentFullOptions\nexport type ComponentArgumentSpec = [schema: ArgumentValueSchema, hasDefault: boolean]\n\nexport type ComponentArgumentOptionsToSpec<T extends ComponentArgumentOptions> =\n T extends ArgumentValueSchema\n ? [T, T extends { default: unknown } ? true : false]\n : T extends ComponentArgumentFullOptions\n ? T[\"schema\"] extends TOptional<TSchema>\n ? [T[\"schema\"], T[\"schema\"] extends { default: unknown } ? true : false]\n : [\n T[\"required\"] extends false ? TOptional<T[\"schema\"]> : T[\"schema\"],\n T[\"schema\"] extends { default: unknown } ? true : false,\n ]\n : never\n\nexport type ComponentArgumentOptionsMapToSpecMap<\n T extends Record<string, ComponentArgumentOptions>,\n> =\n T extends Record<string, never>\n ? Record<string, never>\n : { [K in keyof T]: ComponentArgumentOptionsToSpec<T[K]> }\n\nexport type ComponentArgumentSpecMapToInputStatic<T extends Record<string, ComponentArgumentSpec>> =\n T extends Record<string, never>\n ? Record<string, never>\n : Static<TObject<{ [K in keyof T]: T[K][1] extends false ? T[K][0] : TOptional<T[K][0]> }>>\n\nexport type ComponentArgumentSpecToStatic<T extends Record<string, ComponentArgumentSpec>> =\n T extends Record<string, never>\n ? Record<string, never>\n : Static<TObject<{ [K in keyof T]: T[K][0] }>>\n\nexport type ComponentArgumentOptionsToSchema<T extends ComponentArgumentOptions> = T extends TSchema\n ? T\n : T[\"required\"] extends false\n ? TOptional<T[\"schema\"]>\n : T[\"schema\"]\n\ntype ComponentArgumentMapToValue<T extends Record<string, ComponentArgumentOptions>> = {\n [K in keyof T]: Static<ComponentArgumentOptionsToSchema<T[K]>>\n}\n\n// Input\nexport type ComponentInput = {\n type: string\n required: boolean\n multiple: boolean\n meta: Meta\n}\n\ntype ComponentInputFullOptions = Meta & {\n entity: Entity\n required?: boolean\n multiple?: boolean\n}\n\nexport type ComponentInputOptions = Entity | ComponentInputFullOptions\n\ntype ComponentInputOptionsToOutputRef<T extends ComponentInputOptions> = T extends Entity\n ? InstanceInput<T[\"type\"]>\n : T extends ComponentInputFullOptions\n ? T[\"required\"] extends false\n ? T[\"multiple\"] extends true\n ? InstanceInput<T[\"entity\"][\"type\"]>[] | undefined\n : InstanceInput<T[\"entity\"][\"type\"]> | undefined\n : T[\"multiple\"] extends true\n ? InstanceInput<T[\"entity\"][\"type\"]>[]\n : InstanceInput<T[\"entity\"][\"type\"]>\n : never\n\nexport type ComponentInputSpec = [entity: Entity, required: boolean, multiple: boolean]\n\nexport type ComponentInputOptionsToSpec<T extends ComponentInputOptions> = T extends Entity\n ? [T, true, false] // [Entity, required, multiple]\n : T extends ComponentInputFullOptions\n ? T[\"required\"] extends false\n ? T[\"multiple\"] extends true\n ? [T[\"entity\"], false, true]\n : [T[\"entity\"], false, false]\n : T[\"multiple\"] extends true\n ? [T[\"entity\"], true, true]\n : [T[\"entity\"], true, false]\n : never\n\nexport type ComponentInputOptionsMapToSpecMap<T extends Record<string, ComponentInputOptions>> =\n T extends Record<string, never>\n ? Record<string, never>\n : { [K in keyof T]: ComponentInputOptionsToSpec<T[K]> }\n\ntype ComponentInputMapToValue<T extends Record<string, ComponentInputOptions>> =\n OptionalUndefinedFields<{\n [K in keyof T]: ComponentInputOptionsToOutputRef<T[K]>\n }>\n\ntype ComponentInputMapToReturnType<T extends Record<string, ComponentInputOptions>> =\n T extends Record<string, never> ? void : ComponentInputMapToValue<T>\n\n// Params & Options\nexport type ComponentParams<\n TArgs extends Record<string, ComponentArgumentOptions>,\n TInputs extends Record<string, ComponentInputOptions>,\n> = {\n id: string\n name: string\n args: ComponentArgumentMapToValue<TArgs>\n inputs: ComponentInputMapToValue<TInputs>\n}\n\nexport type InputComponentParams<\n TArgs extends Record<string, ArgumentValue>,\n TInputs extends Record<string, unknown>,\n> = {\n name: string\n} & OptionalEmptyRecords<{\n args: TArgs\n inputs: TInputs\n}>\n\nexport type ComponentOptions<\n TArgs extends Record<string, ComponentArgumentOptions>,\n TInputs extends Record<string, ComponentInputOptions>,\n TOutputs extends Record<string, ComponentInputOptions>,\n> = {\n type: string\n meta?: ComponentMeta\n\n args?: TArgs\n inputs?: TInputs\n outputs?: TOutputs\n\n create: (params: ComponentParams<TArgs, TInputs>) => ComponentInputMapToReturnType<TOutputs>\n}\n\n// Models\nexport type ComponentMeta = Meta & {\n primaryIcon?: string\n primaryIconColor?: string\n secondaryIcon?: string\n secondaryIconColor?: string\n category?: string\n defaultNamePrefix?: string\n}\n\nexport type ComponentModel = {\n /**\n * The type of the component.\n */\n type: string\n\n /**\n * The record of the argument schemas.\n */\n args: Record<string, ComponentArgument>\n\n /**\n * The record of the input schemas.\n */\n inputs: Record<string, ComponentInput>\n\n /**\n * The record of the output schemas.\n */\n outputs: Record<string, ComponentInput>\n\n /**\n * The extra metadata of the component.\n */\n meta: ComponentMeta\n\n /**\n * The hash of the component definition.\n */\n definitionHash: string\n}\n\ntype InputSpecToInputRef<T extends ComponentInputSpec> = T[1] extends true\n ? T[2] extends true\n ? InstanceInput<T[0][\"type\"]>[]\n : InstanceInput<T[0][\"type\"]>\n : T[2] extends true\n ? InstanceInput<T[0][\"type\"]>[] | undefined\n : InstanceInput<T[0][\"type\"]> | undefined\n\ntype InputSpecToOutputRef<T extends ComponentInputSpec> = T[2] extends true\n ? InstanceInput<T[0][\"type\"]>[]\n : InstanceInput<T[0][\"type\"]>\n\nexport type InputRefMap<TInputs extends Record<string, ComponentInputSpec>> =\n TInputs extends Record<string, [string, never, never]>\n ? Record<string, never>\n : { [K in keyof TInputs]: InputSpecToInputRef<TInputs[K]> }\n\nexport type OutputRefMap<TInputs extends Record<string, ComponentInputSpec>> =\n TInputs extends Record<string, [string, never, never]>\n ? Record<string, never>\n : { [K in keyof TInputs]: InputSpecToOutputRef<TInputs[K]> }\n\nexport const originalCreate = Symbol(\"originalCreate\")\n\nexport type Component<\n TArgs extends Record<string, ComponentArgumentSpec> = Record<string, never>,\n TInputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n> = {\n /**\n * The non-generic model of the component.\n */\n model: ComponentModel\n\n /**\n * The entities used in the inputs or outputs of the component.\n */\n entities: Map<string, Entity>\n\n /**\n * Creates the component at the evaluation time.\n */\n (\n context: InputComponentParams<\n ComponentArgumentSpecMapToInputStatic<TArgs>,\n InputRefMap<TInputs>\n >,\n ): OutputRefMap<TOutputs>\n\n /**\n * The original create function.\n *\n * Used to calculate the definition hash.\n */\n [originalCreate]: (params: InputComponentParams<any, any>) => any\n}\n\nexport function defineComponent<\n TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>,\n TInputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n>(\n options: ComponentOptions<TArgs, TInputs, TOutputs>,\n // @ts-expect-error typescript bug\n): Component<\n ComponentArgumentOptionsMapToSpecMap<TArgs>,\n ComponentInputOptionsMapToSpecMap<TInputs>,\n ComponentInputOptionsMapToSpecMap<TOutputs>\n> {\n function create(params: InputComponentParams<any, any>): any {\n const { name, args, inputs } = params\n const id = `${options.type}:${name}`\n\n const flatInputs = mapValues(pickBy(inputs ?? {}, isNonNullish), inputs => [inputs].flat(2))\n\n return registerInstance(\n create.model as ComponentModel,\n {\n id,\n type: options.type,\n name,\n args: args ?? {},\n inputs: mapValues(flatInputs, inputs => inputs.map(input => input[boundaryInput] ?? input)),\n resolvedInputs: flatInputs,\n },\n () => {\n const markedInputs = mapValues(flatInputs, (inputs, key) => {\n const result = inputs.map(input => ({\n ...input,\n [boundaryInput]: { instanceId: id, output: key },\n }))\n\n return (create.model as ComponentModel).inputs?.[key]?.multiple === false\n ? result[0]\n : result\n })\n\n const outputs: Record<string, InstanceInput[]> =\n options.create({\n id,\n name,\n args: validateArgsAndFillDefaults(\n id,\n create.model as ComponentModel,\n args ? { ...args } : {},\n ) as any,\n inputs: markedInputs as any,\n }) ?? {}\n\n return mapValues(pickBy(outputs, isNonNullish), outputs => [outputs].flat(2))\n },\n )\n }\n\n create.entities = new Map<string, Entity>()\n const mapInput = createInputMapper(create.entities)\n\n create.model = {\n type: options.type,\n args: mapValues(options.args ?? {}, mapArgument),\n inputs: mapValues(options.inputs ?? {}, mapInput),\n outputs: mapValues(options.outputs ?? {}, mapInput),\n meta: options.meta ?? {},\n }\n\n create[originalCreate] = options.create\n\n return create as any\n}\n\nexport function isComponent(value: unknown): value is Component {\n return typeof value === \"function\" && \"model\" in value\n}\n\nexport function mapArgument(value: ComponentArgumentOptions) {\n if (\"schema\" in value) {\n return {\n schema: value.schema,\n required:\n value.required ?? (!value.schema[OptionalKind] && value.schema.default === undefined),\n meta: {\n displayName: value.displayName,\n description: value.description,\n color: value.color,\n },\n }\n }\n\n return {\n schema: value,\n required: !value[OptionalKind] && value.default === undefined,\n meta: {},\n }\n}\n\nexport function createInputMapper(entities: Map<string, Entity>) {\n return (value: ComponentInputOptions) => {\n if (\"entity\" in value) {\n entities.set(value.entity.type, value.entity)\n\n return {\n type: value.entity.type,\n required: value.required ?? true,\n multiple: value.multiple ?? false,\n meta: {\n displayName: value.displayName,\n description: value.description,\n color: value.color,\n },\n }\n }\n\n entities.set(value.type, value)\n\n return {\n type: value.type,\n required: true,\n multiple: false,\n meta: {},\n }\n }\n}\n\nfunction validateArgsAndFillDefaults(\n instanceId: string,\n model: ComponentModel,\n args: Record<string, unknown>,\n) {\n for (const [key, argModel] of Object.entries(model.args)) {\n let value = args[key]\n if (!value) {\n if (argModel.required) {\n throw new Error(`Missing required argument \"${key}\" for instance \"${instanceId}\"`)\n }\n\n value = argModel.schema.default\n args[key] = value\n }\n\n if (value && !ajv.validate(argModel.schema, value)) {\n throw new Error(`Invalid argument \"${key}\" for instance \"${instanceId}\": ${ajv.errorsText()}`)\n }\n }\n\n return args as Record<string, ArgumentValue>\n}\n","export type EntityMap<T> = Record<string, T> & {\n default?: T\n}\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\nexport type RequiredKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>\n\n// TODO: refactor this shit\n\ntype PickUndefinedKeys<T extends Record<string, unknown>> =\n T extends Record<string, never>\n ? never\n : Exclude<\n {\n [K in keyof T]: undefined extends T[K] ? K : never\n }[keyof T],\n undefined\n >\n\ntype AllOptionalKeys<T extends Record<string, unknown>> =\n T extends Record<string, never>\n ? never\n : Exclude<\n {\n [K in keyof T]: undefined extends T[K] ? K : never\n }[keyof T],\n undefined\n >\n\ntype HasRequired<T extends Record<string, unknown>> =\n T extends Record<string, never> ? false : [keyof T] extends [AllOptionalKeys<T>] ? false : true\n\ntype PickRecordsWithAnyRequired<T extends Record<string, Record<string, unknown>>> =\n T extends Record<string, never>\n ? never\n : Exclude<\n {\n [K in keyof T]: HasRequired<T[K]> extends true ? K : never\n }[keyof T],\n undefined\n >\n\nexport type OptionalEmptyRecords<T extends Record<string, Record<string, unknown>>> = {\n [K in Exclude<keyof T, PickRecordsWithAnyRequired<T>>]?: OptionalUndefinedFields<T[K]>\n} & {\n [K in PickRecordsWithAnyRequired<T>]: OptionalUndefinedFields<T[K]>\n}\n\nexport type OptionalUndefinedFields<T extends Record<string, unknown>> = {\n [K in PickUndefinedKeys<T>]?: T[K]\n} & {\n [K in Exclude<keyof T, PickUndefinedKeys<T>>]: T[K]\n}\n\n/**\n * Formats a multiline string and trims the indentation.\n *\n * @param str The string to trim.\n * @returns The trimmed string.\n */\nexport function text(strings: TemplateStringsArray, ...values: unknown[]): string {\n // Convert all values to strings\n const stringValues = values.map(String)\n\n // Build full string with values interpolated\n let result = \"\"\n for (let i = 0; i < strings.length; i++) {\n result += strings[i]\n if (i < stringValues.length) {\n const value = stringValues[i]\n const lines = value.split(\"\\n\")\n const lastLineIndentMatch = strings[i].match(/(?:^|\\n)([ \\t]*)$/)\n const indent = lastLineIndentMatch ? lastLineIndentMatch[1] : \"\"\n\n result += lines.map((line, j) => (j === 0 ? line : indent + line)).join(\"\\n\")\n }\n }\n\n return trimIndentation(result)\n}\n\n/**\n * Removes the indentation from a multiline string.\n *\n * @param text The text to trim.\n * @returns The trimmed text.\n */\nexport function trimIndentation(text: string): string {\n const lines = text.split(\"\\n\")\n const indent = lines\n .filter(line => line.trim() !== \"\")\n .map(line => line.match(/^\\s*/)?.[0].length ?? 0)\n .reduce((min, indent) => Math.min(min, indent), Infinity)\n\n return lines\n .map(line => line.slice(indent))\n .join(\"\\n\")\n .trim()\n}\n\nexport function bytesToHumanReadable(bytes: number): string {\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"]\n if (bytes === 0) return \"0 Bytes\"\n\n const i = Math.floor(Math.log(bytes) / Math.log(1024))\n return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + \" \" + sizes[i]\n}\n","import type { TAnySchema, TSchema } from \"@sinclair/typebox\"\nimport type { Meta } from \"./types\"\nimport type { PartialKeys } from \"./utils\"\n\n/**\n * The entity is some abstract object which can be passed from one component to another through their inputs and outputs.\n * Every entity must have a type.\n * Every component inputs and outputs will reference such types and only entities of the same type can be passed.\n */\nexport type Entity<TType extends string = string, TEntitySchema extends TSchema = TSchema> = {\n /**\n * The static type of the entity.\n */\n type: TType\n\n /**\n * The JSON schema of the entity value.\n */\n schema: TEntitySchema\n\n /**\n * The extra metadata of the entity.\n */\n meta: Meta\n\n /**\n * The hash of the entity definition.\n */\n definitionHash: string\n}\n\nexport type EntityOptions<TType extends string, TSchema extends TAnySchema> = Omit<\n PartialKeys<Entity<TType, TSchema>, \"meta\">,\n \"definitionHash\"\n>\n\nexport function defineEntity<TType extends string, TSchema extends TAnySchema>(\n options: EntityOptions<TType, TSchema>,\n): Entity<TType, TSchema> {\n return {\n meta: {},\n ...options,\n } as Entity<TType, TSchema>\n}\n\nexport function isEntity(value: unknown): value is Entity {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n \"schema\" in value &&\n \"meta\" in value\n )\n}\n","import {\n type Static,\n type TAny,\n type TArray,\n type TBoolean,\n type TLiteral,\n type TNumber,\n type TObject,\n type TRecordOrObject,\n type TString,\n type TUnion,\n} from \"@sinclair/typebox\"\n\nexport type ArgumentValueSchema =\n | TString\n | TNumber\n | TBoolean\n | TArray<TString>\n | TArray<TNumber>\n | TUnion<TLiteral[]>\n | TRecordOrObject<TString, TAny>\n | TObject\n | TArray\n | TUnion<TObject[]>\n\nexport type ArgumentValue = Static<ArgumentValueSchema>\n\n/**\n * The generic metadata of some contract.\n */\nexport type Meta = {\n /**\n * The display name of the entity which can be shown in the UI.\n */\n displayName?: string\n\n /**\n * The description of the entity which can be shown in the UI.\n */\n description?: string\n\n /**\n * The hex color of the entity which can be used in the UI.\n *\n * @example \"#ff0000\"\n */\n color?: string\n}\n","export {\n type InstanceInput,\n type HubInput,\n type InstanceModel,\n type Position,\n getInstanceId,\n parseInstanceId,\n findInput,\n findRequiredInput,\n findInputs,\n findRequiredInputs,\n} from \"./instance\"\nexport { getCompositeInstances, resetEvaluation, type CompositeInstance } from \"./evaluation\"\nexport { type Entity, defineEntity, isEntity } from \"./entity\"\nexport {\n type Component,\n type ComponentModel,\n type ComponentMeta,\n type ComponentArgument,\n type ComponentInput,\n type ComponentInputSpec,\n type ComponentArgumentSpec,\n type ComponentArgumentSpecToStatic,\n defineComponent,\n isComponent,\n originalCreate,\n} from \"./component\"\nexport { type Unit, type UnitModel, type UnitSource, defineUnit, isUnitModel } from \"./unit\"\nexport {\n type RequiredKeys,\n type PartialKeys,\n text,\n trimIndentation,\n bytesToHumanReadable,\n} from \"./utils\"\nexport { type ArgumentValue, type ArgumentValueSchema } from \"./types\"\nexport * from \"@sinclair/typebox\"\n\nimport {\n Type as BaseType,\n type Static,\n type TLiteral,\n type TSchema,\n type TUnion,\n} from \"@sinclair/typebox\"\n\ntype MapToLiteral<T extends readonly string[]> = {\n [K in keyof T]: T[K] extends string ? TLiteral<T[K]> : never\n}\n\nfunction StringEnum<T extends string[]>(values: [...T]): TUnion<MapToLiteral<T>> {\n return Type.Union(values.map(value => Type.Literal(value))) as TUnion<MapToLiteral<T>>\n}\n\nfunction Default<T extends TSchema>(\n schema: T,\n defaultValue: Static<T>,\n): T & { default: Static<T> } {\n return { ...schema, default: defaultValue }\n}\n\nexport const Type = {\n ...BaseType,\n StringEnum,\n Default,\n} as typeof BaseType & {\n StringEnum: typeof StringEnum\n Default: typeof Default\n}\n"],"mappings":"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","names":["mapValues","mapValues","text","indent","inputs","outputs","mapValues","mapValues","outputs"]}
1
+ {"version":3,"sources":["../src/instance.ts","../src/evaluation.ts","../src/unit.ts","../src/component.ts","../src/utils.ts","../src/i18n.ts","../src/entity.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["import { Type, type Static } from \"@sinclair/typebox\"\n\ndeclare const type: unique symbol\n\nexport type InstanceInput<TType extends string = string> = {\n [type]?: TType\n [boundaryInput]?: InstanceInput\n instanceId: string\n output: string\n}\n\nexport const boundaryInput = Symbol(\"boundaryInput\")\n\nexport type HubInput = {\n hubId: string\n}\n\nexport type Position = {\n x: number\n y: number\n}\n\nexport type InstanceModel = {\n /**\n * The id of the instance unique within the project.\n *\n * The format is `${instanceType}:${instanceName}`.\n */\n id: string\n\n /**\n * The type of the instance.\n */\n type: string\n\n /**\n * The name of the instance.\n *\n * Must be unique within instances of the same type in the project.\n */\n name: string\n\n /**\n * The static arguments passed to the instance.\n */\n args?: Record<string, unknown>\n\n /**\n * The direct instances passed as inputs to the instance.\n */\n inputs?: Record<string, InstanceInput[]>\n\n /**\n * The resolved unit inputs for the instance.\n *\n * Only for computed composite instances.\n */\n resolvedInputs?: Record<string, InstanceInput[]>\n\n /**\n * The inputs passed to the instance from the hubs.\n *\n * Only for designer-first instances.\n */\n hubInputs?: Record<string, HubInput[]>\n\n /**\n * The inputs injected to the instance from the hubs.\n *\n * While `hubInputs` allows to pass hubs to distinct inputs,\n * `injectionInputs` allows to pass hubs to the instance as a whole filling all inputs with matching types.\n *\n * Only for designer-first instances.\n */\n injectionInputs?: HubInput[]\n\n /**\n * The position of the instance on the canvas.\n *\n * Only for designer-first instances.\n */\n position?: Position\n\n /**\n * The id of the top level parent instance.\n *\n * Only for child instances of the composite instances.\n */\n parentId?: string\n\n /**\n * The direct instance inputs and same-level children outputs returned by the instance as outputs.\n *\n * Only for computed composite instances.\n */\n outputs?: Record<string, InstanceInput[]>\n\n /**\n * The resolved unit outputs for the instance.\n *\n * Only for computed composite instances.\n */\n resolvedOutputs?: Record<string, InstanceInput[]>\n}\n\n/**\n * Formats the instance id from the instance type and instance name.\n *\n * @param instanceType The type of the instance.\n * @param instanceName The name of the instance.\n *\n * @returns The formatted instance id.\n */\nexport function getInstanceId(instanceType: string, instanceName: string): string {\n return `${instanceType}:${instanceName}`\n}\n\n/**\n * Parses the instance id into the instance type and instance name.\n *\n * @param instanceId The instance id to parse.\n *\n * @returns The instance type and instance name.\n */\nexport function parseInstanceId(instanceId: string): [instanceType: string, instanceName: string] {\n const parts = instanceId.split(\":\")\n\n if (parts.length !== 2) {\n throw new Error(`Invalid instance key: ${instanceId}`)\n }\n\n return parts as [string, string]\n}\n\nexport function findInput<T extends string>(\n inputs: InstanceInput<T>[],\n name: string,\n): InstanceInput<T> | null {\n const matchedInputs = inputs.filter(\n input => parseInstanceId(input.instanceId)[1] === name || input.instanceId === name,\n )\n\n if (matchedInputs.length === 0) {\n return null\n }\n\n if (matchedInputs.length > 1) {\n throw new Error(\n `Multiple inputs found for \"${name}\": ${matchedInputs.map(input => input.instanceId).join(\", \")}. Specify the full instance id to disambiguate.`,\n )\n }\n\n return matchedInputs[0]\n}\n\nexport function findRequiredInput<T extends string>(\n inputs: InstanceInput<T>[],\n name: string,\n): InstanceInput<T> {\n const input = findInput(inputs, name)\n\n if (input === null) {\n throw new Error(`Required input \"${name}\" not found.`)\n }\n\n return input\n}\n\nexport function findInputs<T extends string>(\n inputs: InstanceInput<T>[],\n names: string[],\n): InstanceInput<T>[] {\n return names.map(name => findInput(inputs, name)).filter(Boolean) as InstanceInput<T>[]\n}\n\nexport function findRequiredInputs<T extends string>(\n inputs: InstanceInput<T>[],\n names: string[],\n): InstanceInput<T>[] {\n return names.map(name => findRequiredInput(inputs, name))\n}\n\nexport enum HighstateSignature {\n Artifact = \"d55c63ac-3174-4756-808f-f778e99af0d1\",\n}\n\nexport const fileMetaSchema = Type.Object({\n name: Type.String(),\n contentType: Type.Optional(Type.String()),\n size: Type.Optional(Type.Number()),\n mode: Type.Optional(Type.Number()),\n isBinary: Type.Optional(Type.Boolean()),\n})\n\nexport const unitObjectMetaSchema = Type.Object({\n displayName: Type.Optional(Type.String()),\n description: Type.Optional(Type.String()),\n primaryIcon: Type.Optional(Type.String()),\n})\n\nexport const unitArtifactSchema = Type.Object({\n hash: Type.String(),\n meta: Type.Optional(unitObjectMetaSchema),\n})\n\nexport const fileContentSchema = Type.Union([\n Type.Object({\n type: Type.Literal(\"embedded\"),\n value: Type.String(),\n }),\n Type.Object({\n type: Type.Literal(\"artifact\"),\n [HighstateSignature.Artifact]: unitArtifactSchema,\n }),\n])\n\nexport const fileSchema = Type.Object({\n meta: fileMetaSchema,\n content: fileContentSchema,\n})\n\nexport type FileMeta = Static<typeof fileMetaSchema>\nexport type FileContent = Static<typeof fileContentSchema>\nexport type UnitObjectMeta = Static<typeof unitObjectMetaSchema>\nexport type UnitArtifact = Static<typeof unitArtifactSchema>\nexport type File = Static<typeof fileSchema>\n","import type { ComponentModel } from \"./component\"\nimport { mapValues } from \"remeda\"\nimport { boundaryInput, type InstanceInput, type InstanceModel } from \"./instance\"\nimport { isUnitModel } from \"./unit\"\n\nexport type CompositeInstance = {\n instance: InstanceModel\n children: InstanceModel[]\n}\n\nconst compositeInstances: Map<string, CompositeInstance> = new Map()\nlet currentCompositeInstance: CompositeInstance | null = null\n\nexport function resetEvaluation(): void {\n compositeInstances.clear()\n currentCompositeInstance = null\n}\n\nexport function getCompositeInstances(): CompositeInstance[] {\n return Array.from(compositeInstances.values())\n}\n\nexport function registerInstance<T>(\n component: ComponentModel,\n instance: InstanceModel,\n fn: () => T,\n): T {\n let previousParentInstance: CompositeInstance | null = null\n\n if (currentCompositeInstance) {\n instance.parentId = currentCompositeInstance.instance.id\n currentCompositeInstance.children.push(instance)\n }\n\n if (!isUnitModel(component)) {\n previousParentInstance = currentCompositeInstance\n currentCompositeInstance = { instance, children: [] }\n compositeInstances.set(currentCompositeInstance.instance.id, currentCompositeInstance)\n }\n\n try {\n const outputs = fn() as Record<string, InstanceInput[]>\n\n instance.resolvedOutputs = outputs\n instance.outputs = mapValues(outputs ?? {}, outputs =>\n outputs.map(output => output[boundaryInput] ?? output),\n )\n\n // mark all outputs with the boundary input of the instance\n return mapValues(outputs, (outputs, outputKey) =>\n outputs.map(output => ({\n ...output,\n [boundaryInput]: { instanceId: instance.id, output: outputKey },\n })),\n ) as T\n } finally {\n if (previousParentInstance) {\n currentCompositeInstance = previousParentInstance\n }\n }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\nimport type { ArgumentValue, ArgumentValueSchema } from \"./types\"\nimport type { InstanceInput } from \"./instance\"\nimport { mapValues } from \"remeda\"\nimport {\n type ComponentArgumentSpec,\n type Component,\n type ComponentArgument,\n type ComponentArgumentOptions,\n type ComponentInputOptions,\n type ComponentInputOptionsMapToSpecMap,\n type ComponentInputSpec,\n type ComponentModel,\n type ComponentOptions,\n defineComponent,\n mapArgument,\n type ComponentArgumentOptionsMapToSpecMap,\n type ComponentArgumentFullOptions,\n} from \"./component\"\n\nexport type ComponentSecret = ComponentArgument & {\n /**\n * The secret cannot be modified by the user, but can be modified by the unit.\n */\n readonly: boolean\n\n /**\n * The secret value is computed by the unit and should not be passed to it when invoked.\n */\n computed: boolean\n}\n\ntype ComponentSecretFullOptions = ComponentArgumentFullOptions & {\n readonly?: boolean\n computed?: boolean\n}\n\nexport type ComponentSecretOptions = ArgumentValueSchema | ComponentSecretFullOptions\n\ntype UnitOptions<\n TArgs extends Record<string, ComponentArgumentOptions>,\n TInputs extends Record<string, ComponentInputOptions>,\n TOutputs extends Record<string, ComponentInputOptions>,\n TSecrets extends Record<string, ComponentArgumentOptions>,\n> = Omit<ComponentOptions<TArgs, TInputs, TOutputs>, \"create\"> & {\n source: UnitSource\n\n secrets?: TSecrets\n}\n\nexport type UnitSource = {\n package: string\n path?: string\n version?: string\n}\n\nexport type UnitModel = ComponentModel & {\n /**\n * The source of the unit.\n */\n source: UnitSource\n\n /**\n * The record of the secret argument schemas.\n */\n secrets: Record<string, ComponentSecret>\n}\n\nexport type Unit<\n TArgs extends Record<string, ComponentArgumentSpec> = Record<string, never>,\n TInputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n TSecrets extends Record<string, ArgumentValue> = Record<string, never>,\n> = Component<TArgs, TInputs, TOutputs> & {\n __secrets: TSecrets\n\n model: UnitModel\n}\n\nexport function isUnitModel(model: ComponentModel): model is UnitModel {\n return \"source\" in model\n}\n\nexport function defineUnit<\n TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>,\n TInputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n TSecrets extends Record<string, ComponentSecretOptions> = Record<string, never>,\n>(\n options: UnitOptions<TArgs, TInputs, TOutputs, TSecrets>,\n // @ts-expect-error typescript bug\n): Unit<\n ComponentArgumentOptionsMapToSpecMap<TArgs>,\n ComponentInputOptionsMapToSpecMap<TInputs>,\n ComponentInputOptionsMapToSpecMap<TOutputs>,\n ComponentArgumentOptionsMapToSpecMap<TSecrets>\n> {\n const component = defineComponent<TArgs, TInputs, TOutputs>({\n ...options,\n\n create({ id }) {\n const outputs: Record<string, InstanceInput[]> = {}\n for (const key in options.outputs ?? {}) {\n outputs[key] = [\n {\n instanceId: id,\n output: key,\n },\n ]\n }\n\n return outputs as any\n },\n }) as any\n\n component.model.source = options.source ?? {}\n component.model.secrets = mapValues(options.secrets ?? {}, mapArgument)\n\n return component\n}\n\n/**\n * The helper marker for component secrets.\n *\n * Helps validating secrets types and gives the compiler a hint for generating `meta` fields.\n */\nexport function $secrets<T extends Record<string, ComponentSecretOptions>>(secrets: T): T {\n return secrets\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n\nimport type { Entity } from \"./entity\"\nimport type { ArgumentValue, ArgumentValueSchema, Meta } from \"./types\"\nimport {\n type Static,\n type TObject,\n type TOptional,\n type TSchema,\n OptionalKind,\n} from \"@sinclair/typebox\"\nimport { isNonNullish, mapValues, pickBy } from \"remeda\"\nimport { Ajv } from \"ajv\"\nimport { boundaryInput, type InstanceInput } from \"./instance\"\nimport { type OptionalUndefinedFields, type OptionalEmptyRecords } from \"./utils\"\nimport { registerInstance } from \"./evaluation\"\nimport { camelCaseToHumanReadable } from \"./i18n\"\n\nconst ajv = new Ajv({ strict: false })\n\n// Argument\nexport type ComponentArgument = {\n schema: ArgumentValueSchema\n required: boolean\n meta: Meta\n}\n\nexport type ComponentArgumentFullOptions = {\n schema: ArgumentValueSchema\n required?: boolean\n meta?: Meta\n}\n\nexport type ComponentArgumentOptions = ArgumentValueSchema | ComponentArgumentFullOptions\nexport type ComponentArgumentSpec = [schema: ArgumentValueSchema, hasDefault: boolean]\n\nexport type ComponentArgumentOptionsToSpec<T extends ComponentArgumentOptions> =\n T extends ArgumentValueSchema\n ? [T, T extends { default: unknown } ? true : false]\n : T extends ComponentArgumentFullOptions\n ? T[\"schema\"] extends TOptional<TSchema>\n ? [T[\"schema\"], T[\"schema\"] extends { default: unknown } ? true : false]\n : [\n T[\"required\"] extends false ? TOptional<T[\"schema\"]> : T[\"schema\"],\n T[\"schema\"] extends { default: unknown } ? true : false,\n ]\n : never\n\nexport type ComponentArgumentOptionsMapToSpecMap<\n T extends Record<string, ComponentArgumentOptions>,\n> =\n T extends Record<string, never>\n ? Record<string, never>\n : { [K in keyof T]: ComponentArgumentOptionsToSpec<T[K]> }\n\nexport type ComponentArgumentSpecMapToInputStatic<T extends Record<string, ComponentArgumentSpec>> =\n T extends Record<string, never>\n ? Record<string, never>\n : Static<TObject<{ [K in keyof T]: T[K][1] extends false ? T[K][0] : TOptional<T[K][0]> }>>\n\nexport type ComponentArgumentSpecToStatic<T extends Record<string, ComponentArgumentSpec>> =\n T extends Record<string, never>\n ? Record<string, never>\n : Static<TObject<{ [K in keyof T]: T[K][0] }>>\n\nexport type ComponentArgumentOptionsToSchema<T extends ComponentArgumentOptions> = T extends TSchema\n ? T\n : T[\"required\"] extends false\n ? TOptional<T[\"schema\"]>\n : T[\"schema\"]\n\ntype ComponentArgumentMapToValue<T extends Record<string, ComponentArgumentOptions>> = {\n [K in keyof T]: Static<ComponentArgumentOptionsToSchema<T[K]>>\n}\n\n// Input\nexport type ComponentInput = {\n type: string\n required: boolean\n multiple: boolean\n meta: Meta\n}\n\ntype ComponentInputFullOptions = Meta & {\n entity: Entity\n required?: boolean\n multiple?: boolean\n}\n\nexport type ComponentInputOptions = Entity | ComponentInputFullOptions\n\ntype ComponentInputOptionsToOutputRef<T extends ComponentInputOptions> = T extends Entity\n ? InstanceInput<T[\"type\"]>\n : T extends ComponentInputFullOptions\n ? T[\"required\"] extends false\n ? T[\"multiple\"] extends true\n ? InstanceInput<T[\"entity\"][\"type\"]>[] | undefined\n : InstanceInput<T[\"entity\"][\"type\"]> | undefined\n : T[\"multiple\"] extends true\n ? InstanceInput<T[\"entity\"][\"type\"]>[]\n : InstanceInput<T[\"entity\"][\"type\"]>\n : never\n\nexport type ComponentInputSpec = [entity: Entity, required: boolean, multiple: boolean]\n\nexport type ComponentInputOptionsToSpec<T extends ComponentInputOptions> = T extends Entity\n ? [T, true, false] // [Entity, required, multiple]\n : T extends ComponentInputFullOptions\n ? T[\"required\"] extends false\n ? T[\"multiple\"] extends true\n ? [T[\"entity\"], false, true]\n : [T[\"entity\"], false, false]\n : T[\"multiple\"] extends true\n ? [T[\"entity\"], true, true]\n : [T[\"entity\"], true, false]\n : never\n\nexport type ComponentInputOptionsMapToSpecMap<T extends Record<string, ComponentInputOptions>> =\n T extends Record<string, never>\n ? Record<string, never>\n : { [K in keyof T]: ComponentInputOptionsToSpec<T[K]> }\n\ntype ComponentInputMapToValue<T extends Record<string, ComponentInputOptions>> =\n OptionalUndefinedFields<{\n [K in keyof T]: ComponentInputOptionsToOutputRef<T[K]>\n }>\n\ntype ComponentInputMapToReturnType<T extends Record<string, ComponentInputOptions>> =\n T extends Record<string, never> ? void : ComponentInputMapToValue<T>\n\n// Params & Options\nexport type ComponentParams<\n TArgs extends Record<string, ComponentArgumentOptions>,\n TInputs extends Record<string, ComponentInputOptions>,\n> = {\n id: string\n name: string\n args: ComponentArgumentMapToValue<TArgs>\n inputs: ComponentInputMapToValue<TInputs>\n}\n\nexport type InputComponentParams<\n TArgs extends Record<string, ArgumentValue>,\n TInputs extends Record<string, unknown>,\n> = {\n name: string\n} & OptionalEmptyRecords<{\n args: TArgs\n inputs: TInputs\n}>\n\nexport type ComponentOptions<\n TArgs extends Record<string, ComponentArgumentOptions>,\n TInputs extends Record<string, ComponentInputOptions>,\n TOutputs extends Record<string, ComponentInputOptions>,\n> = {\n type: string\n meta?: ComponentMeta\n\n args?: TArgs\n inputs?: TInputs\n outputs?: TOutputs\n\n create: (params: ComponentParams<TArgs, TInputs>) => ComponentInputMapToReturnType<TOutputs>\n}\n\n// Models\nexport type ComponentMeta = Meta & {\n primaryIcon?: string\n primaryIconColor?: string\n secondaryIcon?: string\n secondaryIconColor?: string\n category?: string\n defaultNamePrefix?: string\n}\n\nexport type ComponentModel = {\n /**\n * The type of the component.\n */\n type: string\n\n /**\n * The record of the argument schemas.\n */\n args: Record<string, ComponentArgument>\n\n /**\n * The record of the input schemas.\n */\n inputs: Record<string, ComponentInput>\n\n /**\n * The record of the output schemas.\n */\n outputs: Record<string, ComponentInput>\n\n /**\n * The extra metadata of the component.\n */\n meta: ComponentMeta\n\n /**\n * The CRC32 of the component definition.\n */\n definitionHash: number\n}\n\ntype InputSpecToInputRef<T extends ComponentInputSpec> = T[1] extends true\n ? T[2] extends true\n ? InstanceInput<T[0][\"type\"]>[]\n : InstanceInput<T[0][\"type\"]>\n : T[2] extends true\n ? InstanceInput<T[0][\"type\"]>[] | undefined\n : InstanceInput<T[0][\"type\"]> | undefined\n\ntype InputSpecToOutputRef<T extends ComponentInputSpec> = T[2] extends true\n ? InstanceInput<T[0][\"type\"]>[]\n : InstanceInput<T[0][\"type\"]>\n\nexport type InputRefMap<TInputs extends Record<string, ComponentInputSpec>> =\n TInputs extends Record<string, [string, never, never]>\n ? Record<string, never>\n : { [K in keyof TInputs]: InputSpecToInputRef<TInputs[K]> }\n\nexport type OutputRefMap<TInputs extends Record<string, ComponentInputSpec>> =\n TInputs extends Record<string, [string, never, never]>\n ? Record<string, never>\n : { [K in keyof TInputs]: InputSpecToOutputRef<TInputs[K]> }\n\nexport const originalCreate = Symbol(\"originalCreate\")\n\nexport type Component<\n TArgs extends Record<string, ComponentArgumentSpec> = Record<string, never>,\n TInputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputSpec> = Record<string, never>,\n> = {\n /**\n * The non-generic model of the component.\n */\n model: ComponentModel\n\n /**\n * The entities used in the inputs or outputs of the component.\n */\n entities: Map<string, Entity>\n\n /**\n * Creates the component at the evaluation time.\n */\n (\n context: InputComponentParams<\n ComponentArgumentSpecMapToInputStatic<TArgs>,\n InputRefMap<TInputs>\n >,\n ): OutputRefMap<TOutputs>\n\n /**\n * The original create function.\n *\n * Used to calculate the definition hash.\n */\n [originalCreate]: (params: InputComponentParams<any, any>) => any\n}\n\nexport function defineComponent<\n TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>,\n TInputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>,\n>(\n options: ComponentOptions<TArgs, TInputs, TOutputs>,\n // @ts-expect-error typescript bug\n): Component<\n ComponentArgumentOptionsMapToSpecMap<TArgs>,\n ComponentInputOptionsMapToSpecMap<TInputs>,\n ComponentInputOptionsMapToSpecMap<TOutputs>\n> {\n function create(params: InputComponentParams<any, any>): any {\n const { name, args, inputs } = params\n const id = `${options.type}:${name}`\n\n const flatInputs = mapValues(pickBy(inputs ?? {}, isNonNullish), inputs => [inputs].flat(2))\n\n return registerInstance(\n create.model as ComponentModel,\n {\n id,\n type: options.type,\n name,\n args: args ?? {},\n inputs: mapValues(flatInputs, inputs => inputs.map(input => input[boundaryInput] ?? input)),\n resolvedInputs: flatInputs,\n },\n () => {\n const markedInputs = mapValues(flatInputs, (inputs, key) => {\n const result = inputs.map(input => ({\n ...input,\n [boundaryInput]: { instanceId: id, output: key },\n }))\n\n return (create.model as ComponentModel).inputs?.[key]?.multiple === false\n ? result[0]\n : result\n })\n\n const outputs: Record<string, InstanceInput[]> =\n options.create({\n id,\n name,\n args: validateArgsAndFillDefaults(\n id,\n create.model as ComponentModel,\n args ? { ...args } : {},\n ) as any,\n inputs: markedInputs as any,\n }) ?? {}\n\n return mapValues(pickBy(outputs, isNonNullish), outputs => [outputs].flat(2))\n },\n )\n }\n\n create.entities = new Map<string, Entity>()\n const mapInput = createInputMapper(create.entities)\n\n create.model = {\n type: options.type,\n args: mapValues(options.args ?? {}, mapArgument),\n inputs: mapValues(options.inputs ?? {}, mapInput),\n outputs: mapValues(options.outputs ?? {}, mapInput),\n meta: {\n ...options.meta,\n displayName: options.meta?.displayName ?? camelCaseToHumanReadable(options.type),\n },\n }\n\n create[originalCreate] = options.create\n\n return create as any\n}\n\nexport function isComponent(value: unknown): value is Component {\n return typeof value === \"function\" && \"model\" in value\n}\n\nexport function mapArgument(value: ComponentArgumentOptions, key: string) {\n if (\"schema\" in value) {\n return {\n schema: value.schema,\n required:\n value.required ?? (!value.schema[OptionalKind] && value.schema.default === undefined),\n meta: {\n displayName: value.meta?.displayName ?? camelCaseToHumanReadable(key),\n description: value.meta?.description,\n },\n }\n }\n\n return {\n schema: value,\n required: !value[OptionalKind] && value.default === undefined,\n meta: {\n displayName: camelCaseToHumanReadable(key),\n },\n }\n}\n\nexport function createInputMapper(entities: Map<string, Entity>) {\n return (value: ComponentInputOptions, key: string) => {\n if (!value) {\n throw new Error(`Input/output \"${key}\" is undefined in the component model.`)\n }\n\n if (\"entity\" in value) {\n entities.set(value.entity.type, value.entity)\n\n return {\n type: value.entity.type,\n required: value.required ?? true,\n multiple: value.multiple ?? false,\n meta: {\n displayName: value.displayName ?? camelCaseToHumanReadable(key),\n description: value.description,\n color: value.color,\n },\n }\n }\n\n entities.set(value.type, value)\n\n return {\n type: value.type,\n required: true,\n multiple: false,\n meta: {\n displayName: camelCaseToHumanReadable(key),\n },\n }\n }\n}\n\nfunction validateArgsAndFillDefaults(\n instanceId: string,\n model: ComponentModel,\n args: Record<string, unknown>,\n) {\n for (const [key, argModel] of Object.entries(model.args)) {\n let value = args[key]\n if (!value) {\n if (argModel.required) {\n throw new Error(`Missing required argument \"${key}\" for instance \"${instanceId}\"`)\n }\n\n value = argModel.schema.default\n args[key] = value\n }\n\n if (value && !ajv.validate(argModel.schema, value)) {\n throw new Error(`Invalid argument \"${key}\" for instance \"${instanceId}\": ${ajv.errorsText()}`)\n }\n }\n\n return args as Record<string, ArgumentValue>\n}\n\n/**\n * The helper marker for component arguments.\n *\n * Helps validating arguments types and gives the compiler a hint for generating `meta` fields.\n */\nexport function $args<T extends Record<string, ComponentArgumentOptions>>(args: T): T {\n return args\n}\n\n/**\n * The helper marker for component inputs.\n *\n * Helps validating inputs types and gives the compiler a hint for generating `meta` fields.\n */\nexport function $inputs<T extends Record<string, ComponentInputOptions>>(inputs: T): T {\n return inputs\n}\n\n/**\n * The helper marker for component outputs.\n *\n * Helps validating outputs types and gives the compiler a hint for generating `meta` fields.\n */\nexport function $outputs<T extends Record<string, ComponentInputOptions>>(outputs: T): T {\n return outputs\n}\n","export type EntityMap<T> = Record<string, T> & {\n default?: T\n}\n\nexport type PartialKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>\nexport type RequiredKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>\n\n// TODO: refactor this shit\n\ntype PickUndefinedKeys<T extends Record<string, unknown>> =\n T extends Record<string, never>\n ? never\n : Exclude<\n {\n [K in keyof T]: undefined extends T[K] ? K : never\n }[keyof T],\n undefined\n >\n\ntype AllOptionalKeys<T extends Record<string, unknown>> =\n T extends Record<string, never>\n ? never\n : Exclude<\n {\n [K in keyof T]: undefined extends T[K] ? K : never\n }[keyof T],\n undefined\n >\n\ntype HasRequired<T extends Record<string, unknown>> =\n T extends Record<string, never> ? false : [keyof T] extends [AllOptionalKeys<T>] ? false : true\n\ntype PickRecordsWithAnyRequired<T extends Record<string, Record<string, unknown>>> =\n T extends Record<string, never>\n ? never\n : Exclude<\n {\n [K in keyof T]: HasRequired<T[K]> extends true ? K : never\n }[keyof T],\n undefined\n >\n\nexport type OptionalEmptyRecords<T extends Record<string, Record<string, unknown>>> = {\n [K in Exclude<keyof T, PickRecordsWithAnyRequired<T>>]?: OptionalUndefinedFields<T[K]>\n} & {\n [K in PickRecordsWithAnyRequired<T>]: OptionalUndefinedFields<T[K]>\n}\n\nexport type OptionalUndefinedFields<T extends Record<string, unknown>> = {\n [K in PickUndefinedKeys<T>]?: T[K]\n} & {\n [K in Exclude<keyof T, PickUndefinedKeys<T>>]: T[K]\n}\n\n/**\n * Formats a multiline string and trims the indentation.\n *\n * @param str The string to trim.\n * @returns The trimmed string.\n */\nexport function text(strings: TemplateStringsArray, ...values: unknown[]): string {\n // Convert all values to strings\n const stringValues = values.map(String)\n\n // Build full string with values interpolated\n let result = \"\"\n for (let i = 0; i < strings.length; i++) {\n result += strings[i]\n if (i < stringValues.length) {\n const value = stringValues[i]\n const lines = value.split(\"\\n\")\n const lastLineIndentMatch = strings[i].match(/(?:^|\\n)([ \\t]*)$/)\n const indent = lastLineIndentMatch ? lastLineIndentMatch[1] : \"\"\n\n result += lines.map((line, j) => (j === 0 ? line : indent + line)).join(\"\\n\")\n }\n }\n\n return trimIndentation(result)\n}\n\n/**\n * Removes the indentation from a multiline string.\n *\n * @param text The text to trim.\n * @returns The trimmed text.\n */\nexport function trimIndentation(text: string): string {\n const lines = text.split(\"\\n\")\n const indent = lines\n .filter(line => line.trim() !== \"\")\n .map(line => line.match(/^\\s*/)?.[0].length ?? 0)\n .reduce((min, indent) => Math.min(min, indent), Infinity)\n\n return lines\n .map(line => line.slice(indent))\n .join(\"\\n\")\n .trim()\n}\n\nexport function bytesToHumanReadable(bytes: number): string {\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"]\n if (bytes === 0) return \"0 Bytes\"\n\n const i = Math.floor(Math.log(bytes) / Math.log(1024))\n return parseFloat((bytes / Math.pow(1024, i)).toFixed(2)) + \" \" + sizes[i]\n}\n","const knownAbbreviationsMap = new Map<string, string>()\n\nexport function registerKnownAbbreviations(abbreviations: string[]) {\n for (const abbr of abbreviations) {\n const lower = abbr.toLowerCase()\n if (!knownAbbreviationsMap.has(lower)) {\n knownAbbreviationsMap.set(lower, abbr)\n }\n }\n}\n\nexport function camelCaseToHumanReadable(text: string) {\n const words = text.split(/(?=[A-Z])|_|\\./)\n\n return words\n .map(word => {\n const lower = word.toLowerCase()\n if (knownAbbreviationsMap.has(lower)) {\n return knownAbbreviationsMap.get(lower)\n }\n\n return word.charAt(0).toUpperCase() + word.slice(1)\n })\n .join(\" \")\n}\n","import type { TAnySchema, TSchema } from \"@sinclair/typebox\"\nimport type { Meta } from \"./types\"\nimport type { PartialKeys } from \"./utils\"\n\n/**\n * The entity is some abstract object which can be passed from one component to another through their inputs and outputs.\n * Every entity must have a type.\n * Every component inputs and outputs will reference such types and only entities of the same type can be passed.\n */\nexport type Entity<TType extends string = string, TEntitySchema extends TSchema = TSchema> = {\n /**\n * The static type of the entity.\n */\n type: TType\n\n /**\n * The JSON schema of the entity value.\n */\n schema: TEntitySchema\n\n /**\n * The extra metadata of the entity.\n */\n meta: Meta\n\n /**\n * The CRC32 of the entity definition.\n */\n definitionHash: number\n}\n\nexport type EntityOptions<TType extends string, TSchema extends TAnySchema> = Omit<\n PartialKeys<Entity<TType, TSchema>, \"meta\">,\n \"definitionHash\"\n>\n\nexport function defineEntity<TType extends string, TSchema extends TAnySchema>(\n options: EntityOptions<TType, TSchema>,\n): Entity<TType, TSchema> {\n // TODO: correctly handle refs inside the schema\n // options.schema.$id = options.type\n\n return {\n meta: {},\n ...options,\n } as Entity<TType, TSchema>\n}\n\nexport function isEntity(value: unknown): value is Entity {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n \"schema\" in value &&\n \"meta\" in value\n )\n}\n","import {\n type Static,\n type TAny,\n type TArray,\n type TBoolean,\n type TLiteral,\n type TNumber,\n type TObject,\n type TRecordOrObject,\n type TString,\n type TUnion,\n} from \"@sinclair/typebox\"\n\nexport type ArgumentValueSchema =\n | TString\n | TNumber\n | TBoolean\n | TArray<TString>\n | TArray<TNumber>\n | TUnion<TLiteral[]>\n | TRecordOrObject<TString, TAny>\n | TObject\n | TArray\n | TUnion<TObject[]>\n\nexport type ArgumentValue = Static<ArgumentValueSchema>\n\n/**\n * The generic metadata of some contract.\n */\nexport type Meta = {\n /**\n * The display name of the entity which can be shown in the UI.\n */\n displayName?: string\n\n /**\n * The description of the entity which can be shown in the UI.\n */\n description?: string\n\n /**\n * The primary icon of the entity which can be shown in the UI.\n */\n primaryIcon?: string\n\n /**\n * The hex color of the entity which can be used in the UI.\n *\n * @example \"#ff0000\"\n */\n color?: string\n}\n","export {\n type InstanceInput,\n type HubInput,\n type InstanceModel,\n type Position,\n getInstanceId,\n parseInstanceId,\n findInput,\n findRequiredInput,\n findInputs,\n findRequiredInputs,\n HighstateSignature,\n fileMetaSchema,\n fileContentSchema,\n unitArtifactSchema,\n unitObjectMetaSchema,\n fileSchema,\n type FileMeta,\n type UnitArtifact,\n type FileContent,\n type UnitObjectMeta,\n type File,\n} from \"./instance\"\nexport { getCompositeInstances, resetEvaluation, type CompositeInstance } from \"./evaluation\"\nexport { type Entity, defineEntity, isEntity } from \"./entity\"\nexport {\n type Component,\n type ComponentModel,\n type ComponentMeta,\n type ComponentArgument,\n type ComponentInput,\n type ComponentInputSpec,\n type ComponentArgumentSpec,\n type ComponentArgumentSpecToStatic,\n defineComponent,\n isComponent,\n originalCreate,\n $args,\n $inputs,\n $outputs,\n} from \"./component\"\nexport {\n type Unit,\n type UnitModel,\n type UnitSource,\n defineUnit,\n isUnitModel,\n $secrets,\n} from \"./unit\"\nexport {\n type RequiredKeys,\n type PartialKeys,\n text,\n trimIndentation,\n bytesToHumanReadable,\n} from \"./utils\"\nexport { type ArgumentValue, type ArgumentValueSchema } from \"./types\"\nexport { camelCaseToHumanReadable, registerKnownAbbreviations } from \"./i18n\"\nexport * from \"@sinclair/typebox\"\n\nimport {\n Type as BaseType,\n type Static,\n type TLiteral,\n type TSchema,\n type TUnion,\n} from \"@sinclair/typebox\"\n\ntype MapToLiteral<T extends readonly string[]> = {\n [K in keyof T]: T[K] extends string ? TLiteral<T[K]> : never\n}\n\nfunction StringEnum<T extends string[]>(values: [...T]): TUnion<MapToLiteral<T>> {\n return Type.Union(values.map(value => Type.Literal(value))) as TUnion<MapToLiteral<T>>\n}\n\nfunction Default<T extends TSchema>(\n schema: T,\n defaultValue: Static<T>,\n): T & { default: Static<T> } {\n return { ...schema, default: defaultValue }\n}\n\nexport const Type = {\n ...BaseType,\n StringEnum,\n Default,\n} as typeof BaseType & {\n StringEnum: typeof StringEnum\n Default: typeof Default\n}\n"],"mappings":"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","names":["HighstateSignature","mapValues","mapValues","text","indent","text","inputs","outputs","mapValues","mapValues","outputs","Type"]}
package/package.json CHANGED
@@ -1,11 +1,19 @@
1
1
  {
2
2
  "name": "@highstate/contract",
3
- "version": "0.9.15",
3
+ "version": "0.9.16",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
7
7
  "src"
8
8
  ],
9
+ "highstate": {
10
+ "sourceHash": {
11
+ ".": {
12
+ "mode": "manual",
13
+ "version": "1"
14
+ }
15
+ }
16
+ },
9
17
  "exports": {
10
18
  ".": {
11
19
  "types": "./src/index.ts",
@@ -28,5 +36,5 @@
28
36
  "highstate-cli-bootstrap": "npm:@highstate/cli@0.7.6",
29
37
  "vitest": "^2.1.8"
30
38
  },
31
- "gitHead": "f61b9905d4cd50511b03331411f42595403ebc06"
39
+ "gitHead": "458d6f1f9f6d4aec0ba75a2b2c4c01408cb9c8df"
32
40
  }
package/src/component.ts CHANGED
@@ -17,6 +17,7 @@ import { Ajv } from "ajv"
17
17
  import { boundaryInput, type InstanceInput } from "./instance"
18
18
  import { type OptionalUndefinedFields, type OptionalEmptyRecords } from "./utils"
19
19
  import { registerInstance } from "./evaluation"
20
+ import { camelCaseToHumanReadable } from "./i18n"
20
21
 
21
22
  const ajv = new Ajv({ strict: false })
22
23
 
@@ -27,9 +28,10 @@ export type ComponentArgument = {
27
28
  meta: Meta
28
29
  }
29
30
 
30
- type ComponentArgumentFullOptions = Meta & {
31
+ export type ComponentArgumentFullOptions = {
31
32
  schema: ArgumentValueSchema
32
33
  required?: boolean
34
+ meta?: Meta
33
35
  }
34
36
 
35
37
  export type ComponentArgumentOptions = ArgumentValueSchema | ComponentArgumentFullOptions
@@ -202,9 +204,9 @@ export type ComponentModel = {
202
204
  meta: ComponentMeta
203
205
 
204
206
  /**
205
- * The hash of the component definition.
207
+ * The CRC32 of the component definition.
206
208
  */
207
- definitionHash: string
209
+ definitionHash: number
208
210
  }
209
211
 
210
212
  type InputSpecToInputRef<T extends ComponentInputSpec> = T[1] extends true
@@ -329,7 +331,10 @@ export function defineComponent<
329
331
  args: mapValues(options.args ?? {}, mapArgument),
330
332
  inputs: mapValues(options.inputs ?? {}, mapInput),
331
333
  outputs: mapValues(options.outputs ?? {}, mapInput),
332
- meta: options.meta ?? {},
334
+ meta: {
335
+ ...options.meta,
336
+ displayName: options.meta?.displayName ?? camelCaseToHumanReadable(options.type),
337
+ },
333
338
  }
334
339
 
335
340
  create[originalCreate] = options.create
@@ -341,16 +346,15 @@ export function isComponent(value: unknown): value is Component {
341
346
  return typeof value === "function" && "model" in value
342
347
  }
343
348
 
344
- export function mapArgument(value: ComponentArgumentOptions) {
349
+ export function mapArgument(value: ComponentArgumentOptions, key: string) {
345
350
  if ("schema" in value) {
346
351
  return {
347
352
  schema: value.schema,
348
353
  required:
349
354
  value.required ?? (!value.schema[OptionalKind] && value.schema.default === undefined),
350
355
  meta: {
351
- displayName: value.displayName,
352
- description: value.description,
353
- color: value.color,
356
+ displayName: value.meta?.displayName ?? camelCaseToHumanReadable(key),
357
+ description: value.meta?.description,
354
358
  },
355
359
  }
356
360
  }
@@ -358,12 +362,18 @@ export function mapArgument(value: ComponentArgumentOptions) {
358
362
  return {
359
363
  schema: value,
360
364
  required: !value[OptionalKind] && value.default === undefined,
361
- meta: {},
365
+ meta: {
366
+ displayName: camelCaseToHumanReadable(key),
367
+ },
362
368
  }
363
369
  }
364
370
 
365
371
  export function createInputMapper(entities: Map<string, Entity>) {
366
- return (value: ComponentInputOptions) => {
372
+ return (value: ComponentInputOptions, key: string) => {
373
+ if (!value) {
374
+ throw new Error(`Input/output "${key}" is undefined in the component model.`)
375
+ }
376
+
367
377
  if ("entity" in value) {
368
378
  entities.set(value.entity.type, value.entity)
369
379
 
@@ -372,7 +382,7 @@ export function createInputMapper(entities: Map<string, Entity>) {
372
382
  required: value.required ?? true,
373
383
  multiple: value.multiple ?? false,
374
384
  meta: {
375
- displayName: value.displayName,
385
+ displayName: value.displayName ?? camelCaseToHumanReadable(key),
376
386
  description: value.description,
377
387
  color: value.color,
378
388
  },
@@ -385,7 +395,9 @@ export function createInputMapper(entities: Map<string, Entity>) {
385
395
  type: value.type,
386
396
  required: true,
387
397
  multiple: false,
388
- meta: {},
398
+ meta: {
399
+ displayName: camelCaseToHumanReadable(key),
400
+ },
389
401
  }
390
402
  }
391
403
  }
@@ -413,3 +425,30 @@ function validateArgsAndFillDefaults(
413
425
 
414
426
  return args as Record<string, ArgumentValue>
415
427
  }
428
+
429
+ /**
430
+ * The helper marker for component arguments.
431
+ *
432
+ * Helps validating arguments types and gives the compiler a hint for generating `meta` fields.
433
+ */
434
+ export function $args<T extends Record<string, ComponentArgumentOptions>>(args: T): T {
435
+ return args
436
+ }
437
+
438
+ /**
439
+ * The helper marker for component inputs.
440
+ *
441
+ * Helps validating inputs types and gives the compiler a hint for generating `meta` fields.
442
+ */
443
+ export function $inputs<T extends Record<string, ComponentInputOptions>>(inputs: T): T {
444
+ return inputs
445
+ }
446
+
447
+ /**
448
+ * The helper marker for component outputs.
449
+ *
450
+ * Helps validating outputs types and gives the compiler a hint for generating `meta` fields.
451
+ */
452
+ export function $outputs<T extends Record<string, ComponentInputOptions>>(outputs: T): T {
453
+ return outputs
454
+ }
package/src/entity.ts CHANGED
@@ -24,9 +24,9 @@ export type Entity<TType extends string = string, TEntitySchema extends TSchema
24
24
  meta: Meta
25
25
 
26
26
  /**
27
- * The hash of the entity definition.
27
+ * The CRC32 of the entity definition.
28
28
  */
29
- definitionHash: string
29
+ definitionHash: number
30
30
  }
31
31
 
32
32
  export type EntityOptions<TType extends string, TSchema extends TAnySchema> = Omit<
@@ -37,6 +37,9 @@ export type EntityOptions<TType extends string, TSchema extends TAnySchema> = Om
37
37
  export function defineEntity<TType extends string, TSchema extends TAnySchema>(
38
38
  options: EntityOptions<TType, TSchema>,
39
39
  ): Entity<TType, TSchema> {
40
+ // TODO: correctly handle refs inside the schema
41
+ // options.schema.$id = options.type
42
+
40
43
  return {
41
44
  meta: {},
42
45
  ...options,
package/src/i18n.ts ADDED
@@ -0,0 +1,25 @@
1
+ const knownAbbreviationsMap = new Map<string, string>()
2
+
3
+ export function registerKnownAbbreviations(abbreviations: string[]) {
4
+ for (const abbr of abbreviations) {
5
+ const lower = abbr.toLowerCase()
6
+ if (!knownAbbreviationsMap.has(lower)) {
7
+ knownAbbreviationsMap.set(lower, abbr)
8
+ }
9
+ }
10
+ }
11
+
12
+ export function camelCaseToHumanReadable(text: string) {
13
+ const words = text.split(/(?=[A-Z])|_|\./)
14
+
15
+ return words
16
+ .map(word => {
17
+ const lower = word.toLowerCase()
18
+ if (knownAbbreviationsMap.has(lower)) {
19
+ return knownAbbreviationsMap.get(lower)
20
+ }
21
+
22
+ return word.charAt(0).toUpperCase() + word.slice(1)
23
+ })
24
+ .join(" ")
25
+ }
package/src/index.ts CHANGED
@@ -9,6 +9,17 @@ export {
9
9
  findRequiredInput,
10
10
  findInputs,
11
11
  findRequiredInputs,
12
+ HighstateSignature,
13
+ fileMetaSchema,
14
+ fileContentSchema,
15
+ unitArtifactSchema,
16
+ unitObjectMetaSchema,
17
+ fileSchema,
18
+ type FileMeta,
19
+ type UnitArtifact,
20
+ type FileContent,
21
+ type UnitObjectMeta,
22
+ type File,
12
23
  } from "./instance"
13
24
  export { getCompositeInstances, resetEvaluation, type CompositeInstance } from "./evaluation"
14
25
  export { type Entity, defineEntity, isEntity } from "./entity"
@@ -24,8 +35,18 @@ export {
24
35
  defineComponent,
25
36
  isComponent,
26
37
  originalCreate,
38
+ $args,
39
+ $inputs,
40
+ $outputs,
27
41
  } from "./component"
28
- export { type Unit, type UnitModel, type UnitSource, defineUnit, isUnitModel } from "./unit"
42
+ export {
43
+ type Unit,
44
+ type UnitModel,
45
+ type UnitSource,
46
+ defineUnit,
47
+ isUnitModel,
48
+ $secrets,
49
+ } from "./unit"
29
50
  export {
30
51
  type RequiredKeys,
31
52
  type PartialKeys,
@@ -34,6 +55,7 @@ export {
34
55
  bytesToHumanReadable,
35
56
  } from "./utils"
36
57
  export { type ArgumentValue, type ArgumentValueSchema } from "./types"
58
+ export { camelCaseToHumanReadable, registerKnownAbbreviations } from "./i18n"
37
59
  export * from "@sinclair/typebox"
38
60
 
39
61
  import {
package/src/instance.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Type, type Static } from "@sinclair/typebox"
2
+
1
3
  declare const type: unique symbol
2
4
 
3
5
  export type InstanceInput<TType extends string = string> = {
@@ -177,3 +179,48 @@ export function findRequiredInputs<T extends string>(
177
179
  ): InstanceInput<T>[] {
178
180
  return names.map(name => findRequiredInput(inputs, name))
179
181
  }
182
+
183
+ export enum HighstateSignature {
184
+ Artifact = "d55c63ac-3174-4756-808f-f778e99af0d1",
185
+ }
186
+
187
+ export const fileMetaSchema = Type.Object({
188
+ name: Type.String(),
189
+ contentType: Type.Optional(Type.String()),
190
+ size: Type.Optional(Type.Number()),
191
+ mode: Type.Optional(Type.Number()),
192
+ isBinary: Type.Optional(Type.Boolean()),
193
+ })
194
+
195
+ export const unitObjectMetaSchema = Type.Object({
196
+ displayName: Type.Optional(Type.String()),
197
+ description: Type.Optional(Type.String()),
198
+ primaryIcon: Type.Optional(Type.String()),
199
+ })
200
+
201
+ export const unitArtifactSchema = Type.Object({
202
+ hash: Type.String(),
203
+ meta: Type.Optional(unitObjectMetaSchema),
204
+ })
205
+
206
+ export const fileContentSchema = Type.Union([
207
+ Type.Object({
208
+ type: Type.Literal("embedded"),
209
+ value: Type.String(),
210
+ }),
211
+ Type.Object({
212
+ type: Type.Literal("artifact"),
213
+ [HighstateSignature.Artifact]: unitArtifactSchema,
214
+ }),
215
+ ])
216
+
217
+ export const fileSchema = Type.Object({
218
+ meta: fileMetaSchema,
219
+ content: fileContentSchema,
220
+ })
221
+
222
+ export type FileMeta = Static<typeof fileMetaSchema>
223
+ export type FileContent = Static<typeof fileContentSchema>
224
+ export type UnitObjectMeta = Static<typeof unitObjectMetaSchema>
225
+ export type UnitArtifact = Static<typeof unitArtifactSchema>
226
+ export type File = Static<typeof fileSchema>
package/src/types.ts CHANGED
@@ -39,6 +39,11 @@ export type Meta = {
39
39
  */
40
40
  description?: string
41
41
 
42
+ /**
43
+ * The primary icon of the entity which can be shown in the UI.
44
+ */
45
+ primaryIcon?: string
46
+
42
47
  /**
43
48
  * The hex color of the entity which can be used in the UI.
44
49
  *
package/src/unit.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
4
4
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
5
5
 
6
- import type { ArgumentValue } from "./types"
6
+ import type { ArgumentValue, ArgumentValueSchema } from "./types"
7
7
  import type { InstanceInput } from "./instance"
8
8
  import { mapValues } from "remeda"
9
9
  import {
@@ -19,8 +19,28 @@ import {
19
19
  defineComponent,
20
20
  mapArgument,
21
21
  type ComponentArgumentOptionsMapToSpecMap,
22
+ type ComponentArgumentFullOptions,
22
23
  } from "./component"
23
24
 
25
+ export type ComponentSecret = ComponentArgument & {
26
+ /**
27
+ * The secret cannot be modified by the user, but can be modified by the unit.
28
+ */
29
+ readonly: boolean
30
+
31
+ /**
32
+ * The secret value is computed by the unit and should not be passed to it when invoked.
33
+ */
34
+ computed: boolean
35
+ }
36
+
37
+ type ComponentSecretFullOptions = ComponentArgumentFullOptions & {
38
+ readonly?: boolean
39
+ computed?: boolean
40
+ }
41
+
42
+ export type ComponentSecretOptions = ArgumentValueSchema | ComponentSecretFullOptions
43
+
24
44
  type UnitOptions<
25
45
  TArgs extends Record<string, ComponentArgumentOptions>,
26
46
  TInputs extends Record<string, ComponentInputOptions>,
@@ -47,7 +67,7 @@ export type UnitModel = ComponentModel & {
47
67
  /**
48
68
  * The record of the secret argument schemas.
49
69
  */
50
- secrets: Record<string, ComponentArgument>
70
+ secrets: Record<string, ComponentSecret>
51
71
  }
52
72
 
53
73
  export type Unit<
@@ -69,7 +89,7 @@ export function defineUnit<
69
89
  TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>,
70
90
  TInputs extends Record<string, ComponentInputOptions> = Record<string, never>,
71
91
  TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>,
72
- TSecrets extends Record<string, ComponentArgumentOptions> = Record<string, never>,
92
+ TSecrets extends Record<string, ComponentSecretOptions> = Record<string, never>,
73
93
  >(
74
94
  options: UnitOptions<TArgs, TInputs, TOutputs, TSecrets>,
75
95
  // @ts-expect-error typescript bug
@@ -102,3 +122,12 @@ export function defineUnit<
102
122
 
103
123
  return component
104
124
  }
125
+
126
+ /**
127
+ * The helper marker for component secrets.
128
+ *
129
+ * Helps validating secrets types and gives the compiler a hint for generating `meta` fields.
130
+ */
131
+ export function $secrets<T extends Record<string, ComponentSecretOptions>>(secrets: T): T {
132
+ return secrets
133
+ }