@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/dist/index.js +279 -149
- package/package.json +13 -13
- package/src/entity.ts +108 -0
- package/src/file.ts +87 -49
- package/src/index.ts +2 -0
- package/src/resource-hooks.ts +14 -0
- package/src/unit.ts +150 -110
- package/LICENSE +0 -21
- package/dist/index.js.map +0 -1
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
|
-
|
|
10
|
-
|
|
10
|
+
type EntityValue,
|
|
11
|
+
type EntityValueInput,
|
|
11
12
|
HighstateConfigKey,
|
|
12
|
-
|
|
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
|
|
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
|
-
?
|
|
127
|
-
Output<NonNullable<z.output<T[0]["schema"]>>[]>
|
|
133
|
+
? NonNullable<EntityValue<T[0]>>[]
|
|
128
134
|
: T[1] extends true
|
|
129
|
-
?
|
|
130
|
-
:
|
|
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<
|
|
136
|
-
: NonNullable<
|
|
141
|
+
? NonNullable<EntityValueInput<T[0]>>[]
|
|
142
|
+
: NonNullable<EntityValueInput<T[0]>>[] | undefined
|
|
137
143
|
: T[1] extends true
|
|
138
|
-
? NonNullable<
|
|
139
|
-
: NonNullable<
|
|
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
|
|
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
|
|
208
|
-
config: UnitConfig,
|
|
208
|
+
function getInputValue(
|
|
209
209
|
unit: Unit,
|
|
210
210
|
inputName: string,
|
|
211
211
|
input: ComponentInput,
|
|
212
|
-
|
|
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
|
|
220
|
-
const value =
|
|
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
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
228
|
+
if (Array.isArray(result.data)) {
|
|
229
|
+
return result.data
|
|
230
|
+
}
|
|
253
231
|
|
|
254
|
-
|
|
232
|
+
return input.multiple ? [result.data] : [result.data]
|
|
233
|
+
})
|
|
255
234
|
|
|
256
235
|
if (!input.multiple) {
|
|
257
|
-
return values
|
|
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.
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
282
|
+
const rawValue = hsConfig.secretValues[secretName]
|
|
283
|
+
const value = parseArgumentValue(rawValue)
|
|
284
|
+
const result = secret[runtimeSchema]!.safeParse(value)
|
|
310
285
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
286
|
+
if (!result.success) {
|
|
287
|
+
throw new Error(`Invalid secret "${secretName}": ${z.prettifyError(result.error)}`)
|
|
288
|
+
}
|
|
314
289
|
|
|
315
|
-
|
|
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
|
|
298
|
+
return []
|
|
325
299
|
}
|
|
326
300
|
|
|
327
301
|
return undefined
|
|
328
302
|
}
|
|
329
303
|
|
|
330
|
-
return
|
|
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
|
|
344
|
+
const resolvedOutputs = await toPromise(outputs)
|
|
345
|
+
|
|
346
|
+
const result: any = mapValues(resolvedOutputs, (outputValue, outputName) => {
|
|
365
347
|
if (outputName === "$statusFields") {
|
|
366
|
-
return
|
|
348
|
+
return mapStatusFields(outputValue)
|
|
367
349
|
}
|
|
368
350
|
|
|
369
351
|
if (outputName === "$pages") {
|
|
370
|
-
return
|
|
352
|
+
return mapPages(outputValue)
|
|
371
353
|
}
|
|
372
354
|
|
|
373
355
|
if (outputName === "$terminals") {
|
|
374
|
-
return
|
|
356
|
+
return mapTerminals(outputValue)
|
|
375
357
|
}
|
|
376
358
|
|
|
377
359
|
if (outputName === "$triggers") {
|
|
378
|
-
return
|
|
360
|
+
return mapTriggers(outputValue)
|
|
379
361
|
}
|
|
380
362
|
|
|
381
363
|
if (outputName === "$workers") {
|
|
382
|
-
return
|
|
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
|
-
|
|
404
|
-
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"]}
|