@highstate/pulumi 0.9.15 → 0.9.18

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "sourceHashes": {
3
- "./dist/index.js": "633a08c5c489e757e251aea53802531d602cbc505b32ef20d08092b62c746f6f"
3
+ "./dist/index.js": 938090806
4
4
  }
5
5
  }
package/dist/index.js CHANGED
@@ -1,38 +1,31 @@
1
- // src/index.ts
2
- export * from "@pulumi/pulumi";
3
-
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";
1
+ import { getStack, secret, output, Config, all, StackReference } from '@pulumi/pulumi';
2
+ export * from '@pulumi/pulumi';
3
+ import { HighstateSignature, getInstanceId, camelCaseToHumanReadable, unitArtifactSchema, unitSecretSchema, parseInstanceId } from '@highstate/contract';
4
+ import { mapValues, pipe, pickBy } from 'remeda';
5
+ import { Ajv } from 'ajv';
19
6
 
20
- // src/secret.ts
21
- import { secret } from "@pulumi/pulumi";
22
- var createdSecrets = {};
23
- function getOrCreateSecret(secrets, key, create) {
24
- return secrets[key].apply((value) => {
25
- if (value !== void 0) {
26
- createdSecrets[key] = value;
27
- return value;
28
- }
29
- const secretValue = createdSecrets[key] ?? secret(create());
30
- createdSecrets[key] = secretValue;
31
- return secretValue;
32
- });
7
+ // src/index.ts
8
+ var updatedSecretValues = {};
9
+ function ensureSecretValue(secret2, create) {
10
+ return {
11
+ [HighstateSignature.Secret]: true,
12
+ id: secret2.id,
13
+ value: secret2.value.apply((value) => {
14
+ if (value !== void 0) {
15
+ return value;
16
+ }
17
+ updatedSecretValues[secret2.id] = secret(create());
18
+ return updatedSecretValues[secret2.id];
19
+ })
20
+ };
33
21
  }
34
- function storeSecret(_secrets, key, value) {
35
- createdSecrets[key] = value;
22
+ function updateSecretValue(secret2, value) {
23
+ updatedSecretValues[secret2.id] = secret(value);
24
+ return {
25
+ [HighstateSignature.Secret]: true,
26
+ id: secret2.id,
27
+ value: output(updatedSecretValues[secret2.id])
28
+ };
36
29
  }
37
30
 
38
31
  // src/unit.ts
@@ -68,12 +61,16 @@ function getOutput(unit, input, refs) {
68
61
  const _getOutput = (ref) => {
69
62
  const value = getStackRef(ref).requireOutput(ref.output);
70
63
  return value.apply((value2) => {
71
- let schema = entity.schema;
72
- if (input.multiple) {
73
- schema = Type.Union([schema, Type.Array(schema)]);
74
- }
75
- if (!ajv.validate(schema, value2)) {
76
- throw new Error(`Invalid output for '${input.type}': ${ajv.errorsText()}`);
64
+ if (Array.isArray(value2)) {
65
+ for (const [index, item] of value2.entries()) {
66
+ if (!ajv.validate(entity.schema, item)) {
67
+ throw new Error(`Invalid output for '${input.type}[${index}]': ${ajv.errorsText()}`);
68
+ }
69
+ }
70
+ } else {
71
+ if (!ajv.validate(entity.schema, value2)) {
72
+ throw new Error(`Invalid output for '${input.type}': ${ajv.errorsText()}`);
73
+ }
77
74
  }
78
75
  if (Array.isArray(value2)) {
79
76
  return value2;
@@ -89,9 +86,7 @@ function getOutput(unit, input, refs) {
89
86
  }
90
87
  function isAnyOfSchema(schema, itemType) {
91
88
  if (schema.anyOf) {
92
- return Object.values(schema.anyOf).every(
93
- (schema2) => isAnyOfSchema(schema2, itemType)
94
- );
89
+ return Object.values(schema.anyOf).every((schema2) => isAnyOfSchema(schema2, itemType));
95
90
  }
96
91
  return schema.type === itemType;
97
92
  }
@@ -127,15 +122,38 @@ function forUnit(unit) {
127
122
  const args = mapValues(unit.model.args, (arg, argName) => {
128
123
  switch (true) {
129
124
  case isStringSchema(arg.schema): {
130
- return arg.required ? config.require(argName) : config.get(argName) ?? arg.schema.default;
125
+ if (arg.required) {
126
+ return config.require(argName);
127
+ }
128
+ return config.get(argName) || arg.schema.default;
131
129
  }
132
130
  case isNumberSchema(arg.schema): {
133
- return arg.required ? config.requireNumber(argName) : config.getNumber(argName) ?? arg.schema.default;
131
+ if (arg.required) {
132
+ return config.requireNumber(argName);
133
+ }
134
+ const value = config.get(argName);
135
+ if (!value) {
136
+ return arg.schema.default;
137
+ }
138
+ return config.getNumber(argName) ?? arg.schema.default;
134
139
  }
135
140
  case isBooleanSchema(arg.schema): {
136
- return arg.required ? config.requireBoolean(argName) : config.getBoolean(argName) ?? arg.schema.default;
141
+ if (arg.required) {
142
+ return config.requireBoolean(argName);
143
+ }
144
+ const value = config.get(argName);
145
+ if (!value) {
146
+ return arg.schema.default;
147
+ }
148
+ return config.getBoolean(argName) ?? arg.schema.default;
137
149
  }
138
150
  default: {
151
+ if (!arg.required) {
152
+ const value2 = config.get(argName);
153
+ if (!value2) {
154
+ return arg.schema.default;
155
+ }
156
+ }
139
157
  const value = arg.required ? config.requireObject(argName) : config.getObject(argName);
140
158
  if (value === void 0) return arg.schema.default;
141
159
  if (!ajv.validate(arg.schema, value)) {
@@ -145,28 +163,38 @@ function forUnit(unit) {
145
163
  }
146
164
  }
147
165
  });
148
- const secrets = output(
149
- mapValues(unit.model.secrets, (secret3, secretName) => {
150
- switch (true) {
151
- case isStringSchema(secret3.schema): {
152
- return secret3.required ? config.requireSecret(secretName) : config.getSecret(secretName);
153
- }
154
- case isNumberSchema(secret3.schema): {
155
- return secret3.required ? config.requireSecretNumber(secretName) : config.getSecretNumber(secretName);
156
- }
157
- case isBooleanSchema(secret3.schema): {
158
- return secret3.required ? config.requireSecretBoolean(secretName) : config.getSecretBoolean(secretName);
159
- }
160
- default: {
161
- const value = secret3.required ? config.requireSecretObject(secretName) : config.getSecretObject(secretName);
162
- if (!ajv.validate(secret3.schema, value)) {
163
- throw new Error(`Invalid secret for '${secretName}': ${ajv.errorsText()}`);
164
- }
165
- return value;
166
+ const secretIds = config.requireObject("$secretIds");
167
+ const getSecretValue = (secretName, secret2) => {
168
+ switch (true) {
169
+ case isStringSchema(secret2.schema): {
170
+ return secret2.required ? config.requireSecret(secretName) : config.getSecret(secretName);
171
+ }
172
+ case isNumberSchema(secret2.schema): {
173
+ return secret2.required ? config.requireSecretNumber(secretName) : config.getSecretNumber(secretName);
174
+ }
175
+ case isBooleanSchema(secret2.schema): {
176
+ return secret2.required ? config.requireSecretBoolean(secretName) : config.getSecretBoolean(secretName);
177
+ }
178
+ default: {
179
+ const value = secret2.required ? config.requireSecretObject(secretName) : config.getSecretObject(secretName);
180
+ if (!ajv.validate(secret2.schema, value)) {
181
+ throw new Error(`Invalid secret for '${secretName}': ${ajv.errorsText()}`);
166
182
  }
183
+ return value;
167
184
  }
168
- })
169
- );
185
+ }
186
+ };
187
+ const secrets = mapValues(unit.model.secrets, (secret2, secretName) => {
188
+ const secretId = secretIds[secretName];
189
+ if (!secretId) {
190
+ throw new Error(`Secret '${secretName}' not found in the config.`);
191
+ }
192
+ return {
193
+ [HighstateSignature.Secret]: true,
194
+ id: secretId,
195
+ value: secret2.required ? config.requireSecret(secretName) : output(getSecretValue(secretName, secret2))
196
+ };
197
+ });
170
198
  const inputs = mapValues(unit.model.inputs, (input, inputName) => {
171
199
  const value = input.required ? config.requireObject(`input.${inputName}`) : config.getObject(`input.${inputName}`);
172
200
  if (!value) {
@@ -189,15 +217,12 @@ function forUnit(unit) {
189
217
  invokedTriggers: config.getObject("$invokedTriggers") ?? [],
190
218
  outputs: async (outputs = {}) => {
191
219
  const result = mapValues(outputs, (outputValue, outputName) => {
192
- if (outputName === "$status") {
193
- return output(outputValue).apply(mapStatus);
220
+ if (outputName === "$statusFields") {
221
+ return output(outputValue).apply(mapStatusFields);
194
222
  }
195
223
  if (outputName === "$pages") {
196
224
  return output(outputValue).apply(mapPages);
197
225
  }
198
- if (outputName === "$files") {
199
- return output(outputValue).apply(mapFiles);
200
- }
201
226
  if (outputName === "$terminals") {
202
227
  return output(outputValue).apply(mapTerminals);
203
228
  }
@@ -224,7 +249,7 @@ function forUnit(unit) {
224
249
  }
225
250
  return void 0;
226
251
  }
227
- const schema = outputModel.multiple ? Type.Array(entity.schema) : entity.schema;
252
+ const schema = outputModel.multiple ? entity.schema.array() : entity.schema;
228
253
  if (!ajv.validate(schema, value)) {
229
254
  throw new Error(`Invalid output for '${outputName}': ${ajv.errorsText()}`);
230
255
  }
@@ -232,8 +257,32 @@ function forUnit(unit) {
232
257
  });
233
258
  });
234
259
  await Promise.all(Object.values(result).map((o) => outputToPromise(o)));
235
- if (Object.keys(createdSecrets).length > 0) {
236
- result.$secrets = createdSecrets;
260
+ result.$secrets = updatedSecretValues;
261
+ const secretsMap = {};
262
+ for (const [outputName, outputValue] of Object.entries(outputs)) {
263
+ if (!outputName.startsWith("$")) {
264
+ const resolvedValue = await outputToPromise(outputValue);
265
+ const secrets2 = extractObjectsFromValue(unitSecretSchema, resolvedValue);
266
+ if (secrets2.length > 0) {
267
+ secretsMap[outputName] = secrets2;
268
+ }
269
+ }
270
+ }
271
+ const artifactsMap = {};
272
+ for (const [outputName, outputValue] of Object.entries(outputs)) {
273
+ if (!outputName.startsWith("$")) {
274
+ const resolvedValue = await outputToPromise(outputValue);
275
+ const artifacts = extractObjectsFromValue(unitArtifactSchema, resolvedValue);
276
+ if (artifacts.length > 0) {
277
+ artifactsMap[outputName] = artifacts;
278
+ }
279
+ }
280
+ }
281
+ if (Object.keys(artifactsMap).length > 0) {
282
+ result.$exportedArtifacts = artifactsMap;
283
+ }
284
+ if (Object.keys(secretsMap).length > 0) {
285
+ result.$exportedSecretIds = mapValues(secretsMap, (v) => v.map((secret2) => secret2.id));
237
286
  }
238
287
  return result;
239
288
  }
@@ -242,21 +291,42 @@ function forUnit(unit) {
242
291
  function outputToPromise(o) {
243
292
  return new Promise((resolve) => output(o).apply(resolve));
244
293
  }
245
- function mapStatus(status) {
294
+ function mapStatusFields(status) {
246
295
  if (!status) {
247
296
  return [];
248
297
  }
249
298
  if (Array.isArray(status)) {
250
- return status.filter((field) => !!field?.value);
299
+ return status.filter((field) => !!field?.value).map((field) => {
300
+ return {
301
+ name: field.name,
302
+ meta: {
303
+ title: field.meta?.title ?? camelCaseToHumanReadable(field.name)
304
+ },
305
+ value: field.value
306
+ };
307
+ });
251
308
  }
252
309
  return Object.entries(status).map(([name, field]) => {
253
310
  if (!field) {
254
311
  return void 0;
255
312
  }
256
313
  if (typeof field === "string" || typeof field === "number" || typeof field === "boolean" || Array.isArray(field)) {
257
- return { name, value: field };
314
+ return {
315
+ name,
316
+ meta: {
317
+ title: camelCaseToHumanReadable(name)
318
+ },
319
+ value: field
320
+ };
258
321
  }
259
- return { ...field, name };
322
+ return {
323
+ ...field,
324
+ meta: {
325
+ ...field.meta,
326
+ title: field.meta?.title ?? camelCaseToHumanReadable(name)
327
+ },
328
+ name
329
+ };
260
330
  }).filter((field) => !!field?.value);
261
331
  }
262
332
  function mapPages(pages) {
@@ -275,7 +345,10 @@ function fileFromString(name, content, contentType = "text/plain", isSecret = fa
275
345
  contentType,
276
346
  size: Buffer.byteLength(content, "utf8")
277
347
  },
278
- content: isSecret ? secret2(content) : content
348
+ content: {
349
+ type: "embedded",
350
+ value: isSecret ? secret(content) : content
351
+ }
279
352
  };
280
353
  }
281
354
  function fileFromBuffer(name, content, contentType = "application/octet-stream", isSecret = false) {
@@ -286,12 +359,12 @@ function fileFromBuffer(name, content, contentType = "application/octet-stream",
286
359
  size: content.byteLength,
287
360
  isBinary: true
288
361
  },
289
- content: isSecret ? secret2(content.toString("base64")) : content.toString("base64")
362
+ content: {
363
+ type: "embedded",
364
+ value: isSecret ? secret(content.toString("base64")) : content.toString("base64")
365
+ }
290
366
  };
291
367
  }
292
- function mapFiles(files) {
293
- return files?.filter((file) => !!file) ?? [];
294
- }
295
368
  function mapTerminals(terminals) {
296
369
  if (!terminals) {
297
370
  return [];
@@ -305,21 +378,34 @@ function mapTerminals(terminals) {
305
378
  });
306
379
  }
307
380
  return terminals.filter((terminal) => !!terminal).map((terminal) => {
308
- if (!terminal.files) {
381
+ if (!terminal.spec.files) {
309
382
  return terminal;
310
383
  }
311
384
  return {
312
385
  ...terminal,
313
- files: pipe(
314
- terminal.files,
315
- mapValues((file) => {
316
- if (typeof file === "string") {
317
- return { content: file };
318
- }
319
- return file;
320
- }),
321
- pickBy((value) => !!value?.content)
322
- )
386
+ spec: {
387
+ ...terminal.spec,
388
+ files: pipe(
389
+ terminal.spec.files,
390
+ mapValues((file) => {
391
+ if (typeof file === "string") {
392
+ return {
393
+ meta: {
394
+ name: "content",
395
+ contentType: "text/plain",
396
+ size: Buffer.byteLength(file, "utf8")
397
+ },
398
+ content: {
399
+ type: "embedded",
400
+ value: file
401
+ }
402
+ };
403
+ }
404
+ return file;
405
+ }),
406
+ pickBy((value) => !!value)
407
+ )
408
+ }
323
409
  };
324
410
  });
325
411
  }
@@ -332,9 +418,30 @@ function mapTriggers(triggers) {
332
418
  }
333
419
  return Object.entries(triggers).filter(([, trigger]) => !!trigger).map(([name, trigger]) => ({ ...trigger, name }));
334
420
  }
335
-
336
- // src/utils.ts
337
- import { output as output2, all } from "@pulumi/pulumi";
421
+ function extractObjectsFromValue(schema, data) {
422
+ const result = [];
423
+ function traverse(obj) {
424
+ if (obj === null || obj === void 0 || typeof obj !== "object") {
425
+ return;
426
+ }
427
+ if (Array.isArray(obj)) {
428
+ for (const item of obj) {
429
+ traverse(item);
430
+ }
431
+ return;
432
+ }
433
+ const parseResult = schema.safeParse(obj);
434
+ if (parseResult.success) {
435
+ result.push(parseResult.data);
436
+ return;
437
+ }
438
+ for (const value of Object.values(obj)) {
439
+ traverse(value);
440
+ }
441
+ }
442
+ traverse(data);
443
+ return result;
444
+ }
338
445
  function flattenInputs(...values) {
339
446
  return all(values).apply((allValues) => {
340
447
  const result = [];
@@ -349,7 +456,7 @@ function flattenInputs(...values) {
349
456
  });
350
457
  }
351
458
  function mapInputs(array, fn) {
352
- return output2(array).apply((array2) => {
459
+ return output(array).apply((array2) => {
353
460
  return array2?.map((v, index) => fn(v, index, array2)) ?? [];
354
461
  });
355
462
  }
@@ -365,7 +472,7 @@ function mapOptional(input, func) {
365
472
  return func(input);
366
473
  }
367
474
  function toPromise(input) {
368
- return new Promise((resolve) => output2(input).apply(resolve));
475
+ return new Promise((resolve) => output(input).apply(resolve));
369
476
  }
370
477
  function singleton(factory) {
371
478
  let instance;
@@ -386,7 +493,7 @@ function providerFactory(factory) {
386
493
  };
387
494
  }
388
495
  function mergeInputObjects(...objects) {
389
- return output2(objects).apply((array) => {
496
+ return output(objects).apply((array) => {
390
497
  return Object.assign({}, ...array);
391
498
  });
392
499
  }
@@ -400,30 +507,12 @@ function normalize(item, collection) {
400
507
  return collection ?? [];
401
508
  }
402
509
  function apply(fn) {
403
- return (input) => output2(input).apply(fn);
510
+ return (input) => output(input).apply(fn);
404
511
  }
405
512
  function applyMap(fn) {
406
- return (input) => output2(input).apply((array) => array.map(fn));
513
+ return (input) => output(input).apply((array) => array.map(fn));
407
514
  }
408
- export {
409
- apply,
410
- applyMap,
411
- fileFromBuffer,
412
- fileFromString,
413
- flatMapInput,
414
- flattenInputs,
415
- forUnit,
416
- getOrCreateSecret,
417
- getResourceComment,
418
- getUnitInstanceId,
419
- getUnitInstanceName,
420
- mapInputs,
421
- mapOptional,
422
- mergeInputObjects,
423
- normalize,
424
- providerFactory,
425
- singleton,
426
- storeSecret,
427
- toPromise
428
- };
515
+
516
+ export { apply, applyMap, ensureSecretValue, fileFromBuffer, fileFromString, flatMapInput, flattenInputs, forUnit, getResourceComment, getUnitInstanceId, getUnitInstanceName, mapInputs, mapOptional, mergeInputObjects, normalize, providerFactory, singleton, toPromise, updateSecretValue };
517
+ //# sourceMappingURL=index.js.map
429
518
  //# sourceMappingURL=index.js.map