@highstate/contract 0.4.1 → 0.4.2

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