@cdktn/provider-generator 0.24.0-pre.87 → 0.24.0-pre.89

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.
Files changed (66) hide show
  1. package/build/__tests__/edge-provider-schema/builder.d.ts +9 -3
  2. package/build/__tests__/edge-provider-schema/builder.js +6 -3
  3. package/build/__tests__/edge-provider-schema/index.js +119 -1
  4. package/build/__tests__/provider.test.js +4 -1
  5. package/build/get/__tests__/generator/ephemeral-resources.test.d.ts +2 -0
  6. package/build/get/__tests__/generator/ephemeral-resources.test.js +49 -0
  7. package/build/get/__tests__/generator/provider-functions.test.d.ts +2 -0
  8. package/build/get/__tests__/generator/provider-functions.test.js +176 -0
  9. package/build/get/__tests__/generator/provider.test.js +9 -1
  10. package/build/get/__tests__/generator/write-only.test.d.ts +2 -0
  11. package/build/get/__tests__/generator/write-only.test.js +65 -0
  12. package/build/get/__tests__/target-versions.test.d.ts +2 -0
  13. package/build/get/__tests__/target-versions.test.js +171 -0
  14. package/build/get/constructs-maker.d.ts +8 -1
  15. package/build/get/constructs-maker.js +13 -4
  16. package/build/get/generator/emitter/attributes-emitter.d.ts +12 -2
  17. package/build/get/generator/emitter/attributes-emitter.js +47 -5
  18. package/build/get/generator/emitter/index.d.ts +1 -0
  19. package/build/get/generator/emitter/index.js +2 -1
  20. package/build/get/generator/emitter/provider-functions-emitter.d.ts +11 -0
  21. package/build/get/generator/emitter/provider-functions-emitter.js +94 -0
  22. package/build/get/generator/emitter/resource-emitter.d.ts +5 -1
  23. package/build/get/generator/emitter/resource-emitter.js +83 -7
  24. package/build/get/generator/models/attribute-model.d.ts +2 -0
  25. package/build/get/generator/models/attribute-model.js +2 -1
  26. package/build/get/generator/models/index.d.ts +1 -0
  27. package/build/get/generator/models/index.js +2 -1
  28. package/build/get/generator/models/provider-function-model.d.ts +102 -0
  29. package/build/get/generator/models/provider-function-model.js +667 -0
  30. package/build/get/generator/models/resource-model.d.ts +3 -0
  31. package/build/get/generator/models/resource-model.js +13 -4
  32. package/build/get/generator/models/struct.d.ts +2 -0
  33. package/build/get/generator/models/struct.js +6 -2
  34. package/build/get/generator/provider-generator.d.ts +2 -0
  35. package/build/get/generator/provider-generator.js +31 -3
  36. package/build/get/generator/resource-parser.js +3 -1
  37. package/package.json +5 -5
  38. package/src/__tests__/__snapshots__/edge-provider-schema.test.ts.snap +4 -0
  39. package/src/__tests__/edge-provider-schema/builder.ts +17 -1
  40. package/src/__tests__/edge-provider-schema/index.ts +124 -1
  41. package/src/__tests__/provider.test.ts +3 -0
  42. package/src/get/__tests__/generator/__snapshots__/ephemeral-resources.test.ts.snap +524 -0
  43. package/src/get/__tests__/generator/__snapshots__/provider-functions.test.ts.snap +444 -0
  44. package/src/get/__tests__/generator/__snapshots__/write-only.test.ts.snap +262 -0
  45. package/src/get/__tests__/generator/ephemeral-resources.test.ts +46 -0
  46. package/src/get/__tests__/generator/fixtures/ephemeral-resources.test.fixture.json +160 -0
  47. package/src/get/__tests__/generator/fixtures/provider-functions-collision.test.fixture.json +31 -0
  48. package/src/get/__tests__/generator/fixtures/provider-functions-synthetic.test.fixture.json +192 -0
  49. package/src/get/__tests__/generator/fixtures/provider-functions.test.fixture.json +170 -0
  50. package/src/get/__tests__/generator/fixtures/write-only.test.fixture.json +58 -0
  51. package/src/get/__tests__/generator/provider-functions.test.ts +262 -0
  52. package/src/get/__tests__/generator/provider.test.ts +8 -0
  53. package/src/get/__tests__/generator/write-only.test.ts +71 -0
  54. package/src/get/__tests__/target-versions.test.ts +206 -0
  55. package/src/get/constructs-maker.ts +43 -3
  56. package/src/get/generator/emitter/attributes-emitter.ts +61 -6
  57. package/src/get/generator/emitter/index.ts +1 -0
  58. package/src/get/generator/emitter/provider-functions-emitter.ts +117 -0
  59. package/src/get/generator/emitter/resource-emitter.ts +110 -6
  60. package/src/get/generator/models/attribute-model.ts +3 -0
  61. package/src/get/generator/models/index.ts +1 -0
  62. package/src/get/generator/models/provider-function-model.ts +872 -0
  63. package/src/get/generator/models/resource-model.ts +25 -3
  64. package/src/get/generator/models/struct.ts +9 -1
  65. package/src/get/generator/provider-generator.ts +70 -4
  66. package/src/get/generator/resource-parser.ts +2 -0
