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