@terraforge/terraform 0.0.10 → 0.0.12

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 DELETED
@@ -1,1996 +0,0 @@
1
- // src/type-gen.ts
2
- import { camelCase, pascalCase } from "change-case";
3
- var tab = (indent) => {
4
- return " ".repeat(indent);
5
- };
6
- var generateTypes = (namespace, provider, resources, dataSources) => {
7
- return [
8
- generateImport("c", "@terraforge/core"),
9
- generateImport("t", "@terraforge/terraform"),
10
- "type _Record<T> = Record<string, T>",
11
- generateInstallHelperFunctions(namespace),
12
- generateProviderFactoryTypes(namespace, provider),
13
- generateResourceTypes(resources),
14
- generateDataSourceTypes(dataSources)
15
- ].join("\n\n");
16
- };
17
- var generateResourceTypes = (resources) => {
18
- return generateNamespace(resources, (name, prop, indent) => {
19
- const typeName = pascalCase(name);
20
- return [
21
- `${tab(indent)}export type ${typeName}Input = ${generatePropertyInputType(prop, indent)}`,
22
- `${tab(indent)}export type ${typeName}Output = ${generatePropertyOutputType(prop, indent)}`,
23
- `${tab(indent)}export class ${typeName} {`,
24
- `${tab(indent + 1)}constructor(parent: c.Group, id: string, props: ${typeName}Input, config?:c.ResourceConfig)`,
25
- generateClassProperties(prop, indent + 1),
26
- `${tab(indent)}}`
27
- ].join("\n\n");
28
- });
29
- };
30
- var generateDataSourceTypes = (dataSources) => {
31
- return generateNamespace(dataSources, (name, prop, indent) => {
32
- const typeName = pascalCase(name);
33
- return [
34
- `${tab(indent)}export type Get${typeName}Input = ${generatePropertyInputType(prop, indent)}`,
35
- `${tab(indent)}export type Get${typeName}Output = ${generatePropertyOutputType(prop, indent)}`,
36
- `${tab(indent)}export const get${typeName}:c.DataSourceFunction<Get${typeName}Input, Get${typeName}Output>`
37
- ].join("\n\n");
38
- });
39
- };
40
- var generateProviderFactoryTypes = (namespace, provider) => {
41
- const typeName = namespace.toLowerCase();
42
- return `export declare function ${typeName}(props: ${generatePropertyInputConst(provider, 0)}, config?: t.TerraformProviderConfig): t.TerraformProvider`;
43
- };
44
- var generateImport = (name, from) => {
45
- return `import * as ${name} from '${from}'`;
46
- };
47
- var generateInstallHelperFunctions = (namespace) => {
48
- const typeName = namespace.toLowerCase();
49
- return [
50
- `export declare namespace ${typeName} {`,
51
- `${tab(1)}export function install(props?: t.InstallProps): Promise<void>`,
52
- `${tab(1)}export function uninstall(props?: t.InstallProps): Promise<void>`,
53
- `${tab(1)}export function isInstalled(props?: t.InstallProps): Promise<boolean>`,
54
- `}`
55
- ].join("\n");
56
- };
57
- var generatePropertyInputConst = (prop, indent) => {
58
- return generateValue(prop, {
59
- depth: 0,
60
- indent: indent + 1,
61
- wrap: (v, _, ctx) => {
62
- return `${v}${ctx.depth === 1 ? "," : ""}`;
63
- },
64
- filter: () => true,
65
- optional: (p) => p.optional ?? false
66
- });
67
- };
68
- var generatePropertyInputType = (prop, indent) => {
69
- return generateValue(prop, {
70
- depth: 0,
71
- indent: indent + 1,
72
- wrap: (v, p, ctx) => {
73
- return ctx.depth > 0 ? p.optional ? `c.OptionalInput<${v}>` : `c.Input<${v}>` : v;
74
- },
75
- filter: (prop2) => !(prop2.computed && typeof prop2.optional === "undefined" && typeof prop2.required === "undefined"),
76
- optional: (p) => p.optional ?? false
77
- });
78
- };
79
- var generatePropertyOutputType = (prop, indent) => {
80
- return generateValue(prop, {
81
- depth: 0,
82
- indent: indent + 1,
83
- wrap: (v, p, ctx) => ctx.depth === 1 ? p.optional && !p.computed ? `c.OptionalOutput<${v}>` : `c.Output<${v}>` : v,
84
- filter: () => true,
85
- readonly: true,
86
- // required: true,
87
- optional: (p, ctx) => ctx.depth > 1 && p.optional && !p.computed || false
88
- });
89
- };
90
- var generateClassProperties = (prop, indent) => {
91
- if (prop.type !== "object") {
92
- return "";
93
- }
94
- return Object.entries(prop.properties).map(([name, prop2]) => {
95
- return [
96
- prop2.description ? [`
97
- `, ` `.repeat(indent), `/** `, prop2.description.trim(), " */", "\n"].join("") : "",
98
- ` `.repeat(indent),
99
- "readonly ",
100
- camelCase(name),
101
- // ctx.optional(prop, ctx) ? '?' : '',
102
- ": ",
103
- generateValue(prop2, {
104
- readonly: true,
105
- filter: () => true,
106
- optional: (p, ctx) => ctx.depth > 1 && p.optional && !p.computed || false,
107
- wrap: (v, p, ctx) => {
108
- return ctx.depth === 1 ? p.optional && !p.computed ? `c.OptionalOutput<${v}>` : `c.Output<${v}>` : v;
109
- },
110
- // ctx.depth === 1 ? `c.Output<${p.optional && !p.computed ? `${v} | undefined` : v}>` : v,
111
- indent: indent + 1,
112
- depth: 1
113
- })
114
- ].join("");
115
- }).join("\n");
116
- };
117
- var groupByNamespace = (resources, minLevel, maxLevel) => {
118
- const grouped = {};
119
- const types = Object.keys(resources).sort();
120
- for (const type of types) {
121
- const names = type.split("_");
122
- if (names.length < minLevel) {
123
- throw new Error(`Resource not properly namespaced: ${type}`);
124
- }
125
- let current = grouped;
126
- let count = Math.min(maxLevel, names.length - 1);
127
- while (count--) {
128
- const ns = camelCase(names.shift());
129
- if (!current[ns]) {
130
- current[ns] = {};
131
- }
132
- current = current[ns];
133
- }
134
- const name = pascalCase(names.join("_"));
135
- current[name] = type;
136
- }
137
- return grouped;
138
- };
139
- var generateNamespace = (resources, render) => {
140
- const grouped = groupByNamespace(resources, 1, 2);
141
- const renderNamespace = (name, group, indent) => {
142
- if (name === "default") {
143
- name = "$default";
144
- }
145
- if (typeof group === "string") {
146
- return render(name, resources[group], indent);
147
- }
148
- return [
149
- `${tab(indent)}export ${indent === 0 ? "declare " : ""}namespace ${name.toLowerCase()} {`,
150
- Object.entries(group).map(([name2, entry]) => {
151
- if (typeof entry !== "string") {
152
- return renderNamespace(name2, entry, indent + 1);
153
- } else {
154
- return render(name2, resources[entry], indent + 1);
155
- }
156
- }).join("\n"),
157
- `${tab(indent)}}`
158
- ].join("\n");
159
- };
160
- return Object.entries(grouped).map(([name, entry]) => {
161
- return renderNamespace(name, entry, 0);
162
- });
163
- };
164
- var generateValue = (prop, ctx) => {
165
- if (["string", "number", "boolean", "unknown"].includes(prop.type)) {
166
- return ctx.wrap(prop.type, prop, ctx);
167
- }
168
- if (prop.type === "array") {
169
- const type = generateValue(prop.item, { ...ctx, depth: ctx.depth + 1 });
170
- const array = ctx.readonly ? `ReadonlyArray<${type}>` : `Array<${type}>`;
171
- return ctx.wrap(array, prop, ctx);
172
- }
173
- if (prop.type === "record") {
174
- const type = generateValue(prop.item, { ...ctx, depth: ctx.depth + 1 });
175
- const record = ctx.readonly ? `Readonly<_Record<${type}>>` : `_Record<${type}>`;
176
- return ctx.wrap(record, prop, ctx);
177
- }
178
- if (prop.type === "object" || prop.type === "array-object") {
179
- const type = [
180
- "{",
181
- Object.entries(prop.properties).filter(([_, p]) => ctx.filter(p)).map(
182
- ([name, prop2]) => [
183
- prop2.description ? [`
184
- `, ` `.repeat(ctx.indent), `/** `, prop2.description.trim(), " */", "\n"].join("") : "",
185
- ` `.repeat(ctx.indent),
186
- // ctx.readonly ? "readonly " : "",
187
- camelCase(name),
188
- ctx.optional(prop2, ctx) ? "?" : "",
189
- ": ",
190
- generateValue(prop2, { ...ctx, indent: ctx.indent + 1, depth: ctx.depth + 1 })
191
- ].join("")
192
- ).join("\n"),
193
- `${` `.repeat(ctx.indent - 1)}}`
194
- ].join("\n");
195
- const object = ctx.readonly ? `Readonly<${type}>` : type;
196
- return ctx.wrap(object, prop, ctx);
197
- }
198
- throw new Error(`Unknown property type: ${prop.type}`);
199
- };
200
-
201
- // src/provider.ts
202
- import {
203
- ResourceNotFound
204
- } from "@terraforge/core";
205
- var TerraformProvider = class {
206
- constructor(type, id, createPlugin, config) {
207
- this.type = type;
208
- this.id = id;
209
- this.createPlugin = createPlugin;
210
- this.config = config;
211
- }
212
- configured;
213
- plugin;
214
- async configure() {
215
- const plugin = await this.prepare();
216
- if (!this.configured) {
217
- this.configured = plugin.configure(this.config);
218
- }
219
- await this.configured;
220
- return plugin;
221
- }
222
- prepare() {
223
- if (!this.plugin) {
224
- this.plugin = this.createPlugin();
225
- }
226
- return this.plugin;
227
- }
228
- async destroy() {
229
- if (this.plugin) {
230
- const plugin = await this.plugin;
231
- plugin.stop();
232
- this.plugin = void 0;
233
- this.configured = void 0;
234
- }
235
- }
236
- ownResource(id) {
237
- return `terraform:${this.type}:${this.id}` === id;
238
- }
239
- async getResource({ type, state }) {
240
- const plugin = await this.configure();
241
- const newState = await plugin.readResource(type, state);
242
- if (!newState) {
243
- throw new ResourceNotFound();
244
- }
245
- return {
246
- version: 0,
247
- state: newState
248
- };
249
- }
250
- async createResource({ type, state }) {
251
- const plugin = await this.configure();
252
- const newState = await plugin.applyResourceChange(type, null, state);
253
- return {
254
- version: 0,
255
- state: newState
256
- };
257
- }
258
- async updateResource({ type, priorState, proposedState }) {
259
- const plugin = await this.configure();
260
- const { requiresReplace } = await plugin.planResourceChange(type, priorState, proposedState);
261
- if (requiresReplace.length > 0) {
262
- const formattedAttrs = requiresReplace.map((p) => p.join(".")).join('", "');
263
- throw new Error(
264
- `Updating the "${formattedAttrs}" properties for the "${type}" resource will require the resource to be replaced.`
265
- );
266
- }
267
- const newState = await plugin.applyResourceChange(type, priorState, proposedState);
268
- return {
269
- version: 0,
270
- state: newState
271
- };
272
- }
273
- async deleteResource({ type, state }) {
274
- const plugin = await this.configure();
275
- try {
276
- await plugin.applyResourceChange(type, state, null);
277
- } catch (error) {
278
- try {
279
- const newState = await plugin.readResource(type, state);
280
- if (!newState) {
281
- throw new ResourceNotFound();
282
- }
283
- } catch (_) {
284
- }
285
- throw error;
286
- }
287
- }
288
- async planResourceChange({ type, priorState, proposedState }) {
289
- const plugin = await this.configure();
290
- const result = await plugin.planResourceChange(type, priorState, proposedState);
291
- return {
292
- version: 0,
293
- requiresReplacement: result.requiresReplace.length > 0,
294
- state: result.plannedState
295
- };
296
- }
297
- async getData({ type, state }) {
298
- const plugin = await this.configure();
299
- const data = await plugin.readDataSource(type, state);
300
- if (!data) {
301
- throw new Error(`Data source not found ${type}`);
302
- }
303
- return {
304
- state: data
305
- };
306
- }
307
- // async generateTypes(dir: string) {
308
- // const plugin = await this.prepare()
309
- // const schema = plugin.schema()
310
- // const types = generateTypes(
311
- // {
312
- // [`${this.type}_provider`]: schema.provider,
313
- // },
314
- // schema.resources,
315
- // schema.dataSources
316
- // )
317
- // await mkdir(dir, { recursive: true })
318
- // await writeFile(join(dir, `${this.type}.d.ts`), types)
319
- // await this.destroy()
320
- // }
321
- };
322
-
323
- // src/proxy.ts
324
- import { createMeta, nodeMetaSymbol } from "@terraforge/core";
325
- import { snakeCase as snakeCase2 } from "change-case";
326
-
327
- // src/plugin/client.ts
328
- import { credentials, loadPackageDefinition } from "@grpc/grpc-js";
329
- import { fromJSON } from "@grpc/proto-loader";
330
- import { createDebugger } from "@terraforge/core";
331
-
332
- // src/plugin/diagnostic.ts
333
- var DiagnosticsError = class extends Error {
334
- diagnostics;
335
- constructor(diagnostics) {
336
- super(diagnostics[0]?.summary ?? "Diagnostic error");
337
- this.diagnostics = diagnostics;
338
- }
339
- };
340
- var throwDiagnosticError = (response) => {
341
- const diagnostics = response.diagnostics.map((item) => ({
342
- severity: item.severity === 1 ? "error" : "warning",
343
- summary: item.summary,
344
- detail: item.detail,
345
- path: item.attribute?.steps.map((step) => step.attributeName)
346
- }));
347
- return new DiagnosticsError(diagnostics);
348
- };
349
-
350
- // src/plugin/protocol/tfplugin5.ts
351
- var tfplugin5_default = {
352
- options: { syntax: "proto3" },
353
- nested: {
354
- tfplugin5: {
355
- nested: {
356
- DynamicValue: { fields: { msgpack: { type: "bytes", id: 1 }, json: { type: "bytes", id: 2 } } },
357
- Diagnostic: {
358
- fields: {
359
- severity: { type: "Severity", id: 1 },
360
- summary: { type: "string", id: 2 },
361
- detail: { type: "string", id: 3 },
362
- attribute: { type: "AttributePath", id: 4 }
363
- },
364
- nested: { Severity: { values: { INVALID: 0, ERROR: 1, WARNING: 2 } } }
365
- },
366
- AttributePath: {
367
- fields: { steps: { rule: "repeated", type: "Step", id: 1 } },
368
- nested: {
369
- Step: {
370
- oneofs: { selector: { oneof: ["attributeName", "elementKeyString", "elementKeyInt"] } },
371
- fields: {
372
- attributeName: { type: "string", id: 1 },
373
- elementKeyString: { type: "string", id: 2 },
374
- elementKeyInt: { type: "int64", id: 3 }
375
- }
376
- }
377
- }
378
- },
379
- Stop: {
380
- fields: {},
381
- nested: { Request: { fields: {} }, Response: { fields: { Error: { type: "string", id: 1 } } } }
382
- },
383
- RawState: {
384
- fields: { json: { type: "bytes", id: 1 }, flatmap: { keyType: "string", type: "string", id: 2 } }
385
- },
386
- Schema: {
387
- fields: { version: { type: "int64", id: 1 }, block: { type: "Block", id: 2 } },
388
- nested: {
389
- Block: {
390
- fields: {
391
- version: { type: "int64", id: 1 },
392
- attributes: { rule: "repeated", type: "Attribute", id: 2 },
393
- blockTypes: { rule: "repeated", type: "NestedBlock", id: 3 }
394
- }
395
- },
396
- Attribute: {
397
- fields: {
398
- name: { type: "string", id: 1 },
399
- type: { type: "bytes", id: 2 },
400
- description: { type: "string", id: 3 },
401
- required: { type: "bool", id: 4 },
402
- optional: { type: "bool", id: 5 },
403
- computed: { type: "bool", id: 6 },
404
- sensitive: { type: "bool", id: 7 }
405
- }
406
- },
407
- NestedBlock: {
408
- fields: {
409
- typeName: { type: "string", id: 1 },
410
- block: { type: "Block", id: 2 },
411
- nesting: { type: "NestingMode", id: 3 },
412
- minItems: { type: "int64", id: 4 },
413
- maxItems: { type: "int64", id: 5 }
414
- },
415
- nested: {
416
- NestingMode: { values: { INVALID: 0, SINGLE: 1, LIST: 2, SET: 3, MAP: 4, GROUP: 5 } }
417
- }
418
- }
419
- }
420
- },
421
- Provider: {
422
- methods: {
423
- GetSchema: {
424
- requestType: "GetProviderSchema.Request",
425
- responseType: "GetProviderSchema.Response"
426
- },
427
- PrepareProviderConfig: {
428
- requestType: "PrepareProviderConfig.Request",
429
- responseType: "PrepareProviderConfig.Response"
430
- },
431
- ValidateResourceTypeConfig: {
432
- requestType: "ValidateResourceTypeConfig.Request",
433
- responseType: "ValidateResourceTypeConfig.Response"
434
- },
435
- ValidateDataSourceConfig: {
436
- requestType: "ValidateDataSourceConfig.Request",
437
- responseType: "ValidateDataSourceConfig.Response"
438
- },
439
- UpgradeResourceState: {
440
- requestType: "UpgradeResourceState.Request",
441
- responseType: "UpgradeResourceState.Response"
442
- },
443
- Configure: { requestType: "Configure.Request", responseType: "Configure.Response" },
444
- ReadResource: { requestType: "ReadResource.Request", responseType: "ReadResource.Response" },
445
- PlanResourceChange: {
446
- requestType: "PlanResourceChange.Request",
447
- responseType: "PlanResourceChange.Response"
448
- },
449
- ApplyResourceChange: {
450
- requestType: "ApplyResourceChange.Request",
451
- responseType: "ApplyResourceChange.Response"
452
- },
453
- ImportResourceState: {
454
- requestType: "ImportResourceState.Request",
455
- responseType: "ImportResourceState.Response"
456
- },
457
- ReadDataSource: {
458
- requestType: "ReadDataSource.Request",
459
- responseType: "ReadDataSource.Response"
460
- },
461
- Stop: { requestType: "Stop.Request", responseType: "Stop.Response" }
462
- }
463
- },
464
- GetProviderSchema: {
465
- fields: {},
466
- nested: {
467
- Request: { fields: {} },
468
- Response: {
469
- fields: {
470
- provider: { type: "Schema", id: 1 },
471
- resourceSchemas: { keyType: "string", type: "Schema", id: 2 },
472
- dataSourceSchemas: { keyType: "string", type: "Schema", id: 3 },
473
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 4 }
474
- }
475
- }
476
- }
477
- },
478
- PrepareProviderConfig: {
479
- fields: {},
480
- nested: {
481
- Request: { fields: { config: { type: "DynamicValue", id: 1 } } },
482
- Response: {
483
- fields: {
484
- preparedConfig: { type: "DynamicValue", id: 1 },
485
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
486
- }
487
- }
488
- }
489
- },
490
- UpgradeResourceState: {
491
- fields: {},
492
- nested: {
493
- Request: {
494
- fields: {
495
- typeName: { type: "string", id: 1 },
496
- version: { type: "int64", id: 2 },
497
- rawState: { type: "RawState", id: 3 }
498
- }
499
- },
500
- Response: {
501
- fields: {
502
- upgradedState: { type: "DynamicValue", id: 1 },
503
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
504
- }
505
- }
506
- }
507
- },
508
- ValidateResourceTypeConfig: {
509
- fields: {},
510
- nested: {
511
- Request: {
512
- fields: { typeName: { type: "string", id: 1 }, config: { type: "DynamicValue", id: 2 } }
513
- },
514
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
515
- }
516
- },
517
- ValidateDataSourceConfig: {
518
- fields: {},
519
- nested: {
520
- Request: {
521
- fields: { typeName: { type: "string", id: 1 }, config: { type: "DynamicValue", id: 2 } }
522
- },
523
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
524
- }
525
- },
526
- Configure: {
527
- fields: {},
528
- nested: {
529
- Request: {
530
- fields: {
531
- terraformVersion: { type: "string", id: 1 },
532
- config: { type: "DynamicValue", id: 2 }
533
- }
534
- },
535
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
536
- }
537
- },
538
- ReadResource: {
539
- fields: {},
540
- nested: {
541
- Request: {
542
- fields: {
543
- typeName: { type: "string", id: 1 },
544
- currentState: { type: "DynamicValue", id: 2 },
545
- private: { type: "bytes", id: 3 }
546
- }
547
- },
548
- Response: {
549
- fields: {
550
- newState: { type: "DynamicValue", id: 1 },
551
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 },
552
- private: { type: "bytes", id: 3 }
553
- }
554
- }
555
- }
556
- },
557
- PlanResourceChange: {
558
- fields: {},
559
- nested: {
560
- Request: {
561
- fields: {
562
- typeName: { type: "string", id: 1 },
563
- priorState: { type: "DynamicValue", id: 2 },
564
- proposedNewState: { type: "DynamicValue", id: 3 },
565
- config: { type: "DynamicValue", id: 4 },
566
- priorPrivate: { type: "bytes", id: 5 }
567
- }
568
- },
569
- Response: {
570
- fields: {
571
- plannedState: { type: "DynamicValue", id: 1 },
572
- requiresReplace: { rule: "repeated", type: "AttributePath", id: 2 },
573
- plannedPrivate: { type: "bytes", id: 3 },
574
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 4 },
575
- legacyTypeSystem: { type: "bool", id: 5 }
576
- }
577
- }
578
- }
579
- },
580
- ApplyResourceChange: {
581
- fields: {},
582
- nested: {
583
- Request: {
584
- fields: {
585
- typeName: { type: "string", id: 1 },
586
- priorState: { type: "DynamicValue", id: 2 },
587
- plannedState: { type: "DynamicValue", id: 3 },
588
- config: { type: "DynamicValue", id: 4 },
589
- plannedPrivate: { type: "bytes", id: 5 }
590
- }
591
- },
592
- Response: {
593
- fields: {
594
- newState: { type: "DynamicValue", id: 1 },
595
- private: { type: "bytes", id: 2 },
596
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 3 },
597
- legacyTypeSystem: { type: "bool", id: 4 }
598
- }
599
- }
600
- }
601
- },
602
- ImportResourceState: {
603
- fields: {},
604
- nested: {
605
- Request: { fields: { typeName: { type: "string", id: 1 }, id: { type: "string", id: 2 } } },
606
- ImportedResource: {
607
- fields: {
608
- typeName: { type: "string", id: 1 },
609
- state: { type: "DynamicValue", id: 2 },
610
- private: { type: "bytes", id: 3 }
611
- }
612
- },
613
- Response: {
614
- fields: {
615
- importedResources: { rule: "repeated", type: "ImportedResource", id: 1 },
616
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
617
- }
618
- }
619
- }
620
- },
621
- ReadDataSource: {
622
- fields: {},
623
- nested: {
624
- Request: {
625
- fields: { typeName: { type: "string", id: 1 }, config: { type: "DynamicValue", id: 2 } }
626
- },
627
- Response: {
628
- fields: {
629
- state: { type: "DynamicValue", id: 1 },
630
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
631
- }
632
- }
633
- }
634
- },
635
- Provisioner: {
636
- methods: {
637
- GetSchema: {
638
- requestType: "GetProvisionerSchema.Request",
639
- responseType: "GetProvisionerSchema.Response"
640
- },
641
- ValidateProvisionerConfig: {
642
- requestType: "ValidateProvisionerConfig.Request",
643
- responseType: "ValidateProvisionerConfig.Response"
644
- },
645
- ProvisionResource: {
646
- requestType: "ProvisionResource.Request",
647
- responseType: "ProvisionResource.Response",
648
- responseStream: true
649
- },
650
- Stop: { requestType: "Stop.Request", responseType: "Stop.Response" }
651
- }
652
- },
653
- GetProvisionerSchema: {
654
- fields: {},
655
- nested: {
656
- Request: { fields: {} },
657
- Response: {
658
- fields: {
659
- provisioner: { type: "Schema", id: 1 },
660
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
661
- }
662
- }
663
- }
664
- },
665
- ValidateProvisionerConfig: {
666
- fields: {},
667
- nested: {
668
- Request: { fields: { config: { type: "DynamicValue", id: 1 } } },
669
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
670
- }
671
- },
672
- ProvisionResource: {
673
- fields: {},
674
- nested: {
675
- Request: {
676
- fields: {
677
- config: { type: "DynamicValue", id: 1 },
678
- connection: { type: "DynamicValue", id: 2 }
679
- }
680
- },
681
- Response: {
682
- fields: {
683
- output: { type: "string", id: 1 },
684
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
685
- }
686
- }
687
- }
688
- }
689
- }
690
- }
691
- }
692
- };
693
-
694
- // src/plugin/protocol/tfplugin6.ts
695
- var tfplugin6_default = {
696
- options: { syntax: "proto3", go_package: "github.com/hashicorp/terraform/internal/tfplugin6" },
697
- nested: {
698
- tfplugin6: {
699
- nested: {
700
- DynamicValue: { fields: { msgpack: { type: "bytes", id: 1 }, json: { type: "bytes", id: 2 } } },
701
- Diagnostic: {
702
- fields: {
703
- severity: { type: "Severity", id: 1 },
704
- summary: { type: "string", id: 2 },
705
- detail: { type: "string", id: 3 },
706
- attribute: { type: "AttributePath", id: 4 }
707
- },
708
- nested: { Severity: { values: { INVALID: 0, ERROR: 1, WARNING: 2 } } }
709
- },
710
- AttributePath: {
711
- fields: { steps: { rule: "repeated", type: "Step", id: 1 } },
712
- nested: {
713
- Step: {
714
- oneofs: { selector: { oneof: ["attributeName", "elementKeyString", "elementKeyInt"] } },
715
- fields: {
716
- attributeName: { type: "string", id: 1 },
717
- elementKeyString: { type: "string", id: 2 },
718
- elementKeyInt: { type: "int64", id: 3 }
719
- }
720
- }
721
- }
722
- },
723
- StopProvider: {
724
- fields: {},
725
- nested: { Request: { fields: {} }, Response: { fields: { Error: { type: "string", id: 1 } } } }
726
- },
727
- RawState: {
728
- fields: { json: { type: "bytes", id: 1 }, flatmap: { keyType: "string", type: "string", id: 2 } }
729
- },
730
- StringKind: { values: { PLAIN: 0, MARKDOWN: 1 } },
731
- Schema: {
732
- fields: { version: { type: "int64", id: 1 }, block: { type: "Block", id: 2 } },
733
- nested: {
734
- Block: {
735
- fields: {
736
- version: { type: "int64", id: 1 },
737
- attributes: { rule: "repeated", type: "Attribute", id: 2 },
738
- blockTypes: { rule: "repeated", type: "NestedBlock", id: 3 },
739
- description: { type: "string", id: 4 },
740
- descriptionKind: { type: "StringKind", id: 5 },
741
- deprecated: { type: "bool", id: 6 }
742
- }
743
- },
744
- Attribute: {
745
- fields: {
746
- name: { type: "string", id: 1 },
747
- type: { type: "bytes", id: 2 },
748
- nestedType: { type: "Object", id: 10 },
749
- description: { type: "string", id: 3 },
750
- required: { type: "bool", id: 4 },
751
- optional: { type: "bool", id: 5 },
752
- computed: { type: "bool", id: 6 },
753
- sensitive: { type: "bool", id: 7 },
754
- descriptionKind: { type: "StringKind", id: 8 },
755
- deprecated: { type: "bool", id: 9 }
756
- }
757
- },
758
- NestedBlock: {
759
- fields: {
760
- typeName: { type: "string", id: 1 },
761
- block: { type: "Block", id: 2 },
762
- nesting: { type: "NestingMode", id: 3 },
763
- minItems: { type: "int64", id: 4 },
764
- maxItems: { type: "int64", id: 5 }
765
- },
766
- nested: {
767
- NestingMode: { values: { INVALID: 0, SINGLE: 1, LIST: 2, SET: 3, MAP: 4, GROUP: 5 } }
768
- }
769
- },
770
- Object: {
771
- fields: {
772
- attributes: { rule: "repeated", type: "Attribute", id: 1 },
773
- nesting: { type: "NestingMode", id: 3 },
774
- minItems: { type: "int64", id: 4 },
775
- maxItems: { type: "int64", id: 5 }
776
- },
777
- nested: { NestingMode: { values: { INVALID: 0, SINGLE: 1, LIST: 2, SET: 3, MAP: 4 } } }
778
- }
779
- }
780
- },
781
- Provider: {
782
- methods: {
783
- GetProviderSchema: {
784
- requestType: "GetProviderSchema.Request",
785
- responseType: "GetProviderSchema.Response"
786
- },
787
- ValidateProviderConfig: {
788
- requestType: "ValidateProviderConfig.Request",
789
- responseType: "ValidateProviderConfig.Response"
790
- },
791
- ValidateResourceConfig: {
792
- requestType: "ValidateResourceConfig.Request",
793
- responseType: "ValidateResourceConfig.Response"
794
- },
795
- ValidateDataResourceConfig: {
796
- requestType: "ValidateDataResourceConfig.Request",
797
- responseType: "ValidateDataResourceConfig.Response"
798
- },
799
- UpgradeResourceState: {
800
- requestType: "UpgradeResourceState.Request",
801
- responseType: "UpgradeResourceState.Response"
802
- },
803
- ConfigureProvider: {
804
- requestType: "ConfigureProvider.Request",
805
- responseType: "ConfigureProvider.Response"
806
- },
807
- ReadResource: { requestType: "ReadResource.Request", responseType: "ReadResource.Response" },
808
- PlanResourceChange: {
809
- requestType: "PlanResourceChange.Request",
810
- responseType: "PlanResourceChange.Response"
811
- },
812
- ApplyResourceChange: {
813
- requestType: "ApplyResourceChange.Request",
814
- responseType: "ApplyResourceChange.Response"
815
- },
816
- ImportResourceState: {
817
- requestType: "ImportResourceState.Request",
818
- responseType: "ImportResourceState.Response"
819
- },
820
- ReadDataSource: {
821
- requestType: "ReadDataSource.Request",
822
- responseType: "ReadDataSource.Response"
823
- },
824
- StopProvider: { requestType: "StopProvider.Request", responseType: "StopProvider.Response" }
825
- }
826
- },
827
- GetProviderSchema: {
828
- fields: {},
829
- nested: {
830
- Request: { fields: {} },
831
- Response: {
832
- fields: {
833
- provider: { type: "Schema", id: 1 },
834
- resourceSchemas: { keyType: "string", type: "Schema", id: 2 },
835
- dataSourceSchemas: { keyType: "string", type: "Schema", id: 3 },
836
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 4 },
837
- providerMeta: { type: "Schema", id: 5 }
838
- }
839
- }
840
- }
841
- },
842
- ValidateProviderConfig: {
843
- fields: {},
844
- nested: {
845
- Request: { fields: { config: { type: "DynamicValue", id: 1 } } },
846
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 } } }
847
- }
848
- },
849
- UpgradeResourceState: {
850
- fields: {},
851
- nested: {
852
- Request: {
853
- fields: {
854
- typeName: { type: "string", id: 1 },
855
- version: { type: "int64", id: 2 },
856
- rawState: { type: "RawState", id: 3 }
857
- }
858
- },
859
- Response: {
860
- fields: {
861
- upgradedState: { type: "DynamicValue", id: 1 },
862
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
863
- }
864
- }
865
- }
866
- },
867
- ValidateResourceConfig: {
868
- fields: {},
869
- nested: {
870
- Request: {
871
- fields: { typeName: { type: "string", id: 1 }, config: { type: "DynamicValue", id: 2 } }
872
- },
873
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
874
- }
875
- },
876
- ValidateDataResourceConfig: {
877
- fields: {},
878
- nested: {
879
- Request: {
880
- fields: { typeName: { type: "string", id: 1 }, config: { type: "DynamicValue", id: 2 } }
881
- },
882
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
883
- }
884
- },
885
- ConfigureProvider: {
886
- fields: {},
887
- nested: {
888
- Request: {
889
- fields: {
890
- terraformVersion: { type: "string", id: 1 },
891
- config: { type: "DynamicValue", id: 2 }
892
- }
893
- },
894
- Response: { fields: { diagnostics: { rule: "repeated", type: "Diagnostic", id: 1 } } }
895
- }
896
- },
897
- ReadResource: {
898
- fields: {},
899
- nested: {
900
- Request: {
901
- fields: {
902
- typeName: { type: "string", id: 1 },
903
- currentState: { type: "DynamicValue", id: 2 },
904
- private: { type: "bytes", id: 3 },
905
- providerMeta: { type: "DynamicValue", id: 4 }
906
- }
907
- },
908
- Response: {
909
- fields: {
910
- newState: { type: "DynamicValue", id: 1 },
911
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 },
912
- private: { type: "bytes", id: 3 }
913
- }
914
- }
915
- }
916
- },
917
- PlanResourceChange: {
918
- fields: {},
919
- nested: {
920
- Request: {
921
- fields: {
922
- typeName: { type: "string", id: 1 },
923
- priorState: { type: "DynamicValue", id: 2 },
924
- proposedNewState: { type: "DynamicValue", id: 3 },
925
- config: { type: "DynamicValue", id: 4 },
926
- priorPrivate: { type: "bytes", id: 5 },
927
- providerMeta: { type: "DynamicValue", id: 6 }
928
- }
929
- },
930
- Response: {
931
- fields: {
932
- plannedState: { type: "DynamicValue", id: 1 },
933
- requiresReplace: { rule: "repeated", type: "AttributePath", id: 2 },
934
- plannedPrivate: { type: "bytes", id: 3 },
935
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 4 }
936
- }
937
- }
938
- }
939
- },
940
- ApplyResourceChange: {
941
- fields: {},
942
- nested: {
943
- Request: {
944
- fields: {
945
- typeName: { type: "string", id: 1 },
946
- priorState: { type: "DynamicValue", id: 2 },
947
- plannedState: { type: "DynamicValue", id: 3 },
948
- config: { type: "DynamicValue", id: 4 },
949
- plannedPrivate: { type: "bytes", id: 5 },
950
- providerMeta: { type: "DynamicValue", id: 6 }
951
- }
952
- },
953
- Response: {
954
- fields: {
955
- newState: { type: "DynamicValue", id: 1 },
956
- private: { type: "bytes", id: 2 },
957
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 3 }
958
- }
959
- }
960
- }
961
- },
962
- ImportResourceState: {
963
- fields: {},
964
- nested: {
965
- Request: { fields: { typeName: { type: "string", id: 1 }, id: { type: "string", id: 2 } } },
966
- ImportedResource: {
967
- fields: {
968
- typeName: { type: "string", id: 1 },
969
- state: { type: "DynamicValue", id: 2 },
970
- private: { type: "bytes", id: 3 }
971
- }
972
- },
973
- Response: {
974
- fields: {
975
- importedResources: { rule: "repeated", type: "ImportedResource", id: 1 },
976
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
977
- }
978
- }
979
- }
980
- },
981
- ReadDataSource: {
982
- fields: {},
983
- nested: {
984
- Request: {
985
- fields: {
986
- typeName: { type: "string", id: 1 },
987
- config: { type: "DynamicValue", id: 2 },
988
- providerMeta: { type: "DynamicValue", id: 3 }
989
- }
990
- },
991
- Response: {
992
- fields: {
993
- state: { type: "DynamicValue", id: 1 },
994
- diagnostics: { rule: "repeated", type: "Diagnostic", id: 2 }
995
- }
996
- }
997
- }
998
- }
999
- }
1000
- }
1001
- }
1002
- };
1003
-
1004
- // src/plugin/client.ts
1005
- var debug = createDebugger("Client");
1006
- var protocols = {
1007
- tfplugin5: tfplugin5_default,
1008
- tfplugin6: tfplugin6_default
1009
- };
1010
- var createPluginClient = async (props) => {
1011
- const proto = protocols[props.protocol.split(".").at(0) ?? ""];
1012
- if (!proto) {
1013
- throw new Error(`We don't have support for the ${props.protocol} protocol`);
1014
- }
1015
- const pack2 = fromJSON(proto);
1016
- const grpc = loadPackageDefinition(pack2);
1017
- const client = new grpc["tfplugin" + props.version].Provider(
1018
- `unix://${props.endpoint}`,
1019
- credentials.createInsecure(),
1020
- {
1021
- "grpc.max_receive_message_length": 100 * 1024 * 1024,
1022
- "grpc.max_send_message_length": 100 * 1024 * 1024
1023
- }
1024
- );
1025
- debug("init", props.protocol);
1026
- await new Promise((resolve, reject) => {
1027
- const deadline = /* @__PURE__ */ new Date();
1028
- deadline.setSeconds(deadline.getSeconds() + 10);
1029
- client.waitForReady(deadline, (error) => {
1030
- if (error) {
1031
- reject(error);
1032
- } else {
1033
- resolve();
1034
- }
1035
- });
1036
- });
1037
- debug("connected");
1038
- return {
1039
- call(method, payload) {
1040
- return new Promise((resolve, reject) => {
1041
- const fn = client[method];
1042
- debug("call", method);
1043
- if (!fn) {
1044
- reject(new Error(`Unknown method call: ${method}`));
1045
- return;
1046
- }
1047
- fn.call(client, payload, (error, response) => {
1048
- if (error) {
1049
- debug("failed", error);
1050
- reject(error);
1051
- } else if (response.diagnostics) {
1052
- debug("failed", response.diagnostics);
1053
- reject(throwDiagnosticError(response));
1054
- } else {
1055
- resolve(response);
1056
- }
1057
- });
1058
- });
1059
- }
1060
- };
1061
- };
1062
-
1063
- // src/plugin/download.ts
1064
- import { createDebugger as createDebugger2 } from "@terraforge/core";
1065
- import jszip from "jszip";
1066
- import { mkdir, rm, stat, writeFile } from "fs/promises";
1067
- import { homedir } from "os";
1068
- import { dirname, join } from "path";
1069
-
1070
- // src/plugin/registry.ts
1071
- import { arch, platform } from "os";
1072
- import { compare } from "semver";
1073
- var baseUrl = "https://registry.terraform.io/v1/providers";
1074
- var getProviderVersions = async (org, type) => {
1075
- const resp = await fetch(`${baseUrl}/${org}/${type}/versions`);
1076
- const data = await resp.json();
1077
- const versions = data.versions;
1078
- const os = getOS();
1079
- const ar = getArchitecture();
1080
- const supported = versions.filter((v) => {
1081
- return !!v.platforms.find((p) => p.os === os && p.arch === ar);
1082
- });
1083
- const sorted = supported.sort((a, b) => compare(a.version, b.version));
1084
- const latest = sorted.at(-1);
1085
- if (!latest) {
1086
- throw new Error("Version is unsupported for your platform.");
1087
- }
1088
- return {
1089
- versions,
1090
- supported,
1091
- latest: latest.version
1092
- };
1093
- };
1094
- var getProviderDownloadUrl = async (org, type, version) => {
1095
- const url = [
1096
- //
1097
- baseUrl,
1098
- org,
1099
- type,
1100
- version,
1101
- "download",
1102
- getOS(),
1103
- getArchitecture()
1104
- ].join("/");
1105
- const response = await fetch(url);
1106
- const result = await response.json();
1107
- return {
1108
- url: result.download_url,
1109
- shasum: result.shasum,
1110
- protocols: result.protocols
1111
- };
1112
- };
1113
- var getOS = () => {
1114
- const os = platform();
1115
- switch (os) {
1116
- case "linux":
1117
- return "linux";
1118
- case "win32":
1119
- return "windows";
1120
- case "darwin":
1121
- return "darwin";
1122
- case "freebsd":
1123
- return "freebsd";
1124
- case "openbsd":
1125
- return "openbsd";
1126
- }
1127
- throw new Error(`Unsupported OS platform: ${os}`);
1128
- };
1129
- var getArchitecture = () => {
1130
- const ar = arch();
1131
- switch (ar) {
1132
- case "arm":
1133
- return "arm";
1134
- case "arm64":
1135
- return "arm64";
1136
- case "x64":
1137
- return "amd64";
1138
- case "ia32":
1139
- return "386";
1140
- }
1141
- throw new Error(`Unsupported architecture: ${ar}`);
1142
- };
1143
-
1144
- // src/plugin/download.ts
1145
- var exists = async (file) => {
1146
- try {
1147
- await stat(file);
1148
- } catch (error) {
1149
- return false;
1150
- }
1151
- return true;
1152
- };
1153
- var debug2 = createDebugger2("Downloader");
1154
- var installPath = join(homedir(), ".terraforge", "plugins");
1155
- var getInstallPath = (props) => {
1156
- const dir = props.location ?? installPath;
1157
- const file = join(dir, `${props.org}-${props.type}-${props.version}`);
1158
- return file;
1159
- };
1160
- var isPluginInstalled = (props) => {
1161
- return exists(getInstallPath(props));
1162
- };
1163
- var deletePlugin = async (props) => {
1164
- const file = getInstallPath(props);
1165
- const isAlreadyInstalled = await isPluginInstalled(props);
1166
- if (isAlreadyInstalled) {
1167
- debug2(props.type, "deleting...");
1168
- await rm(file);
1169
- debug2(props.type, "deleted");
1170
- } else {
1171
- debug2(props.type, "not installed");
1172
- }
1173
- };
1174
- var downloadPlugin = async (props) => {
1175
- if (props.version === "latest") {
1176
- const { latest } = await getProviderVersions(props.org, props.type);
1177
- props.version = latest;
1178
- }
1179
- const file = getInstallPath(props);
1180
- const isAlreadyInstalled = await isPluginInstalled(props);
1181
- if (!isAlreadyInstalled) {
1182
- debug2(props.type, "downloading...");
1183
- const info = await getProviderDownloadUrl(props.org, props.type, props.version);
1184
- const res = await fetch(info.url);
1185
- const buf = await res.bytes();
1186
- const zip = await jszip.loadAsync(buf);
1187
- const zipped = zip.filter((file2) => file2.startsWith("terraform-provider")).at(0);
1188
- if (!zipped) {
1189
- throw new Error(`Can't find the provider inside the downloaded zip file.`);
1190
- }
1191
- const binary = await zipped.async("nodebuffer");
1192
- debug2(props.type, "done");
1193
- await mkdir(dirname(file), { recursive: true });
1194
- await writeFile(file, binary, {
1195
- mode: 509
1196
- });
1197
- } else {
1198
- debug2(props.type, "already downloaded");
1199
- }
1200
- return {
1201
- file,
1202
- version: props.version
1203
- };
1204
- };
1205
-
1206
- // src/plugin/server.ts
1207
- import { createDebugger as createDebugger3 } from "@terraforge/core";
1208
- import { spawn } from "child_process";
1209
- var debug3 = createDebugger3("Server");
1210
- var createPluginServer = (props) => {
1211
- return new Promise((resolve, reject) => {
1212
- debug3("init");
1213
- const process = spawn(`${props.file}`, ["-debug"]);
1214
- process.stderr.on("data", (data) => {
1215
- if (props.debug) {
1216
- const message = data.toString("utf8");
1217
- console.log(message);
1218
- }
1219
- });
1220
- process.stdout.once("data", (data) => {
1221
- try {
1222
- const message = data.toString("utf8");
1223
- const matches = message.match(/TF_REATTACH_PROVIDERS\=\'(.*)\'/);
1224
- if (matches && matches.length > 0) {
1225
- const match = matches[0];
1226
- const json = match.slice(23, -1);
1227
- const data2 = JSON.parse(json);
1228
- const entries = Object.values(data2);
1229
- if (entries.length > 0) {
1230
- const entry = entries[0];
1231
- const version = entry.ProtocolVersion;
1232
- const endpoint = entry.Addr.String;
1233
- debug3("started", endpoint);
1234
- resolve({
1235
- kill() {
1236
- process.kill();
1237
- },
1238
- protocol: "tfplugin" + version.toFixed(1),
1239
- version,
1240
- endpoint
1241
- });
1242
- return;
1243
- }
1244
- }
1245
- } catch (error) {
1246
- }
1247
- debug3("failed");
1248
- reject(new Error("Failed to start the plugin"));
1249
- });
1250
- });
1251
- };
1252
-
1253
- // src/plugin/schema.ts
1254
- var NestingMode = {
1255
- INVALID: 0,
1256
- SINGLE: 1,
1257
- LIST: 2,
1258
- SET: 3,
1259
- MAP: 4,
1260
- GROUP: 5
1261
- };
1262
- var parseResourceSchema = (schemas) => {
1263
- const props = {};
1264
- for (const [name, schema] of Object.entries(schemas)) {
1265
- if (schema.block) {
1266
- const block = parseBlock(schema.block);
1267
- props[name] = {
1268
- ...block,
1269
- version: block.version ?? schema.version
1270
- };
1271
- }
1272
- }
1273
- return props;
1274
- };
1275
- var parseProviderSchema = (schema) => {
1276
- if (schema.block) {
1277
- const block = parseBlock(schema.block);
1278
- return {
1279
- ...block,
1280
- version: block.version ?? schema.version
1281
- };
1282
- }
1283
- throw new Error("Invalid block");
1284
- };
1285
- var parseBlock = (block) => {
1286
- const properties = {};
1287
- for (const entry of block.attributes ?? []) {
1288
- properties[entry.name] = parseAttribute(entry);
1289
- }
1290
- for (const entry of block.blockTypes ?? []) {
1291
- properties[entry.typeName] = parseNestedBlock(entry);
1292
- }
1293
- if (block.deprecated) {
1294
- console.warn("Deprecated block");
1295
- }
1296
- return {
1297
- type: "object",
1298
- version: block.version,
1299
- description: block.description,
1300
- // deprecated: block.deprecated,
1301
- properties
1302
- };
1303
- };
1304
- var parseNestedBlock = (block) => {
1305
- const type = parseNestedBlockType(block);
1306
- const item = parseBlock(block.block);
1307
- const prop = {
1308
- optional: true,
1309
- required: false,
1310
- computed: false
1311
- };
1312
- if (type === "array" || type === "record") {
1313
- return {
1314
- ...prop,
1315
- type,
1316
- item
1317
- };
1318
- }
1319
- if (type === "array-object") {
1320
- return {
1321
- ...prop,
1322
- ...item,
1323
- type
1324
- };
1325
- }
1326
- return {
1327
- ...prop,
1328
- ...item
1329
- };
1330
- };
1331
- var parseNestedBlockType = (block) => {
1332
- if (block.nesting === NestingMode.SET) {
1333
- return "array";
1334
- }
1335
- if (block.nesting === NestingMode.LIST) {
1336
- if (block.maxItems?.eq(1)) {
1337
- return "array-object";
1338
- }
1339
- return "array";
1340
- }
1341
- if (block.nesting === NestingMode.MAP) {
1342
- return "record";
1343
- }
1344
- if (block.nesting === NestingMode.GROUP) {
1345
- return "object";
1346
- }
1347
- if (block.nesting === NestingMode.SINGLE) {
1348
- return "object";
1349
- }
1350
- throw new Error(`Invalid nested block type ${block.nesting}`);
1351
- };
1352
- var parseAttribute = (attr) => {
1353
- const prop = {
1354
- description: attr.description,
1355
- required: attr.required,
1356
- optional: attr.optional,
1357
- computed: attr.computed,
1358
- deprecated: attr.deprecated,
1359
- sensitive: attr.sensitive
1360
- };
1361
- if (attr.type) {
1362
- const json = JSON.parse(attr.type.toString("utf8"));
1363
- return {
1364
- ...prop,
1365
- ...parseAttributeType(json)
1366
- };
1367
- }
1368
- if (attr.nestedType) {
1369
- return {
1370
- ...prop,
1371
- ...parseBlock(attr.nestedType)
1372
- // properties: parseBlock(attr.nestedType).properties,
1373
- };
1374
- }
1375
- throw new Error("Empty attr");
1376
- };
1377
- var parseAttributeType = (item) => {
1378
- if (Array.isArray(item)) {
1379
- const type2 = parseType(item[0]);
1380
- if (type2 === "array" || type2 === "record" && item) {
1381
- const record = item[1];
1382
- return {
1383
- type: type2,
1384
- item: parseAttributeType(record)
1385
- };
1386
- }
1387
- if (type2 === "object") {
1388
- const object = item[1];
1389
- const properties = {};
1390
- for (const [name, prop] of Object.entries(object)) {
1391
- properties[name] = parseAttributeType(prop);
1392
- }
1393
- return {
1394
- type: type2,
1395
- properties
1396
- };
1397
- }
1398
- throw new Error("Invalid attribute type");
1399
- }
1400
- const type = parseType(item);
1401
- if (isLeafType(type)) {
1402
- return {
1403
- type
1404
- };
1405
- }
1406
- throw new Error(`Invalid attribute type`);
1407
- };
1408
- var isLeafType = (type) => {
1409
- return ["string", "number", "boolean", "unknown"].includes(type);
1410
- };
1411
- var parseType = (type) => {
1412
- if (type === "string") {
1413
- return "string";
1414
- }
1415
- if (type === "number") {
1416
- return "number";
1417
- }
1418
- if (type === "bool") {
1419
- return "boolean";
1420
- }
1421
- if (["set", "list"].includes(type)) {
1422
- return "array";
1423
- }
1424
- if (type === "object") {
1425
- return "object";
1426
- }
1427
- if (type === "map") {
1428
- return "record";
1429
- }
1430
- if (type === "dynamic") {
1431
- return "unknown";
1432
- }
1433
- throw new Error(`Invalid type: ${type}`);
1434
- };
1435
-
1436
- // src/plugin/version/util.ts
1437
- import { camelCase as camelCase2, snakeCase } from "change-case";
1438
- import { pack, unpack } from "msgpackr";
1439
- var encodeDynamicValue = (value) => {
1440
- return {
1441
- msgpack: pack(value),
1442
- json: value
1443
- };
1444
- };
1445
- var decodeDynamicValue = (value) => {
1446
- return unpack(value.msgpack);
1447
- };
1448
- var getResourceSchema = (resources, type) => {
1449
- const resource = resources[type];
1450
- if (!resource) {
1451
- throw new Error(`Unknown resource type: ${type}`);
1452
- }
1453
- return resource;
1454
- };
1455
- var formatAttributePath = (state) => {
1456
- if (!state) {
1457
- return [];
1458
- }
1459
- return state.map((item) => {
1460
- if (!item.steps) {
1461
- throw new Error("AttributePath should always have steps");
1462
- }
1463
- return item.steps.map((attr) => {
1464
- if ("attributeName" in attr) {
1465
- return attr.attributeName;
1466
- }
1467
- if ("elementKeyString" in attr) {
1468
- return attr.elementKeyString;
1469
- }
1470
- if ("elementKeyInt" in attr) {
1471
- return attr.elementKeyInt;
1472
- }
1473
- throw new Error("AttributePath step should always have an element");
1474
- });
1475
- });
1476
- };
1477
- var IncorrectType = class extends TypeError {
1478
- constructor(type, path) {
1479
- super(`${path.join(".")} should be a ${type}`);
1480
- }
1481
- };
1482
- var formatInputState = (schema, state, includeSchemaFields = true, path = []) => {
1483
- if (state === null) {
1484
- return null;
1485
- }
1486
- if (typeof state === "undefined") {
1487
- return null;
1488
- }
1489
- if (schema.type === "unknown") {
1490
- return state;
1491
- }
1492
- if (schema.type === "string") {
1493
- if (typeof state === "string") {
1494
- return state;
1495
- }
1496
- throw new IncorrectType(schema.type, path);
1497
- }
1498
- if (schema.type === "number") {
1499
- if (typeof state === "number") {
1500
- return state;
1501
- }
1502
- throw new IncorrectType(schema.type, path);
1503
- }
1504
- if (schema.type === "boolean") {
1505
- if (typeof state === "boolean") {
1506
- return state;
1507
- }
1508
- throw new IncorrectType(schema.type, path);
1509
- }
1510
- if (schema.type === "array") {
1511
- if (Array.isArray(state)) {
1512
- return state.map((item, i) => formatInputState(schema.item, item, includeSchemaFields, [...path, i]));
1513
- }
1514
- throw new IncorrectType(schema.type, path);
1515
- }
1516
- if (schema.type === "record") {
1517
- if (typeof state === "object" && state !== null) {
1518
- const record = {};
1519
- for (const [key, value] of Object.entries(state)) {
1520
- record[key] = formatInputState(schema.item, value, includeSchemaFields, [...path, key]);
1521
- }
1522
- return record;
1523
- }
1524
- throw new IncorrectType(schema.type, path);
1525
- }
1526
- if (schema.type === "object" || schema.type === "array-object") {
1527
- if (typeof state === "object" && state !== null) {
1528
- const object = {};
1529
- if (includeSchemaFields) {
1530
- for (const [key, prop] of Object.entries(schema.properties)) {
1531
- const value = state[camelCase2(key)];
1532
- object[key] = formatInputState(prop, value, true, [...path, key]);
1533
- }
1534
- } else {
1535
- for (const [key, value] of Object.entries(state)) {
1536
- const prop = schema.properties[snakeCase(key)];
1537
- if (prop) {
1538
- object[key] = formatInputState(prop, value, false, [...path, key]);
1539
- }
1540
- }
1541
- }
1542
- if (schema.type === "array-object") {
1543
- return [object];
1544
- }
1545
- return object;
1546
- }
1547
- throw new IncorrectType(schema.type, path);
1548
- }
1549
- throw new Error(`Unknown schema type: ${schema.type}`);
1550
- };
1551
- var formatOutputState = (schema, state, path = []) => {
1552
- if (state === null) {
1553
- return void 0;
1554
- }
1555
- if (schema.type === "array") {
1556
- if (Array.isArray(state)) {
1557
- return state.map((item, i) => formatOutputState(schema.item, item, [...path, i]));
1558
- }
1559
- throw new IncorrectType(schema.type, path);
1560
- }
1561
- if (schema.type === "record") {
1562
- if (typeof state === "object" && state !== null) {
1563
- const record = {};
1564
- for (const [key, value] of Object.entries(state)) {
1565
- record[key] = formatOutputState(schema.item, value, [...path, key]);
1566
- }
1567
- return record;
1568
- }
1569
- throw new IncorrectType(schema.type, path);
1570
- }
1571
- if (schema.type === "object") {
1572
- if (typeof state === "object" && state !== null) {
1573
- const object = {};
1574
- for (const [key, prop] of Object.entries(schema.properties)) {
1575
- const value = state[key];
1576
- object[camelCase2(key)] = formatOutputState(prop, value, [...path, key]);
1577
- }
1578
- return object;
1579
- }
1580
- throw new IncorrectType(schema.type, path);
1581
- }
1582
- if (schema.type === "array-object") {
1583
- if (Array.isArray(state)) {
1584
- if (state.length === 1) {
1585
- const object = {};
1586
- for (const [key, prop] of Object.entries(schema.properties)) {
1587
- const value = state[0][key];
1588
- object[camelCase2(key)] = formatOutputState(prop, value, [...path, key]);
1589
- }
1590
- return object;
1591
- } else {
1592
- return void 0;
1593
- }
1594
- }
1595
- throw new IncorrectType(schema.type, path);
1596
- }
1597
- return state;
1598
- };
1599
-
1600
- // src/plugin/version/5.ts
1601
- var createPlugin5 = async ({
1602
- server,
1603
- client
1604
- }) => {
1605
- const schema = await client.call("GetSchema");
1606
- const provider = parseProviderSchema(schema.provider);
1607
- const resources = parseResourceSchema(schema.resourceSchemas);
1608
- const dataSources = parseResourceSchema(schema.dataSourceSchemas);
1609
- return {
1610
- schema() {
1611
- return {
1612
- provider,
1613
- resources,
1614
- dataSources
1615
- };
1616
- },
1617
- async stop() {
1618
- await client.call("Stop");
1619
- server.kill();
1620
- },
1621
- async configure(config) {
1622
- const prepared = await client.call("PrepareProviderConfig", {
1623
- config: encodeDynamicValue(formatInputState(provider, config))
1624
- });
1625
- await client.call("Configure", {
1626
- config: prepared.preparedConfig
1627
- });
1628
- },
1629
- async readResource(type, state) {
1630
- const schema2 = getResourceSchema(resources, type);
1631
- const read = await client.call("ReadResource", {
1632
- typeName: type,
1633
- currentState: encodeDynamicValue(formatInputState(schema2, state))
1634
- });
1635
- return formatOutputState(schema2, decodeDynamicValue(read.newState));
1636
- },
1637
- async readDataSource(type, state) {
1638
- const schema2 = getResourceSchema(dataSources, type);
1639
- const read = await client.call("ReadDataSource", {
1640
- typeName: type,
1641
- config: encodeDynamicValue(formatInputState(schema2, state))
1642
- });
1643
- return formatOutputState(schema2, decodeDynamicValue(read.state));
1644
- },
1645
- async validateResource(type, state) {
1646
- const schema2 = getResourceSchema(resources, type);
1647
- await client.call("ValidateResourceTypeConfig", {
1648
- typeName: type,
1649
- config: encodeDynamicValue(formatInputState(schema2, state))
1650
- });
1651
- },
1652
- async planResourceChange(type, priorState, proposedState) {
1653
- const schema2 = getResourceSchema(resources, type);
1654
- const preparedPriorState = formatInputState(schema2, priorState);
1655
- const preparedProposedState = formatInputState(schema2, proposedState);
1656
- const plan = await client.call("PlanResourceChange", {
1657
- typeName: type,
1658
- priorState: encodeDynamicValue(preparedPriorState),
1659
- proposedNewState: encodeDynamicValue(preparedProposedState),
1660
- config: encodeDynamicValue(preparedProposedState)
1661
- });
1662
- const plannedState = decodeDynamicValue(plan.plannedState);
1663
- const requiresReplace = formatAttributePath(plan.requiresReplace);
1664
- return {
1665
- requiresReplace,
1666
- plannedState
1667
- };
1668
- },
1669
- async applyResourceChange(type, priorState, proposedState) {
1670
- const schema2 = getResourceSchema(resources, type);
1671
- const preparedPriorState = formatInputState(schema2, priorState);
1672
- const preparedProposedState = formatInputState(schema2, proposedState);
1673
- const apply = await client.call("ApplyResourceChange", {
1674
- typeName: type,
1675
- priorState: encodeDynamicValue(preparedPriorState),
1676
- plannedState: encodeDynamicValue(preparedProposedState),
1677
- config: encodeDynamicValue(preparedProposedState)
1678
- });
1679
- return formatOutputState(schema2, decodeDynamicValue(apply.newState));
1680
- }
1681
- };
1682
- };
1683
-
1684
- // src/plugin/version/6.ts
1685
- var createPlugin6 = async ({
1686
- server,
1687
- client
1688
- }) => {
1689
- const schema = await client.call("GetProviderSchema");
1690
- const provider = parseProviderSchema(schema.provider);
1691
- const resources = parseResourceSchema(schema.resourceSchemas);
1692
- const dataSources = parseResourceSchema(schema.dataSourceSchemas);
1693
- return {
1694
- schema() {
1695
- return {
1696
- provider,
1697
- resources,
1698
- dataSources
1699
- };
1700
- },
1701
- async stop() {
1702
- await client.call("StopProvider");
1703
- server.kill();
1704
- },
1705
- async configure(config) {
1706
- const prepared = await client.call("ValidateProviderConfig", {
1707
- config: encodeDynamicValue(formatInputState(provider, config))
1708
- });
1709
- await client.call("ConfigureProvider", {
1710
- config: prepared.preparedConfig
1711
- });
1712
- },
1713
- async readResource(type, state) {
1714
- const schema2 = getResourceSchema(resources, type);
1715
- const read = await client.call("ReadResource", {
1716
- typeName: type,
1717
- currentState: encodeDynamicValue(formatInputState(schema2, state))
1718
- });
1719
- return formatOutputState(schema2, decodeDynamicValue(read.newState));
1720
- },
1721
- async readDataSource(type, state) {
1722
- const schema2 = getResourceSchema(dataSources, type);
1723
- const read = await client.call("ReadDataSource", {
1724
- typeName: type,
1725
- config: encodeDynamicValue(formatInputState(schema2, state))
1726
- });
1727
- return formatOutputState(schema2, decodeDynamicValue(read.state));
1728
- },
1729
- async validateResource(type, state) {
1730
- const schema2 = getResourceSchema(resources, type);
1731
- await client.call("ValidateResourceConfig", {
1732
- typeName: type,
1733
- config: encodeDynamicValue(formatInputState(schema2, state))
1734
- });
1735
- },
1736
- async planResourceChange(type, priorState, proposedState) {
1737
- const schema2 = getResourceSchema(resources, type);
1738
- const preparedPriorState = formatInputState(schema2, priorState);
1739
- const preparedProposedState = formatInputState(schema2, proposedState);
1740
- const plan = await client.call("PlanResourceChange", {
1741
- typeName: type,
1742
- priorState: encodeDynamicValue(preparedPriorState),
1743
- proposedNewState: encodeDynamicValue(preparedProposedState),
1744
- config: encodeDynamicValue(preparedProposedState)
1745
- });
1746
- const plannedState = decodeDynamicValue(plan.plannedState);
1747
- const requiresReplace = formatAttributePath(plan.requiresReplace);
1748
- return {
1749
- requiresReplace,
1750
- plannedState
1751
- };
1752
- },
1753
- async applyResourceChange(type, priorState, proposedState) {
1754
- const schema2 = getResourceSchema(resources, type);
1755
- const preparedPriorState = formatInputState(schema2, priorState);
1756
- const preparedProposedState = formatInputState(schema2, proposedState);
1757
- const apply = await client.call("ApplyResourceChange", {
1758
- typeName: type,
1759
- priorState: encodeDynamicValue(preparedPriorState),
1760
- plannedState: encodeDynamicValue(preparedProposedState),
1761
- config: encodeDynamicValue(preparedProposedState)
1762
- });
1763
- return formatOutputState(schema2, decodeDynamicValue(apply.newState));
1764
- }
1765
- // async applyResourceChange(
1766
- // type: string,
1767
- // priorState: Record<string, unknown> | null,
1768
- // proposedState: Record<string, unknown> | null
1769
- // ) {
1770
- // const schema = getResourceSchema(resources, type)
1771
- // const preparedPriorState = formatInputState(schema, priorState)
1772
- // const preparedProposedState = formatInputState(schema, proposedState)
1773
- // const plan = await client.call('PlanResourceChange', {
1774
- // typeName: type,
1775
- // priorState: encodeDynamicValue(preparedPriorState),
1776
- // proposedNewState: encodeDynamicValue(preparedProposedState),
1777
- // config: encodeDynamicValue(preparedProposedState),
1778
- // })
1779
- // const plannedState = decodeDynamicValue(plan.plannedState)
1780
- // const apply = await client.call('ApplyResourceChange', {
1781
- // typeName: type,
1782
- // priorState: encodeDynamicValue(preparedPriorState),
1783
- // plannedState: encodeDynamicValue(plannedState),
1784
- // config: encodeDynamicValue(plannedState),
1785
- // })
1786
- // return formatOutputState(schema, decodeDynamicValue(apply.newState))
1787
- // },
1788
- };
1789
- };
1790
-
1791
- // src/lazy-plugin.ts
1792
- var createLazyPlugin = (props) => {
1793
- return async () => {
1794
- const { file } = await downloadPlugin(props);
1795
- const server = await retry(3, () => createPluginServer({ file, debug: false }));
1796
- const client = await retry(3, () => createPluginClient(server));
1797
- const plugins = {
1798
- 5: () => createPlugin5({ server, client }),
1799
- 6: () => createPlugin6({ server, client })
1800
- };
1801
- const plugin = await plugins[server.version]?.();
1802
- if (!plugin) {
1803
- throw new Error(`No plugin client available for protocol version ${server.version}`);
1804
- }
1805
- return plugin;
1806
- };
1807
- };
1808
- var retry = async (tries, cb) => {
1809
- let latestError;
1810
- while (--tries) {
1811
- try {
1812
- const result = await cb();
1813
- return result;
1814
- } catch (error) {
1815
- latestError = error;
1816
- }
1817
- }
1818
- throw latestError;
1819
- };
1820
-
1821
- // src/proxy.ts
1822
- var createResourceProxy = (cb) => {
1823
- return new Proxy(
1824
- {},
1825
- {
1826
- get(_, key) {
1827
- return cb(key);
1828
- },
1829
- set(_, key) {
1830
- if (typeof key === "string") {
1831
- throw new Error(`Cannot set property ${key} on read-only object.`);
1832
- }
1833
- throw new Error(`This object is read-only.`);
1834
- }
1835
- }
1836
- );
1837
- };
1838
- var createNamespaceProxy = (cb) => {
1839
- const cache = /* @__PURE__ */ new Map();
1840
- return new Proxy(
1841
- {},
1842
- {
1843
- get(_, key) {
1844
- if (typeof key === "string") {
1845
- if (!cache.has(key)) {
1846
- const value = cb(key);
1847
- cache.set(key, value);
1848
- }
1849
- return cache.get(key);
1850
- }
1851
- return;
1852
- },
1853
- set(_, key) {
1854
- if (typeof key === "string") {
1855
- throw new Error(`Cannot set property ${key} on read-only object.`);
1856
- }
1857
- throw new Error(`This object is read-only.`);
1858
- }
1859
- }
1860
- );
1861
- };
1862
- var createRootProxy = (apply, get) => {
1863
- const cache = /* @__PURE__ */ new Map();
1864
- return new Proxy(() => {
1865
- }, {
1866
- apply(_, _this, args) {
1867
- return apply(...args);
1868
- },
1869
- get(_, key) {
1870
- if (typeof key === "string") {
1871
- if (!cache.has(key)) {
1872
- const value = get(key);
1873
- cache.set(key, value);
1874
- }
1875
- return cache.get(key);
1876
- }
1877
- return;
1878
- }
1879
- });
1880
- };
1881
- var createClassProxy = (construct, get) => {
1882
- return new Proxy(class {
1883
- }, {
1884
- construct(_, args) {
1885
- return construct(...args);
1886
- },
1887
- get(_, key) {
1888
- if (key === "get") {
1889
- return (...args) => {
1890
- return get(...args);
1891
- };
1892
- }
1893
- return;
1894
- }
1895
- });
1896
- };
1897
- var createRecursiveProxy = ({
1898
- provider,
1899
- install,
1900
- uninstall,
1901
- isInstalled,
1902
- resource,
1903
- dataSource
1904
- }) => {
1905
- const findNextProxy = (ns, name) => {
1906
- if (name === name.toLowerCase()) {
1907
- return createNamespaceProxy((key) => {
1908
- return findNextProxy([...ns, name], key);
1909
- });
1910
- } else if (name.startsWith("get")) {
1911
- return (...args) => {
1912
- return dataSource([...ns, name.substring(3)], ...args);
1913
- };
1914
- } else {
1915
- return createClassProxy(
1916
- (...args) => {
1917
- return resource([...ns, name], ...args);
1918
- },
1919
- (...args) => {
1920
- return dataSource([...ns, name], ...args);
1921
- }
1922
- );
1923
- }
1924
- };
1925
- return createRootProxy(provider, (key) => {
1926
- if (key === "install") {
1927
- return install;
1928
- }
1929
- if (key === "uninstall") {
1930
- return uninstall;
1931
- }
1932
- if (key === "isInstalled") {
1933
- return isInstalled;
1934
- }
1935
- return findNextProxy([], key);
1936
- });
1937
- };
1938
- var createTerraformProxy = (props) => {
1939
- return createRecursiveProxy({
1940
- provider(input, config) {
1941
- return new TerraformProvider(
1942
- props.namespace,
1943
- config?.id ?? "default",
1944
- createLazyPlugin({
1945
- ...props.provider,
1946
- location: config?.location
1947
- }),
1948
- input
1949
- );
1950
- },
1951
- async install(installProps) {
1952
- await downloadPlugin({ ...props.provider, ...installProps });
1953
- },
1954
- async uninstall(installProps) {
1955
- await deletePlugin({ ...props.provider, ...installProps });
1956
- },
1957
- isInstalled(installProps) {
1958
- return isPluginInstalled({ ...props.provider, ...installProps });
1959
- },
1960
- resource: (ns, parent, id, input, config) => {
1961
- const type = snakeCase2([props.namespace, ...ns].join("_"));
1962
- const provider = `terraform:${props.namespace}:${config?.provider ?? "default"}`;
1963
- const meta = createMeta("resource", provider, parent, type, id, input, config);
1964
- const resource = createResourceProxy((key) => {
1965
- if (typeof key === "string") {
1966
- return meta.output((data) => data[key]);
1967
- } else if (key === nodeMetaSymbol) {
1968
- return meta;
1969
- }
1970
- return;
1971
- });
1972
- parent.add(resource);
1973
- return resource;
1974
- },
1975
- dataSource: (ns, parent, id, input, config) => {
1976
- const type = snakeCase2([props.namespace, ...ns].join("_"));
1977
- const provider = `terraform:${props.namespace}:${config?.provider ?? "default"}`;
1978
- const meta = createMeta("data", provider, parent, type, id, input, config);
1979
- const dataSource = createResourceProxy((key) => {
1980
- if (typeof key === "string") {
1981
- return meta.output((data) => data[key]);
1982
- } else if (key === nodeMetaSymbol) {
1983
- return meta;
1984
- }
1985
- return;
1986
- });
1987
- parent.add(dataSource);
1988
- return dataSource;
1989
- }
1990
- });
1991
- };
1992
- export {
1993
- TerraformProvider,
1994
- createTerraformProxy,
1995
- generateTypes
1996
- };