@@ -6,6 +6,7 @@ import { FQPN, parseFQPN, ProviderName } from "@cdktn/provider-schema";
6
6
  import { AttributeModel } from "./attribute-model";
7
7
  import { Struct, ConfigStruct } from "./struct";
8
8
  import { Schema } from "@cdktn/commons";
9
+ import { ProviderFunctionsModel } from "./provider-function-model";
9
10
 
10
11
  // Limit is 1200 to prevent stack size error.
11
12
  // Could increase now that calculation is more accurate;
@@ -42,6 +43,13 @@ export class ResourceModel {
42
43
  * to be able to use two providers with the same name
43
44
  */
44
45
  public terraformProviderName: string;
46
+ /*
47
+ * Only set (by provider-generator.ts) when isProvider is true and the
48
+ * provider schema declares provider-defined functions - drives whether
49
+ * ResourceEmitter emits the memoized `functions` getter and its
50
+ * cross-directory import of the sibling provider-functions/index.ts file.
51
+ */
52
+ public providerFunctionsModel?: ProviderFunctionsModel;
45
53
  public fileName: string;
46
54
  public attributes: AttributeModel[];
47
55
  public schema: Schema;
@@ -81,7 +89,11 @@ export class ResourceModel {
81
89
  }
82
90
 
83
91
  public get configStruct() {
84
- return new ConfigStruct(this.configStructName, this.attributes);
92
+ return new ConfigStruct(
93
+ this.configStructName,
94
+ this.attributes,
95
+ this.isEphemeralResource ? "TerraformEphemeralMetaArguments" : undefined,
96
+ );
85
97
  }
86
98
 
87
99
  public get synthesizableAttributes(): AttributeModel[] {
@@ -103,6 +115,8 @@ export class ResourceModel {
103
115
  if (this.isProvider) return base;
104
116
  if (this.isDataSource)
105
117
  return `${base}/data-sources/${this.terraformDocName}`;
118
+ if (this.isEphemeralResource)
119
+ return `${base}/ephemeral-resources/${this.terraformDocName}`;
106
120
  return `${base}/resources/${this.terraformDocName}`;
107
121
  }
108
122
 
@@ -114,12 +128,18 @@ export class ResourceModel {
114
128
  return this.terraformSchemaType === "data_source";
115
129
  }
116
130
 
131
+ public get isEphemeralResource(): boolean {
132
+ return this.terraformSchemaType === "ephemeral_resource";
133
+ }
134
+
117
135
  public get parentClassName(): string {
118
136
  return this.isProvider
119
137
  ? "TerraformProvider"
120
138
  : this.isDataSource
121
139
  ? "TerraformDataSource"
122
- : "TerraformResource";
140
+ : this.isEphemeralResource
141
+ ? "TerraformEphemeralResource"
142
+ : "TerraformResource";
123
143
  }
124
144
 
125
145
  public get terraformResourceType(): string {
@@ -127,7 +147,9 @@ export class ResourceModel {
127
147
  ? this.terraformProviderName
128
148
  : this.isDataSource
129
149
  ? this.terraformType.replace(/^data_/, "")
130
- : this.terraformType;
150
+ : this.isEphemeralResource
151
+ ? this.terraformType.replace(/^ephemeral_/, "")
152
+ : this.terraformType;
131
153
  }
132
154
 
133
155
  public get terraformDocName(): string {
@@ -110,7 +110,15 @@ export class Struct {
110
110
  }
111
111
 
112
112
  export class ConfigStruct extends Struct {
113
+ constructor(
114
+ name: string,
115
+ attributes: AttributeModel[],
116
+ private readonly extendsClass: string = "TerraformMetaArguments",
117
+ ) {
118
+ super(name, attributes);
119
+ }
120
+
113
121
  public get extends(): string {
114
- return ` extends cdktn.TerraformMetaArguments`;
122
+ return ` extends cdktn.${this.extendsClass}`;
115
123
  }
116
124
  }
@@ -10,9 +10,18 @@ import {
10
10
  TerraformProviderConstraint,
11
11
  } from "@cdktn/commons";
12
12
  import { FQPN, parseFQPN, ProviderName } from "@cdktn/provider-schema";
13
- import { ResourceModel } from "./models";
13
+ import {
14
+ ProviderFunctionsModel,
15
+ ResourceModel,
16
+ assertNoFunctionsGetterCollision,
17
+ buildProviderFunctionsModel,
18
+ } from "./models";
14
19
  import { ResourceParser } from "./resource-parser";
15
- import { ResourceEmitter, StructEmitter } from "./emitter";
20
+ import {
21
+ ProviderFunctionsEmitter,
22
+ ResourceEmitter,
23
+ StructEmitter,
24
+ } from "./emitter";
16
25
 
17
26
  export interface TerraformProviderGeneratorOptions {
18
27
  /**
@@ -101,6 +110,7 @@ export class TerraformProviderGenerator {
101
110
  private resourceParser = new ResourceParser();
102
111
  private resourceEmitter: ResourceEmitter;
103
112
  private structEmitter: StructEmitter;
113
+ private providerFunctionsEmitter: ProviderFunctionsEmitter;
104
114
  private readonly importExtension: string;
105
115
  public versions: { [fqpn: string]: string | undefined } = {};
106
116
 
@@ -111,8 +121,9 @@ export class TerraformProviderGenerator {
111
121
  ) {
112
122
  this.code.indentation = 2;
113
123
  this.importExtension = options.importExtension ?? "";
114
- this.resourceEmitter = new ResourceEmitter(this.code);
124
+ this.resourceEmitter = new ResourceEmitter(this.code, this.importExtension);
115
125
  this.structEmitter = new StructEmitter(this.code, this.importExtension);
126
+ this.providerFunctionsEmitter = new ProviderFunctionsEmitter(this.code);
116
127
  }
117
128
 
118
129
  private getProviderByConstraint(
@@ -185,7 +196,26 @@ export class TerraformProviderGenerator {
185
196
  ),
186
197
  );
187
198
 
188
- return ([] as ResourceModel[]).concat(...resources, ...dataSources);
199
+ const ephemeralResources = Object.entries(
200
+ provider.ephemeral_resource_schemas || {},
201
+ ).map(([type, resource]) =>
202
+ this.resourceParser.parse(
203
+ fqpn,
204
+ `ephemeral_${type}`,
205
+ resource,
206
+ "ephemeral_resource",
207
+ constraint,
208
+ ),
209
+ );
210
+
211
+ // CRITICAL: ephemeral resources must be appended AFTER resources and data
212
+ // sources - uniqueClassName dedup is order-dependent and existing
213
+ // prebuilt snapshots must not churn.
214
+ return ([] as ResourceModel[]).concat(
215
+ ...resources,
216
+ ...dataSources,
217
+ ...ephemeralResources,
218
+ );
189
219
  }
190
220
 
191
221
  public getClassNameForResource(terraformType: string) {
@@ -225,6 +255,16 @@ export class TerraformProviderGenerator {
225
255
  this.emitResourceReadme(resourceModel);
226
256
  });
227
257
 
258
+ // Built before the provider class is emitted (rather than after, as
259
+ // resources/data sources/ephemeral resources above already are) so that
260
+ // the model can be attached to providerResource and picked up by
261
+ // ResourceEmitter while it still emits the provider class file below -
262
+ // see the engineering brief for why this ordering matters.
263
+ const providerFunctionsModel = buildProviderFunctionsModel(
264
+ name,
265
+ provider.functions,
266
+ );
267
+
228
268
  if (provider.provider) {
229
269
  const providerResource = this.resourceParser.parse(
230
270
  fqpn,
@@ -239,14 +279,40 @@ export class TerraformProviderGenerator {
239
279
  providerResource.terraformProviderName = constraint.name;
240
280
  }
241
281
  providerResource.providerVersion = providerVersion;
282
+
283
+ if (providerFunctionsModel) {
284
+ assertNoFunctionsGetterCollision(
285
+ name,
286
+ providerResource.attributes.map((att) => att.name),
287
+ );
288
+ providerResource.providerFunctionsModel = providerFunctionsModel;
289
+ }
290
+
242
291
  files.push(this.emitResource(providerResource));
243
292
  this.emitResourceReadme(providerResource);
244
293
  }
245
294
 
295
+ if (providerFunctionsModel) {
296
+ files.push(this.emitProviderFunctions(name, providerFunctionsModel));
297
+ }
298
+
246
299
  this.emitIndexFile(name, files);
247
300
  this.emitLazyIndexFile(name, files);
248
301
  }
249
302
 
303
+ private emitProviderFunctions(
304
+ provider: ProviderName,
305
+ model: ProviderFunctionsModel,
306
+ ): string {
307
+ const filePath = `providers/${provider}/provider-functions/index.ts`;
308
+ this.code.openFile(filePath);
309
+ this.code.line(`// generated from provider function schema`);
310
+ this.code.line();
311
+ this.providerFunctionsEmitter.emit(model);
312
+ this.code.closeFile(filePath);
313
+ return filePath;
314
+ }
315
+
250
316
  private emitResourceReadme(resource: ResourceModel): void {
251
317
  const filePath = `${resource.namespaceFolderPath}/README.md`;
252
318
  this.code.openFile(filePath);
@@ -463,6 +463,7 @@ class Parser {
463
463
  provider: parentType.isProvider,
464
464
  required: !!att.required,
465
465
  forcePlainGetterType,
466
+ isWriteOnly: !!att.write_only,
466
467
  }),
467
468
  );
468
469
  }
@@ -669,6 +670,7 @@ class Parser {
669
670
  type,
670
671
  provider: parent.isProvider,
671
672
  required: required,
673
+ isWriteOnly: !!att.write_only,
672
674
  }),
673
675
  );
674
676
  }