@cdktn/provider-generator 0.24.0-pre.9 → 0.24.0-pre.90

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 (124) hide show
  1. package/.spec.swcrc +22 -0
  2. package/LICENSE +355 -0
  3. package/README.md +1 -1
  4. package/build/__tests__/edge-provider-schema/builder.d.ts +9 -3
  5. package/build/__tests__/edge-provider-schema/builder.js +6 -3
  6. package/build/__tests__/edge-provider-schema/cli.js +8 -3
  7. package/build/__tests__/edge-provider-schema/index.js +119 -1
  8. package/build/__tests__/provider.test.js +4 -1
  9. package/build/get/__tests__/generator/ephemeral-resources.test.d.ts +2 -0
  10. package/build/get/__tests__/generator/ephemeral-resources.test.js +49 -0
  11. package/build/get/__tests__/generator/module-generator.test.js +12 -12
  12. package/build/get/__tests__/generator/provider-functions.test.d.ts +2 -0
  13. package/build/get/__tests__/generator/provider-functions.test.js +176 -0
  14. package/build/get/__tests__/generator/provider-source-matching.test.d.ts +2 -0
  15. package/build/get/__tests__/generator/provider-source-matching.test.js +45 -0
  16. package/build/get/__tests__/generator/provider.test.js +9 -1
  17. package/build/get/__tests__/generator/supported-stored-classes.test.d.ts +2 -0
  18. package/build/get/__tests__/generator/supported-stored-classes.test.js +137 -0
  19. package/build/get/__tests__/generator/types.test.js +44 -1
  20. package/build/get/__tests__/generator/write-only.test.d.ts +2 -0
  21. package/build/get/__tests__/generator/write-only.test.js +65 -0
  22. package/build/get/__tests__/target-versions.test.d.ts +2 -0
  23. package/build/get/__tests__/target-versions.test.js +171 -0
  24. package/build/get/constructs-maker.d.ts +8 -1
  25. package/build/get/constructs-maker.js +46 -10
  26. package/build/get/generator/emitter/attributes-emitter.d.ts +13 -2
  27. package/build/get/generator/emitter/attributes-emitter.js +71 -5
  28. package/build/get/generator/emitter/index.d.ts +1 -0
  29. package/build/get/generator/emitter/index.js +2 -1
  30. package/build/get/generator/emitter/provider-functions-emitter.d.ts +11 -0
  31. package/build/get/generator/emitter/provider-functions-emitter.js +94 -0
  32. package/build/get/generator/emitter/resource-emitter.d.ts +5 -1
  33. package/build/get/generator/emitter/resource-emitter.js +83 -7
  34. package/build/get/generator/emitter/struct-emitter.js +10 -10
  35. package/build/get/generator/models/attribute-model.d.ts +4 -0
  36. package/build/get/generator/models/attribute-model.js +50 -4
  37. package/build/get/generator/models/attribute-type-model.d.ts +24 -0
  38. package/build/get/generator/models/attribute-type-model.js +91 -5
  39. package/build/get/generator/models/index.d.ts +1 -0
  40. package/build/get/generator/models/index.js +2 -1
  41. package/build/get/generator/models/provider-function-model.d.ts +102 -0
  42. package/build/get/generator/models/provider-function-model.js +667 -0
  43. package/build/get/generator/models/resource-model.d.ts +3 -0
  44. package/build/get/generator/models/resource-model.js +13 -4
  45. package/build/get/generator/models/struct.d.ts +2 -0
  46. package/build/get/generator/models/struct.js +6 -2
  47. package/build/get/generator/models/supported-stored-classes.d.ts +5 -0
  48. package/build/get/generator/models/supported-stored-classes.js +86 -0
  49. package/build/get/generator/module-generator.js +3 -3
  50. package/build/get/generator/provider-generator.d.ts +2 -0
  51. package/build/get/generator/provider-generator.js +41 -6
  52. package/build/get/generator/resource-parser.js +3 -1
  53. package/jest.config.js +16 -9
  54. package/package.json +28 -27
  55. package/package.sh +1 -1
  56. package/src/__tests__/__snapshots__/edge-provider-schema.test.ts.snap +4 -0
  57. package/src/__tests__/__snapshots__/provider.test.ts.snap +2828 -2828
  58. package/src/__tests__/edge-provider-schema/builder.ts +201 -0
  59. package/src/__tests__/edge-provider-schema/cli.ts +51 -0
  60. package/src/__tests__/edge-provider-schema/index.ts +284 -0
  61. package/src/__tests__/edge-provider-schema.test.ts +24 -0
  62. package/src/__tests__/provider.test.ts +183 -0
  63. package/src/get/__tests__/constructs-maker.test.ts +118 -0
  64. package/src/get/__tests__/generator/__snapshots__/complex-computed-types.test.ts.snap +5 -5
  65. package/src/get/__tests__/generator/__snapshots__/ephemeral-resources.test.ts.snap +524 -0
  66. package/src/get/__tests__/generator/__snapshots__/export-sharding.test.ts.snap +3310 -3310
  67. package/src/get/__tests__/generator/__snapshots__/module-generator.test.ts.snap +355 -355
  68. package/src/get/__tests__/generator/__snapshots__/nested-types.test.ts.snap +8 -8
  69. package/src/get/__tests__/generator/__snapshots__/provider-functions.test.ts.snap +444 -0
  70. package/src/get/__tests__/generator/__snapshots__/provider.test.ts.snap +8 -8
  71. package/src/get/__tests__/generator/__snapshots__/resource-types.test.ts.snap +126 -126
  72. package/src/get/__tests__/generator/__snapshots__/skipped-attributes.test.ts.snap +17 -17
  73. package/src/get/__tests__/generator/__snapshots__/types.test.ts.snap +201 -52
  74. package/src/get/__tests__/generator/__snapshots__/write-only.test.ts.snap +262 -0
  75. package/src/get/__tests__/generator/complex-computed-types.test.ts +28 -0
  76. package/src/get/__tests__/generator/deep-nested-attributes.test.ts +56 -0
  77. package/src/get/__tests__/generator/description-escaping.test.ts +84 -0
  78. package/src/get/__tests__/generator/empty-provider-resources.test.ts +26 -0
  79. package/src/get/__tests__/generator/ephemeral-resources.test.ts +46 -0
  80. package/src/get/__tests__/generator/export-sharding.test.ts +169 -0
  81. package/src/get/__tests__/generator/fixtures/deeply-nested-collections.test.fixture.json +129 -0
  82. package/src/get/__tests__/generator/fixtures/ephemeral-resources.test.fixture.json +160 -0
  83. package/src/get/__tests__/generator/fixtures/provider-functions-collision.test.fixture.json +31 -0
  84. package/src/get/__tests__/generator/fixtures/provider-functions-synthetic.test.fixture.json +192 -0
  85. package/src/get/__tests__/generator/fixtures/provider-functions.test.fixture.json +170 -0
  86. package/src/get/__tests__/generator/fixtures/write-only.test.fixture.json +58 -0
  87. package/src/get/__tests__/generator/import-style.test.ts +129 -0
  88. package/src/get/__tests__/generator/module-generator.test.ts +528 -0
  89. package/src/get/__tests__/generator/nested-types.test.ts +54 -0
  90. package/src/get/__tests__/generator/provider-functions.test.ts +262 -0
  91. package/src/get/__tests__/generator/provider-source-matching.test.ts +84 -0
  92. package/src/get/__tests__/generator/provider.test.ts +59 -0
  93. package/src/get/__tests__/generator/resource-types.test.ts +118 -0
  94. package/src/get/__tests__/generator/skipped-attributes.test.ts +72 -0
  95. package/src/get/__tests__/generator/supported-stored-classes.test.ts +147 -0
  96. package/src/get/__tests__/generator/types.test.ts +686 -0
  97. package/src/get/__tests__/generator/versions-file.test.ts +72 -0
  98. package/src/get/__tests__/generator/write-only.test.ts +71 -0
  99. package/src/get/__tests__/target-versions.test.ts +206 -0
  100. package/src/get/__tests__/util.ts +75 -0
  101. package/src/get/constructs-maker.ts +885 -0
  102. package/src/get/generator/custom-defaults.ts +493 -0
  103. package/src/get/generator/emitter/attributes-emitter.ts +316 -0
  104. package/src/get/generator/emitter/index.ts +6 -0
  105. package/src/get/generator/emitter/provider-functions-emitter.ts +117 -0
  106. package/src/get/generator/emitter/resource-emitter.ts +330 -0
  107. package/src/get/generator/emitter/struct-emitter.ts +683 -0
  108. package/src/get/generator/loop-detection.ts +81 -0
  109. package/src/get/generator/models/attribute-model.ts +273 -0
  110. package/src/get/generator/models/attribute-type-model.ts +560 -0
  111. package/src/get/generator/models/index.ts +8 -0
  112. package/src/get/generator/models/provider-function-model.ts +872 -0
  113. package/src/get/generator/models/resource-model.ts +183 -0
  114. package/src/get/generator/models/scope.ts +54 -0
  115. package/src/get/generator/models/struct.ts +124 -0
  116. package/src/get/generator/models/supported-stored-classes.ts +88 -0
  117. package/src/get/generator/module-generator.ts +234 -0
  118. package/src/get/generator/provider-generator.ts +428 -0
  119. package/src/get/generator/resource-parser.ts +764 -0
  120. package/src/get/generator/sanitized-comments.ts +49 -0
  121. package/src/get/generator/skipped-attributes.ts +27 -0
  122. package/src/index.ts +40 -0
  123. package/src/util.ts +26 -0
  124. package/tsconfig.json +1 -2
