@highstate/pulumi 0.7.2 → 0.7.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/highstate.manifest.json +5 -0
- package/dist/{index.mjs → index.js} +93 -33
- package/dist/index.js.map +1 -0
- package/package.json +10 -11
- package/src/index.ts +4 -0
- package/src/secret.ts +23 -0
- package/src/unit.ts +574 -0
- package/src/utils.ts +184 -0
- package/dist/index.d.ts +0 -153
@@ -1,11 +1,25 @@
|
|
1
|
-
|
2
|
-
export * from
|
3
|
-
import { getInstanceId, parseInstanceId } from '@highstate/contract';
|
4
|
-
import { Type } from '@sinclair/typebox';
|
5
|
-
import { mapValues, pipe, pickBy } from 'remeda';
|
6
|
-
import { Ajv } from 'ajv';
|
1
|
+
// src/index.ts
|
2
|
+
export * from "@pulumi/pulumi";
|
7
3
|
|
8
|
-
|
4
|
+
// src/unit.ts
|
5
|
+
import {
|
6
|
+
parseInstanceId,
|
7
|
+
getInstanceId
|
8
|
+
} from "@highstate/contract";
|
9
|
+
import { Type } from "@sinclair/typebox";
|
10
|
+
import { mapValues, pickBy, pipe } from "remeda";
|
11
|
+
import {
|
12
|
+
Config,
|
13
|
+
getStack,
|
14
|
+
output,
|
15
|
+
secret as secret2,
|
16
|
+
StackReference
|
17
|
+
} from "@pulumi/pulumi";
|
18
|
+
import { Ajv } from "ajv";
|
19
|
+
|
20
|
+
// src/secret.ts
|
21
|
+
import { secret } from "@pulumi/pulumi";
|
22
|
+
var createdSecrets = {};
|
9
23
|
function getOrCreateSecret(secrets, key, create) {
|
10
24
|
return secrets[key].apply((value) => {
|
11
25
|
if (value !== void 0) {
|
@@ -18,9 +32,20 @@ function getOrCreateSecret(secrets, key, create) {
|
|
18
32
|
});
|
19
33
|
}
|
20
34
|
|
21
|
-
|
22
|
-
|
23
|
-
|
35
|
+
// src/unit.ts
|
36
|
+
var ajv = new Ajv();
|
37
|
+
var stackRefMap = /* @__PURE__ */ new Map();
|
38
|
+
var [projectId, instanceName] = getStack().split("_");
|
39
|
+
var instanceId;
|
40
|
+
function getUnitInstanceId() {
|
41
|
+
if (!instanceId) {
|
42
|
+
throw new Error("Instance id is not set. Did you call 'forUnit' function?");
|
43
|
+
}
|
44
|
+
return instanceId;
|
45
|
+
}
|
46
|
+
function getUnitInstanceName() {
|
47
|
+
return instanceName;
|
48
|
+
}
|
24
49
|
function getStackRef(input) {
|
25
50
|
const [instanceType, instanceName2] = parseInstanceId(input.instanceId);
|
26
51
|
const key = `organization/${instanceType}/${projectId}_${instanceName2}`;
|
@@ -115,20 +140,20 @@ function forUnit(unit) {
|
|
115
140
|
}
|
116
141
|
});
|
117
142
|
const secrets = output(
|
118
|
-
mapValues(unit.model.secrets, (
|
143
|
+
mapValues(unit.model.secrets, (secret3, secretName) => {
|
119
144
|
switch (true) {
|
120
|
-
case isStringSchema(
|
121
|
-
return
|
145
|
+
case isStringSchema(secret3.schema): {
|
146
|
+
return secret3.required ? config.requireSecret(secretName) : config.getSecret(secretName);
|
122
147
|
}
|
123
|
-
case isNumberSchema(
|
124
|
-
return
|
148
|
+
case isNumberSchema(secret3.schema): {
|
149
|
+
return secret3.required ? config.requireSecretNumber(secretName) : config.getSecretNumber(secretName);
|
125
150
|
}
|
126
|
-
case isBooleanSchema(
|
127
|
-
return
|
151
|
+
case isBooleanSchema(secret3.schema): {
|
152
|
+
return secret3.required ? config.requireSecretBoolean(secretName) : config.getSecretBoolean(secretName);
|
128
153
|
}
|
129
154
|
default: {
|
130
|
-
const value =
|
131
|
-
if (!ajv.validate(
|
155
|
+
const value = secret3.required ? config.requireSecretObject(secretName) : config.getSecretObject(secretName);
|
156
|
+
if (!ajv.validate(secret3.schema, value)) {
|
132
157
|
throw new Error(`Invalid secret for '${secretName}': ${ajv.errorsText()}`);
|
133
158
|
}
|
134
159
|
return value;
|
@@ -147,9 +172,10 @@ function forUnit(unit) {
|
|
147
172
|
return getOutput(unit, input, value);
|
148
173
|
});
|
149
174
|
const type = unit.model.type;
|
175
|
+
instanceId = getInstanceId(type, instanceName);
|
150
176
|
return {
|
151
177
|
args,
|
152
|
-
instanceId
|
178
|
+
instanceId,
|
153
179
|
type,
|
154
180
|
name: instanceName,
|
155
181
|
secrets,
|
@@ -235,14 +261,29 @@ function mapPages(pages) {
|
|
235
261
|
}
|
236
262
|
return Object.entries(pages).filter(([, page]) => !!page).map(([name, page]) => ({ ...page, name }));
|
237
263
|
}
|
264
|
+
function fileFromString(name, content, contentType = "text/plain", isSecret = false) {
|
265
|
+
return {
|
266
|
+
meta: {
|
267
|
+
name,
|
268
|
+
contentType,
|
269
|
+
size: Buffer.byteLength(content, "utf8")
|
270
|
+
},
|
271
|
+
content: isSecret ? secret2(content) : content
|
272
|
+
};
|
273
|
+
}
|
274
|
+
function fileFromBuffer(name, content, contentType = "application/octet-stream", isSecret = false) {
|
275
|
+
return {
|
276
|
+
meta: {
|
277
|
+
name,
|
278
|
+
contentType,
|
279
|
+
size: content.byteLength,
|
280
|
+
isBinary: true
|
281
|
+
},
|
282
|
+
content: isSecret ? secret2(content.toString("base64")) : content.toString("base64")
|
283
|
+
};
|
284
|
+
}
|
238
285
|
function mapFiles(files) {
|
239
|
-
|
240
|
-
return [];
|
241
|
-
}
|
242
|
-
if (Array.isArray(files)) {
|
243
|
-
return files.filter((file) => !!file);
|
244
|
-
}
|
245
|
-
return Object.entries(files).filter(([, file]) => !!file).map(([name, file]) => ({ ...file, name }));
|
286
|
+
return files?.filter((file) => !!file) ?? [];
|
246
287
|
}
|
247
288
|
function mapTerminals(terminals) {
|
248
289
|
if (!terminals) {
|
@@ -285,6 +326,8 @@ function mapTriggers(triggers) {
|
|
285
326
|
return Object.entries(triggers).filter(([, trigger]) => !!trigger).map(([name, trigger]) => ({ ...trigger, name }));
|
286
327
|
}
|
287
328
|
|
329
|
+
// src/utils.ts
|
330
|
+
import { output as output2, all } from "@pulumi/pulumi";
|
288
331
|
function flattenInputs(...values) {
|
289
332
|
return all(values).apply((allValues) => {
|
290
333
|
const result = [];
|
@@ -299,7 +342,7 @@ function flattenInputs(...values) {
|
|
299
342
|
});
|
300
343
|
}
|
301
344
|
function mapInputs(array, fn) {
|
302
|
-
return
|
345
|
+
return output2(array).apply((array2) => {
|
303
346
|
return array2?.map((v, index) => fn(v, index, array2)) ?? [];
|
304
347
|
});
|
305
348
|
}
|
@@ -315,7 +358,7 @@ function mapOptional(input, func) {
|
|
315
358
|
return func(input);
|
316
359
|
}
|
317
360
|
function toPromise(input) {
|
318
|
-
return new Promise((resolve) =>
|
361
|
+
return new Promise((resolve) => output2(input).apply(resolve));
|
319
362
|
}
|
320
363
|
function singleton(factory) {
|
321
364
|
let instance;
|
@@ -336,7 +379,7 @@ function providerFactory(factory) {
|
|
336
379
|
};
|
337
380
|
}
|
338
381
|
function mergeInputObjects(...objects) {
|
339
|
-
return
|
382
|
+
return output2(objects).apply((array) => {
|
340
383
|
return Object.assign({}, ...array);
|
341
384
|
});
|
342
385
|
}
|
@@ -350,7 +393,24 @@ function normalize(item, collection) {
|
|
350
393
|
return collection ?? [];
|
351
394
|
}
|
352
395
|
function apply(fn) {
|
353
|
-
return (input) =>
|
396
|
+
return (input) => output2(input).apply(fn);
|
354
397
|
}
|
355
|
-
|
356
|
-
|
398
|
+
export {
|
399
|
+
apply,
|
400
|
+
fileFromBuffer,
|
401
|
+
fileFromString,
|
402
|
+
flatMapInput,
|
403
|
+
flattenInputs,
|
404
|
+
forUnit,
|
405
|
+
getOrCreateSecret,
|
406
|
+
getUnitInstanceId,
|
407
|
+
getUnitInstanceName,
|
408
|
+
mapInputs,
|
409
|
+
mapOptional,
|
410
|
+
mergeInputObjects,
|
411
|
+
normalize,
|
412
|
+
providerFactory,
|
413
|
+
singleton,
|
414
|
+
toPromise
|
415
|
+
};
|
416
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/unit.ts","../src/secret.ts","../src/utils.ts"],"sourcesContent":["export * from \"@pulumi/pulumi\"\nexport * from \"./unit\"\nexport * from \"./utils\"\nexport { getOrCreateSecret } from \"./secret\"\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { DeepInput, InputArray, InputMap } from \"./utils\"\nimport {\n type ArgumentValue,\n type ComponentInputSpec,\n type Entity,\n type Unit,\n type ComponentInput,\n type InstanceInput,\n parseInstanceId,\n type ArgumentValueSchema,\n getInstanceId,\n} from \"@highstate/contract\"\nimport { Type, type Static } from \"@sinclair/typebox\"\nimport { mapValues, pickBy, pipe } from \"remeda\"\nimport {\n Config,\n getStack,\n Output,\n output,\n secret,\n StackReference,\n type Input,\n type Unwrap,\n} from \"@pulumi/pulumi\"\nimport { Ajv } from \"ajv\"\nimport { createdSecrets } from \"./secret\"\n\nconst ajv = new Ajv()\n\nexport type InstanceTerminalFile = {\n content: Input<string | undefined>\n mode?: Input<number | undefined>\n isBinary?: Input<boolean>\n}\n\nexport type InstanceTerminal = {\n name: Input<string>\n title: Input<string>\n description?: Input<string>\n image: Input<string>\n command: InputArray<string>\n cwd?: Input<string | undefined>\n env?: InputMap<string | undefined>\n files?: InputMap<InstanceTerminalFile | string | undefined>\n}\n\nexport type StatusField<TArgName extends string = string> = {\n name: Input<string>\n value?: Input<string | undefined>\n displayName?: Input<string | undefined>\n sensitive?: Input<boolean | undefined>\n url?: Input<string | undefined>\n complementaryTo?: Input<TArgName | undefined>\n}\n\nexport type InstanceFileMeta = {\n name: Input<string>\n contentType: Input<string>\n isBinary?: Input<boolean>\n size: Input<number>\n}\n\nexport type InstanceFile = {\n meta: Input<InstanceFileMeta>\n content: Input<string>\n}\n\nexport type InstancePageBlock =\n | { type: \"markdown\"; content: Input<string> }\n | { type: \"qr\"; content: Input<string>; showContent?: boolean; language?: string }\n | { type: \"file\"; fileMeta: Input<InstanceFileMeta> }\n\nexport type InstancePage = {\n name: Input<string>\n title: Input<string>\n content: InputArray<InstancePageBlock>\n}\n\nexport type InstanceTriggerSpec =\n | {\n type: \"before-destroy\"\n }\n | {\n type: \"schedule\"\n schedule: string\n }\n\nexport type InstanceTrigger = {\n name: Input<string>\n title: Input<string>\n description?: Input<string>\n spec: Input<InstanceTriggerSpec>\n}\n\nexport type ExtraOutputs<TArgName extends string = string> = {\n $status?:\n | InputMap<Omit<StatusField<TArgName>, \"name\"> | string | undefined>\n | InputArray<StatusField<TArgName> | undefined>\n\n $terminals?:\n | InputMap<Omit<InstanceTerminal, \"name\"> | undefined>\n | InputArray<InstanceTerminal | undefined>\n\n $pages?: InputMap<Omit<InstancePage, \"name\"> | undefined> | InputArray<InstancePage | undefined>\n $files?: InputArray<InstanceFile | undefined>\n\n $triggers?:\n | InputMap<Omit<InstanceTrigger, \"name\"> | undefined>\n | InputArray<InstanceTrigger | undefined>\n}\n\nexport type InstanceTriggerInvocation = {\n name: string\n}\n\ntype OutputMapToDeepInputMap<T extends Record<string, unknown>, TArgName extends string> =\n T extends Record<string, never>\n ? ExtraOutputs\n : { [K in keyof T]: DeepInput<T[K]> } & ExtraOutputs<TArgName>\n\nexport interface UnitContext<\n TArgs extends Record<string, ArgumentValue>,\n TInputs extends Record<string, unknown>,\n TOutputs extends Record<string, unknown>,\n TSecrets extends Record<string, ArgumentValue>,\n> {\n args: TArgs\n instanceId: string\n type: string\n name: string\n secrets: Output<TSecrets>\n\n inputs: {\n [K in keyof TInputs]: undefined extends TInputs[K]\n ? Output<NonNullable<TInputs[K]>> | undefined\n : Output<TInputs[K]>\n }\n\n invokedTriggers: InstanceTriggerInvocation[]\n\n outputs(\n this: void,\n outputs?: OutputMapToDeepInputMap<TOutputs, keyof TArgs & string>,\n ): Promise<unknown>\n}\n\ntype InputSpecToValue<T extends ComponentInputSpec> = T[2] extends true\n ? Static<T[0][\"schema\"]>[]\n : T[1] extends true\n ? Static<T[0][\"schema\"]>\n : Static<T[0][\"schema\"]> | undefined\n\ntype InputSpecMapToValueMap<T extends Record<string, ComponentInputSpec>> =\n T extends Record<string, never>\n ? Record<string, never>\n : { [K in keyof T]: InputSpecToValue<T[K]> }\n\nconst stackRefMap = new Map<string, StackReference>()\nconst [projectId, instanceName] = getStack().split(\"_\")\n\nlet instanceId: string | undefined\n\nexport function getUnitInstanceId(): string {\n if (!instanceId) {\n throw new Error(\"Instance id is not set. Did you call 'forUnit' function?\")\n }\n\n return instanceId\n}\n\nexport function getUnitInstanceName(): string {\n return instanceName\n}\n\nfunction getStackRef(input: InstanceInput) {\n const [instanceType, instanceName] = parseInstanceId(input.instanceId)\n const key = `organization/${instanceType}/${projectId}_${instanceName}`\n\n if (!stackRefMap.has(key)) {\n stackRefMap.set(key, new StackReference(key))\n }\n\n return stackRefMap.get(key)!\n}\n\nfunction getOutput(unit: Unit, input: ComponentInput, refs: InstanceInput[]) {\n const entity = unit.entities.get(input.type)\n if (!entity) {\n throw new Error(`Entity '${input.type}' not found in the unit '${unit.model.type}'.`)\n }\n\n const _getOutput = (ref: InstanceInput) => {\n const value = getStackRef(ref).requireOutput(ref.output)\n\n return value.apply(value => {\n let schema = entity.schema\n\n if (input.multiple) {\n schema = Type.Union([schema, Type.Array(schema)])\n }\n\n if (!ajv.validate(schema, value)) {\n throw new Error(`Invalid output for '${input.type}': ${ajv.errorsText()}`)\n }\n\n if (Array.isArray(value)) {\n return value as unknown\n }\n\n return input.multiple ? [value] : value\n })\n }\n\n const values = output(refs.map(ref => _getOutput(ref))).apply(values => values.flat())\n\n if (!input.multiple) {\n return values.apply(values => values[0])\n }\n\n return values\n}\n\nfunction isAnyOfSchema(schema: ArgumentValueSchema, itemType: string): boolean {\n if (schema.anyOf) {\n return Object.values(schema.anyOf).every(schema =>\n isAnyOfSchema(schema as ArgumentValueSchema, itemType),\n )\n }\n\n return schema.type === itemType\n}\n\nfunction isStringSchema(schema: ArgumentValueSchema): boolean {\n if (schema.type === \"string\") {\n return true\n }\n\n if (isAnyOfSchema(schema, \"string\")) {\n return true\n }\n\n return false\n}\n\nfunction isNumberSchema(schema: ArgumentValueSchema): boolean {\n if (schema.type === \"number\") {\n return true\n }\n\n if (isAnyOfSchema(schema, \"number\")) {\n return true\n }\n\n return false\n}\n\nfunction isBooleanSchema(schema: ArgumentValueSchema): boolean {\n if (schema.type === \"boolean\") {\n return true\n }\n\n if (isAnyOfSchema(schema, \"boolean\")) {\n return true\n }\n\n return false\n}\n\nexport function forUnit<\n TArgs extends Record<string, ArgumentValue>,\n TInputs extends Record<string, ComponentInputSpec>,\n TOutputs extends Record<string, ComponentInputSpec>,\n TSecrets extends Record<string, ArgumentValue>,\n>(\n unit: Unit<TArgs, TInputs, TOutputs, TSecrets>,\n): UnitContext<\n //\n TArgs,\n InputSpecMapToValueMap<TInputs>,\n InputSpecMapToValueMap<TOutputs>,\n TSecrets\n> {\n const config = new Config()\n\n const args = mapValues(unit.model.args, (arg, argName) => {\n switch (true) {\n case isStringSchema(arg.schema): {\n return arg.required ? config.require(argName) : config.get(argName)\n }\n case isNumberSchema(arg.schema): {\n return arg.required ? config.requireNumber(argName) : config.getNumber(argName)\n }\n case isBooleanSchema(arg.schema): {\n return arg.required ? config.requireBoolean(argName) : config.getBoolean(argName)\n }\n default: {\n const value = arg.required ? config.requireObject(argName) : config.getObject(argName)\n if (value === undefined) return undefined\n\n if (!ajv.validate(arg.schema, value)) {\n throw new Error(`Invalid config for '${argName}': ${ajv.errorsText()}`)\n }\n\n return value\n }\n }\n }) as TArgs\n\n const secrets = output(\n mapValues(unit.model.secrets, (secret, secretName) => {\n switch (true) {\n case isStringSchema(secret.schema): {\n return secret.required ? config.requireSecret(secretName) : config.getSecret(secretName)\n }\n case isNumberSchema(secret.schema): {\n return secret.required\n ? config.requireSecretNumber(secretName)\n : config.getSecretNumber(secretName)\n }\n case isBooleanSchema(secret.schema): {\n return secret.required\n ? config.requireSecretBoolean(secretName)\n : config.getSecretBoolean(secretName)\n }\n default: {\n const value = secret.required\n ? config.requireSecretObject(secretName)\n : config.getSecretObject(secretName)\n\n if (!ajv.validate(secret.schema, value)) {\n throw new Error(`Invalid secret for '${secretName}': ${ajv.errorsText()}`)\n }\n\n return value\n }\n }\n }),\n ) as unknown as Output<TSecrets>\n\n const inputs = mapValues(unit.model.inputs, (input, inputName) => {\n const value = input.required\n ? config.requireObject<InstanceInput[]>(`input.${inputName}`)\n : config.getObject<InstanceInput[]>(`input.${inputName}`)\n\n if (!value) {\n if (input.multiple) {\n return output([])\n }\n\n return undefined\n }\n\n return getOutput(unit as unknown as Unit, input, value)\n })\n\n const type = unit.model.type\n instanceId = getInstanceId(type, instanceName)\n\n return {\n args,\n instanceId,\n type,\n name: instanceName,\n secrets,\n inputs: inputs as any,\n invokedTriggers: config.getObject<InstanceTriggerInvocation[]>(\"$invokedTriggers\") ?? [],\n\n outputs: async (outputs: any = {}) => {\n const result: any = mapValues(outputs, (outputValue, outputName) => {\n if (outputName === \"$status\") {\n return output(outputValue).apply(mapStatus)\n }\n\n if (outputName === \"$pages\") {\n return output(outputValue).apply(mapPages)\n }\n\n if (outputName === \"$files\") {\n return output(outputValue).apply(mapFiles)\n }\n\n if (outputName === \"$terminals\") {\n return output(outputValue).apply(mapTerminals)\n }\n\n if (outputName === \"$triggers\") {\n return output(outputValue).apply(mapTriggers)\n }\n\n if (outputName.startsWith(\"$\")) {\n throw new Error(`Unknown extra output '${outputName}'.`)\n }\n\n const outputModel = unit.model.outputs[outputName]\n if (!outputModel) {\n throw new Error(`Output '${outputName}' not found in the unit '${unit.model.type}'.`)\n }\n\n const entity = unit.entities.get(outputModel.type)\n if (!entity) {\n throw new Error(\n `Entity '${outputModel.type}' not found in the unit '${unit.model.type}'.`,\n )\n }\n\n return output(outputValue).apply(value => {\n if (value === undefined) {\n if (outputModel.required) {\n throw new Error(`Output '${outputName}' is required.`)\n }\n\n return undefined\n }\n\n if (!ajv.validate(entity.schema, value)) {\n throw new Error(`Invalid output for '${outputModel.type}': ${ajv.errorsText()}`)\n }\n\n return value\n })\n }) as Record<string, Output<unknown>> & ExtraOutputs\n\n await Promise.all(Object.values(result).map(o => outputToPromise(o)))\n\n if (Object.keys(createdSecrets).length > 0) {\n result.$secrets = createdSecrets\n }\n\n return result\n },\n }\n}\n\nexport type EntityValue<T extends Entity> = Static<T[\"schema\"]>\nexport type EntityInput<T extends Entity> = Output<EntityValue<T>>\n\nfunction outputToPromise(o: unknown): Promise<unknown> {\n return new Promise(resolve => (output(o) as Output<unknown>).apply(resolve))\n}\n\nfunction mapStatus(status: Unwrap<ExtraOutputs[\"$status\"]>): StatusField[] {\n if (!status) {\n return []\n }\n\n if (Array.isArray(status)) {\n return status.filter(field => !!field?.value) as StatusField[]\n }\n\n return Object.entries(status)\n .map(([name, field]) => {\n if (!field) {\n return undefined\n }\n\n if (typeof field === \"string\") {\n return { name, value: field }\n }\n\n return { ...(field as StatusField), name }\n })\n .filter(field => !!field?.value) as StatusField[]\n}\n\nfunction mapPages(pages: Unwrap<ExtraOutputs[\"$pages\"]>): InstancePage[] {\n if (!pages) {\n return []\n }\n\n if (Array.isArray(pages)) {\n return pages.filter(page => !!page)\n }\n\n return Object.entries(pages)\n .filter(([, page]) => !!page)\n .map(([name, page]) => ({ ...page!, name }))\n}\n\nexport function fileFromString(\n name: string,\n content: string,\n contentType = \"text/plain\",\n isSecret = false,\n): InstanceFile {\n return {\n meta: {\n name,\n contentType,\n size: Buffer.byteLength(content, \"utf8\"),\n },\n content: isSecret ? secret(content) : content,\n }\n}\n\nexport function fileFromBuffer(\n name: string,\n content: Buffer,\n contentType = \"application/octet-stream\",\n isSecret = false,\n): InstanceFile {\n return {\n meta: {\n name,\n contentType,\n size: content.byteLength,\n isBinary: true,\n },\n content: isSecret ? secret(content.toString(\"base64\")) : content.toString(\"base64\"),\n }\n}\n\nfunction mapFiles(files: Unwrap<ExtraOutputs[\"$files\"]>): InstanceFile[] {\n return files?.filter(file => !!file) ?? []\n}\n\nfunction mapTerminals(terminals: Unwrap<ExtraOutputs[\"$terminals\"]>): InstanceTerminal[] {\n if (!terminals) {\n return []\n }\n\n if (!Array.isArray(terminals)) {\n terminals = Object.entries(terminals).map(([name, terminal]) => {\n if (!terminal) {\n return undefined\n }\n\n return { ...terminal, name }\n })\n }\n\n return terminals\n .filter(terminal => !!terminal)\n .map(terminal => {\n if (!terminal.files) {\n return terminal\n }\n\n return {\n ...terminal,\n\n files: pipe(\n terminal.files,\n mapValues(file => {\n if (typeof file === \"string\") {\n return { content: file }\n }\n\n return file\n }),\n pickBy(value => !!value?.content),\n ),\n }\n })\n}\n\nfunction mapTriggers(triggers: Unwrap<ExtraOutputs[\"$triggers\"]>): InstanceTrigger[] {\n if (!triggers) {\n return []\n }\n\n if (Array.isArray(triggers)) {\n return triggers.filter(trigger => !!trigger)\n }\n\n return Object.entries(triggers)\n .filter(([, trigger]) => !!trigger)\n .map(([name, trigger]) => ({ ...(trigger as InstanceTrigger), name }))\n}\n","import { secret, type Input, type Output } from \"@pulumi/pulumi\"\n\nexport const createdSecrets: Record<string, Output<unknown>> = {}\n\nexport function getOrCreateSecret<\n TSecrets extends Record<string, unknown>,\n TResult extends TSecrets[keyof TSecrets],\n>(secrets: Output<TSecrets>, key: keyof TSecrets, create: () => Input<TResult>): Output<TResult> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\n return secrets[key as any].apply(value => {\n if (value !== undefined) {\n // if the secret is accessed via \"getOrCreateSecret\" with assume it automatically created (even if it was not)\n // in order to provide stable stack outputs\n createdSecrets[key as string] = value as Output<unknown>\n return value as TResult\n }\n\n const secretValue = createdSecrets[key as string] ?? secret(create())\n createdSecrets[key as string] = secretValue\n\n return secretValue\n }) as Output<TResult>\n}\n","import { type Input, type Unwrap, type Output, output, all } from \"@pulumi/pulumi\"\n\n/**\n * The input type for an array of inputs.\n * The same as `Input<Input<T>[]>`, but more readable.\n */\nexport type InputArray<T> = Input<Input<T>[]>\n\n/**\n * The input type for a map of inputs.\n * The same as `Input<Record<string, Input<T>>>`, but more readable.\n */\nexport type InputMap<T> = Input<Readonly<Record<string, Input<T>>>>\n\n/**\n * The input or input array type for a value.\n */\nexport type InputOrArray<T> = Input<T> | InputArray<T>\n\n/**\n * The input of inputs of inputs of inputs, so you got the idea.\n */\nexport type DeepInput<T> = [T] extends [Record<string, unknown> | undefined]\n ? [T] extends [infer U | undefined]\n ? Input<{ [K in keyof U]: DeepInput<U[K]> } | undefined>\n : Input<{ [K in keyof T]: DeepInput<T[K]> }>\n : [T] extends [Array<unknown> | undefined]\n ? [T] extends [(infer U)[] | undefined]\n ? Input<DeepInput<U>[] | undefined>\n : Input<DeepInput<T>[]>\n : Input<T>\n\n/**\n * Merges the given array of `InputOrArray` values into a single flat output array.\n *\n * @param values The values to merge.\n * @returns The merged output array.\n */\nexport function flattenInputs<T>(...values: (InputOrArray<T> | undefined)[]): Output<T[]> {\n return all(values).apply(allValues => {\n const result: T[] = []\n for (const value of allValues) {\n if (Array.isArray(value)) {\n result.push(...(value as T[]))\n } else if (value) {\n result.push(value as T)\n }\n }\n return result\n })\n}\n\n/**\n * Maps each element of an input array to a new value.\n * Produces an output array with the same length.\n *\n * @param array The input array.\n * @param fn The mapping function.\n * @returns The output array.\n */\nexport function mapInputs<T, U>(\n array: InputArray<T>,\n fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U,\n): Output<U[]> {\n return output(array).apply(array => {\n return array?.map((v, index) => fn(v as Unwrap<T>, index, array as Unwrap<T>[])) ?? []\n })\n}\n\nexport function flatMapInput<T, U>(\n v1: InputOrArray<T>,\n v2: InputOrArray<T>,\n fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U,\n): Output<U[]>\n\nexport function flatMapInput<T, U>(\n v1: InputOrArray<T>,\n v2: InputOrArray<T>,\n v3: InputOrArray<T>,\n fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U,\n): Output<U[]>\n\n/**\n * Merges the given array of `InputOrArray` values into a single flat output array and maps each element to a new value.\n *\n * @param values The values to merge.\n * @param fn The mapping function.\n */\nexport function flatMapInput<T, U>(\n ...args: (InputOrArray<T> | ((v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U))[]\n): Output<U[]> {\n const fn = args.pop() as (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U\n const values = args as InputOrArray<T>[]\n\n return mapInputs(flattenInputs(...values), fn)\n}\n\n/**\n * Map an optional value to another optional value.\n *\n * @param input The input value.\n * @param func The function to apply to the input value.\n * @returns The output value, or `undefined` if the input value is `undefined`.\n */\nexport function mapOptional<T, U>(input: T | undefined, func: (value: T) => U): U | undefined {\n if (input === undefined) {\n return undefined\n }\n\n return func(input)\n}\n\nexport function toPromise<T>(input: Input<T>): Promise<Unwrap<T>> {\n return new Promise(resolve => output(input).apply(resolve))\n}\n\nexport function singleton<T>(factory: () => T): () => T {\n let instance: T | undefined\n return () => {\n if (instance === undefined) {\n instance = factory()\n }\n\n return instance\n }\n}\n\nexport function providerFactory<TInput>(\n factory: (name: string) => TInput,\n): (name: string) => TInput {\n const instances = new Map<string, TInput>()\n return name => {\n if (!instances.has(name)) {\n instances.set(name, factory(name))\n }\n\n return instances.get(name)!\n }\n}\n\nexport function mergeInputObjects<\n T1 extends Record<string, unknown>,\n T2 extends Record<string, unknown>,\n>(obj1: Input<T1 | undefined> | undefined, obj2: Input<T2 | undefined> | undefined): Output<T1 & T2>\n\nexport function mergeInputObjects<\n T1 extends Record<string, unknown>,\n T2 extends Record<string, unknown>,\n T3 extends Record<string, unknown>,\n>(\n obj1: Input<T1 | undefined> | undefined,\n obj2: Input<T2 | undefined> | undefined,\n obj3: Input<T3 | undefined> | undefined,\n): Output<T1 & T2 & T3>\n\n/**\n * Merges the given input objects into a single output object.\n *\n * @param objects The input objects.\n * @returns The output object.\n */\nexport function mergeInputObjects(\n ...objects: Input<Record<string, unknown>>[]\n): Output<Record<string, unknown>> {\n return output(objects).apply(array => {\n return Object.assign({}, ...array) as Record<string, unknown>\n })\n}\n\nexport function normalize<T>(item: T | undefined, collection: T[] | undefined): T[] {\n if (item && collection) {\n return [item, ...collection]\n }\n\n if (item) {\n return [item]\n }\n\n return collection ?? []\n}\n\nexport function apply<T, U>(fn: (value: Unwrap<T>) => U): (input: Input<T>) => Output<U> {\n return input => output(input).apply(fn)\n}\n"],"mappings":"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","names":["secret","instanceName","value","values","schema","secret","output","array"]}
|
package/package.json
CHANGED
@@ -1,34 +1,33 @@
|
|
1
1
|
{
|
2
2
|
"name": "@highstate/pulumi",
|
3
|
-
"version": "0.7.
|
3
|
+
"version": "0.7.3",
|
4
4
|
"type": "module",
|
5
|
-
"module": "dist/index.mjs",
|
6
|
-
"types": "dist/index.d.ts",
|
7
5
|
"files": [
|
8
|
-
"dist"
|
6
|
+
"dist",
|
7
|
+
"src"
|
9
8
|
],
|
10
9
|
"exports": {
|
11
10
|
".": {
|
12
|
-
"types": "./
|
13
|
-
"default": "./dist/index.
|
11
|
+
"types": "./src/index.ts",
|
12
|
+
"default": "./dist/index.js"
|
14
13
|
}
|
15
14
|
},
|
16
15
|
"publishConfig": {
|
17
16
|
"access": "public"
|
18
17
|
},
|
19
18
|
"scripts": {
|
20
|
-
"build": "
|
19
|
+
"build": "highstate build"
|
21
20
|
},
|
22
21
|
"dependencies": {
|
23
|
-
"@highstate/contract": "^0.7.
|
24
|
-
"@pulumi/pulumi": "
|
22
|
+
"@highstate/contract": "^0.7.3",
|
23
|
+
"@pulumi/pulumi": "patch:@pulumi/pulumi@npm%3A3.159.0#~/.yarn/patches/@pulumi-pulumi-npm-3.159.0-d07eefce5c.patch",
|
25
24
|
"@sinclair/typebox": "^0.34.11",
|
26
25
|
"ajv": "^8.17.1",
|
27
26
|
"import-meta-resolve": "^4.1.0",
|
28
27
|
"remeda": "^2.21.0"
|
29
28
|
},
|
30
29
|
"devDependencies": {
|
31
|
-
"
|
30
|
+
"@highstate/cli": "^0.7.3"
|
32
31
|
},
|
33
|
-
"gitHead": "
|
32
|
+
"gitHead": "5cf7cec27262c8fa1d96f6478833b94841459d64"
|
34
33
|
}
|
package/src/index.ts
ADDED
package/src/secret.ts
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
import { secret, type Input, type Output } from "@pulumi/pulumi"
|
2
|
+
|
3
|
+
export const createdSecrets: Record<string, Output<unknown>> = {}
|
4
|
+
|
5
|
+
export function getOrCreateSecret<
|
6
|
+
TSecrets extends Record<string, unknown>,
|
7
|
+
TResult extends TSecrets[keyof TSecrets],
|
8
|
+
>(secrets: Output<TSecrets>, key: keyof TSecrets, create: () => Input<TResult>): Output<TResult> {
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
10
|
+
return secrets[key as any].apply(value => {
|
11
|
+
if (value !== undefined) {
|
12
|
+
// if the secret is accessed via "getOrCreateSecret" with assume it automatically created (even if it was not)
|
13
|
+
// in order to provide stable stack outputs
|
14
|
+
createdSecrets[key as string] = value as Output<unknown>
|
15
|
+
return value as TResult
|
16
|
+
}
|
17
|
+
|
18
|
+
const secretValue = createdSecrets[key as string] ?? secret(create())
|
19
|
+
createdSecrets[key as string] = secretValue
|
20
|
+
|
21
|
+
return secretValue
|
22
|
+
}) as Output<TResult>
|
23
|
+
}
|
package/src/unit.ts
ADDED
@@ -0,0 +1,574 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
3
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
4
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
5
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
6
|
+
|
7
|
+
import type { DeepInput, InputArray, InputMap } from "./utils"
|
8
|
+
import {
|
9
|
+
type ArgumentValue,
|
10
|
+
type ComponentInputSpec,
|
11
|
+
type Entity,
|
12
|
+
type Unit,
|
13
|
+
type ComponentInput,
|
14
|
+
type InstanceInput,
|
15
|
+
parseInstanceId,
|
16
|
+
type ArgumentValueSchema,
|
17
|
+
getInstanceId,
|
18
|
+
} from "@highstate/contract"
|
19
|
+
import { Type, type Static } from "@sinclair/typebox"
|
20
|
+
import { mapValues, pickBy, pipe } from "remeda"
|
21
|
+
import {
|
22
|
+
Config,
|
23
|
+
getStack,
|
24
|
+
Output,
|
25
|
+
output,
|
26
|
+
secret,
|
27
|
+
StackReference,
|
28
|
+
type Input,
|
29
|
+
type Unwrap,
|
30
|
+
} from "@pulumi/pulumi"
|
31
|
+
import { Ajv } from "ajv"
|
32
|
+
import { createdSecrets } from "./secret"
|
33
|
+
|
34
|
+
const ajv = new Ajv()
|
35
|
+
|
36
|
+
export type InstanceTerminalFile = {
|
37
|
+
content: Input<string | undefined>
|
38
|
+
mode?: Input<number | undefined>
|
39
|
+
isBinary?: Input<boolean>
|
40
|
+
}
|
41
|
+
|
42
|
+
export type InstanceTerminal = {
|
43
|
+
name: Input<string>
|
44
|
+
title: Input<string>
|
45
|
+
description?: Input<string>
|
46
|
+
image: Input<string>
|
47
|
+
command: InputArray<string>
|
48
|
+
cwd?: Input<string | undefined>
|
49
|
+
env?: InputMap<string | undefined>
|
50
|
+
files?: InputMap<InstanceTerminalFile | string | undefined>
|
51
|
+
}
|
52
|
+
|
53
|
+
export type StatusField<TArgName extends string = string> = {
|
54
|
+
name: Input<string>
|
55
|
+
value?: Input<string | undefined>
|
56
|
+
displayName?: Input<string | undefined>
|
57
|
+
sensitive?: Input<boolean | undefined>
|
58
|
+
url?: Input<string | undefined>
|
59
|
+
complementaryTo?: Input<TArgName | undefined>
|
60
|
+
}
|
61
|
+
|
62
|
+
export type InstanceFileMeta = {
|
63
|
+
name: Input<string>
|
64
|
+
contentType: Input<string>
|
65
|
+
isBinary?: Input<boolean>
|
66
|
+
size: Input<number>
|
67
|
+
}
|
68
|
+
|
69
|
+
export type InstanceFile = {
|
70
|
+
meta: Input<InstanceFileMeta>
|
71
|
+
content: Input<string>
|
72
|
+
}
|
73
|
+
|
74
|
+
export type InstancePageBlock =
|
75
|
+
| { type: "markdown"; content: Input<string> }
|
76
|
+
| { type: "qr"; content: Input<string>; showContent?: boolean; language?: string }
|
77
|
+
| { type: "file"; fileMeta: Input<InstanceFileMeta> }
|
78
|
+
|
79
|
+
export type InstancePage = {
|
80
|
+
name: Input<string>
|
81
|
+
title: Input<string>
|
82
|
+
content: InputArray<InstancePageBlock>
|
83
|
+
}
|
84
|
+
|
85
|
+
export type InstanceTriggerSpec =
|
86
|
+
| {
|
87
|
+
type: "before-destroy"
|
88
|
+
}
|
89
|
+
| {
|
90
|
+
type: "schedule"
|
91
|
+
schedule: string
|
92
|
+
}
|
93
|
+
|
94
|
+
export type InstanceTrigger = {
|
95
|
+
name: Input<string>
|
96
|
+
title: Input<string>
|
97
|
+
description?: Input<string>
|
98
|
+
spec: Input<InstanceTriggerSpec>
|
99
|
+
}
|
100
|
+
|
101
|
+
export type ExtraOutputs<TArgName extends string = string> = {
|
102
|
+
$status?:
|
103
|
+
| InputMap<Omit<StatusField<TArgName>, "name"> | string | undefined>
|
104
|
+
| InputArray<StatusField<TArgName> | undefined>
|
105
|
+
|
106
|
+
$terminals?:
|
107
|
+
| InputMap<Omit<InstanceTerminal, "name"> | undefined>
|
108
|
+
| InputArray<InstanceTerminal | undefined>
|
109
|
+
|
110
|
+
$pages?: InputMap<Omit<InstancePage, "name"> | undefined> | InputArray<InstancePage | undefined>
|
111
|
+
$files?: InputArray<InstanceFile | undefined>
|
112
|
+
|
113
|
+
$triggers?:
|
114
|
+
| InputMap<Omit<InstanceTrigger, "name"> | undefined>
|
115
|
+
| InputArray<InstanceTrigger | undefined>
|
116
|
+
}
|
117
|
+
|
118
|
+
export type InstanceTriggerInvocation = {
|
119
|
+
name: string
|
120
|
+
}
|
121
|
+
|
122
|
+
type OutputMapToDeepInputMap<T extends Record<string, unknown>, TArgName extends string> =
|
123
|
+
T extends Record<string, never>
|
124
|
+
? ExtraOutputs
|
125
|
+
: { [K in keyof T]: DeepInput<T[K]> } & ExtraOutputs<TArgName>
|
126
|
+
|
127
|
+
export interface UnitContext<
|
128
|
+
TArgs extends Record<string, ArgumentValue>,
|
129
|
+
TInputs extends Record<string, unknown>,
|
130
|
+
TOutputs extends Record<string, unknown>,
|
131
|
+
TSecrets extends Record<string, ArgumentValue>,
|
132
|
+
> {
|
133
|
+
args: TArgs
|
134
|
+
instanceId: string
|
135
|
+
type: string
|
136
|
+
name: string
|
137
|
+
secrets: Output<TSecrets>
|
138
|
+
|
139
|
+
inputs: {
|
140
|
+
[K in keyof TInputs]: undefined extends TInputs[K]
|
141
|
+
? Output<NonNullable<TInputs[K]>> | undefined
|
142
|
+
: Output<TInputs[K]>
|
143
|
+
}
|
144
|
+
|
145
|
+
invokedTriggers: InstanceTriggerInvocation[]
|
146
|
+
|
147
|
+
outputs(
|
148
|
+
this: void,
|
149
|
+
outputs?: OutputMapToDeepInputMap<TOutputs, keyof TArgs & string>,
|
150
|
+
): Promise<unknown>
|
151
|
+
}
|
152
|
+
|
153
|
+
type InputSpecToValue<T extends ComponentInputSpec> = T[2] extends true
|
154
|
+
? Static<T[0]["schema"]>[]
|
155
|
+
: T[1] extends true
|
156
|
+
? Static<T[0]["schema"]>
|
157
|
+
: Static<T[0]["schema"]> | undefined
|
158
|
+
|
159
|
+
type InputSpecMapToValueMap<T extends Record<string, ComponentInputSpec>> =
|
160
|
+
T extends Record<string, never>
|
161
|
+
? Record<string, never>
|
162
|
+
: { [K in keyof T]: InputSpecToValue<T[K]> }
|
163
|
+
|
164
|
+
const stackRefMap = new Map<string, StackReference>()
|
165
|
+
const [projectId, instanceName] = getStack().split("_")
|
166
|
+
|
167
|
+
let instanceId: string | undefined
|
168
|
+
|
169
|
+
export function getUnitInstanceId(): string {
|
170
|
+
if (!instanceId) {
|
171
|
+
throw new Error("Instance id is not set. Did you call 'forUnit' function?")
|
172
|
+
}
|
173
|
+
|
174
|
+
return instanceId
|
175
|
+
}
|
176
|
+
|
177
|
+
export function getUnitInstanceName(): string {
|
178
|
+
return instanceName
|
179
|
+
}
|
180
|
+
|
181
|
+
function getStackRef(input: InstanceInput) {
|
182
|
+
const [instanceType, instanceName] = parseInstanceId(input.instanceId)
|
183
|
+
const key = `organization/${instanceType}/${projectId}_${instanceName}`
|
184
|
+
|
185
|
+
if (!stackRefMap.has(key)) {
|
186
|
+
stackRefMap.set(key, new StackReference(key))
|
187
|
+
}
|
188
|
+
|
189
|
+
return stackRefMap.get(key)!
|
190
|
+
}
|
191
|
+
|
192
|
+
function getOutput(unit: Unit, input: ComponentInput, refs: InstanceInput[]) {
|
193
|
+
const entity = unit.entities.get(input.type)
|
194
|
+
if (!entity) {
|
195
|
+
throw new Error(`Entity '${input.type}' not found in the unit '${unit.model.type}'.`)
|
196
|
+
}
|
197
|
+
|
198
|
+
const _getOutput = (ref: InstanceInput) => {
|
199
|
+
const value = getStackRef(ref).requireOutput(ref.output)
|
200
|
+
|
201
|
+
return value.apply(value => {
|
202
|
+
let schema = entity.schema
|
203
|
+
|
204
|
+
if (input.multiple) {
|
205
|
+
schema = Type.Union([schema, Type.Array(schema)])
|
206
|
+
}
|
207
|
+
|
208
|
+
if (!ajv.validate(schema, value)) {
|
209
|
+
throw new Error(`Invalid output for '${input.type}': ${ajv.errorsText()}`)
|
210
|
+
}
|
211
|
+
|
212
|
+
if (Array.isArray(value)) {
|
213
|
+
return value as unknown
|
214
|
+
}
|
215
|
+
|
216
|
+
return input.multiple ? [value] : value
|
217
|
+
})
|
218
|
+
}
|
219
|
+
|
220
|
+
const values = output(refs.map(ref => _getOutput(ref))).apply(values => values.flat())
|
221
|
+
|
222
|
+
if (!input.multiple) {
|
223
|
+
return values.apply(values => values[0])
|
224
|
+
}
|
225
|
+
|
226
|
+
return values
|
227
|
+
}
|
228
|
+
|
229
|
+
function isAnyOfSchema(schema: ArgumentValueSchema, itemType: string): boolean {
|
230
|
+
if (schema.anyOf) {
|
231
|
+
return Object.values(schema.anyOf).every(schema =>
|
232
|
+
isAnyOfSchema(schema as ArgumentValueSchema, itemType),
|
233
|
+
)
|
234
|
+
}
|
235
|
+
|
236
|
+
return schema.type === itemType
|
237
|
+
}
|
238
|
+
|
239
|
+
function isStringSchema(schema: ArgumentValueSchema): boolean {
|
240
|
+
if (schema.type === "string") {
|
241
|
+
return true
|
242
|
+
}
|
243
|
+
|
244
|
+
if (isAnyOfSchema(schema, "string")) {
|
245
|
+
return true
|
246
|
+
}
|
247
|
+
|
248
|
+
return false
|
249
|
+
}
|
250
|
+
|
251
|
+
function isNumberSchema(schema: ArgumentValueSchema): boolean {
|
252
|
+
if (schema.type === "number") {
|
253
|
+
return true
|
254
|
+
}
|
255
|
+
|
256
|
+
if (isAnyOfSchema(schema, "number")) {
|
257
|
+
return true
|
258
|
+
}
|
259
|
+
|
260
|
+
return false
|
261
|
+
}
|
262
|
+
|
263
|
+
function isBooleanSchema(schema: ArgumentValueSchema): boolean {
|
264
|
+
if (schema.type === "boolean") {
|
265
|
+
return true
|
266
|
+
}
|
267
|
+
|
268
|
+
if (isAnyOfSchema(schema, "boolean")) {
|
269
|
+
return true
|
270
|
+
}
|
271
|
+
|
272
|
+
return false
|
273
|
+
}
|
274
|
+
|
275
|
+
export function forUnit<
|
276
|
+
TArgs extends Record<string, ArgumentValue>,
|
277
|
+
TInputs extends Record<string, ComponentInputSpec>,
|
278
|
+
TOutputs extends Record<string, ComponentInputSpec>,
|
279
|
+
TSecrets extends Record<string, ArgumentValue>,
|
280
|
+
>(
|
281
|
+
unit: Unit<TArgs, TInputs, TOutputs, TSecrets>,
|
282
|
+
): UnitContext<
|
283
|
+
//
|
284
|
+
TArgs,
|
285
|
+
InputSpecMapToValueMap<TInputs>,
|
286
|
+
InputSpecMapToValueMap<TOutputs>,
|
287
|
+
TSecrets
|
288
|
+
> {
|
289
|
+
const config = new Config()
|
290
|
+
|
291
|
+
const args = mapValues(unit.model.args, (arg, argName) => {
|
292
|
+
switch (true) {
|
293
|
+
case isStringSchema(arg.schema): {
|
294
|
+
return arg.required ? config.require(argName) : config.get(argName)
|
295
|
+
}
|
296
|
+
case isNumberSchema(arg.schema): {
|
297
|
+
return arg.required ? config.requireNumber(argName) : config.getNumber(argName)
|
298
|
+
}
|
299
|
+
case isBooleanSchema(arg.schema): {
|
300
|
+
return arg.required ? config.requireBoolean(argName) : config.getBoolean(argName)
|
301
|
+
}
|
302
|
+
default: {
|
303
|
+
const value = arg.required ? config.requireObject(argName) : config.getObject(argName)
|
304
|
+
if (value === undefined) return undefined
|
305
|
+
|
306
|
+
if (!ajv.validate(arg.schema, value)) {
|
307
|
+
throw new Error(`Invalid config for '${argName}': ${ajv.errorsText()}`)
|
308
|
+
}
|
309
|
+
|
310
|
+
return value
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}) as TArgs
|
314
|
+
|
315
|
+
const secrets = output(
|
316
|
+
mapValues(unit.model.secrets, (secret, secretName) => {
|
317
|
+
switch (true) {
|
318
|
+
case isStringSchema(secret.schema): {
|
319
|
+
return secret.required ? config.requireSecret(secretName) : config.getSecret(secretName)
|
320
|
+
}
|
321
|
+
case isNumberSchema(secret.schema): {
|
322
|
+
return secret.required
|
323
|
+
? config.requireSecretNumber(secretName)
|
324
|
+
: config.getSecretNumber(secretName)
|
325
|
+
}
|
326
|
+
case isBooleanSchema(secret.schema): {
|
327
|
+
return secret.required
|
328
|
+
? config.requireSecretBoolean(secretName)
|
329
|
+
: config.getSecretBoolean(secretName)
|
330
|
+
}
|
331
|
+
default: {
|
332
|
+
const value = secret.required
|
333
|
+
? config.requireSecretObject(secretName)
|
334
|
+
: config.getSecretObject(secretName)
|
335
|
+
|
336
|
+
if (!ajv.validate(secret.schema, value)) {
|
337
|
+
throw new Error(`Invalid secret for '${secretName}': ${ajv.errorsText()}`)
|
338
|
+
}
|
339
|
+
|
340
|
+
return value
|
341
|
+
}
|
342
|
+
}
|
343
|
+
}),
|
344
|
+
) as unknown as Output<TSecrets>
|
345
|
+
|
346
|
+
const inputs = mapValues(unit.model.inputs, (input, inputName) => {
|
347
|
+
const value = input.required
|
348
|
+
? config.requireObject<InstanceInput[]>(`input.${inputName}`)
|
349
|
+
: config.getObject<InstanceInput[]>(`input.${inputName}`)
|
350
|
+
|
351
|
+
if (!value) {
|
352
|
+
if (input.multiple) {
|
353
|
+
return output([])
|
354
|
+
}
|
355
|
+
|
356
|
+
return undefined
|
357
|
+
}
|
358
|
+
|
359
|
+
return getOutput(unit as unknown as Unit, input, value)
|
360
|
+
})
|
361
|
+
|
362
|
+
const type = unit.model.type
|
363
|
+
instanceId = getInstanceId(type, instanceName)
|
364
|
+
|
365
|
+
return {
|
366
|
+
args,
|
367
|
+
instanceId,
|
368
|
+
type,
|
369
|
+
name: instanceName,
|
370
|
+
secrets,
|
371
|
+
inputs: inputs as any,
|
372
|
+
invokedTriggers: config.getObject<InstanceTriggerInvocation[]>("$invokedTriggers") ?? [],
|
373
|
+
|
374
|
+
outputs: async (outputs: any = {}) => {
|
375
|
+
const result: any = mapValues(outputs, (outputValue, outputName) => {
|
376
|
+
if (outputName === "$status") {
|
377
|
+
return output(outputValue).apply(mapStatus)
|
378
|
+
}
|
379
|
+
|
380
|
+
if (outputName === "$pages") {
|
381
|
+
return output(outputValue).apply(mapPages)
|
382
|
+
}
|
383
|
+
|
384
|
+
if (outputName === "$files") {
|
385
|
+
return output(outputValue).apply(mapFiles)
|
386
|
+
}
|
387
|
+
|
388
|
+
if (outputName === "$terminals") {
|
389
|
+
return output(outputValue).apply(mapTerminals)
|
390
|
+
}
|
391
|
+
|
392
|
+
if (outputName === "$triggers") {
|
393
|
+
return output(outputValue).apply(mapTriggers)
|
394
|
+
}
|
395
|
+
|
396
|
+
if (outputName.startsWith("$")) {
|
397
|
+
throw new Error(`Unknown extra output '${outputName}'.`)
|
398
|
+
}
|
399
|
+
|
400
|
+
const outputModel = unit.model.outputs[outputName]
|
401
|
+
if (!outputModel) {
|
402
|
+
throw new Error(`Output '${outputName}' not found in the unit '${unit.model.type}'.`)
|
403
|
+
}
|
404
|
+
|
405
|
+
const entity = unit.entities.get(outputModel.type)
|
406
|
+
if (!entity) {
|
407
|
+
throw new Error(
|
408
|
+
`Entity '${outputModel.type}' not found in the unit '${unit.model.type}'.`,
|
409
|
+
)
|
410
|
+
}
|
411
|
+
|
412
|
+
return output(outputValue).apply(value => {
|
413
|
+
if (value === undefined) {
|
414
|
+
if (outputModel.required) {
|
415
|
+
throw new Error(`Output '${outputName}' is required.`)
|
416
|
+
}
|
417
|
+
|
418
|
+
return undefined
|
419
|
+
}
|
420
|
+
|
421
|
+
if (!ajv.validate(entity.schema, value)) {
|
422
|
+
throw new Error(`Invalid output for '${outputModel.type}': ${ajv.errorsText()}`)
|
423
|
+
}
|
424
|
+
|
425
|
+
return value
|
426
|
+
})
|
427
|
+
}) as Record<string, Output<unknown>> & ExtraOutputs
|
428
|
+
|
429
|
+
await Promise.all(Object.values(result).map(o => outputToPromise(o)))
|
430
|
+
|
431
|
+
if (Object.keys(createdSecrets).length > 0) {
|
432
|
+
result.$secrets = createdSecrets
|
433
|
+
}
|
434
|
+
|
435
|
+
return result
|
436
|
+
},
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
440
|
+
export type EntityValue<T extends Entity> = Static<T["schema"]>
|
441
|
+
export type EntityInput<T extends Entity> = Output<EntityValue<T>>
|
442
|
+
|
443
|
+
function outputToPromise(o: unknown): Promise<unknown> {
|
444
|
+
return new Promise(resolve => (output(o) as Output<unknown>).apply(resolve))
|
445
|
+
}
|
446
|
+
|
447
|
+
function mapStatus(status: Unwrap<ExtraOutputs["$status"]>): StatusField[] {
|
448
|
+
if (!status) {
|
449
|
+
return []
|
450
|
+
}
|
451
|
+
|
452
|
+
if (Array.isArray(status)) {
|
453
|
+
return status.filter(field => !!field?.value) as StatusField[]
|
454
|
+
}
|
455
|
+
|
456
|
+
return Object.entries(status)
|
457
|
+
.map(([name, field]) => {
|
458
|
+
if (!field) {
|
459
|
+
return undefined
|
460
|
+
}
|
461
|
+
|
462
|
+
if (typeof field === "string") {
|
463
|
+
return { name, value: field }
|
464
|
+
}
|
465
|
+
|
466
|
+
return { ...(field as StatusField), name }
|
467
|
+
})
|
468
|
+
.filter(field => !!field?.value) as StatusField[]
|
469
|
+
}
|
470
|
+
|
471
|
+
function mapPages(pages: Unwrap<ExtraOutputs["$pages"]>): InstancePage[] {
|
472
|
+
if (!pages) {
|
473
|
+
return []
|
474
|
+
}
|
475
|
+
|
476
|
+
if (Array.isArray(pages)) {
|
477
|
+
return pages.filter(page => !!page)
|
478
|
+
}
|
479
|
+
|
480
|
+
return Object.entries(pages)
|
481
|
+
.filter(([, page]) => !!page)
|
482
|
+
.map(([name, page]) => ({ ...page!, name }))
|
483
|
+
}
|
484
|
+
|
485
|
+
export function fileFromString(
|
486
|
+
name: string,
|
487
|
+
content: string,
|
488
|
+
contentType = "text/plain",
|
489
|
+
isSecret = false,
|
490
|
+
): InstanceFile {
|
491
|
+
return {
|
492
|
+
meta: {
|
493
|
+
name,
|
494
|
+
contentType,
|
495
|
+
size: Buffer.byteLength(content, "utf8"),
|
496
|
+
},
|
497
|
+
content: isSecret ? secret(content) : content,
|
498
|
+
}
|
499
|
+
}
|
500
|
+
|
501
|
+
export function fileFromBuffer(
|
502
|
+
name: string,
|
503
|
+
content: Buffer,
|
504
|
+
contentType = "application/octet-stream",
|
505
|
+
isSecret = false,
|
506
|
+
): InstanceFile {
|
507
|
+
return {
|
508
|
+
meta: {
|
509
|
+
name,
|
510
|
+
contentType,
|
511
|
+
size: content.byteLength,
|
512
|
+
isBinary: true,
|
513
|
+
},
|
514
|
+
content: isSecret ? secret(content.toString("base64")) : content.toString("base64"),
|
515
|
+
}
|
516
|
+
}
|
517
|
+
|
518
|
+
function mapFiles(files: Unwrap<ExtraOutputs["$files"]>): InstanceFile[] {
|
519
|
+
return files?.filter(file => !!file) ?? []
|
520
|
+
}
|
521
|
+
|
522
|
+
function mapTerminals(terminals: Unwrap<ExtraOutputs["$terminals"]>): InstanceTerminal[] {
|
523
|
+
if (!terminals) {
|
524
|
+
return []
|
525
|
+
}
|
526
|
+
|
527
|
+
if (!Array.isArray(terminals)) {
|
528
|
+
terminals = Object.entries(terminals).map(([name, terminal]) => {
|
529
|
+
if (!terminal) {
|
530
|
+
return undefined
|
531
|
+
}
|
532
|
+
|
533
|
+
return { ...terminal, name }
|
534
|
+
})
|
535
|
+
}
|
536
|
+
|
537
|
+
return terminals
|
538
|
+
.filter(terminal => !!terminal)
|
539
|
+
.map(terminal => {
|
540
|
+
if (!terminal.files) {
|
541
|
+
return terminal
|
542
|
+
}
|
543
|
+
|
544
|
+
return {
|
545
|
+
...terminal,
|
546
|
+
|
547
|
+
files: pipe(
|
548
|
+
terminal.files,
|
549
|
+
mapValues(file => {
|
550
|
+
if (typeof file === "string") {
|
551
|
+
return { content: file }
|
552
|
+
}
|
553
|
+
|
554
|
+
return file
|
555
|
+
}),
|
556
|
+
pickBy(value => !!value?.content),
|
557
|
+
),
|
558
|
+
}
|
559
|
+
})
|
560
|
+
}
|
561
|
+
|
562
|
+
function mapTriggers(triggers: Unwrap<ExtraOutputs["$triggers"]>): InstanceTrigger[] {
|
563
|
+
if (!triggers) {
|
564
|
+
return []
|
565
|
+
}
|
566
|
+
|
567
|
+
if (Array.isArray(triggers)) {
|
568
|
+
return triggers.filter(trigger => !!trigger)
|
569
|
+
}
|
570
|
+
|
571
|
+
return Object.entries(triggers)
|
572
|
+
.filter(([, trigger]) => !!trigger)
|
573
|
+
.map(([name, trigger]) => ({ ...(trigger as InstanceTrigger), name }))
|
574
|
+
}
|
package/src/utils.ts
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
import { type Input, type Unwrap, type Output, output, all } from "@pulumi/pulumi"
|
2
|
+
|
3
|
+
/**
|
4
|
+
* The input type for an array of inputs.
|
5
|
+
* The same as `Input<Input<T>[]>`, but more readable.
|
6
|
+
*/
|
7
|
+
export type InputArray<T> = Input<Input<T>[]>
|
8
|
+
|
9
|
+
/**
|
10
|
+
* The input type for a map of inputs.
|
11
|
+
* The same as `Input<Record<string, Input<T>>>`, but more readable.
|
12
|
+
*/
|
13
|
+
export type InputMap<T> = Input<Readonly<Record<string, Input<T>>>>
|
14
|
+
|
15
|
+
/**
|
16
|
+
* The input or input array type for a value.
|
17
|
+
*/
|
18
|
+
export type InputOrArray<T> = Input<T> | InputArray<T>
|
19
|
+
|
20
|
+
/**
|
21
|
+
* The input of inputs of inputs of inputs, so you got the idea.
|
22
|
+
*/
|
23
|
+
export type DeepInput<T> = [T] extends [Record<string, unknown> | undefined]
|
24
|
+
? [T] extends [infer U | undefined]
|
25
|
+
? Input<{ [K in keyof U]: DeepInput<U[K]> } | undefined>
|
26
|
+
: Input<{ [K in keyof T]: DeepInput<T[K]> }>
|
27
|
+
: [T] extends [Array<unknown> | undefined]
|
28
|
+
? [T] extends [(infer U)[] | undefined]
|
29
|
+
? Input<DeepInput<U>[] | undefined>
|
30
|
+
: Input<DeepInput<T>[]>
|
31
|
+
: Input<T>
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Merges the given array of `InputOrArray` values into a single flat output array.
|
35
|
+
*
|
36
|
+
* @param values The values to merge.
|
37
|
+
* @returns The merged output array.
|
38
|
+
*/
|
39
|
+
export function flattenInputs<T>(...values: (InputOrArray<T> | undefined)[]): Output<T[]> {
|
40
|
+
return all(values).apply(allValues => {
|
41
|
+
const result: T[] = []
|
42
|
+
for (const value of allValues) {
|
43
|
+
if (Array.isArray(value)) {
|
44
|
+
result.push(...(value as T[]))
|
45
|
+
} else if (value) {
|
46
|
+
result.push(value as T)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
return result
|
50
|
+
})
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Maps each element of an input array to a new value.
|
55
|
+
* Produces an output array with the same length.
|
56
|
+
*
|
57
|
+
* @param array The input array.
|
58
|
+
* @param fn The mapping function.
|
59
|
+
* @returns The output array.
|
60
|
+
*/
|
61
|
+
export function mapInputs<T, U>(
|
62
|
+
array: InputArray<T>,
|
63
|
+
fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U,
|
64
|
+
): Output<U[]> {
|
65
|
+
return output(array).apply(array => {
|
66
|
+
return array?.map((v, index) => fn(v as Unwrap<T>, index, array as Unwrap<T>[])) ?? []
|
67
|
+
})
|
68
|
+
}
|
69
|
+
|
70
|
+
export function flatMapInput<T, U>(
|
71
|
+
v1: InputOrArray<T>,
|
72
|
+
v2: InputOrArray<T>,
|
73
|
+
fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U,
|
74
|
+
): Output<U[]>
|
75
|
+
|
76
|
+
export function flatMapInput<T, U>(
|
77
|
+
v1: InputOrArray<T>,
|
78
|
+
v2: InputOrArray<T>,
|
79
|
+
v3: InputOrArray<T>,
|
80
|
+
fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U,
|
81
|
+
): Output<U[]>
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Merges the given array of `InputOrArray` values into a single flat output array and maps each element to a new value.
|
85
|
+
*
|
86
|
+
* @param values The values to merge.
|
87
|
+
* @param fn The mapping function.
|
88
|
+
*/
|
89
|
+
export function flatMapInput<T, U>(
|
90
|
+
...args: (InputOrArray<T> | ((v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U))[]
|
91
|
+
): Output<U[]> {
|
92
|
+
const fn = args.pop() as (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U
|
93
|
+
const values = args as InputOrArray<T>[]
|
94
|
+
|
95
|
+
return mapInputs(flattenInputs(...values), fn)
|
96
|
+
}
|
97
|
+
|
98
|
+
/**
|
99
|
+
* Map an optional value to another optional value.
|
100
|
+
*
|
101
|
+
* @param input The input value.
|
102
|
+
* @param func The function to apply to the input value.
|
103
|
+
* @returns The output value, or `undefined` if the input value is `undefined`.
|
104
|
+
*/
|
105
|
+
export function mapOptional<T, U>(input: T | undefined, func: (value: T) => U): U | undefined {
|
106
|
+
if (input === undefined) {
|
107
|
+
return undefined
|
108
|
+
}
|
109
|
+
|
110
|
+
return func(input)
|
111
|
+
}
|
112
|
+
|
113
|
+
export function toPromise<T>(input: Input<T>): Promise<Unwrap<T>> {
|
114
|
+
return new Promise(resolve => output(input).apply(resolve))
|
115
|
+
}
|
116
|
+
|
117
|
+
export function singleton<T>(factory: () => T): () => T {
|
118
|
+
let instance: T | undefined
|
119
|
+
return () => {
|
120
|
+
if (instance === undefined) {
|
121
|
+
instance = factory()
|
122
|
+
}
|
123
|
+
|
124
|
+
return instance
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
export function providerFactory<TInput>(
|
129
|
+
factory: (name: string) => TInput,
|
130
|
+
): (name: string) => TInput {
|
131
|
+
const instances = new Map<string, TInput>()
|
132
|
+
return name => {
|
133
|
+
if (!instances.has(name)) {
|
134
|
+
instances.set(name, factory(name))
|
135
|
+
}
|
136
|
+
|
137
|
+
return instances.get(name)!
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
export function mergeInputObjects<
|
142
|
+
T1 extends Record<string, unknown>,
|
143
|
+
T2 extends Record<string, unknown>,
|
144
|
+
>(obj1: Input<T1 | undefined> | undefined, obj2: Input<T2 | undefined> | undefined): Output<T1 & T2>
|
145
|
+
|
146
|
+
export function mergeInputObjects<
|
147
|
+
T1 extends Record<string, unknown>,
|
148
|
+
T2 extends Record<string, unknown>,
|
149
|
+
T3 extends Record<string, unknown>,
|
150
|
+
>(
|
151
|
+
obj1: Input<T1 | undefined> | undefined,
|
152
|
+
obj2: Input<T2 | undefined> | undefined,
|
153
|
+
obj3: Input<T3 | undefined> | undefined,
|
154
|
+
): Output<T1 & T2 & T3>
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Merges the given input objects into a single output object.
|
158
|
+
*
|
159
|
+
* @param objects The input objects.
|
160
|
+
* @returns The output object.
|
161
|
+
*/
|
162
|
+
export function mergeInputObjects(
|
163
|
+
...objects: Input<Record<string, unknown>>[]
|
164
|
+
): Output<Record<string, unknown>> {
|
165
|
+
return output(objects).apply(array => {
|
166
|
+
return Object.assign({}, ...array) as Record<string, unknown>
|
167
|
+
})
|
168
|
+
}
|
169
|
+
|
170
|
+
export function normalize<T>(item: T | undefined, collection: T[] | undefined): T[] {
|
171
|
+
if (item && collection) {
|
172
|
+
return [item, ...collection]
|
173
|
+
}
|
174
|
+
|
175
|
+
if (item) {
|
176
|
+
return [item]
|
177
|
+
}
|
178
|
+
|
179
|
+
return collection ?? []
|
180
|
+
}
|
181
|
+
|
182
|
+
export function apply<T, U>(fn: (value: Unwrap<T>) => U): (input: Input<T>) => Output<U> {
|
183
|
+
return input => output(input).apply(fn)
|
184
|
+
}
|
package/dist/index.d.ts
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
import { Input, Output, Unwrap } from '@pulumi/pulumi';
|
2
|
-
export * from '@pulumi/pulumi';
|
3
|
-
import { ArgumentValue, ComponentInputSpec, Unit, Entity } from '@highstate/contract';
|
4
|
-
import { Static } from '@sinclair/typebox';
|
5
|
-
|
6
|
-
/**
|
7
|
-
* The input type for an array of inputs.
|
8
|
-
* The same as `Input<Input<T>[]>`, but more readable.
|
9
|
-
*/
|
10
|
-
type InputArray<T> = Input<Input<T>[]>;
|
11
|
-
/**
|
12
|
-
* The input type for a map of inputs.
|
13
|
-
* The same as `Input<Record<string, Input<T>>>`, but more readable.
|
14
|
-
*/
|
15
|
-
type InputMap<T> = Input<Readonly<Record<string, Input<T>>>>;
|
16
|
-
/**
|
17
|
-
* The input or input array type for a value.
|
18
|
-
*/
|
19
|
-
type InputOrArray<T> = Input<T> | InputArray<T>;
|
20
|
-
/**
|
21
|
-
* The input of inputs of inputs of inputs, so you got the idea.
|
22
|
-
*/
|
23
|
-
type DeepInput<T> = [T] extends [Record<string, unknown> | undefined] ? [T] extends [infer U | undefined] ? Input<{
|
24
|
-
[K in keyof U]: DeepInput<U[K]>;
|
25
|
-
} | undefined> : Input<{
|
26
|
-
[K in keyof T]: DeepInput<T[K]>;
|
27
|
-
}> : [T] extends [Array<unknown> | undefined] ? [T] extends [(infer U)[] | undefined] ? Input<DeepInput<U>[] | undefined> : Input<DeepInput<T>[]> : Input<T>;
|
28
|
-
/**
|
29
|
-
* Merges the given array of `InputOrArray` values into a single flat output array.
|
30
|
-
*
|
31
|
-
* @param values The values to merge.
|
32
|
-
* @returns The merged output array.
|
33
|
-
*/
|
34
|
-
declare function flattenInputs<T>(...values: (InputOrArray<T> | undefined)[]): Output<T[]>;
|
35
|
-
/**
|
36
|
-
* Maps each element of an input array to a new value.
|
37
|
-
* Produces an output array with the same length.
|
38
|
-
*
|
39
|
-
* @param array The input array.
|
40
|
-
* @param fn The mapping function.
|
41
|
-
* @returns The output array.
|
42
|
-
*/
|
43
|
-
declare function mapInputs<T, U>(array: InputArray<T>, fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U): Output<U[]>;
|
44
|
-
declare function flatMapInput<T, U>(v1: InputOrArray<T>, v2: InputOrArray<T>, fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U): Output<U[]>;
|
45
|
-
declare function flatMapInput<T, U>(v1: InputOrArray<T>, v2: InputOrArray<T>, v3: InputOrArray<T>, fn: (v: Unwrap<T>, index: number, all: Unwrap<T>[]) => U): Output<U[]>;
|
46
|
-
/**
|
47
|
-
* Map an optional value to another optional value.
|
48
|
-
*
|
49
|
-
* @param input The input value.
|
50
|
-
* @param func The function to apply to the input value.
|
51
|
-
* @returns The output value, or `undefined` if the input value is `undefined`.
|
52
|
-
*/
|
53
|
-
declare function mapOptional<T, U>(input: T | undefined, func: (value: T) => U): U | undefined;
|
54
|
-
declare function toPromise<T>(input: Input<T>): Promise<Unwrap<T>>;
|
55
|
-
declare function singleton<T>(factory: () => T): () => T;
|
56
|
-
declare function providerFactory<TInput>(factory: (name: string) => TInput): (name: string) => TInput;
|
57
|
-
declare function mergeInputObjects<T1 extends Record<string, unknown>, T2 extends Record<string, unknown>>(obj1: Input<T1 | undefined> | undefined, obj2: Input<T2 | undefined> | undefined): Output<T1 & T2>;
|
58
|
-
declare function mergeInputObjects<T1 extends Record<string, unknown>, T2 extends Record<string, unknown>, T3 extends Record<string, unknown>>(obj1: Input<T1 | undefined> | undefined, obj2: Input<T2 | undefined> | undefined, obj3: Input<T3 | undefined> | undefined): Output<T1 & T2 & T3>;
|
59
|
-
declare function normalize<T>(item: T | undefined, collection: T[] | undefined): T[];
|
60
|
-
declare function apply<T, U>(fn: (value: Unwrap<T>) => U): (input: Input<T>) => Output<U>;
|
61
|
-
|
62
|
-
type InstanceTerminalFile = {
|
63
|
-
content: Input<string | undefined>;
|
64
|
-
mode?: Input<number | undefined>;
|
65
|
-
isBinary?: Input<boolean>;
|
66
|
-
};
|
67
|
-
type InstanceTerminal = {
|
68
|
-
name: Input<string>;
|
69
|
-
title: Input<string>;
|
70
|
-
description?: Input<string>;
|
71
|
-
image: Input<string>;
|
72
|
-
command: InputArray<string>;
|
73
|
-
cwd?: Input<string | undefined>;
|
74
|
-
env?: InputMap<string | undefined>;
|
75
|
-
files?: InputMap<InstanceTerminalFile | string | undefined>;
|
76
|
-
};
|
77
|
-
type StatusField = {
|
78
|
-
name: Input<string>;
|
79
|
-
value?: Input<string | undefined>;
|
80
|
-
displayName?: Input<string | undefined>;
|
81
|
-
sensitive?: Input<boolean | undefined>;
|
82
|
-
url?: Input<string | undefined>;
|
83
|
-
};
|
84
|
-
type InstanceFile = {
|
85
|
-
name: Input<string>;
|
86
|
-
contentType: Input<string>;
|
87
|
-
content: Input<string>;
|
88
|
-
};
|
89
|
-
type InstancePageBlock = {
|
90
|
-
type: "markdown";
|
91
|
-
content: Input<string>;
|
92
|
-
} | {
|
93
|
-
type: "qr";
|
94
|
-
content: Input<string>;
|
95
|
-
showContent?: boolean;
|
96
|
-
language?: string;
|
97
|
-
} | {
|
98
|
-
type: "file";
|
99
|
-
fileMeta: Omit<InstanceFile, "content">;
|
100
|
-
};
|
101
|
-
type InstancePage = {
|
102
|
-
name: Input<string>;
|
103
|
-
title: Input<string>;
|
104
|
-
content: InputArray<InstancePageBlock>;
|
105
|
-
};
|
106
|
-
type InstanceTriggerSpec = {
|
107
|
-
type: "before-destroy";
|
108
|
-
} | {
|
109
|
-
type: "schedule";
|
110
|
-
schedule: string;
|
111
|
-
};
|
112
|
-
type InstanceTrigger = {
|
113
|
-
name: Input<string>;
|
114
|
-
title: Input<string>;
|
115
|
-
description?: Input<string>;
|
116
|
-
spec: Input<InstanceTriggerSpec>;
|
117
|
-
};
|
118
|
-
type ExtraOutputs = {
|
119
|
-
$status?: InputMap<Omit<StatusField, "name"> | string | undefined> | InputArray<StatusField | undefined>;
|
120
|
-
$terminals?: InputMap<Omit<InstanceTerminal, "name"> | undefined> | InputArray<InstanceTerminal | undefined>;
|
121
|
-
$pages?: InputMap<Omit<InstancePage, "name"> | undefined> | InputArray<InstancePage | undefined>;
|
122
|
-
$files?: InputMap<Omit<InstanceFile, "name"> | undefined> | InputArray<InstanceFile | undefined>;
|
123
|
-
$triggers?: InputMap<Omit<InstanceTrigger, "name"> | undefined> | InputArray<InstanceTrigger | undefined>;
|
124
|
-
};
|
125
|
-
type InstanceTriggerInvocation = {
|
126
|
-
name: string;
|
127
|
-
};
|
128
|
-
type OutputMapToDeepInputMap<T extends Record<string, unknown>> = T extends Record<string, never> ? ExtraOutputs : {
|
129
|
-
[K in keyof T]: DeepInput<T[K]>;
|
130
|
-
} & ExtraOutputs;
|
131
|
-
interface UnitContext<TArgs extends Record<string, ArgumentValue>, TInputs extends Record<string, unknown>, TOutputs extends Record<string, unknown>, TSecrets extends Record<string, ArgumentValue>> {
|
132
|
-
args: TArgs;
|
133
|
-
instanceId: string;
|
134
|
-
type: string;
|
135
|
-
name: string;
|
136
|
-
secrets: Output<TSecrets>;
|
137
|
-
inputs: {
|
138
|
-
[K in keyof TInputs]: undefined extends TInputs[K] ? Output<NonNullable<TInputs[K]>> | undefined : Output<TInputs[K]>;
|
139
|
-
};
|
140
|
-
invokedTriggers: InstanceTriggerInvocation[];
|
141
|
-
outputs(this: void, outputs?: OutputMapToDeepInputMap<TOutputs>): Promise<unknown>;
|
142
|
-
}
|
143
|
-
type InputSpecToValue<T extends ComponentInputSpec> = T[2] extends true ? Static<T[0]["schema"]>[] : T[1] extends true ? Static<T[0]["schema"]> : Static<T[0]["schema"]> | undefined;
|
144
|
-
type InputSpecMapToValueMap<T extends Record<string, ComponentInputSpec>> = T extends Record<string, never> ? Record<string, never> : {
|
145
|
-
[K in keyof T]: InputSpecToValue<T[K]>;
|
146
|
-
};
|
147
|
-
declare function forUnit<TArgs extends Record<string, ArgumentValue>, TInputs extends Record<string, ComponentInputSpec>, TOutputs extends Record<string, ComponentInputSpec>, TSecrets extends Record<string, ArgumentValue>>(unit: Unit<TArgs, TInputs, TOutputs, TSecrets>): UnitContext<TArgs, InputSpecMapToValueMap<TInputs>, InputSpecMapToValueMap<TOutputs>, TSecrets>;
|
148
|
-
type EntityValue<T extends Entity> = Static<T["schema"]>;
|
149
|
-
type EntityInput<T extends Entity> = Output<EntityValue<T>>;
|
150
|
-
|
151
|
-
declare function getOrCreateSecret<TSecrets extends Record<string, unknown>, TResult extends TSecrets[keyof TSecrets]>(secrets: Output<TSecrets>, key: keyof TSecrets, create: () => Input<TResult>): Output<TResult>;
|
152
|
-
|
153
|
-
export { type DeepInput, type EntityInput, type EntityValue, type ExtraOutputs, type InputArray, type InputMap, type InputOrArray, type InstanceFile, type InstancePage, type InstancePageBlock, type InstanceTerminal, type InstanceTerminalFile, type InstanceTrigger, type InstanceTriggerInvocation, type InstanceTriggerSpec, type StatusField, type UnitContext, apply, flatMapInput, flattenInputs, forUnit, getOrCreateSecret, mapInputs, mapOptional, mergeInputObjects, normalize, providerFactory, singleton, toPromise };
|