@highstate/contract 0.4.1 → 0.4.3

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.d.ts CHANGED
@@ -1,24 +1,34 @@
1
- import { Static, TUnion, TString, TNumber, TBoolean, TArray, TLiteral, TSchema, TAnySchema, TObject, TOptional } from '@sinclair/typebox';
1
+ import { TString, TNumber, TBoolean, TArray, TUnion, TLiteral, TRecordOrObject, TAny, Static, TSchema, TAnySchema, TObject, TOptional } from '@sinclair/typebox';
2
+ export { Static, Type } from '@sinclair/typebox';
2
3
 
3
- type UnitRegistration = Readonly<{
4
+ type InstanceInput<TType extends string = string> = {
5
+ type: TType;
6
+ instanceId: string;
7
+ output: string;
8
+ };
9
+ type InstanceInputMap = Record<string, InstanceInput | InstanceInput[]>;
10
+ type BaseInstanceModel = {
11
+ id: string;
4
12
  type: string;
5
13
  name: string;
6
- config: Readonly<Record<string, string>>;
7
- dependencies: readonly string[];
8
- }>;
9
- declare function getUnitRegistrations(): Readonly<Record<string, UnitRegistration>>;
14
+ parentId?: string;
15
+ args: Record<string, unknown>;
16
+ inputs: InstanceInputMap;
17
+ outputs?: InstanceInputMap;
18
+ };
19
+ declare function getInstanceId(instanceType: string, instanceName: string): string;
20
+ declare function parseInstanceId(key: string): [string, string];
10
21
 
11
- /**
12
- * The schema for a single argument value.
13
- *
14
- * This argument can have a limited set of types: primitive types, arrays of strings or numbers.
15
- * This limitation is due to the fact that we need to display the arguments in the UI, and we can't display more complex types.
16
- * Moreover, it encourages using separate components for organizing complex data.
17
- */
18
- declare const argumentValueSchema: TUnion<[TString, TNumber, TBoolean, TArray<TString>, TArray<TNumber>]>;
19
- type ArgumentValueSchema = typeof argumentValueSchema;
22
+ type CompositeInstance = {
23
+ instance: BaseInstanceModel;
24
+ children: BaseInstanceModel[];
25
+ };
26
+ declare function resetEvaluation(): void;
27
+ declare function getInstances(): readonly BaseInstanceModel[];
28
+ declare function getCompositeInstances(): readonly CompositeInstance[];
29
+
30
+ type ArgumentValueSchema = TString | TNumber | TBoolean | TArray<TString> | TArray<TNumber> | TUnion<TLiteral[]> | TRecordOrObject<TString, TAny> | TArray;
20
31
  type ArgumentValue = Static<ArgumentValueSchema>;
21
- type AllowedArgumentSchema = TString | TNumber | TBoolean | TArray<TString> | TArray<TNumber> | TUnion<TLiteral[]>;
22
32
  /**
23
33
  * The generic metadata of some contract.
24
34
  */
@@ -96,12 +106,6 @@ type Entity<TType extends string = string, TEntitySchema extends TSchema = TSche
96
106
  type EntityOptions<TType extends string, TSchema extends TAnySchema> = PartialKeys<Entity<TType, TSchema>, "sensitive" | "meta">;
97
107
  declare function defineEntity<TType extends string, TSchema extends TAnySchema>(options: EntityOptions<TType, TSchema>): Entity<TType, TSchema>;
98
108
  declare function isEntity(value: unknown): value is Entity;
99
- type OutputRef<TType extends string = string> = {
100
- type: TType;
101
- project: string;
102
- stack: string;
103
- output: string;
104
- };
105
109
 