@@ -0,0 +1,81 @@
1
+ // Copyright (c) HashiCorp, Inc
2
+ // SPDX-License-Identifier: MPL-2.0
3
+ import { AttributeModel } from "./models/attribute-model";
4
+
5
+ type AttributeIdentifier = [string, Set<string>];
6
+ const equalAttributeIdentifiers = (
7
+ x: AttributeIdentifier,
8
+ y: AttributeIdentifier,
9
+ ) =>
10
+ x[0] === y[0] &&
11
+ x[1].size === y[1].size &&
12
+ [...x[1]].every((x) => y[1].has(x));
13
+
14
+ function typeStructure(model: AttributeModel) {
15
+ if (!model.type.isComplex) {
16
+ return model.type.storedClassType;
17
+ }
18
+
19
+ return `<complex:{${model.type.struct?.attributes
20
+ .map((att) => att.name)
21
+ .sort()}}${model.type.typeModelType}>`;
22
+ }
23
+
24
+ function getAttributeIdentifier(model: AttributeModel): AttributeIdentifier {
25
+ return [
26
+ model.terraformName,
27
+ new Set(
28
+ model.type.struct!.attributes.map((a) => `${a.name}:${typeStructure(a)}`),
29
+ ),
30
+ ];
31
+ }
32
+
33
+ /**
34
+ * Detects recursive attribute schemas and returns an Object
35
+ * describing what property should be linking to which class
36
+ */
37
+ export function detectAttributeLoops(attributes: AttributeModel[]): {
38
+ [loopEntrypoint: string]: string; // attribute path to be replaced -> attribute path of the type to replace with
39
+ } {
40
+ // We aproximate a class as a set of attributes names
41
+ // This is not a perfect approximation, but it's good enough for our purposes
42
+ const redirects: Record<string, string> = {};
43
+
44
+ function depthFirstSearch(
45
+ attribute: AttributeModel,
46
+ path: string[] = [],
47
+ knownStructs: { [attributePath: string]: AttributeIdentifier } = {},
48
+ ) {
49
+ const name = attribute.terraformName;
50
+ const struct = attribute.type.struct;
51
+ if (!struct) {
52
+ return;
53
+ }
54
+
55
+ const structIdentifier = getAttributeIdentifier(attribute);
56
+ // Detect if we visited this already
57
+ const visited = Object.entries(knownStructs).find(([, attrIdentifier]) =>
58
+ equalAttributeIdentifiers(structIdentifier, attrIdentifier),
59
+ );
60
+
61
+ if (visited) {
62
+ // We have a loop, we don't need to search deeper
63
+ const toBeReplacedWith = visited[0];
64
+ const toReplace = [...path, name].join(".");
65
+ redirects[toReplace] = toBeReplacedWith;
66
+ } else {
67
+ // Search deeper
68
+ struct.attributes.forEach((a) =>
69
+ depthFirstSearch(a, [...path, name], {
70
+ ...knownStructs,
71
+ // We haven't visited this yet, add it to the list of known structs
72
+ [[...path, name].join(".")]: structIdentifier,
73
+ }),
74
+ );
75
+ }
76
+ }
77
+
78
+ attributes.forEach((attr) => depthFirstSearch(attr));
79
+
80
+ return redirects;
81
+ }
@@ -0,0 +1,273 @@
1
+ // Copyright (c) HashiCorp, Inc
2
+ // SPDX-License-Identifier: MPL-2.0
3
+ import { logger } from "@cdktn/commons";
4
+ import {
5
+ AttributeTypeModel,
6
+ CollectionAttributeTypeModel,
7
+ } from "./attribute-type-model";
8
+
9
+ export type GetterType =
10
+ | { _type: "plain" }
11
+ | {
12
+ _type: "args";
13
+ args: string;
14
+ returnType?: string;
15
+ returnStatement: string;
16
+ }
17
+ | {
18
+ _type: "stored_class";
19
+ };
20
+
21
+ export type SetterType =
22
+ | { _type: "none" }
23
+ | { _type: "set"; type: string }
24
+ | { _type: "put"; type: string }
25
+ | { _type: "stored_class"; type: string };
26
+
27
+ export interface AttributeModelOptions {
28
+ storageName: string; // private property
29
+ name: string;
30
+ type: AttributeTypeModel;
31
+ optional: boolean;
32
+ computed: boolean;
33
+ terraformName: string;
34
+ terraformFullName: string;
35
+ description?: string;
36
+ getAttCall?: string;
37
+ provider: boolean;
38
+ required: boolean;
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
41
+ }
42
+
43
+ export function escapeAttributeName(name: string) {
44
+ // `self` and `build` doesn't work in as property name in Python
45
+ if (name === "self" || name === "build") return `${name}Attribute`;
46
+ // jsii can't handle `getFoo` properties, since it's incompatible with Java
47
+ if (name.match(/^get[A-Za-z]+/)) return name.replace("get", "fetch");
48
+ // `equals` is a prohibited name in jsii
49
+ if (name === "equals") return "equalTo";
50
+ // `node` is already used by the Constructs base class
51
+ if (name === "node") return "nodeAttribute";
52
+ // `System` shadows built-in types in CSharp (see #1420)
53
+ if (name === "system") return "systemAttribute";
54
+ // `tfResourceType` is already used by resources to distinguish between different resource types
55
+ if (name === "tfResourceType") return `${name}Attribute`;
56
+ // `importFrom` has potential for common name collision with providers
57
+ if (name === "importFrom") return `${name}Attribute`;
58
+ // `move` could have common name collision with providers
59
+ if (name === "moveTo") return `${name}Attribute`;
60
+ // `software` attribute can be confused with the JSII Java runtime package (see #3115)
61
+ if (name === "software") return `${name}Attribute`;
62
+ return name;
63
+ }
64
+
65
+ export class AttributeModel {
66
+ public storageName: string; // private property
67
+ private _name: string;
68
+ public type: AttributeTypeModel;
69
+ public optional: boolean;
70
+ public computed: boolean;
71
+ public terraformName: string;
72
+ public terraformFullName: string;
73
+ private _description?: string;
74
+ public provider: boolean;
75
+ public required: boolean;
76
+ public forcePlainGetterType?: boolean;
77
+ private loggedStoredClassUnavailable = false;
78
+ public isWriteOnly: boolean;
79
+
80
+ constructor(options: AttributeModelOptions) {
81
+ this.storageName = options.storageName;
82
+ this._name = options.name;
83
+ this.type = options.type;
84
+ this.optional = options.optional;
85
+ this.computed = options.computed;
86
+ this.terraformName = options.terraformName;
87
+ this.terraformFullName = options.terraformFullName;
88
+ this._description = options.description;
89
+ this.provider = options.provider;
90
+ this.required = options.required;
91
+ this.forcePlainGetterType = options.forcePlainGetterType;
92
+ this.isWriteOnly = !!options.isWriteOnly;
93
+ }
94
+
95
+ public get typeDefinition() {
96
+ const optional = this.optional ? "?" : "";
97
+ return `${this.name}${optional}: ${this.type.inputTypeDefinition}`;
98
+ }
99
+
100
+ public get isAssignable() {
101
+ return this.required || this.optional;
102
+ }
103
+
104
+ public get isOptional(): boolean {
105
+ return this.optional;
106
+ }
107
+
108
+ public get isRequired(): boolean {
109
+ return this.required;
110
+ }
111
+
112
+ public get isProvider(): boolean {
113
+ return this.provider;
114
+ }
115
+
116
+ public get getterType(): GetterType {
117
+ let getterType: GetterType = { _type: "plain" };
118
+
119
+ if (this.forcePlainGetterType) {
120
+ return getterType;
121
+ }
122
+
123
+ if (this.isProvider) {
124
+ return getterType;
125
+ }
126
+
127
+ if (this.type.hasReferenceClass) {
128
+ getterType = {
129
+ _type: "stored_class",
130
+ };
131
+ } else if (
132
+ this.computed &&
133
+ !this.isAssignable &&
134
+ (!this.type.isTokenizable || this.type.typeModelType === "map")
135
+ ) {
136
+ if (this.type.isStoredClassUnavailable) {
137
+ // Defensive fallback: neither the composed stored class name (e.g.
138
+ // "StringListMapMap") nor a collapsed nearest-Any wrapper (e.g. "AnyMapMap")
139
+ // exists in the core cdktn package for this type. This should be rare - see
140
+ // resolveStoredClassName in supported-stored-classes.ts - so log it loudly to
141
+ // make regressions in the collapse logic visible.
142
+ if (!this.loggedStoredClassUnavailable) {
143
+ this.loggedStoredClassUnavailable = true;
144
+ logger.debug(
145
+ `No stored class (not even a collapsed nearest-Any wrapper) is available for computed attribute "${this.terraformFullName}" (composed storedClassType: "${this.type.storedClassType}"). Falling back to a plain, untyped getter.`,
146
+ );
147
+ }
148
+ } else {
149
+ getterType = {
150
+ _type: "stored_class",
151
+ };
152
+ }
153
+ }
154
+
155
+ return getterType;
156
+ }
157
+
158
+ // Reports whether this attribute's getter sits at a "stored class boundary" that is
159
+ // worth documenting: "collapsed" when a deeper, unsupported nesting was collapsed into
160
+ // the nearest typed "Any"-wrapper (e.g. "AnyMapMap"), or "fallback" when no stored class
161
+ // at all is available and a plain, untyped getter is emitted instead. Mirrors the same
162
+ // condition tree as getterType above, so it only ever reports a boundary for attributes
163
+ // that actually went through that computed-collection branch - plain getters for
164
+ // ordinary tokenizable types (e.g. list(string)) are never flagged.
165
+ public get storedClassBoundaryKind(): "collapsed" | "fallback" | undefined {
166
+ if (this.forcePlainGetterType || this.isProvider) {
167
+ return undefined;
168
+ }
169
+
170
+ if (this.type.hasReferenceClass) {
171
+ return undefined;
172
+ }
173
+
174
+ if (
175
+ this.computed &&
176
+ !this.isAssignable &&
177
+ (!this.type.isTokenizable || this.type.typeModelType === "map")
178
+ ) {
179
+ if (this.type.isStoredClassUnavailable) {
180
+ return "fallback";
181
+ }
182
+
183
+ const resolvedStoredClass = (this.type as CollectionAttributeTypeModel)
184
+ .resolvedStoredClass;
185
+ if (resolvedStoredClass?.collapsed) {
186
+ return "collapsed";
187
+ }
188
+ }
189
+
190
+ return undefined;
191
+ }
192
+
193
+ public get isStored(): boolean {
194
+ return this.isAssignable;
195
+ }
196
+
197
+ public get setterType(): SetterType {
198
+ if (!this.isStored) {
199
+ return { _type: "none" };
200
+ }
201
+
202
+ if (this.getterType._type === "stored_class") {
203
+ return {
204
+ _type: "stored_class",
205
+ type: this.type.inputTypeDefinition,
206
+ };
207
+ }
208
+
209
+ return {
210
+ _type: "set",
211
+ type: `${this.type.inputTypeDefinition}${
212
+ this.isProvider ? " | undefined" : ""
213
+ }`,
214
+ };
215
+ }
216
+
217
+ public get name(): string {
218
+ return AttributeModel.escapeName(this._name);
219
+ }
220
+
221
+ public static escapeName(name: string): string {
222
+ return escapeAttributeName(name);
223
+ }
224
+
225
+ public get description(): string | undefined {
226
+ return this._description?.replace(/'''/gi, "```");
227
+ }
228
+
229
+ public getReferencedTypes(isConfigStruct: boolean): string[] | undefined {
230
+ const attTypeStruct = this.type.struct;
231
+ if (!attTypeStruct) {
232
+ return undefined;
233
+ }
234
+
235
+ const types: string[] = [];
236
+
237
+ if (this.isAssignable) {
238
+ types.push(attTypeStruct.name);
239
+ types.push(attTypeStruct.mapperName);
240
+ types.push(attTypeStruct.hclMapperName);
241
+ }
242
+
243
+ if (
244
+ !attTypeStruct.isSingleItem &&
245
+ (attTypeStruct.nestingMode === "list" ||
246
+ attTypeStruct.nestingMode === "set")
247
+ ) {
248
+ types.push(attTypeStruct.listName);
249
+ } else if (attTypeStruct.nestingMode === "map") {
250
+ types.push(attTypeStruct.mapName);
251
+ } else if (attTypeStruct.nestingMode === "maplist") {
252
+ types.push(attTypeStruct.mapListName);
253
+ } else if (attTypeStruct.nestingMode === "mapset") {
254
+ types.push(attTypeStruct.mapListName);
255
+ } else if (attTypeStruct.nestingMode === "listmap") {
256
+ types.push(attTypeStruct.listMapName);
257
+ } else if (attTypeStruct.nestingMode === "setmap") {
258
+ types.push(attTypeStruct.listMapName);
259
+ } else if (
260
+ attTypeStruct.nestingMode === "listlist" ||
261
+ attTypeStruct.nestingMode === "listset" ||
262
+ attTypeStruct.nestingMode === "setlist" ||
263
+ attTypeStruct.nestingMode == "setset"
264
+ ) {
265
+ types.push(attTypeStruct.listListName);
266
+ } else if (!isConfigStruct) {
267
+ types.push(attTypeStruct.outputReferenceName);
268
+ }
269
+ // other types of nested collections aren't supported
270
+
271
+ return types;
272
+ }
273
+ }