@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
@@ -43,12 +43,14 @@ export class AttributesEmitter {
43
43
 
44
44
  switch (getterType._type) {
45
45
  case "plain":
46
+ this.emitWriteOnlyGetterDeprecationNotice(att);
46
47
  this.code.openBlock(`public get ${att.name}()`);
47
48
  this.code.line(`return ${this.determineGetAttCall(att)};`);
48
49
  this.code.closeBlock();
49
50
  break;
50
51
 
51
52
  case "args":
53
+ this.emitWriteOnlyGetterDeprecationNotice(att);
52
54
  this.code.openBlock(
53
55
  `public ${att.name}(${getterType.args})${
54
56
  getterType.returnType ? ": " + getterType.returnType : ""
@@ -59,6 +61,7 @@ export class AttributesEmitter {
59
61
  break;
60
62
 
61
63
  case "stored_class":
64
+ this.emitWriteOnlyGetterDeprecationNotice(att);
62
65
  this.code.openBlock(`public get ${att.name}()`);
63
66
  this.code.line(`return this.${att.storageName};`);
64
67
  this.code.closeBlock();
@@ -67,6 +70,10 @@ export class AttributesEmitter {
67
70
 
68
71
  const setterType = att.setterType;
69
72
 
73
+ // Write-only usage is registered at resolve time instead (see
74
+ // #emitToTerraform/#emitToHclTerraform and
75
+ // TerraformResource#markWriteOnlyAttribute), so setters intentionally
76
+ // emit no registration call here: they only store the value.
70
77
  switch (setterType._type) {
71
78
  case "set":
72
79
  this.code.openBlock(
@@ -123,6 +130,21 @@ export class AttributesEmitter {
123
130
  }
124
131
  }
125
132
 
133
+ // emits a @deprecated JSDoc block above a write-only attribute's getter:
134
+ // providers never persist/return write-only values, so the state-backed
135
+ // getter always reads back null by protocol contract
136
+ private emitWriteOnlyGetterDeprecationNotice(att: AttributeModel) {
137
+ if (!att.isWriteOnly) {
138
+ return;
139
+ }
140
+
141
+ const comment = sanitizedComment(this.code);
142
+ comment.line(
143
+ "@deprecated Write-only: the provider never returns this value; reading it always yields null by protocol contract. The getter remains for compatibility and will be removed in a future prebuilt-provider major.",
144
+ );
145
+ comment.end();
146
+ }
147
+
126
148
  // returns an invocation of a stored class, e.g. 'new DeplotmentMetadataOutputReference(this, "metadata")'
127
149
  private storedClassInit(att: AttributeModel) {
128
150
  return att.type.getStoredClassInitializer(att.terraformName);
@@ -204,7 +226,20 @@ export class AttributesEmitter {
204
226
  }
205
227
  }
206
228
 
207
- public emitToHclTerraform(att: AttributeModel, isStruct: boolean) {
229
+ /**
230
+ * @param canRegisterProviderFeatureUsage Whether this attribute's mapped
231
+ * value should be wrapped in `this.markWriteOnlyAttribute(...)` when it is
232
+ * write-only. Only true for attributes emitted on classes that extend
233
+ * TerraformResource (managed resources) - struct-level `xToTerraform`/
234
+ * `xToHclTerraform` functions are standalone functions with no `this` of
235
+ * that type, so they never pass this (see ResourceEmitter's
236
+ * `supportsWriteOnlyRegistration`).
237
+ */
238
+ public emitToHclTerraform(
239
+ att: AttributeModel,
240
+ isStruct: boolean,
241
+ canRegisterProviderFeatureUsage = false,
242
+ ) {
208
243
  const type = att.type;
209
244
  const context = isStruct ? "struct!" : "this";
210
245
  const name = isStruct ? att.name : att.storageName;
@@ -223,7 +258,15 @@ export class AttributesEmitter {
223
258
  ? `${varReference} === undefined ? ${customDefault} : `
224
259
  : "";
225
260
 
226
- const value = `${defaultCheck}${type.toHclTerraformFunction}(${varReference})`;
261
+ const mappedValue = `${defaultCheck}${type.toHclTerraformFunction}(${varReference})`;
262
+ // markWriteOnlyAttribute() passes `undefined`/`null` straight through
263
+ // unwrapped, so this keeps the "remove undefined attributes" filter in
264
+ // the caller (which checks `value.value !== undefined`) working exactly
265
+ // as before for unset/cleared write-only attributes.
266
+ const value =
267
+ att.isWriteOnly && canRegisterProviderFeatureUsage
268
+ ? `this.markWriteOnlyAttribute(${mappedValue})`
269
+ : mappedValue;
227
270
  const isBlock = att.type.isComplex;
228
271
  const tt = att.type.typeModelType;
229
272
 
@@ -235,7 +278,11 @@ export class AttributesEmitter {
235
278
  this.code.close("},");
236
279
  }
237
280
 
238
- public emitToTerraform(att: AttributeModel, isStruct: boolean) {
281
+ public emitToTerraform(
282
+ att: AttributeModel,
283
+ isStruct: boolean,
284
+ canRegisterProviderFeatureUsage = false,
285
+ ) {
239
286
  const type = att.type;
240
287
  const context = isStruct ? "struct!" : "this";
241
288
  const name = isStruct ? att.name : att.storageName;
@@ -254,8 +301,16 @@ export class AttributesEmitter {
254
301
  ? `${varReference} === undefined ? ${customDefault} : `
255
302
  : "";
256
303
 
257
- this.code.line(
258
- `${att.terraformName}: ${defaultCheck}${type.toTerraformFunction}(${varReference}),`,
259
- );
304
+ const mappedValue = `${defaultCheck}${type.toTerraformFunction}(${varReference})`;
305
+ // markWriteOnlyAttribute() passes `undefined`/`null` straight through
306
+ // unwrapped, so an unset/cleared write-only attribute still vanishes
307
+ // from the returned object exactly as before (see the "skip undefined"
308
+ // step in tokens/private/resolve.ts).
309
+ const value =
310
+ att.isWriteOnly && canRegisterProviderFeatureUsage
311
+ ? `this.markWriteOnlyAttribute(${mappedValue})`
312
+ : mappedValue;
313
+
314
+ this.code.line(`${att.terraformName}: ${value},`);
260
315
  }
261
316
  }
@@ -1,5 +1,6 @@
1
1
  // Copyright (c) HashiCorp, Inc
2
2
  // SPDX-License-Identifier: MPL-2.0
3
3
  export * from "./attributes-emitter";
4
+ export * from "./provider-functions-emitter";
4
5
  export * from "./resource-emitter";
5
6
  export * from "./struct-emitter";
@@ -0,0 +1,117 @@
1
+ // Copyright (c) HashiCorp, Inc
2
+ // SPDX-License-Identifier: MPL-2.0
3
+ import { CodeMaker } from "codemaker";
4
+ import {
5
+ ProviderFunctionModel,
6
+ ProviderFunctionsModel,
7
+ } from "../models/provider-function-model";
8
+ import { sanitizedComment } from "../sanitized-comments";
9
+
10
+ const PROVIDER_LOCAL_NAME_JSDOC =
11
+ "The local name of the provider in required_providers; defaults to the registry short name. Override when the provider is declared under a different local name — aliases do not change the namespace, local names do.";
12
+
13
+ export class ProviderFunctionsEmitter {
14
+ constructor(private readonly code: CodeMaker) {}
15
+
16
+ public emit(model: ProviderFunctionsModel) {
17
+ this.code.line(`import * as cdktn from 'cdktn';`);
18
+ this.code.line();
19
+ this.emitClass(model);
20
+ }
21
+
22
+ private emitClass(model: ProviderFunctionsModel) {
23
+ const comment = sanitizedComment(this.code);
24
+ comment.line(
25
+ `Provider-defined functions of the ${model.providerName} provider.`,
26
+ );
27
+ comment.end();
28
+ this.code.openBlock(`export class ${model.className}`);
29
+
30
+ this.emitConstructor();
31
+
32
+ for (const fn of model.functions) {
33
+ this.emitMethod(fn);
34
+ }
35
+
36
+ this.code.closeBlock();
37
+ }
38
+
39
+ private emitConstructor() {
40
+ // A TypeScript parameter property (`constructor(private readonly x: T)`)
41
+ // requires the compiler to synthesize a `this.x = x;` assignment - that's
42
+ // a real transform, not a type-only erasure, so it isn't recognized by
43
+ // Node's native type-stripping (`node file.ts` with no bundler/transpiler,
44
+ // e.g. `--experimental-strip-types`), which throws
45
+ // `ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX` on sight of one. Declare the field
46
+ // and assign it in the constructor body instead, which strips cleanly.
47
+ this.code.line(`private readonly providerLocalName: string;`);
48
+ this.code.line();
49
+ const comment = sanitizedComment(this.code);
50
+ comment.line(`@param providerLocalName ${PROVIDER_LOCAL_NAME_JSDOC}`);
51
+ comment.end();
52
+ this.code.openBlock(`constructor(providerLocalName: string)`);
53
+ this.code.line(`this.providerLocalName = providerLocalName;`);
54
+ this.code.closeBlock();
55
+ }
56
+
57
+ private emitMethod(fn: ProviderFunctionModel) {
58
+ this.code.line();
59
+
60
+ const comment = sanitizedComment(this.code);
61
+ const description = fn.description ?? fn.summary;
62
+ if (description) comment.line(description);
63
+ if (fn.deprecationMessage) {
64
+ comment.line(`@deprecated ${fn.deprecationMessage}`);
65
+ }
66
+ // The variadic parameter's docstringType is already wrapped in
67
+ // `Array<...>` by buildFunctionModel (see provider-function-model.ts),
68
+ // so it shares this one `@param` emission path with every fixed
69
+ // parameter instead of needing its own wrapping here.
70
+ const allParameters = fn.variadicParameter
71
+ ? [...fn.parameters, fn.variadicParameter]
72
+ : fn.parameters;
73
+ for (const param of allParameters) {
74
+ // Official JSDoc grammar: only the type expression goes inside the
75
+ // braces; prose (the schema description plus any generated
76
+ // list/set/nullability guidance - see the model's `docstringNote`)
77
+ // follows the parameter name after ` - `.
78
+ const prose = [param.description, param.docstringNote]
79
+ .filter(Boolean)
80
+ .join(" ");
81
+ comment.line(
82
+ `@param {${param.docstringType}} ${param.name}${prose ? ` - ${prose}` : ""}`,
83
+ );
84
+ }
85
+ comment.line(
86
+ `@returns {${fn.returnDocstringType}}${fn.returnDocstringNote ? ` ${fn.returnDocstringNote}` : ""}`,
87
+ );
88
+ comment.end();
89
+
90
+ const methodParams = [
91
+ ...fn.parameters.map(
92
+ (p) => `${p.name}${p.optional ? "?" : ""}: ${p.tsType}`,
93
+ ),
94
+ ...(fn.variadicParameter
95
+ ? // `Array<T>` rather than `T[]`: for a union element type (e.g.
96
+ // `boolean | cdktn.IResolvable`), bare `T[]` binds as `boolean |
97
+ // (cdktn.IResolvable[])` instead of `(boolean | cdktn.IResolvable)[]`.
98
+ [
99
+ `${fn.variadicParameter.name}: Array<${fn.variadicParameter.tsType}>`,
100
+ ]
101
+ : []),
102
+ ];
103
+
104
+ const invokeArgs = [
105
+ ...fn.parameters.map((p) => p.name),
106
+ ...(fn.variadicParameter ? [`...${fn.variadicParameter.name}`] : []),
107
+ ];
108
+
109
+ const invokeExpression = `cdktn.TerraformProviderFunction.invoke(this.providerLocalName, "${fn.terraformName}", [${invokeArgs.join(", ")}])`;
110
+
111
+ this.code.openBlock(
112
+ `public ${fn.methodName}(${methodParams.join(", ")}): ${fn.returnTsType}`,
113
+ );
114
+ this.code.line(`return ${fn.wrapReturn(invokeExpression)};`);
115
+ this.code.closeBlock();
116
+ }
117
+ }
@@ -8,12 +8,26 @@ import { sanitizedComment } from "../sanitized-comments";
8
8
  export class ResourceEmitter {
9
9
  attributesEmitter: AttributesEmitter;
10
10
 
11
- constructor(private readonly code: CodeMaker) {
11
+ constructor(
12
+ private readonly code: CodeMaker,
13
+ private readonly importExtension: string,
14
+ ) {
12
15
  this.attributesEmitter = new AttributesEmitter(this.code);
13
16
  }
14
17
 
15
18
  public emit(resource: ResourceModel) {
16
19
  this.code.line();
20
+
21
+ if (resource.isProvider && resource.providerFunctionsModel) {
22
+ // Sibling-directory import: providers/<provider>/provider/index.ts
23
+ // (the emitted file) and providers/<provider>/provider-functions/
24
+ // index.ts are siblings under providers/<provider>/, so unlike the
25
+ // child-folder struct imports this one has to step up a level.
26
+ this.code.line(
27
+ `import { ${resource.providerFunctionsModel.className} } from '../provider-functions/index${this.importExtension}';`,
28
+ );
29
+ }
30
+
17
31
  const comment = sanitizedComment(this.code);
18
32
  comment.line(
19
33
  `Represents a {@link ${resource.linkToDocs} ${resource.terraformResourceType}}`,
@@ -26,8 +40,10 @@ export class ResourceEmitter {
26
40
  this.emitHeader("STATIC PROPERTIES");
27
41
  this.emitStaticProperties(resource);
28
42
 
29
- this.emitHeader("STATIC Methods");
30
- this.emitStaticMethods(resource);
43
+ if (!resource.isEphemeralResource) {
44
+ this.emitHeader("STATIC Methods");
45
+ this.emitStaticMethods(resource);
46
+ }
31
47
 
32
48
  this.emitHeader("INITIALIZER");
33
49
  this.emitInitializer(resource);
@@ -35,6 +51,11 @@ export class ResourceEmitter {
35
51
  this.emitHeader("ATTRIBUTES");
36
52
  this.emitResourceAttributes(resource);
37
53
 
54
+ if (resource.isProvider && resource.providerFunctionsModel) {
55
+ this.emitHeader("PROVIDER-DEFINED FUNCTIONS");
56
+ this.emitFunctionsGetter(resource.providerFunctionsModel);
57
+ }
58
+
38
59
  // synthesis
39
60
  this.emitHeader("SYNTHESIS");
40
61
  this.emitResourceSynthesis(resource);
@@ -43,6 +64,38 @@ export class ResourceEmitter {
43
64
  this.code.closeBlock(); // construct
44
65
  }
45
66
 
67
+ // Emits a memoized `functions` getter on a provider class that declares
68
+ // provider-defined functions. The local name to invoke functions under is
69
+ // derived from `this.terraformResourceType`, not baked in as the schema
70
+ // name constant: terraform-provider.ts keys both `required_providers` and
71
+ // the `provider` block directly off `terraformResourceType`, so whatever
72
+ // this instance's `terraformResourceType` is IS its correct
73
+ // required_providers local name (it already accounts for a `name`
74
+ // override in the cdktf.json provider constraint, see
75
+ // ConstructsMakerProviderTarget/TerraformProviderConstraint) - the
76
+ // instance always knows its own correct local name, so there is no need
77
+ // for a providerLocalName override parameter here.
78
+ private emitFunctionsGetter(
79
+ model: NonNullable<ResourceModel["providerFunctionsModel"]>,
80
+ ) {
81
+ this.code.line(`private _functions?: ${model.className};`);
82
+ this.code.line();
83
+
84
+ const comment = sanitizedComment(this.code);
85
+ comment.line(
86
+ `Provider-defined functions of the ${model.providerName} provider.`,
87
+ );
88
+ comment.end();
89
+ this.code.openBlock(`public get functions(): ${model.className}`);
90
+ this.code.openBlock(`if (!this._functions)`);
91
+ this.code.line(
92
+ `this._functions = new ${model.className}(this.terraformResourceType);`,
93
+ );
94
+ this.code.closeBlock();
95
+ this.code.line(`return this._functions;`);
96
+ this.code.closeBlock();
97
+ }
98
+
46
99
  private emitHeader(title: string) {
47
100
  this.code.line();
48
101
  this.code.line("// " + "=".repeat(title.length));
@@ -86,8 +139,13 @@ export class ResourceEmitter {
86
139
  );
87
140
  this.code.open(`const attrs = {`);
88
141
 
142
+ const registerWriteOnlyUsage = this.supportsWriteOnlyRegistration(resource);
89
143
  for (const att of resource.synthesizableAttributes) {
90
- this.attributesEmitter.emitToHclTerraform(att, false);
144
+ this.attributesEmitter.emitToHclTerraform(
145
+ att,
146
+ false,
147
+ registerWriteOnlyUsage,
148
+ );
91
149
  }
92
150
 
93
151
  this.code.close(`};`);
@@ -112,14 +170,38 @@ export class ResourceEmitter {
112
170
  );
113
171
  this.code.open(`return {`);
114
172
 
173
+ const registerWriteOnlyUsage = this.supportsWriteOnlyRegistration(resource);
115
174
  for (const att of resource.synthesizableAttributes) {
116
- this.attributesEmitter.emitToTerraform(att, false);
175
+ this.attributesEmitter.emitToTerraform(
176
+ att,
177
+ false,
178
+ registerWriteOnlyUsage,
179
+ );
117
180
  }
118
181
 
119
182
  this.code.close(`};`);
120
183
  this.code.closeBlock();
121
184
  }
122
185
 
186
+ // `markWriteOnlyAttribute` (called from generated `synthesizeAttributes()`/
187
+ // `synthesizeHclAttributes()` for write-only attributes, see
188
+ // AttributesEmitter#emitToTerraform/#emitToHclTerraform) lives on
189
+ // TerraformResource - so only managed resources can register write-only
190
+ // usage; data sources, providers, and ephemeral resources only get the
191
+ // deprecated getter.
192
+ //
193
+ // write-only is fundamentally a state concept - the value is passed to
194
+ // the provider but never persisted to state - so gating this on
195
+ // TerraformResource is a semantic choice, not a capability one: ephemeral
196
+ // resources have no state at all, and, consistent with that, no provider
197
+ // schema in the RFC-04 sweep (including vault's 16 ephemeral resources)
198
+ // marks an ephemeral attribute write_only. So ephemeral classes
199
+ // deliberately land in the same "getter only" bucket as data sources and
200
+ // providers.
201
+ private supportsWriteOnlyRegistration(resource: ResourceModel): boolean {
202
+ return resource.parentClassName === "TerraformResource";
203
+ }
204
+
123
205
  private emitResourceAttributes(resource: ResourceModel) {
124
206
  for (const att of resource.attributes) {
125
207
  this.attributesEmitter.emit(
@@ -136,7 +218,13 @@ export class ResourceEmitter {
136
218
  comment.line(
137
219
  `Create a new {@link ${resource.linkToDocs} ${
138
220
  resource.terraformResourceType
139
- }} ${resource.isDataSource ? "Data Source" : "Resource"}`,
221
+ }} ${
222
+ resource.isDataSource
223
+ ? "Data Source"
224
+ : resource.isEphemeralResource
225
+ ? "Ephemeral Resource"
226
+ : "Resource"
227
+ }`,
140
228
  );
141
229
  comment.line(``);
142
230
  comment.line(`@param scope The scope in which to define this construct`);
@@ -151,6 +239,8 @@ export class ResourceEmitter {
151
239
 
152
240
  if (resource.isProvider) {
153
241
  this.emitProviderSuper(resource);
242
+ } else if (resource.isEphemeralResource) {
243
+ this.emitEphemeralResourceSuper(resource);
154
244
  } else {
155
245
  this.emitResourceSuper(resource);
156
246
  }
@@ -185,6 +275,20 @@ export class ResourceEmitter {
185
275
  this.code.close(`});`);
186
276
  }
187
277
 
278
+ private emitEphemeralResourceSuper(resource: ResourceModel) {
279
+ this.code.open(`super(scope, id, {`);
280
+ this.code.line(
281
+ `terraformResourceType: '${resource.terraformResourceType}',`,
282
+ );
283
+ this.emitTerraformGeneratorMetadata(resource);
284
+ this.code.line(`provider: config.provider,`);
285
+ this.code.line(`dependsOn: config.dependsOn,`);
286
+ this.code.line(`count: config.count,`);
287
+ this.code.line(`lifecycle: config.lifecycle,`);
288
+ this.code.line(`forEach: config.forEach`);
289
+ this.code.close(`});`);
290
+ }
291
+
188
292
  private emitProviderSuper(resource: ResourceModel) {
189
293
  this.code.open(`super(scope, id, {`);
190
294
  this.code.line(
@@ -37,6 +37,7 @@ export interface AttributeModelOptions {
37
37
  provider: boolean;
38
38
  required: boolean;
39
39
  forcePlainGetterType?: boolean; // used for skipping attribute type attributes that use the SkippedAttributeTypeModel which returns an interpolation and has no stored type
40
+ isWriteOnly?: boolean; // provider protocol write-only attribute: providers never persist/return its value, see RFC-04
40
41
  }
41
42
 
42
43
  export function escapeAttributeName(name: string) {
@@ -74,6 +75,7 @@ export class AttributeModel {
74
75
  public required: boolean;
75
76
  public forcePlainGetterType?: boolean;
76
77
  private loggedStoredClassUnavailable = false;
78
+ public isWriteOnly: boolean;
77
79
 
78
80
  constructor(options: AttributeModelOptions) {
79
81
  this.storageName = options.storageName;
@@ -87,6 +89,7 @@ export class AttributeModel {
87
89
  this.provider = options.provider;
88
90
  this.required = options.required;
89
91
  this.forcePlainGetterType = options.forcePlainGetterType;
92
+ this.isWriteOnly = !!options.isWriteOnly;
90
93
  }
91
94
 
92
95
  public get typeDefinition() {
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: MPL-2.0
3
3
  export * from "./attribute-model";
4
4
  export * from "./attribute-type-model";
5
+ export * from "./provider-function-model";
5
6
  export * from "./resource-model";
6
7
  export * from "./scope";
7
8
  export * from "./struct";