106
110
  type ComponentArgument = {
107
111
  schema: ArgumentValueSchema;
@@ -109,10 +113,10 @@ type ComponentArgument = {
109
113
  meta: Meta;
110
114
  };
111
115
  type ComponentArgumentFullOptions = Meta & {
112
- schema: AllowedArgumentSchema;
116
+ schema: ArgumentValueSchema;
113
117
  required?: boolean;
114
118
  };
115
- type ComponentArgumentOptions = AllowedArgumentSchema | ComponentArgumentFullOptions;
119
+ type ComponentArgumentOptions = ArgumentValueSchema | ComponentArgumentFullOptions;
116
120
  type ComponentArgumentOptionsToSchema<T extends ComponentArgumentOptions> = T extends TSchema ? T : T["required"] extends false ? TOptional<T["schema"]> : T["schema"];
117
121
  type ComponentArgumentMapToValue<T extends Record<string, ComponentArgumentOptions>> = {
118
122
  [K in keyof T]: Static<ComponentArgumentOptionsToSchema<T[K]>>;
@@ -129,13 +133,18 @@ type ComponentInputFullOptions = Meta & {
129
133
  multiple?: boolean;
130
134
  };
131
135
  type ComponentInputOptions = Entity | ComponentInputFullOptions;
132
- type ComponentInputOptionsToOutputRef<T extends ComponentInputOptions> = T extends Entity ? OutputRef<T["type"]> : T extends ComponentInputFullOptions ? T["required"] extends false ? T["multiple"] extends true ? OutputRef<T["entity"]["type"]>[] | undefined : OutputRef<T["entity"]["type"]> | undefined : T["multiple"] extends true ? OutputRef<T["entity"]["type"]>[] : OutputRef<T["entity"]["type"]> : never;
136
+ type ComponentInputOptionsToOutputRef<T extends ComponentInputOptions> = T extends Entity ? InstanceInput<T["type"]> : T extends ComponentInputFullOptions ? T["required"] extends false ? T["multiple"] extends true ? InstanceInput<T["entity"]["type"]>[] | undefined : InstanceInput<T["entity"]["type"]> | undefined : T["multiple"] extends true ? InstanceInput<T["entity"]["type"]>[] : InstanceInput<T["entity"]["type"]> : never;
133
137
  type ComponentInputSpec = [entity: Entity, required: boolean, multiple: boolean];
134
138
  type ComponentInputOptionsToSpec<T extends ComponentInputOptions> = T extends Entity ? [T, true, false] : T extends ComponentInputFullOptions ? T["required"] extends false ? T["multiple"] extends true ? [T["entity"], false, true] : [T["entity"], false, false] : T["multiple"] extends true ? [T["entity"], true, true] : [T["entity"], true, false] : never;
139
+ type ComponentInputOptionsMapToSpecMap<T extends Record<string, ComponentInputOptions>> = T extends Record<string, never> ? Record<string, never> : {
140
+ [K in keyof T]: ComponentInputOptionsToSpec<T[K]>;
141
+ };
135
142
  type ComponentInputMapToValue<T extends Record<string, ComponentInputOptions>> = OptionalUndefinedFields<{
136
143
  [K in keyof T]: ComponentInputOptionsToOutputRef<T[K]>;
137
144
  }>;
145
+ type ComponentInputMapToReturnType<T extends Record<string, ComponentInputOptions>> = T extends Record<string, never> ? void : ComponentInputMapToValue<T>;
138
146
  type ComponentParams<TArgs extends Record<string, ComponentArgumentOptions>, TInputs extends Record<string, ComponentInputOptions>> = {
147
+ id: string;
139
148
  name: string;
140
149
  args: ComponentArgumentMapToValue<TArgs>;
141
150
  inputs: ComponentInputMapToValue<TInputs>;
@@ -152,7 +161,7 @@ type ComponentOptions<TArgs extends Record<string, ComponentArgumentOptions>, TI
152
161
  args?: TArgs;
153
162
  inputs?: TInputs;
154
163
  outputs?: TOutputs;
155
- create: (params: ComponentParams<TArgs, TInputs>) => ComponentInputMapToValue<TOutputs>;
164
+ create: (params: ComponentParams<TArgs, TInputs>) => ComponentInputMapToReturnType<TOutputs>;
156
165
  };
157
166
  type ComponentMeta = Meta & {
158
167
  primaryIcon?: string;
@@ -160,6 +169,7 @@ type ComponentMeta = Meta & {
160
169
  secondaryIcon?: string;
161
170
  secondaryIconColor?: string;
162
171
  category?: string;
172
+ defaultNamePrefix?: string;
163
173
  };
164
174
  type ComponentModel = {
165
175
  /**
@@ -183,7 +193,7 @@ type ComponentModel = {
183
193
  */
184
194
  meta: ComponentMeta;
185
195
  };
186
- type InputSpecToOutputRef<T extends ComponentInputSpec> = T[1] extends true ? T[2] extends true ? OutputRef<T[0]["type"]>[] : OutputRef<T[0]["type"]> : T[2] extends true ? OutputRef<T[0]["type"]>[] | undefined : OutputRef<T[0]["type"]> | undefined;
196
+ type InputSpecToOutputRef<T extends ComponentInputSpec> = T[1] extends true ? T[2] extends true ? InstanceInput<T[0]["type"]>[] : InstanceInput<T[0]["type"]> : T[2] extends true ? InstanceInput<T[0]["type"]>[] | undefined : InstanceInput<T[0]["type"]> | undefined;
187
197
  type OutputRefMap<TInputs extends Record<string, ComponentInputSpec>> = TInputs extends Record<string, [string, never, never]> ? Record<string, never> : {
188
198
  [K in keyof TInputs]: InputSpecToOutputRef<TInputs[K]>;
189
199
  };
@@ -192,6 +202,10 @@ type Component<TArgs extends Record<string, ArgumentValue> = Record<string, neve
192
202
  * The non-generic model of the component.
193
203
  */
194
204
  model: ComponentModel;
205
+ /**
206
+ * The entities used in the inputs or outputs of the component.
207
+ */
208
+ entities: Map<string, Entity>;
195
209
  /**
196
210
  * Creates the component at the evaluation time.
197
211
  */
@@ -200,11 +214,7 @@ type Component<TArgs extends Record<string, ArgumentValue> = Record<string, neve
200
214
  type ArgumentOptionsMapToStatic<T extends Record<string, ComponentArgumentOptions>> = T extends Record<string, never> ? Record<string, never> : Static<TObject<{
201
215
  [K in keyof T]: ComponentArgumentOptionsToSchema<T[K]>;
202
216
  }>>;
203
- declare function defineComponent<TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>, TInputs extends Record<string, ComponentInputOptions> = Record<string, never>, TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>>(options: ComponentOptions<TArgs, TInputs, TOutputs>): Component<ArgumentOptionsMapToStatic<TArgs>, {
204
- [K in keyof TInputs]: ComponentInputOptionsToSpec<TInputs[K]>;
205
- }, {
206
- [K in keyof TOutputs]: ComponentInputOptionsToSpec<TOutputs[K]>;
207
- }>;
217
+ declare function defineComponent<TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>, TInputs extends Record<string, ComponentInputOptions> = Record<string, never>, TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>>(options: ComponentOptions<TArgs, TInputs, TOutputs>): Component<ArgumentOptionsMapToStatic<TArgs>, ComponentInputOptionsMapToSpecMap<TInputs>, ComponentInputOptionsMapToSpecMap<TOutputs>>;
208
218
  declare function isComponent(value: unknown): value is Component;
209
219
 
210
220
  type UnitOptions<TArgs extends Record<string, ComponentArgumentOptions>, TInputs extends Record<string, ComponentInputOptions>, TOutputs extends Record<string, ComponentInputOptions>, TSecrets extends Record<string, ComponentArgumentOptions>> = Omit<ComponentOptions<TArgs, TInputs, TOutputs>, "create"> & {
@@ -214,11 +224,17 @@ type UnitOptions<TArgs extends Record<string, ComponentArgumentOptions>, TInputs
214
224
  type UnitSource = {
215
225
  type: "npm";
216
226
  package: string;
227
+ path?: string;
217
228
  version?: string;
229
+ } | {
230
+ type: "local";
218
231
  path?: string;
219
232
  };
220
233
  type UnitModel = ComponentModel & {
221
- source: UnitSource;
234
+ /**
235
+ * The source of the unit.
236
+ */
237
+ source?: UnitSource;
222
238
  /**
223
239
  * The record of the secret argument schemas.
224
240
  */
@@ -229,10 +245,6 @@ type Unit<TArgs extends Record<string, ArgumentValue> = Record<string, never>, T
229
245
  model: UnitModel;
230
246
  };
231
247
  declare function isUnitModel(model: ComponentModel): model is UnitModel;
232
- declare function defineUnit<TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>, TInputs extends Record<string, ComponentInputOptions> = Record<string, never>, TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>, TSecrets extends Record<string, ComponentArgumentOptions> = Record<string, never>>(options: UnitOptions<TArgs, TInputs, TOutputs, TSecrets>): Unit<ArgumentOptionsMapToStatic<TArgs>, {
233
- [K in keyof TInputs]: ComponentInputOptionsToSpec<TInputs[K]>;
234
- }, {
235
- [K in keyof TOutputs]: ComponentInputOptionsToSpec<TOutputs[K]>;
236
- }, ArgumentOptionsMapToStatic<TSecrets>>;
248
+ declare function defineUnit<TArgs extends Record<string, ComponentArgumentOptions> = Record<string, never>, TInputs extends Record<string, ComponentInputOptions> = Record<string, never>, TOutputs extends Record<string, ComponentInputOptions> = Record<string, never>, TSecrets extends Record<string, ComponentArgumentOptions> = Record<string, never>>(options: UnitOptions<TArgs, TInputs, TOutputs, TSecrets>): Unit<ArgumentOptionsMapToStatic<TArgs>, ComponentInputOptionsMapToSpecMap<TInputs>, ComponentInputOptionsMapToSpecMap<TOutputs>, ArgumentOptionsMapToStatic<TSecrets>>;
237
249
 
238
- export { type ArgumentValue, type Component, type ComponentArgument, type ComponentInput, type ComponentInputSpec, type ComponentMeta, type ComponentModel, type Entity, type OutputRef, type Unit, type UnitModel, type UnitRegistration, type UnitSource, defineComponent, defineEntity, defineUnit, getUnitRegistrations, isComponent, isEntity, isUnitModel, text };
250
+ export { type ArgumentValue, type ArgumentValueSchema, type BaseInstanceModel, type Component, type ComponentArgument, type ComponentInput, type ComponentInputSpec, type ComponentMeta, type ComponentModel, type CompositeInstance, type Entity, type InstanceInput, type InstanceInputMap, type Unit, type UnitModel, type UnitSource, defineComponent, defineEntity, defineUnit, getCompositeInstances, getInstanceId, getInstances, isComponent, isEntity, isUnitModel, parseInstanceId, resetEvaluation, text };
package/dist/index.mjs CHANGED
@@ -1,12 +1,52 @@
1
- import { OptionalKind, Type } from '@sinclair/typebox';
1
+ import { OptionalKind } from '@sinclair/typebox';
2
+ export { Type } from '@sinclair/typebox';
2
3
  import { mapValues } from 'remeda';
3
4
 
4
- const unitRegistrations = {};
5
- function getUnitRegistrations() {
6
- return unitRegistrations;
5
+ function getInstanceId(instanceType, instanceName) {
6
+ return `${instanceType}:${instanceName}`;
7
7
  }
8
- function registerUnit(unit) {
9
- unitRegistrations[`${unit.type}.${unit.name}`] = unit;
8
+ function parseInstanceId(key) {
9
+ const parts = key.split(":");
10
+ if (parts.length !== 2) {
11
+ throw new Error(`Invalid instance key: ${key}`);
12
+ }
13
+ return parts;
14
+ }
15
+
16
+ const instances = [];
17
+ const compositeInstances = /* @__PURE__ */ new Map();
18
+ let currentParentInstance = null;
19
+ function resetEvaluation() {
20
+ instances.length = 0;
21
+ compositeInstances.clear();
22
+ currentParentInstance = null;
23
+ }
24
+ function getInstances() {
25
+ return instances;
26
+ }
27
+ function getCompositeInstances() {
28
+ return Array.from(compositeInstances.values());
29
+ }
30
+ function registerInstance(instance, fn) {
31
+ instances.push(instance);
32
+ if (currentParentInstance) {
33
+ instance.parentId = currentParentInstance.id;
34
+ let compositeInstance = compositeInstances.get(currentParentInstance.id);
35
+ if (!compositeInstance) {
36
+ compositeInstance = { instance: currentParentInstance, children: [] };
37
+ compositeInstances.set(currentParentInstance.id, compositeInstance);
38
+ }
39
+ compositeInstance.children.push(instance);
40
+ }
41
+ const previousParentInstance = currentParentInstance;
42
+ currentParentInstance = instance;
43
+ try {
44
+ const [outputs, instanceOutputs] = fn();
45
+ instance.outputs = instanceOutputs;
46
+ return outputs;
47
+ } finally {
48
+ currentParentInstance = previousParentInstance;
49
+ }
10
50
  }
11
51
 
12
52
  function defineEntity(options) {
@@ -23,12 +63,39 @@ function isEntity(value) {
23
63
  function defineComponent(options) {
24
64
  function create(params) {
25
65
  const { name, args, inputs } = params;
26
- return options.create({
27
- name,
28
- args: args ?? {},
29
- inputs: inputs ?? {}
30
- });
66
+ const id = `${options.type}:${name}`;
67
+ return registerInstance(
68
+ {
69
+ id,
70
+ type: options.type,
71
+ name,
72
+ args: args ?? {},
73
+ inputs: inputs ?? {}
74
+ },
75
+ () => {
76
+ const outputs = options.create({
77
+ id,
78
+ name,
79
+ args: args ?? {},
80
+ inputs: mapValues(inputs ?? {}, (value, key) => {
81
+ if (Array.isArray(value)) {
82
+ return value.map((x) => substituteInstanceInput(id, x, key));
83
+ }
84
+ return substituteInstanceInput(id, value, key);
85
+ })
86
+ }) ?? {};
87
+ const substitutedOutputs = mapValues(outputs, (value, key) => {
88
+ if (Array.isArray(value)) {
89
+ return value.map((x) => substituteInstanceInput(id, x, key));
90
+ }
91
+ return substituteInstanceInput(id, value, key);
92
+ });
93
+ return [substitutedOutputs, outputs];
94
+ }
95
+ );
31
96
  }
97
+ create.entities = /* @__PURE__ */ new Map();
98
+ const mapInput = createInputMapper(create.entities);
32
99
  create.model = {
33
100
  type: options.type,
34
101
  args: mapValues(options.args ?? {}, mapArgument),
@@ -38,6 +105,13 @@ function defineComponent(options) {
38
105
  };
39
106
  return create;
40
107
  }
108
+ function substituteInstanceInput(instanceId, input, outputKey) {
109
+ return {
110
+ type: input.type,
111
+ instanceId,
112
+ output: outputKey
113
+ };
114
+ }
41
115
  function isComponent(value) {
42
116
  return typeof value === "function" && "model" in value;
43
117
  }
@@ -60,24 +134,28 @@ function mapArgument(value) {
60
134
  meta: {}
61
135
  };
62
136
  }
63
- function mapInput(value) {
64
- if ("entity" in value) {
137
+ function createInputMapper(entities) {
138
+ return (value) => {
139
+ if ("entity" in value) {
140
+ entities.set(value.entity.type, value.entity);
141
+ return {
142
+ type: value.entity.type,
143
+ required: value.required ?? true,
144
+ multiple: value.multiple ?? false,
145
+ meta: {
146
+ displayName: value.displayName,
147
+ description: value.description,
148
+ color: value.color
149
+ }
150
+ };
151
+ }
152
+ entities.set(value.type, value);
65
153
  return {
66
- type: value.entity.type,
67
- required: value.required ?? true,
68
- multiple: value.multiple ?? false,
69
- meta: {
70
- displayName: value.displayName,
71
- description: value.description,
72
- color: value.color
73
- }
154
+ type: value.type,
155
+ required: true,
156
+ multiple: false,
157
+ meta: {}
74
158
  };
75
- }
76
- return {
77
- type: value.type,
78
- required: true,
79
- multiple: false,
80
- meta: {}
81
159
  };
82
160
  }
83
161
 
@@ -87,30 +165,21 @@ function isUnitModel(model) {
87
165
  function defineUnit(options) {
88
166
  const component = defineComponent({
89
167
  ...options,
90
- create({ name, args, inputs }) {
91
- registerUnit({
92
- type: options.type,
93
- name,
94
- config: {
95
- ...mapValues(args, (value) => typeof value === "string" ? value : JSON.stringify(value)),
96
- ...mapValues(inputs, (value) => JSON.stringify(value))
97
- },
98
- dependencies: Object.values(inputs).map((value) => `${value.project}.${value.stack}`)
99
- });
100
- return fillUnitOutputs(name, options.type, options.outputs);
168
+ create({ id }) {
169
+ return fillUnitOutputs(id, options.outputs);
101
170
  }
102
171
  });
103
172
  component.model.source = options.source;
104
173
  component.model.secrets = mapValues(options.secrets ?? {}, mapArgument);
105
174
  return component;
106
175
  }
107
- function fillUnitOutputs(name, type, optionsOutputs = {}) {
176
+ function fillUnitOutputs(instanceId, optionsOutputs = {}) {
108
177
  const outputs = {};
109
178
  for (const key in optionsOutputs) {
179
+ const entity = "entity" in optionsOutputs[key] ? optionsOutputs[key].entity : optionsOutputs[key];
110
180
  outputs[key] = {
111
- type,
112
- project: type,
113
- stack: name,
181
+ type: entity.type,
182
+ instanceId,
114
183
  output: key
115
184
  };
116
185
  }
@@ -124,12 +193,4 @@ function text(array, ...values) {
124
193
  return lines.map((line) => line.slice(indent)).join("\n").trim();
125
194
  }
126
195
 
127
- Type.Union([
128
- Type.String(),
129
- Type.Number(),
130
- Type.Boolean(),
131
- Type.Array(Type.String()),
132
- Type.Array(Type.Number())
133
- ]);
134
-
135
- export { defineComponent, defineEntity, defineUnit, getUnitRegistrations, isComponent, isEntity, isUnitModel, text };
196
+ export { defineComponent, defineEntity, defineUnit, getCompositeInstances, getInstanceId, getInstances, isComponent, isEntity, isUnitModel, parseInstanceId, resetEvaluation, text };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/contract",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "type": "module",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,7 @@
8
8
  "dist"
9
9
  ],
10
10
  "exports": {
11
- "import": {
11
+ ".": {
12
12
  "types": "./dist/index.d.ts",
13
13
  "default": "./dist/index.mjs"
14
14
  }
@@ -17,7 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "scripts": {
20
- "build": "pkgroll --clean-dist",
20
+ "build": "pkgroll --tsconfig=tsconfig.build.json",
21
21
  "test": "vitest run --coverage"
22
22
  },
23
23
  "dependencies": {
@@ -29,5 +29,5 @@
29
29
  "pkgroll": "^2.5.1",
30
30
  "vitest": "^2.1.8"
31
31
  },
32
- "gitHead": "0ebd5c9d6f0176a38e8786d239a0b0828fa635f0"
32
+ "gitHead": "5b99600bd04872a4817c97b26501e1f22c8a0780"
33
33
  }