@highstate/pulumi 0.19.1 → 0.21.1

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/src/unit.ts CHANGED
@@ -1,15 +1,16 @@
1
1
  /** biome-ignore-all lint/suspicious/noExplicitAny: здесь орать запрещено */
2
2
 
3
3
  import type { IsEmptyObject } from "type-fest"
4
+ import { join } from "node:path"
4
5
  import { pathToFileURL } from "node:url"
5
6
  import {
6
7
  type ComponentInput,
7
8
  type ComponentInputSpec,
8
9
  camelCaseToHumanReadable,
9
- compact,
10
- decompact,
10
+ type EntityValue,
11
+ type EntityValueInput,
11
12
  HighstateConfigKey,
12
- type InstanceInput,
13
+ HighstateSignature,
13
14
  type InstanceStatusField,
14
15
  type InstanceStatusFieldValue,
15
16
  type PartialKeys,
@@ -19,8 +20,7 @@ import {
19
20
  type TriggerInvocation,
20
21
  type Unit,
21
22
  type UnitArtifact,
22
- type UnitConfig,
23
- type UnitInputReference,
23
+ type UnitInputValue,
24
24
  type UnitPage,
25
25
  type UnitTerminal,
26
26
  type UnitTrigger,
@@ -36,10 +36,10 @@ import {
36
36
  type Output,
37
37
  output,
38
38
  secret as pulumiSecret,
39
- StackReference,
40
39
  type Unwrap,
41
40
  } from "@pulumi/pulumi"
42
- import { mapValues } from "remeda"
41
+ import { isPlainObject, mapValues } from "remeda"
42
+ import { getHasResourceHooks } from "./resource-hooks"
43
43
  import { type DeepInput, toPromise } from "./utils"
44
44
 
45
45
  type StatusField<TArgName extends string = string> = Omit<
@@ -92,6 +92,7 @@ interface UnitContext<
92
92
  > {
93
93
  args: TArgs
94
94
  instanceId: string
95
+ stateId: string
95
96
  type: string
96
97
  name: string
97
98
 
@@ -112,6 +113,12 @@ interface UnitContext<
112
113
  factory: () => Input<NonNullable<TSecrets[K]>>,
113
114
  ): Output<NonNullable<TSecrets[K]>>
114
115
 
116
+ setSecret<K extends keyof TSecrets>(
117
+ this: void,
118
+ name: K,
119
+ value: Input<NonNullable<TSecrets[K]>>,
120
+ ): void
121
+
115
122
  inputs: TInputs
116
123
  invokedTriggers: TriggerInvocation[]
117
124
 
@@ -123,24 +130,22 @@ interface UnitContext<
123
130
 
124
131
  // z.output since the values are validated/transformed and passed to the user
125
132
  type InputSpecToWrappedValue<T extends ComponentInputSpec> = T[2] extends true
126
- ? // we have to wrap the array in Output since we don't know how many items will be returned by each multiple input
127
- Output<NonNullable<z.output<T[0]["schema"]>>[]>
133
+ ? NonNullable<EntityValue<T[0]>>[]
128
134
  : T[1] extends true
129
- ? Output<NonNullable<z.output<T[0]["schema"]>>>
130
- : Output<NonNullable<z.output<T[0]["schema"]>>> | undefined
135
+ ? NonNullable<EntityValue<T[0]>>
136
+ : NonNullable<EntityValue<T[0]>> | undefined
131
137
 
132
138
  // z.input since the values are passed from the user and should be validated/transformed before returning from the unit
133
139
  type OutputSpecToValue<T extends ComponentInputSpec> = T[2] extends true
134
140
  ? T[1] extends true
135
- ? NonNullable<z.input<T[0]["schema"]>>[]
136
- : NonNullable<z.input<T[0]["schema"]>>[] | undefined
141
+ ? NonNullable<EntityValueInput<T[0]>>[]
142
+ : NonNullable<EntityValueInput<T[0]>>[] | undefined
137
143
  : T[1] extends true
138
- ? NonNullable<z.input<T[0]["schema"]>>
139
- : NonNullable<z.input<T[0]["schema"]>> | undefined
140
-
141
- const stackRefMap = new Map<string, StackReference>()
144
+ ? NonNullable<EntityValueInput<T[0]>>
145
+ : NonNullable<EntityValueInput<T[0]>> | undefined
142
146
 
143
147
  let instanceId: string | undefined
148
+ let stateId: string | undefined
144
149
  let instanceName: string | undefined
145
150
  let importBaseUrl: URL | undefined
146
151
 
@@ -157,6 +162,20 @@ export function getUnitInstanceId(): string {
157
162
  return instanceId
158
163
  }
159
164
 
165
+ /**
166
+ * Returns the current unit instance state id.
167
+ *
168
+ * The state id is provided by the runner via Pulumi config.
169
+ * Only available after calling `forUnit` function.
170
+ */
171
+ export function getUnitStateId(): string {
172
+ if (!stateId) {
173
+ throw new Error(`State id is not set. Did you call "forUnit" function?`)
174
+ }
175
+
176
+ return stateId
177
+ }
178
+
160
179
  /**
161
180
  * Returns the current unit instance name.
162
181
  */
@@ -183,78 +202,38 @@ export function getImportBaseUrl(): URL {
183
202
  * Returns a comment that can be used in resources to indicate that they are managed by Highstate.
184
203
  */
185
204
  export function getResourceComment(): string {
186
- return `Managed by Highstate (${getUnitInstanceId()})`
187
- }
188
-
189
- function getStackRef(config: UnitConfig, input: InstanceInput) {
190
- const [instanceType] = parseInstanceId(input.instanceId)
191
- const stateId = config.stateIdMap[input.instanceId]
192
- if (!stateId) {
193
- throw new Error(`State ID for instance "${input.instanceId}" not found in the unit config.`)
194
- }
195
-
196
- const key = `organization/${instanceType}/${stateId}`
197
- let stackRef = stackRefMap.get(key)
198
-
199
- if (!stackRef) {
200
- stackRef = new StackReference(key)
201
- stackRefMap.set(key, stackRef)
202
- }
203
-
204
- return stackRef
205
+ return `Managed by Highstate [${getUnitStateId()}]`
205
206
  }
206
207
 
207
- function getOutput(
208
- config: UnitConfig,
208
+ function getInputValue(
209
209
  unit: Unit,
210
210
  inputName: string,
211
211
  input: ComponentInput,
212
- refs: UnitInputReference[],
212
+ entries: UnitInputValue[],
213
213
  ) {
214
214
  const entity = unit.entities.get(input.type)
215
215
  if (!entity) {
216
216
  throw new Error(`Entity "${input.type}" not found in the unit "${unit.model.type}".`)
217
217
  }
218
218
 
219
- const _getOutput = (ref: UnitInputReference) => {
220
- const value = getStackRef(config, ref).requireOutput(ref.output)
219
+ const values = entries.flatMap(entry => {
220
+ const value = parseArgumentValue(entry.value)
221
+ const schema = Array.isArray(value) ? entity.schema.array() : entity.schema
222
+ const result = schema.safeParse(value)
221
223
 
222
- return value.apply(value => {
223
- if (ref.inclusion) {
224
- if (value === null || value === undefined || typeof value !== "object") {
225
- throw new Error(
226
- `Cannot extract field "${ref.inclusion.field}" from non-object output "${ref.output}" of instance "${ref.instanceId}".`,
227
- )
228
- }
229
-
230
- value = (value as Record<string, unknown>)[ref.inclusion.field]
231
- }
232
-
233
- const schema = Array.isArray(value) ? entity.schema.array() : entity.schema
234
- const result = schema.safeParse(value)
235
-
236
- if (!result.success) {
237
- throw new Error(
238
- `Invalid output "${ref.output}" from "${ref.instanceId}" for input "${inputName}": ${result.error.message}`,
239
- )
240
- }
241
-
242
- if (Array.isArray(value)) {
243
- return value
244
- }
245
-
246
- return input.multiple ? [value] : value
247
- })
248
- }
224
+ if (!result.success) {
225
+ throw new Error(`Invalid value for input "${inputName}": ${z.prettifyError(result.error)}`)
226
+ }
249
227
 
250
- const _getDecompactedOutput = (ref: UnitInputReference) => {
251
- return _getOutput(ref).apply(decompact)
252
- }
228
+ if (Array.isArray(result.data)) {
229
+ return result.data
230
+ }
253
231
 
254
- const values = output(refs.map(_getDecompactedOutput)).apply(values => values.flat())
232
+ return input.multiple ? [result.data] : [result.data]
233
+ })
255
234
 
256
235
  if (!input.multiple) {
257
- return values.apply(values => values[0])
236
+ return values[0]
258
237
  }
259
238
 
260
239
  return values
@@ -278,10 +257,6 @@ export function forUnit<
278
257
  const rawHSConfig = config.requireObject(HighstateConfigKey.Config)
279
258
  const hsConfig = unitConfigSchema.parse(rawHSConfig)
280
259
 
281
- const rawHsSecrets = config
282
- .requireSecretObject(HighstateConfigKey.Secrets)
283
- .apply(secrets => z.record(z.string(), z.unknown()).parse(secrets))
284
-
285
260
  const args = mapValues(unit.model.args, (arg, argName) => {
286
261
  const value = parseArgumentValue(hsConfig.args[argName])
287
262
  const result = arg[runtimeSchema]!.safeParse(value)
@@ -294,7 +269,7 @@ export function forUnit<
294
269
  })
295
270
 
296
271
  const secrets = mapValues(unit.model.secrets, (secret, secretName) => {
297
- const hasValue = hsConfig.secretNames.includes(secretName)
272
+ const hasValue = secretName in hsConfig.secretValues
298
273
 
299
274
  if (!hasValue && !secret.required) {
300
275
  return secret.schema.default ? pulumiSecret(secret.schema.default) : undefined
@@ -304,16 +279,15 @@ export function forUnit<
304
279
  throw new Error(`Secret "${secretName}" is required but not provided.`)
305
280
  }
306
281
 
307
- return rawHsSecrets[secretName].apply(rawValue => {
308
- const value = parseArgumentValue(rawValue)
309
- const result = secret[runtimeSchema]!.safeParse(value)
282
+ const rawValue = hsConfig.secretValues[secretName]
283
+ const value = parseArgumentValue(rawValue)
284
+ const result = secret[runtimeSchema]!.safeParse(value)
310
285
 
311
- if (!result.success) {
312
- throw new Error(`Invalid secret "${secretName}": ${z.prettifyError(result.error)}`)
313
- }
286
+ if (!result.success) {
287
+ throw new Error(`Invalid secret "${secretName}": ${z.prettifyError(result.error)}`)
288
+ }
314
289
 
315
- return pulumiSecret(result.data)
316
- })
290
+ return pulumiSecret(result.data)
317
291
  })
318
292
 
319
293
  const inputs = mapValues(unit.model.inputs, (input, inputName) => {
@@ -321,23 +295,25 @@ export function forUnit<
321
295
 
322
296
  if (!value) {
323
297
  if (input.multiple) {
324
- return output([])
298
+ return []
325
299
  }
326
300
 
327
301
  return undefined
328
302
  }
329
303
 
330
- return getOutput(hsConfig, unit as unknown as Unit, inputName, input, value)
304
+ return getInputValue(unit as unknown as Unit, inputName, input, value)
331
305
  })
332
306
 
333
307
  const [type, name] = parseInstanceId(hsConfig.instanceId)
334
308
 
335
309
  instanceId = hsConfig.instanceId
310
+ stateId = hsConfig.stateId
336
311
  instanceName = name
337
312
  importBaseUrl = pathToFileURL(hsConfig.importBasePath)
338
313
 
339
314
  return {
340
315
  instanceId: hsConfig.instanceId,
316
+ stateId: hsConfig.stateId,
341
317
  type,
342
318
  name,
343
319
 
@@ -360,26 +336,32 @@ export function forUnit<
360
336
  return value
361
337
  }) as any,
362
338
 
339
+ setSecret: ((name: keyof TSecrets, value: Input<NonNullable<TSecrets[keyof TSecrets]>>) => {
340
+ secrets[name as string] = pulumiSecret(value)
341
+ }) as any,
342
+
363
343
  outputs: async (outputs: any = {}) => {
364
- const result: any = mapValues(outputs, (outputValue, outputName) => {
344
+ const resolvedOutputs = await toPromise(outputs)
345
+
346
+ const result: any = mapValues(resolvedOutputs, (outputValue, outputName) => {
365
347
  if (outputName === "$statusFields") {
366
- return output(outputValue).apply(mapStatusFields)
348
+ return mapStatusFields(outputValue)
367
349
  }
368
350
 
369
351
  if (outputName === "$pages") {
370
- return output(outputValue).apply(mapPages)
352
+ return mapPages(outputValue)
371
353
  }
372
354
 
373
355
  if (outputName === "$terminals") {
374
- return output(outputValue).apply(mapTerminals)
356
+ return mapTerminals(outputValue)
375
357
  }
376
358
 
377
359
  if (outputName === "$triggers") {
378
- return output(outputValue).apply(mapTriggers)
360
+ return mapTriggers(outputValue)
379
361
  }
380
362
 
381
363
  if (outputName === "$workers") {
382
- return output(outputValue).apply(mapWorkers)
364
+ return mapWorkers(outputValue)
383
365
  }
384
366
 
385
367
  if (outputName.startsWith("$")) {
@@ -400,25 +382,20 @@ export function forUnit<
400
382
  )
401
383
  }
402
384
 
403
- return output(outputValue).apply(value => {
404
- const schema = outputModel.multiple ? entity.schema.array() : entity.schema
405
- const result = schema.safeParse(value)
385
+ const schema = outputModel.multiple ? entity.schema.array() : entity.schema
386
+ const result = schema.safeParse(outputValue)
406
387
 
407
- if (!result.success) {
408
- throw new Error(
409
- `Invalid value for output "${outputName}" of type "${outputModel.type}": ${z.prettifyError(
410
- result.error,
411
- )}`,
412
- )
413
- }
388
+ if (!result.success) {
389
+ throw new Error(
390
+ `Invalid value for output "${outputName}" of type "${outputModel.type}": ${z.prettifyError(
391
+ result.error,
392
+ )}`,
393
+ )
394
+ }
414
395
 
415
- return compact(result.data)
416
- })
396
+ return result.data
417
397
  })
418
398
 
419
- // wait for all outputs to resolve before collecting secrets and artifacts
420
- await Promise.all(Object.values(result).map(o => toPromise(o)))
421
-
422
399
  result.$secrets = secrets
423
400
 
424
401
  // collect artifacts from all outputs
@@ -435,11 +412,64 @@ export function forUnit<
435
412
  result.$artifacts = artifactsMap
436
413
  }
437
414
 
438
- return result
415
+ result.$hasResourceHooks = getHasResourceHooks()
416
+
417
+ return wrapHighstateSecretValues(result)
439
418
  },
440
419
  }
441
420
  }
442
421
 
422
+ function wrapHighstateSecretValues<T>(data: T): T {
423
+ const cache = new WeakMap<object, unknown>()
424
+
425
+ const traverse = (value: unknown): unknown => {
426
+ if (value === null || value === undefined || typeof value !== "object") {
427
+ return value
428
+ }
429
+
430
+ if (Array.isArray(value)) {
431
+ const cached = cache.get(value)
432
+ if (cached) {
433
+ return cached
434
+ }
435
+
436
+ const mapped: unknown[] = []
437
+ cache.set(value, mapped)
438
+
439
+ for (const item of value) {
440
+ mapped.push(traverse(item))
441
+ }
442
+
443
+ return mapped
444
+ }
445
+
446
+ if (!isPlainObject(value)) {
447
+ return value
448
+ }
449
+
450
+ const cached = cache.get(value)
451
+ if (cached) {
452
+ return cached
453
+ }
454
+
455
+ const record = value as Record<string, unknown>
456
+ const mapped: Record<string, unknown> = {}
457
+ cache.set(value, mapped)
458
+
459
+ for (const [key, nestedValue] of Object.entries(record)) {
460
+ mapped[key] = traverse(nestedValue)
461
+ }
462
+
463
+ if (record[HighstateSignature.Secret] === true && "value" in record) {
464
+ return pulumiSecret(mapped)
465
+ }
466
+
467
+ return mapped
468
+ }
469
+
470
+ return traverse(data) as T
471
+ }
472
+
443
473
  function mapStatusFields(status: Unwrap<ExtraOutputs["$statusFields"]>): InstanceStatusField[] {
444
474
  if (!status) {
445
475
  return []
@@ -600,3 +630,13 @@ function extractObjectsFromValue<TSchema extends z.ZodType>(
600
630
  traverse(data)
601
631
  return result
602
632
  }
633
+
634
+ /**
635
+ * Returns a temporary file path for the current unit instance.
636
+ *
637
+ * The format is `/tmp/highstate/{stateId}`.
638
+ * This directory does not change between different runs of the same unit instance.
639
+ */
640
+ export function getUnitTempPath(): string {
641
+ return join("/tmp/highstate", getUnitStateId())
642
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Exeteres
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/file.ts","../src/utils.ts","../src/unit.ts"],"names":["content","output","item","collection","value","values","secrets","secret","pulumiSecret","name","result"],"mappings":"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","file":"index.js","sourcesContent":["import type { File } from \"@highstate/contract\"\nimport { type Input, type Output, output, secret } from \"@pulumi/pulumi\"\n\nexport type FileOptions = {\n isSecret?: boolean\n contentType?: Input<string>\n mode?: Input<number>\n}\n\n/**\n * Creates a file from a string input.\n * This file can then be passed to terminals/pages or other components.\n *\n * @param name The name of the file.\n * @param content The content of the file.\n * @param options Additional options for the file.\n */\nexport function fileFromString(\n name: Input<string>,\n content: Input<string>,\n { contentType = \"text/plain\", isSecret = false, mode }: FileOptions = {},\n): Output<File> {\n return output({\n meta: {\n name,\n contentType,\n size: output(content).apply(content => Buffer.byteLength(content, \"utf8\")),\n mode,\n },\n content: {\n type: \"embedded\",\n value: isSecret ? secret(content) : content,\n },\n })\n}\n\n/**\n * Creates a file from a buffer input.\n * This file can then be passed to terminals/pages or other components.\n *\n * @param name The name of the file.\n * @param content The content of the file as a Buffer.\n * @param options Additional options for the file.\n */\nexport function fileFromBuffer(\n name: Input<string>,\n content: Buffer,\n { contentType = \"application/octet-stream\", isSecret = false, mode }: FileOptions = {},\n): Output<File> {\n // const base64Content = output(content).apply(\n // c => (console.log(\"fileFromBuffer\", c), c.toString(\"base64\")),\n // )\n const base64Content = content.toString(\"base64\")\n\n return output({\n meta: {\n name,\n contentType,\n size: output(content).apply(content => content.byteLength),\n mode,\n },\n content: {\n type: \"embedded\",\n isBinary: true,\n value: isSecret ? secret(base64Content) : base64Content,\n },\n })\n}\n","import { type Input, type Output, output, type Unwrap } 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 record of inputs.\n * The same as `Input<Record<string, Input<T>>>`, but more readable.\n */\nexport type InputRecord<T> = Input<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\ntype LeafValue = string | number | boolean | null | undefined\ntype IsUnknown<T> = unknown extends T ? (T extends unknown ? true : false) : false\n\n/**\n * The recursive input type for a value.\n */\nexport type DeepInput<T> = [T] extends [LeafValue]\n ? Input<T>\n : IsUnknown<T> extends true\n ? Input<unknown>\n : Input<{ [K in keyof T]: DeepInput<T[K]> }>\n\n/**\n * Transforms an input value to a promise that resolves to the unwrapped value.\n *\n * @param input The input value to transform.\n * @returns A promise that resolves to the unwrapped value.\n */\nexport function toPromise<T>(input: Input<T>): Promise<Unwrap<T>> {\n return new Promise(resolve => output(input).apply(resolve))\n}\n\n/**\n * Receives an item and a collection, and returns an array containing the item and the collection.\n *\n * Excludes the item if it is undefined.\n *\n * @param item The single item input.\n * @param collection The collection of items input.\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\n/**\n * The same as `normalize`, but accepts inputs and returns output.\n *\n * @param item The single item input.\n * @param collection The collection of items input.\n */\nexport function normalizeInputs<T>(\n item: Input<T> | undefined,\n collection: InputArray<T> | undefined,\n): Output<Unwrap<T>[]> {\n return (\n output({ item, collection })\n //\n .apply(({ item, collection }) => normalize(item, collection)) as Output<Unwrap<T>[]>\n )\n}\n\n/**\n * The convenience function to normalize inputs and map them to a new type.\n *\n * @param item The single item input.\n * @param collection The collection of items input.\n * @param mapFn The function to map each item to a new type.\n */\nexport function normalizeInputsAndMap<T, U>(\n item: Input<T> | undefined,\n collection: InputArray<T> | undefined,\n mapFn: (value: Unwrap<T>) => U,\n): Output<U[]> {\n return normalizeInputs(item, collection).apply(values => values.map(mapFn))\n}\n\n/**\n * Applies a function to the input and returns an output.\n *\n * Can be used in `remeda` pipelines.\n *\n * @param fn The function to apply to the input.\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","/** biome-ignore-all lint/suspicious/noExplicitAny: здесь орать запрещено */\n\nimport type { IsEmptyObject } from \"type-fest\"\nimport { pathToFileURL } from \"node:url\"\nimport {\n type ComponentInput,\n type ComponentInputSpec,\n camelCaseToHumanReadable,\n compact,\n decompact,\n HighstateConfigKey,\n type InstanceInput,\n type InstanceStatusField,\n type InstanceStatusFieldValue,\n type PartialKeys,\n parseArgumentValue,\n parseInstanceId,\n runtimeSchema,\n type TriggerInvocation,\n type Unit,\n type UnitArtifact,\n type UnitConfig,\n type UnitInputReference,\n type UnitPage,\n type UnitTerminal,\n type UnitTrigger,\n type UnitWorker,\n unitArtifactSchema,\n unitConfigSchema,\n type VersionedName,\n z,\n} from \"@highstate/contract\"\nimport {\n Config,\n type Input,\n type Output,\n output,\n secret as pulumiSecret,\n StackReference,\n type Unwrap,\n} from \"@pulumi/pulumi\"\nimport { mapValues } from \"remeda\"\nimport { type DeepInput, toPromise } from \"./utils\"\n\ntype StatusField<TArgName extends string = string> = Omit<\n InstanceStatusField,\n \"complementaryTo\" | \"meta\"\n> & {\n meta?: PartialKeys<InstanceStatusField[\"meta\"], \"title\">\n complementaryTo?: TArgName\n}\n\ntype ExtraOutputs<TArgName extends string = string> = {\n $statusFields?:\n | Input<\n Record<\n string,\n DeepInput<Omit<StatusField<TArgName>, \"name\"> | InstanceStatusFieldValue | undefined>\n >\n >\n | Input<DeepInput<StatusField<TArgName> | undefined>[]>\n\n $terminals?:\n | Input<Record<string, DeepInput<Omit<UnitTerminal, \"name\"> | undefined>>>\n | Input<DeepInput<UnitTerminal | undefined>[]>\n\n $pages?:\n | Input<Record<string, DeepInput<Omit<UnitPage, \"name\"> | undefined>>>\n | Input<DeepInput<UnitPage | undefined>[]>\n\n $triggers?:\n | Input<Record<string, DeepInput<Omit<UnitTrigger, \"name\"> | undefined>>>\n | Input<DeepInput<UnitTrigger | undefined>[]>\n\n $workers?:\n | Input<Record<string, DeepInput<Omit<UnitWorker, \"name\"> | undefined>>>\n | Input<DeepInput<UnitWorker | undefined>[]>\n}\n\ntype OutputMapToDeepInputMap<\n T extends Record<string, unknown>,\n TArgName extends string,\n> = IsEmptyObject<T> extends true\n ? ExtraOutputs\n : { [K in keyof T]: DeepInput<T[K]> } & ExtraOutputs<TArgName>\n\ninterface UnitContext<\n TArgs extends Record<string, unknown>,\n TInputs extends Record<string, unknown>,\n TOutputs extends Record<string, unknown>,\n TSecrets extends Record<string, unknown>,\n> {\n args: TArgs\n instanceId: string\n type: string\n name: string\n\n secrets: {\n [K in keyof TSecrets]: undefined extends TSecrets[K]\n ? Output<NonNullable<TSecrets[K]>> | undefined\n : Output<TSecrets[K]>\n }\n\n getSecret<K extends keyof TSecrets>(\n this: void,\n name: K,\n ): Output<NonNullable<TSecrets[K]> | undefined>\n\n getSecret<K extends keyof TSecrets>(\n this: void,\n name: K,\n factory: () => Input<NonNullable<TSecrets[K]>>,\n ): Output<NonNullable<TSecrets[K]>>\n\n inputs: TInputs\n invokedTriggers: TriggerInvocation[]\n\n outputs(\n this: void,\n outputs?: OutputMapToDeepInputMap<TOutputs, keyof TArgs & string>,\n ): Promise<unknown>\n}\n\n// z.output since the values are validated/transformed and passed to the user\ntype InputSpecToWrappedValue<T extends ComponentInputSpec> = T[2] extends true\n ? // we have to wrap the array in Output since we don't know how many items will be returned by each multiple input\n Output<NonNullable<z.output<T[0][\"schema\"]>>[]>\n : T[1] extends true\n ? Output<NonNullable<z.output<T[0][\"schema\"]>>>\n : Output<NonNullable<z.output<T[0][\"schema\"]>>> | undefined\n\n// z.input since the values are passed from the user and should be validated/transformed before returning from the unit\ntype OutputSpecToValue<T extends ComponentInputSpec> = T[2] extends true\n ? T[1] extends true\n ? NonNullable<z.input<T[0][\"schema\"]>>[]\n : NonNullable<z.input<T[0][\"schema\"]>>[] | undefined\n : T[1] extends true\n ? NonNullable<z.input<T[0][\"schema\"]>>\n : NonNullable<z.input<T[0][\"schema\"]>> | undefined\n\nconst stackRefMap = new Map<string, StackReference>()\n\nlet instanceId: string | undefined\nlet instanceName: string | undefined\nlet importBaseUrl: URL | undefined\n\n/**\n * Returns the current unit instance id.\n *\n * Only available after calling `forUnit` function.\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\n/**\n * Returns the current unit instance name.\n */\nexport function getUnitInstanceName(): string {\n if (!instanceName) {\n throw new Error(`Instance name is not set. Did you call \"forUnit\" function?`)\n }\n\n return instanceName\n}\n\n/**\n * Returns the base URL for dynamic imports.\n */\nexport function getImportBaseUrl(): URL {\n if (!importBaseUrl) {\n throw new Error(`Import base URL is not set. Did you call \"forUnit\" function?`)\n }\n\n return importBaseUrl\n}\n\n/**\n * Returns a comment that can be used in resources to indicate that they are managed by Highstate.\n */\nexport function getResourceComment(): string {\n return `Managed by Highstate (${getUnitInstanceId()})`\n}\n\nfunction getStackRef(config: UnitConfig, input: InstanceInput) {\n const [instanceType] = parseInstanceId(input.instanceId)\n const stateId = config.stateIdMap[input.instanceId]\n if (!stateId) {\n throw new Error(`State ID for instance \"${input.instanceId}\" not found in the unit config.`)\n }\n\n const key = `organization/${instanceType}/${stateId}`\n let stackRef = stackRefMap.get(key)\n\n if (!stackRef) {\n stackRef = new StackReference(key)\n stackRefMap.set(key, stackRef)\n }\n\n return stackRef\n}\n\nfunction getOutput(\n config: UnitConfig,\n unit: Unit,\n inputName: string,\n input: ComponentInput,\n refs: UnitInputReference[],\n) {\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: UnitInputReference) => {\n const value = getStackRef(config, ref).requireOutput(ref.output)\n\n return value.apply(value => {\n if (ref.inclusion) {\n if (value === null || value === undefined || typeof value !== \"object\") {\n throw new Error(\n `Cannot extract field \"${ref.inclusion.field}\" from non-object output \"${ref.output}\" of instance \"${ref.instanceId}\".`,\n )\n }\n\n value = (value as Record<string, unknown>)[ref.inclusion.field]\n }\n\n const schema = Array.isArray(value) ? entity.schema.array() : entity.schema\n const result = schema.safeParse(value)\n\n if (!result.success) {\n throw new Error(\n `Invalid output \"${ref.output}\" from \"${ref.instanceId}\" for input \"${inputName}\": ${result.error.message}`,\n )\n }\n\n if (Array.isArray(value)) {\n return value\n }\n\n return input.multiple ? [value] : value\n })\n }\n\n const _getDecompactedOutput = (ref: UnitInputReference) => {\n return _getOutput(ref).apply(decompact)\n }\n\n const values = output(refs.map(_getDecompactedOutput)).apply(values => values.flat())\n\n if (!input.multiple) {\n return values.apply(values => values[0])\n }\n\n return values\n}\n\nexport function forUnit<\n TType extends VersionedName,\n TArgs extends Record<string, z.ZodType>,\n TInputs extends Record<string, ComponentInputSpec>,\n TOutputs extends Record<string, ComponentInputSpec>,\n TSecrets extends Record<string, z.ZodType>,\n>(\n unit: Unit<TType, TArgs, TInputs, TOutputs, TSecrets>,\n): UnitContext<\n { [K in keyof TArgs]: z.output<TArgs[K]> },\n { [K in keyof TInputs]: InputSpecToWrappedValue<TInputs[K]> },\n { [K in keyof TOutputs]: OutputSpecToValue<TOutputs[K]> },\n { [K in keyof TSecrets]: z.output<TSecrets[K]> }\n> {\n const config = new Config()\n const rawHSConfig = config.requireObject(HighstateConfigKey.Config)\n const hsConfig = unitConfigSchema.parse(rawHSConfig)\n\n const rawHsSecrets = config\n .requireSecretObject(HighstateConfigKey.Secrets)\n .apply(secrets => z.record(z.string(), z.unknown()).parse(secrets))\n\n const args = mapValues(unit.model.args, (arg, argName) => {\n const value = parseArgumentValue(hsConfig.args[argName])\n const result = arg[runtimeSchema]!.safeParse(value)\n\n if (!result.success) {\n throw new Error(`Invalid argument \"${argName}\": ${z.prettifyError(result.error)}`)\n }\n\n return result.data\n })\n\n const secrets = mapValues(unit.model.secrets, (secret, secretName) => {\n const hasValue = hsConfig.secretNames.includes(secretName)\n\n if (!hasValue && !secret.required) {\n return secret.schema.default ? pulumiSecret(secret.schema.default) : undefined\n }\n\n if (!hasValue && secret.required) {\n throw new Error(`Secret \"${secretName}\" is required but not provided.`)\n }\n\n return rawHsSecrets[secretName].apply(rawValue => {\n const value = parseArgumentValue(rawValue)\n const result = secret[runtimeSchema]!.safeParse(value)\n\n if (!result.success) {\n throw new Error(`Invalid secret \"${secretName}\": ${z.prettifyError(result.error)}`)\n }\n\n return pulumiSecret(result.data)\n })\n })\n\n const inputs = mapValues(unit.model.inputs, (input, inputName) => {\n const value = hsConfig.inputs[inputName]\n\n if (!value) {\n if (input.multiple) {\n return output([])\n }\n\n return undefined\n }\n\n return getOutput(hsConfig, unit as unknown as Unit, inputName, input, value)\n })\n\n const [type, name] = parseInstanceId(hsConfig.instanceId)\n\n instanceId = hsConfig.instanceId\n instanceName = name\n importBaseUrl = pathToFileURL(hsConfig.importBasePath)\n\n return {\n instanceId: hsConfig.instanceId,\n type,\n name,\n\n args: args as any,\n secrets: secrets as any,\n inputs: inputs as any,\n invokedTriggers: hsConfig.invokedTriggers,\n\n getSecret: (<K extends keyof TSecrets>(\n name: K,\n factory?: () => Input<NonNullable<TSecrets[K]>>,\n ) => {\n if (!factory) {\n return secrets[name as string]\n }\n\n const value = secrets[name as string] ?? pulumiSecret(factory())\n secrets[name as string] = value\n\n return value\n }) as any,\n\n outputs: async (outputs: any = {}) => {\n const result: any = mapValues(outputs, (outputValue, outputName) => {\n if (outputName === \"$statusFields\") {\n return output(outputValue).apply(mapStatusFields)\n }\n\n if (outputName === \"$pages\") {\n return output(outputValue).apply(mapPages)\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 === \"$workers\") {\n return output(outputValue).apply(mapWorkers)\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(\n `Output \"${outputName}\" not found in the unit \"${unit.model.type}\", but was passed to outputs(...).`,\n )\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}\". It looks like a bug in the unit definition.`,\n )\n }\n\n return output(outputValue).apply(value => {\n const schema = outputModel.multiple ? entity.schema.array() : entity.schema\n const result = schema.safeParse(value)\n\n if (!result.success) {\n throw new Error(\n `Invalid value for output \"${outputName}\" of type \"${outputModel.type}\": ${z.prettifyError(\n result.error,\n )}`,\n )\n }\n\n return compact(result.data)\n })\n })\n\n // wait for all outputs to resolve before collecting secrets and artifacts\n await Promise.all(Object.values(result).map(o => toPromise(o)))\n\n result.$secrets = secrets\n\n // collect artifacts from all outputs\n const artifactsMap: Record<string, UnitArtifact[]> = {}\n for (const [outputName, outputValue] of Object.entries(outputs)) {\n const resolvedValue = await toPromise(outputValue)\n const artifacts = extractObjectsFromValue(unitArtifactSchema, resolvedValue)\n if (artifacts.length > 0) {\n artifactsMap[outputName] = artifacts\n }\n }\n\n if (Object.keys(artifactsMap).length > 0) {\n result.$artifacts = artifactsMap\n }\n\n return result\n },\n }\n}\n\nfunction mapStatusFields(status: Unwrap<ExtraOutputs[\"$statusFields\"]>): InstanceStatusField[] {\n if (!status) {\n return []\n }\n\n if (Array.isArray(status)) {\n return status\n .filter((field): field is NonNullable<StatusField> => field?.value !== undefined)\n .map(field => {\n return {\n name: field.name,\n meta: {\n title: field.meta?.title ?? camelCaseToHumanReadable(field.name),\n },\n value: field.value,\n }\n })\n }\n\n return Object.entries(status)\n .map(([name, field]) => {\n if (!field) {\n return undefined\n }\n\n if (\n typeof field === \"string\" ||\n typeof field === \"number\" ||\n typeof field === \"boolean\" ||\n Array.isArray(field)\n ) {\n return {\n name,\n meta: {\n title: camelCaseToHumanReadable(name),\n },\n value: field,\n }\n }\n\n return {\n ...field,\n meta: {\n ...field.meta,\n title: field.meta?.title ?? camelCaseToHumanReadable(name),\n },\n name,\n }\n })\n .filter((field): field is InstanceStatusField => field?.value !== undefined)\n}\n\nfunction mapPages(pages: Unwrap<ExtraOutputs[\"$pages\"]>): Output<UnitPage[]> {\n if (!pages) {\n return output([])\n }\n\n if (!Array.isArray(pages)) {\n pages = Object.entries(pages).map(([name, page]) => {\n if (!page) {\n return undefined\n }\n\n return { ...page, name }\n })\n }\n\n return output(pages.filter((page): page is NonNullable<UnitPage> => !!page))\n}\n\nfunction mapTerminals(terminals: Unwrap<ExtraOutputs[\"$terminals\"]>): Output<UnitTerminal[]> {\n if (!terminals) {\n return output([])\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 output(terminals.filter((terminal): terminal is NonNullable<UnitTerminal> => !!terminal))\n}\n\nfunction mapTriggers(triggers: Unwrap<ExtraOutputs[\"$triggers\"]>): Output<UnitTrigger[]> {\n if (!triggers) {\n return output([])\n }\n\n if (!Array.isArray(triggers)) {\n triggers = Object.entries(triggers).map(([name, trigger]) => {\n if (!trigger) {\n return undefined\n }\n\n return { ...trigger, name }\n })\n }\n\n return output(triggers.filter((trigger): trigger is NonNullable<UnitTrigger> => !!trigger))\n}\n\nfunction mapWorkers(workers: Unwrap<ExtraOutputs[\"$workers\"]>): Output<Unwrap<UnitWorker>[]> {\n if (!workers) {\n return output([])\n }\n\n if (!Array.isArray(workers)) {\n workers = Object.entries(workers).map(([name, worker]) => {\n if (!worker) {\n return undefined\n }\n\n return { ...worker, name }\n })\n }\n\n return output(workers.filter((worker): worker is NonNullable<Unwrap<UnitWorker>> => !!worker))\n}\n\n/**\n * Extracts all objects with the specified schema from a value.\n */\nfunction extractObjectsFromValue<TSchema extends z.ZodType>(\n schema: TSchema,\n data: unknown,\n): z.infer<TSchema>[] {\n const result: z.infer<TSchema>[] = []\n\n function traverse(obj: unknown): void {\n if (obj === null || obj === undefined || typeof obj !== \"object\") {\n return\n }\n\n if (Array.isArray(obj)) {\n for (const item of obj) {\n traverse(item)\n }\n return\n }\n\n const parseResult = schema.safeParse(obj)\n if (parseResult.success) {\n result.push(parseResult.data)\n return\n }\n\n // recursively traverse all properties\n for (const value of Object.values(obj)) {\n traverse(value)\n }\n }\n\n traverse(data)\n return result\n}\n"]}