@cdktn/provider-generator 0.24.0-pre.72 → 0.24.0-pre.75
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/build/get/__tests__/generator/supported-stored-classes.test.d.ts +2 -0
- package/build/get/__tests__/generator/supported-stored-classes.test.js +137 -0
- package/build/get/__tests__/generator/types.test.js +44 -1
- package/build/get/generator/emitter/attributes-emitter.d.ts +1 -0
- package/build/get/generator/emitter/attributes-emitter.js +25 -1
- package/build/get/generator/models/attribute-model.d.ts +2 -0
- package/build/get/generator/models/attribute-model.js +49 -4
- package/build/get/generator/models/attribute-type-model.d.ts +24 -0
- package/build/get/generator/models/attribute-type-model.js +91 -5
- package/build/get/generator/models/supported-stored-classes.d.ts +5 -0
- package/build/get/generator/models/supported-stored-classes.js +86 -0
- package/package.json +4 -4
- package/src/get/__tests__/generator/__snapshots__/types.test.ts.snap +149 -0
- package/src/get/__tests__/generator/fixtures/deeply-nested-collections.test.fixture.json +129 -0
- package/src/get/__tests__/generator/supported-stored-classes.test.ts +147 -0
- package/src/get/__tests__/generator/types.test.ts +75 -0
- package/src/get/generator/emitter/attributes-emitter.ts +37 -1
- package/src/get/generator/models/attribute-model.ts +58 -4
- package/src/get/generator/models/attribute-type-model.ts +121 -9
- package/src/get/generator/models/supported-stored-classes.ts +88 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveStoredClassName = void 0;
|
|
4
|
+
// Copyright (c) HashiCorp, Inc
|
|
5
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
6
|
+
const util_1 = require("../../../util");
|
|
7
|
+
// The core cdktn package (packages/cdktn/src/complex-computed-list.ts) only hand-writes
|
|
8
|
+
// this fixed set of wrapper classes for computed, non-complex collection attributes.
|
|
9
|
+
// Arbitrarily deep nestings of list/set/map (e.g. map(map(list(string)))) compose a
|
|
10
|
+
// storedClassType (e.g. "stringListMapMap") that has no corresponding class. Rather than
|
|
11
|
+
// falling back straight to a plain, untyped getter, resolveStoredClassName below first
|
|
12
|
+
// looks for the nearest typed "Any"-wrapper that still exists in this set, collapsing the
|
|
13
|
+
// unsupported inner shape into an untyped boundary while preserving typed navigation for
|
|
14
|
+
// the outer layers (see https://github.com/open-constructs/cdk-terrain/issues/11).
|
|
15
|
+
const SUPPORTED_STORED_CLASSES = new Set([
|
|
16
|
+
"StringMap",
|
|
17
|
+
"NumberMap",
|
|
18
|
+
"BooleanMap",
|
|
19
|
+
"AnyMap",
|
|
20
|
+
"StringMapMap",
|
|
21
|
+
"NumberMapMap",
|
|
22
|
+
"BooleanMapMap",
|
|
23
|
+
"AnyMapMap",
|
|
24
|
+
"BooleanList",
|
|
25
|
+
"StringListList",
|
|
26
|
+
"NumberListList",
|
|
27
|
+
"BooleanListList",
|
|
28
|
+
"AnyListList",
|
|
29
|
+
"StringMapList",
|
|
30
|
+
"NumberMapList",
|
|
31
|
+
"BooleanMapList",
|
|
32
|
+
"AnyMapList",
|
|
33
|
+
"StringListMap",
|
|
34
|
+
"NumberListMap",
|
|
35
|
+
"BooleanListMap",
|
|
36
|
+
"AnyListMap",
|
|
37
|
+
]);
|
|
38
|
+
// Resolves the composed stored class name to use for a collection attribute (list/set/map)
|
|
39
|
+
// whose element is itself a non-complex collection (or simple type).
|
|
40
|
+
//
|
|
41
|
+
// `ownStoredClassType` is this type's own composed storedClassType (e.g. "stringListMapMap"
|
|
42
|
+
// for map(map(list(string)))) and `elementTypeModelType` is the element's typeModelType
|
|
43
|
+
// ("list" | "set" | "map" | "simple" | ...).
|
|
44
|
+
//
|
|
45
|
+
// Resolution order:
|
|
46
|
+
// 1. The own composed name (e.g. "StringListMapMap") - used as-is when it refers to a
|
|
47
|
+
// class that is hand-written in the core package (not collapsed).
|
|
48
|
+
// 2. Otherwise, the nearest typed "Any"-wrapper that still encodes the outer two layers
|
|
49
|
+
// (this type's own layer and its element's layer), e.g. "AnyMapMap" - collapsing the
|
|
50
|
+
// unsupported inner shape into an untyped boundary while preserving typed navigation
|
|
51
|
+
// for the outer layers.
|
|
52
|
+
// 3. Otherwise (defensively; every depth should resolve via 1 or 2), undefined - the
|
|
53
|
+
// caller must fall back to a plain, untyped getter.
|
|
54
|
+
function resolveStoredClassName(ownStoredClassType, elementTypeModelType) {
|
|
55
|
+
const candidate1 = (0, util_1.uppercaseFirst)(ownStoredClassType);
|
|
56
|
+
if (SUPPORTED_STORED_CLASSES.has(candidate1)) {
|
|
57
|
+
return { name: candidate1, collapsed: false };
|
|
58
|
+
}
|
|
59
|
+
let ownLayer;
|
|
60
|
+
if (ownStoredClassType.endsWith("List")) {
|
|
61
|
+
ownLayer = "List";
|
|
62
|
+
}
|
|
63
|
+
else if (ownStoredClassType.endsWith("Map")) {
|
|
64
|
+
ownLayer = "Map";
|
|
65
|
+
}
|
|
66
|
+
if (!ownLayer) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
let innerLayer;
|
|
70
|
+
if (elementTypeModelType === "list" || elementTypeModelType === "set") {
|
|
71
|
+
innerLayer = "List";
|
|
72
|
+
}
|
|
73
|
+
else if (elementTypeModelType === "map") {
|
|
74
|
+
innerLayer = "Map";
|
|
75
|
+
}
|
|
76
|
+
if (!innerLayer) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
const candidate2 = `Any${innerLayer}${ownLayer}`;
|
|
80
|
+
if (SUPPORTED_STORED_CLASSES.has(candidate2)) {
|
|
81
|
+
return { name: candidate2, collapsed: true };
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
exports.resolveStoredClassName = resolveStoredClassName;
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VwcG9ydGVkLXN0b3JlZC1jbGFzc2VzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2dldC9nZW5lcmF0b3IvbW9kZWxzL3N1cHBvcnRlZC1zdG9yZWQtY2xhc3Nlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsbUNBQW1DO0FBQ25DLHdDQUErQztBQUUvQyx3RkFBd0Y7QUFDeEYscUZBQXFGO0FBQ3JGLG9GQUFvRjtBQUNwRix5RkFBeUY7QUFDekYsdUZBQXVGO0FBQ3ZGLDBGQUEwRjtBQUMxRix5RkFBeUY7QUFDekYsbUZBQW1GO0FBQ25GLE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDdkMsV0FBVztJQUNYLFdBQVc7SUFDWCxZQUFZO0lBQ1osUUFBUTtJQUNSLGNBQWM7SUFDZCxjQUFjO0lBQ2QsZUFBZTtJQUNmLFdBQVc7SUFDWCxhQUFhO0lBQ2IsZ0JBQWdCO0lBQ2hCLGdCQUFnQjtJQUNoQixpQkFBaUI7SUFDakIsYUFBYTtJQUNiLGVBQWU7SUFDZixlQUFlO0lBQ2YsZ0JBQWdCO0lBQ2hCLFlBQVk7SUFDWixlQUFlO0lBQ2YsZUFBZTtJQUNmLGdCQUFnQjtJQUNoQixZQUFZO0NBQ2IsQ0FBQyxDQUFDO0FBRUgsMkZBQTJGO0FBQzNGLHFFQUFxRTtBQUNyRSxFQUFFO0FBQ0YsNEZBQTRGO0FBQzVGLHdGQUF3RjtBQUN4Riw2Q0FBNkM7QUFDN0MsRUFBRTtBQUNGLG9CQUFvQjtBQUNwQix3RkFBd0Y7QUFDeEYsdUVBQXVFO0FBQ3ZFLDBGQUEwRjtBQUMxRiwwRkFBMEY7QUFDMUYsMEZBQTBGO0FBQzFGLDZCQUE2QjtBQUM3Qix1RkFBdUY7QUFDdkYseURBQXlEO0FBQ3pELFNBQWdCLHNCQUFzQixDQUNwQyxrQkFBMEIsRUFDMUIsb0JBQTRCO0lBRTVCLE1BQU0sVUFBVSxHQUFHLElBQUEscUJBQWMsRUFBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3RELElBQUksd0JBQXdCLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDN0MsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ2hELENBQUM7SUFFRCxJQUFJLFFBQW9DLENBQUM7SUFDekMsSUFBSSxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUN4QyxRQUFRLEdBQUcsTUFBTSxDQUFDO0lBQ3BCLENBQUM7U0FBTSxJQUFJLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzlDLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDbkIsQ0FBQztJQUNELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNkLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxJQUFJLFVBQXNDLENBQUM7SUFDM0MsSUFBSSxvQkFBb0IsS0FBSyxNQUFNLElBQUksb0JBQW9CLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDdEUsVUFBVSxHQUFHLE1BQU0sQ0FBQztJQUN0QixDQUFDO1NBQU0sSUFBSSxvQkFBb0IsS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUMxQyxVQUFVLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLENBQUM7SUFDRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELE1BQU0sVUFBVSxHQUFHLE1BQU0sVUFBVSxHQUFHLFFBQVEsRUFBRSxDQUFDO0lBQ2pELElBQUksd0JBQXdCLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDN0MsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDO0lBQy9DLENBQUM7SUFFRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDO0FBbkNELHdEQW1DQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgSGFzaGlDb3JwLCBJbmNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNUEwtMi4wXG5pbXBvcnQgeyB1cHBlcmNhc2VGaXJzdCB9IGZyb20gXCIuLi8uLi8uLi91dGlsXCI7XG5cbi8vIFRoZSBjb3JlIGNka3RuIHBhY2thZ2UgKHBhY2thZ2VzL2Nka3RuL3NyYy9jb21wbGV4LWNvbXB1dGVkLWxpc3QudHMpIG9ubHkgaGFuZC13cml0ZXNcbi8vIHRoaXMgZml4ZWQgc2V0IG9mIHdyYXBwZXIgY2xhc3NlcyBmb3IgY29tcHV0ZWQsIG5vbi1jb21wbGV4IGNvbGxlY3Rpb24gYXR0cmlidXRlcy5cbi8vIEFyYml0cmFyaWx5IGRlZXAgbmVzdGluZ3Mgb2YgbGlzdC9zZXQvbWFwIChlLmcuIG1hcChtYXAobGlzdChzdHJpbmcpKSkpIGNvbXBvc2UgYVxuLy8gc3RvcmVkQ2xhc3NUeXBlIChlLmcuIFwic3RyaW5nTGlzdE1hcE1hcFwiKSB0aGF0IGhhcyBubyBjb3JyZXNwb25kaW5nIGNsYXNzLiBSYXRoZXIgdGhhblxuLy8gZmFsbGluZyBiYWNrIHN0cmFpZ2h0IHRvIGEgcGxhaW4sIHVudHlwZWQgZ2V0dGVyLCByZXNvbHZlU3RvcmVkQ2xhc3NOYW1lIGJlbG93IGZpcnN0XG4vLyBsb29rcyBmb3IgdGhlIG5lYXJlc3QgdHlwZWQgXCJBbnlcIi13cmFwcGVyIHRoYXQgc3RpbGwgZXhpc3RzIGluIHRoaXMgc2V0LCBjb2xsYXBzaW5nIHRoZVxuLy8gdW5zdXBwb3J0ZWQgaW5uZXIgc2hhcGUgaW50byBhbiB1bnR5cGVkIGJvdW5kYXJ5IHdoaWxlIHByZXNlcnZpbmcgdHlwZWQgbmF2aWdhdGlvbiBmb3Jcbi8vIHRoZSBvdXRlciBsYXllcnMgKHNlZSBodHRwczovL2dpdGh1Yi5jb20vb3Blbi1jb25zdHJ1Y3RzL2Nkay10ZXJyYWluL2lzc3Vlcy8xMSkuXG5jb25zdCBTVVBQT1JURURfU1RPUkVEX0NMQVNTRVMgPSBuZXcgU2V0KFtcbiAgXCJTdHJpbmdNYXBcIixcbiAgXCJOdW1iZXJNYXBcIixcbiAgXCJCb29sZWFuTWFwXCIsXG4gIFwiQW55TWFwXCIsXG4gIFwiU3RyaW5nTWFwTWFwXCIsXG4gIFwiTnVtYmVyTWFwTWFwXCIsXG4gIFwiQm9vbGVhbk1hcE1hcFwiLFxuICBcIkFueU1hcE1hcFwiLFxuICBcIkJvb2xlYW5MaXN0XCIsXG4gIFwiU3RyaW5nTGlzdExpc3RcIixcbiAgXCJOdW1iZXJMaXN0TGlzdFwiLFxuICBcIkJvb2xlYW5MaXN0TGlzdFwiLFxuICBcIkFueUxpc3RMaXN0XCIsXG4gIFwiU3RyaW5nTWFwTGlzdFwiLFxuICBcIk51bWJlck1hcExpc3RcIixcbiAgXCJCb29sZWFuTWFwTGlzdFwiLFxuICBcIkFueU1hcExpc3RcIixcbiAgXCJTdHJpbmdMaXN0TWFwXCIsXG4gIFwiTnVtYmVyTGlzdE1hcFwiLFxuICBcIkJvb2xlYW5MaXN0TWFwXCIsXG4gIFwiQW55TGlzdE1hcFwiLFxuXSk7XG5cbi8vIFJlc29sdmVzIHRoZSBjb21wb3NlZCBzdG9yZWQgY2xhc3MgbmFtZSB0byB1c2UgZm9yIGEgY29sbGVjdGlvbiBhdHRyaWJ1dGUgKGxpc3Qvc2V0L21hcClcbi8vIHdob3NlIGVsZW1lbnQgaXMgaXRzZWxmIGEgbm9uLWNvbXBsZXggY29sbGVjdGlvbiAob3Igc2ltcGxlIHR5cGUpLlxuLy9cbi8vIGBvd25TdG9yZWRDbGFzc1R5cGVgIGlzIHRoaXMgdHlwZSdzIG93biBjb21wb3NlZCBzdG9yZWRDbGFzc1R5cGUgKGUuZy4gXCJzdHJpbmdMaXN0TWFwTWFwXCJcbi8vIGZvciBtYXAobWFwKGxpc3Qoc3RyaW5nKSkpKSBhbmQgYGVsZW1lbnRUeXBlTW9kZWxUeXBlYCBpcyB0aGUgZWxlbWVudCdzIHR5cGVNb2RlbFR5cGVcbi8vIChcImxpc3RcIiB8IFwic2V0XCIgfCBcIm1hcFwiIHwgXCJzaW1wbGVcIiB8IC4uLikuXG4vL1xuLy8gUmVzb2x1dGlvbiBvcmRlcjpcbi8vICAgMS4gVGhlIG93biBjb21wb3NlZCBuYW1lIChlLmcuIFwiU3RyaW5nTGlzdE1hcE1hcFwiKSAtIHVzZWQgYXMtaXMgd2hlbiBpdCByZWZlcnMgdG8gYVxuLy8gICAgICBjbGFzcyB0aGF0IGlzIGhhbmQtd3JpdHRlbiBpbiB0aGUgY29yZSBwYWNrYWdlIChub3QgY29sbGFwc2VkKS5cbi8vICAgMi4gT3RoZXJ3aXNlLCB0aGUgbmVhcmVzdCB0eXBlZCBcIkFueVwiLXdyYXBwZXIgdGhhdCBzdGlsbCBlbmNvZGVzIHRoZSBvdXRlciB0d28gbGF5ZXJzXG4vLyAgICAgICh0aGlzIHR5cGUncyBvd24gbGF5ZXIgYW5kIGl0cyBlbGVtZW50J3MgbGF5ZXIpLCBlLmcuIFwiQW55TWFwTWFwXCIgLSBjb2xsYXBzaW5nIHRoZVxuLy8gICAgICB1bnN1cHBvcnRlZCBpbm5lciBzaGFwZSBpbnRvIGFuIHVudHlwZWQgYm91bmRhcnkgd2hpbGUgcHJlc2VydmluZyB0eXBlZCBuYXZpZ2F0aW9uXG4vLyAgICAgIGZvciB0aGUgb3V0ZXIgbGF5ZXJzLlxuLy8gICAzLiBPdGhlcndpc2UgKGRlZmVuc2l2ZWx5OyBldmVyeSBkZXB0aCBzaG91bGQgcmVzb2x2ZSB2aWEgMSBvciAyKSwgdW5kZWZpbmVkIC0gdGhlXG4vLyAgICAgIGNhbGxlciBtdXN0IGZhbGwgYmFjayB0byBhIHBsYWluLCB1bnR5cGVkIGdldHRlci5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU3RvcmVkQ2xhc3NOYW1lKFxuICBvd25TdG9yZWRDbGFzc1R5cGU6IHN0cmluZyxcbiAgZWxlbWVudFR5cGVNb2RlbFR5cGU6IHN0cmluZyxcbik6IHsgbmFtZTogc3RyaW5nOyBjb2xsYXBzZWQ6IGJvb2xlYW4gfSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGNhbmRpZGF0ZTEgPSB1cHBlcmNhc2VGaXJzdChvd25TdG9yZWRDbGFzc1R5cGUpO1xuICBpZiAoU1VQUE9SVEVEX1NUT1JFRF9DTEFTU0VTLmhhcyhjYW5kaWRhdGUxKSkge1xuICAgIHJldHVybiB7IG5hbWU6IGNhbmRpZGF0ZTEsIGNvbGxhcHNlZDogZmFsc2UgfTtcbiAgfVxuXG4gIGxldCBvd25MYXllcjogXCJMaXN0XCIgfCBcIk1hcFwiIHwgdW5kZWZpbmVkO1xuICBpZiAob3duU3RvcmVkQ2xhc3NUeXBlLmVuZHNXaXRoKFwiTGlzdFwiKSkge1xuICAgIG93bkxheWVyID0gXCJMaXN0XCI7XG4gIH0gZWxzZSBpZiAob3duU3RvcmVkQ2xhc3NUeXBlLmVuZHNXaXRoKFwiTWFwXCIpKSB7XG4gICAgb3duTGF5ZXIgPSBcIk1hcFwiO1xuICB9XG4gIGlmICghb3duTGF5ZXIpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgbGV0IGlubmVyTGF5ZXI6IFwiTGlzdFwiIHwgXCJNYXBcIiB8IHVuZGVmaW5lZDtcbiAgaWYgKGVsZW1lbnRUeXBlTW9kZWxUeXBlID09PSBcImxpc3RcIiB8fCBlbGVtZW50VHlwZU1vZGVsVHlwZSA9PT0gXCJzZXRcIikge1xuICAgIGlubmVyTGF5ZXIgPSBcIkxpc3RcIjtcbiAgfSBlbHNlIGlmIChlbGVtZW50VHlwZU1vZGVsVHlwZSA9PT0gXCJtYXBcIikge1xuICAgIGlubmVyTGF5ZXIgPSBcIk1hcFwiO1xuICB9XG4gIGlmICghaW5uZXJMYXllcikge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBjYW5kaWRhdGUyID0gYEFueSR7aW5uZXJMYXllcn0ke293bkxheWVyfWA7XG4gIGlmIChTVVBQT1JURURfU1RPUkVEX0NMQVNTRVMuaGFzKGNhbmRpZGF0ZTIpKSB7XG4gICAgcmV0dXJuIHsgbmFtZTogY2FuZGlkYXRlMiwgY29sbGFwc2VkOiB0cnVlIH07XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdktn/provider-generator",
|
|
3
|
-
"version": "0.24.0-pre.
|
|
3
|
+
"version": "0.24.0-pre.75",
|
|
4
4
|
"description": "Exposes API to generate Terraform CDK provider bindings",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"glob": "13.0.6",
|
|
36
36
|
"jsii": "~5.9.0",
|
|
37
37
|
"jsii-pacmak": "1.128.0",
|
|
38
|
-
"@cdktn/commons": "0.24.0-pre.
|
|
39
|
-
"@cdktn/provider-schema": "0.24.0-pre.
|
|
40
|
-
"cdktn": "0.24.0-pre.
|
|
38
|
+
"@cdktn/commons": "0.24.0-pre.75",
|
|
39
|
+
"@cdktn/provider-schema": "0.24.0-pre.75",
|
|
40
|
+
"cdktn": "0.24.0-pre.75"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/fs-extra": "8.1.5",
|
|
@@ -2172,6 +2172,155 @@ export class ComputedOptionalComplex extends cdktn.TerraformResource {
|
|
|
2172
2172
|
"
|
|
2173
2173
|
`;
|
|
2174
2174
|
|
|
2175
|
+
exports[`deeply nested (unsupported) collection attribute types 1`] = `
|
|
2176
|
+
"// https://registry.terraform.io/providers/hashicorp/test/latest/docs/data-sources/deeply_nested_collections
|
|
2177
|
+
// generated from terraform resource schema
|
|
2178
|
+
|
|
2179
|
+
import { Construct } from 'constructs';
|
|
2180
|
+
import * as cdktn from 'cdktn';
|
|
2181
|
+
|
|
2182
|
+
// Configuration
|
|
2183
|
+
|
|
2184
|
+
export interface DataDeeplyNestedCollectionsConfig extends cdktn.TerraformMetaArguments {
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
/**
|
|
2188
|
+
* Represents a {@link https://registry.terraform.io/providers/hashicorp/test/latest/docs/data-sources/deeply_nested_collections deeply_nested_collections}
|
|
2189
|
+
*/
|
|
2190
|
+
export class DataDeeplyNestedCollections extends cdktn.TerraformDataSource {
|
|
2191
|
+
|
|
2192
|
+
// =================
|
|
2193
|
+
// STATIC PROPERTIES
|
|
2194
|
+
// =================
|
|
2195
|
+
public static readonly tfResourceType = "deeply_nested_collections";
|
|
2196
|
+
|
|
2197
|
+
// ==============
|
|
2198
|
+
// STATIC Methods
|
|
2199
|
+
// ==============
|
|
2200
|
+
/**
|
|
2201
|
+
* Generates CDKTN code for importing a DataDeeplyNestedCollections resource upon running "cdktn plan <stack-name>"
|
|
2202
|
+
* @param scope The scope in which to define this construct
|
|
2203
|
+
* @param importToId The construct id used in the generated config for the DataDeeplyNestedCollections to import
|
|
2204
|
+
* @param importFromId The id of the existing DataDeeplyNestedCollections that should be imported. Refer to the {@link https://registry.terraform.io/providers/hashicorp/test/latest/docs/data-sources/deeply_nested_collections#import import section} in the documentation of this resource for the id to use
|
|
2205
|
+
* @param provider? Optional instance of the provider where the DataDeeplyNestedCollections to import is found
|
|
2206
|
+
*/
|
|
2207
|
+
public static generateConfigForImport(scope: Construct, importToId: string, importFromId: string, provider?: cdktn.TerraformProvider) {
|
|
2208
|
+
return new cdktn.ImportableResource(scope, importToId, { terraformResourceType: "deeply_nested_collections", importId: importFromId, provider });
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
// ===========
|
|
2212
|
+
// INITIALIZER
|
|
2213
|
+
// ===========
|
|
2214
|
+
|
|
2215
|
+
/**
|
|
2216
|
+
* Create a new {@link https://registry.terraform.io/providers/hashicorp/test/latest/docs/data-sources/deeply_nested_collections deeply_nested_collections} Data Source
|
|
2217
|
+
*
|
|
2218
|
+
* @param scope The scope in which to define this construct
|
|
2219
|
+
* @param id The scoped construct ID. Must be unique amongst siblings in the same scope
|
|
2220
|
+
* @param options DataDeeplyNestedCollectionsConfig = {}
|
|
2221
|
+
*/
|
|
2222
|
+
public constructor(scope: Construct, id: string, config: DataDeeplyNestedCollectionsConfig = {}) {
|
|
2223
|
+
super(scope, id, {
|
|
2224
|
+
terraformResourceType: 'deeply_nested_collections',
|
|
2225
|
+
terraformGeneratorMetadata: {
|
|
2226
|
+
providerName: 'test'
|
|
2227
|
+
},
|
|
2228
|
+
provider: config.provider,
|
|
2229
|
+
dependsOn: config.dependsOn,
|
|
2230
|
+
count: config.count,
|
|
2231
|
+
lifecycle: config.lifecycle,
|
|
2232
|
+
provisioners: config.provisioners,
|
|
2233
|
+
connection: config.connection,
|
|
2234
|
+
forEach: config.forEach
|
|
2235
|
+
});
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
// ==========
|
|
2239
|
+
// ATTRIBUTES
|
|
2240
|
+
// ==========
|
|
2241
|
+
|
|
2242
|
+
// map_map_list_string - computed: true, optional: false, required: false
|
|
2243
|
+
private _mapMapListString = new cdktn.AnyMapMap(this, "map_map_list_string");
|
|
2244
|
+
/**
|
|
2245
|
+
* Terraform type: \`map(map(list(string)))\`.
|
|
2246
|
+
* This nesting is deeper than the typed wrapper classes in the core cdktn package; it is exposed as \`AnyMapMap\` and values below that boundary are untyped tokens.
|
|
2247
|
+
*/
|
|
2248
|
+
public get mapMapListString() {
|
|
2249
|
+
return this._mapMapListString;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
// list_map_map_string - computed: true, optional: false, required: false
|
|
2253
|
+
private _listMapMapString = new cdktn.AnyMapList(this, "list_map_map_string", false);
|
|
2254
|
+
/**
|
|
2255
|
+
* Terraform type: \`list(map(map(string)))\`.
|
|
2256
|
+
* This nesting is deeper than the typed wrapper classes in the core cdktn package; it is exposed as \`AnyMapList\` and values below that boundary are untyped tokens.
|
|
2257
|
+
*/
|
|
2258
|
+
public get listMapMapString() {
|
|
2259
|
+
return this._listMapMapString;
|
|
2260
|
+
}
|
|
2261
|
+
|
|
2262
|
+
// set_map_list_number - computed: true, optional: false, required: false
|
|
2263
|
+
private _setMapListNumber = new cdktn.AnyMapList(this, "set_map_list_number", true);
|
|
2264
|
+
/**
|
|
2265
|
+
* Terraform type: \`set(map(list(number)))\`.
|
|
2266
|
+
* This nesting is deeper than the typed wrapper classes in the core cdktn package; it is exposed as \`AnyMapList\` and values below that boundary are untyped tokens.
|
|
2267
|
+
*/
|
|
2268
|
+
public get setMapListNumber() {
|
|
2269
|
+
return this._setMapListNumber;
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
// map_list_string - computed: true, optional: false, required: false
|
|
2273
|
+
private _mapListString = new cdktn.StringListMap(this, "map_list_string");
|
|
2274
|
+
public get mapListString() {
|
|
2275
|
+
return this._mapListString;
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
// map_map_number - computed: true, optional: false, required: false
|
|
2279
|
+
private _mapMapNumber = new cdktn.NumberMapMap(this, "map_map_number");
|
|
2280
|
+
public get mapMapNumber() {
|
|
2281
|
+
return this._mapMapNumber;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// map_map_bool - computed: true, optional: false, required: false
|
|
2285
|
+
private _mapMapBool = new cdktn.BooleanMapMap(this, "map_map_bool");
|
|
2286
|
+
public get mapMapBool() {
|
|
2287
|
+
return this._mapMapBool;
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
// map_map_string - computed: true, optional: false, required: false
|
|
2291
|
+
private _mapMapString = new cdktn.StringMapMap(this, "map_map_string");
|
|
2292
|
+
public get mapMapString() {
|
|
2293
|
+
return this._mapMapString;
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
// map_map_map_list_string - computed: true, optional: false, required: false
|
|
2297
|
+
private _mapMapMapListString = new cdktn.AnyMapMap(this, "map_map_map_list_string");
|
|
2298
|
+
/**
|
|
2299
|
+
* Terraform type: \`map(map(map(list(string))))\`.
|
|
2300
|
+
* This nesting is deeper than the typed wrapper classes in the core cdktn package; it is exposed as \`AnyMapMap\` and values below that boundary are untyped tokens.
|
|
2301
|
+
*/
|
|
2302
|
+
public get mapMapMapListString() {
|
|
2303
|
+
return this._mapMapMapListString;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
// =========
|
|
2307
|
+
// SYNTHESIS
|
|
2308
|
+
// =========
|
|
2309
|
+
|
|
2310
|
+
protected synthesizeAttributes(): { [name: string]: any } {
|
|
2311
|
+
return {
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
protected synthesizeHclAttributes(): { [name: string]: any } {
|
|
2316
|
+
const attrs = {
|
|
2317
|
+
};
|
|
2318
|
+
return attrs;
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
"
|
|
2322
|
+
`;
|
|
2323
|
+
|
|
2175
2324
|
exports[`deeply nested block types 1`] = `
|
|
2176
2325
|
"// https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/deeply_nested_block_types
|
|
2177
2326
|
// generated from terraform resource schema
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format_version": "1.0",
|
|
3
|
+
"provider_schemas": {
|
|
4
|
+
"registry.terraform.io/hashicorp/test": {
|
|
5
|
+
"data_source_schemas": {
|
|
6
|
+
"deeply_nested_collections": {
|
|
7
|
+
"version": 0,
|
|
8
|
+
"block": {
|
|
9
|
+
"attributes": {
|
|
10
|
+
"map_map_list_string": {
|
|
11
|
+
"type": [
|
|
12
|
+
"map",
|
|
13
|
+
[
|
|
14
|
+
"map",
|
|
15
|
+
[
|
|
16
|
+
"list",
|
|
17
|
+
"string"
|
|
18
|
+
]
|
|
19
|
+
]
|
|
20
|
+
],
|
|
21
|
+
"description": "map(map(list(string))) - unsupported triple nesting, reproduces open-constructs/cdk-terrain#11.",
|
|
22
|
+
"description_kind": "plain",
|
|
23
|
+
"computed": true
|
|
24
|
+
},
|
|
25
|
+
"list_map_map_string": {
|
|
26
|
+
"type": [
|
|
27
|
+
"list",
|
|
28
|
+
[
|
|
29
|
+
"map",
|
|
30
|
+
[
|
|
31
|
+
"map",
|
|
32
|
+
"string"
|
|
33
|
+
]
|
|
34
|
+
]
|
|
35
|
+
],
|
|
36
|
+
"description": "list(map(map(string))) - unsupported triple nesting.",
|
|
37
|
+
"description_kind": "plain",
|
|
38
|
+
"computed": true
|
|
39
|
+
},
|
|
40
|
+
"set_map_list_number": {
|
|
41
|
+
"type": [
|
|
42
|
+
"set",
|
|
43
|
+
[
|
|
44
|
+
"map",
|
|
45
|
+
[
|
|
46
|
+
"list",
|
|
47
|
+
"number"
|
|
48
|
+
]
|
|
49
|
+
]
|
|
50
|
+
],
|
|
51
|
+
"description": "set(map(list(number))) - unsupported triple nesting.",
|
|
52
|
+
"description_kind": "plain",
|
|
53
|
+
"computed": true
|
|
54
|
+
},
|
|
55
|
+
"map_list_string": {
|
|
56
|
+
"type": [
|
|
57
|
+
"map",
|
|
58
|
+
[
|
|
59
|
+
"list",
|
|
60
|
+
"string"
|
|
61
|
+
]
|
|
62
|
+
],
|
|
63
|
+
"description": "map(list(string)) - supported double nesting, must still emit cdktn.StringListMap.",
|
|
64
|
+
"description_kind": "plain",
|
|
65
|
+
"computed": true
|
|
66
|
+
},
|
|
67
|
+
"map_map_number": {
|
|
68
|
+
"type": [
|
|
69
|
+
"map",
|
|
70
|
+
[
|
|
71
|
+
"map",
|
|
72
|
+
"number"
|
|
73
|
+
]
|
|
74
|
+
],
|
|
75
|
+
"description": "map(map(number)) - now directly supported via cdktn.NumberMapMap.",
|
|
76
|
+
"description_kind": "plain",
|
|
77
|
+
"computed": true
|
|
78
|
+
},
|
|
79
|
+
"map_map_bool": {
|
|
80
|
+
"type": [
|
|
81
|
+
"map",
|
|
82
|
+
[
|
|
83
|
+
"map",
|
|
84
|
+
"bool"
|
|
85
|
+
]
|
|
86
|
+
],
|
|
87
|
+
"description": "map(map(bool)) - now directly supported via cdktn.BooleanMapMap.",
|
|
88
|
+
"description_kind": "plain",
|
|
89
|
+
"computed": true
|
|
90
|
+
},
|
|
91
|
+
"map_map_string": {
|
|
92
|
+
"type": [
|
|
93
|
+
"map",
|
|
94
|
+
[
|
|
95
|
+
"map",
|
|
96
|
+
"string"
|
|
97
|
+
]
|
|
98
|
+
],
|
|
99
|
+
"description": "map(map(string)) - pre-existing support via cdktn.StringMapMap, unchanged.",
|
|
100
|
+
"description_kind": "plain",
|
|
101
|
+
"computed": true
|
|
102
|
+
},
|
|
103
|
+
"map_map_map_list_string": {
|
|
104
|
+
"type": [
|
|
105
|
+
"map",
|
|
106
|
+
[
|
|
107
|
+
"map",
|
|
108
|
+
[
|
|
109
|
+
"map",
|
|
110
|
+
[
|
|
111
|
+
"list",
|
|
112
|
+
"string"
|
|
113
|
+
]
|
|
114
|
+
]
|
|
115
|
+
]
|
|
116
|
+
],
|
|
117
|
+
"description": "map(map(map(list(string)))) - unsupported quadruple nesting, collapses to cdktn.AnyMapMap.",
|
|
118
|
+
"description_kind": "plain",
|
|
119
|
+
"computed": true
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"description": "Data source used to verify deeply nested collection attribute types are handled without generating references to non-existent cdktn classes.",
|
|
123
|
+
"description_kind": "plain"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Copyright (c) HashiCorp, Inc
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
import { logger } from "@cdktn/commons";
|
|
4
|
+
import { resolveStoredClassName } from "../../generator/models/supported-stored-classes";
|
|
5
|
+
import {
|
|
6
|
+
AttributeModel,
|
|
7
|
+
AttributeTypeModel,
|
|
8
|
+
MapAttributeTypeModel,
|
|
9
|
+
} from "../../generator/models";
|
|
10
|
+
|
|
11
|
+
describe("resolveStoredClassName", () => {
|
|
12
|
+
test("own composed name resolves as-is when supported (not collapsed)", () => {
|
|
13
|
+
expect(resolveStoredClassName("stringListMap", "list")).toEqual({
|
|
14
|
+
name: "StringListMap",
|
|
15
|
+
collapsed: false,
|
|
16
|
+
});
|
|
17
|
+
expect(resolveStoredClassName("stringMapMap", "map")).toEqual({
|
|
18
|
+
name: "StringMapMap",
|
|
19
|
+
collapsed: false,
|
|
20
|
+
});
|
|
21
|
+
expect(resolveStoredClassName("numberMapMap", "map")).toEqual({
|
|
22
|
+
name: "NumberMapMap",
|
|
23
|
+
collapsed: false,
|
|
24
|
+
});
|
|
25
|
+
expect(resolveStoredClassName("booleanMapMap", "map")).toEqual({
|
|
26
|
+
name: "BooleanMapMap",
|
|
27
|
+
collapsed: false,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("unsupported own composed name collapses to nearest Any-wrapper", () => {
|
|
32
|
+
// map(map(list(string))) - own "stringListMapMap" unsupported, element is a map
|
|
33
|
+
expect(resolveStoredClassName("stringListMapMap", "map")).toEqual({
|
|
34
|
+
name: "AnyMapMap",
|
|
35
|
+
collapsed: true,
|
|
36
|
+
});
|
|
37
|
+
// list(map(map(string))) - own "stringMapMapList" unsupported, element is a map
|
|
38
|
+
expect(resolveStoredClassName("stringMapMapList", "map")).toEqual({
|
|
39
|
+
name: "AnyMapList",
|
|
40
|
+
collapsed: true,
|
|
41
|
+
});
|
|
42
|
+
// set(map(list(number))) - own "numberListMapList" unsupported, element is a map
|
|
43
|
+
expect(resolveStoredClassName("numberListMapList", "map")).toEqual({
|
|
44
|
+
name: "AnyMapList",
|
|
45
|
+
collapsed: true,
|
|
46
|
+
});
|
|
47
|
+
// map(map(map(list(string)))) - own "stringListMapMapMap" unsupported, element is a map
|
|
48
|
+
expect(resolveStoredClassName("stringListMapMapMap", "map")).toEqual({
|
|
49
|
+
name: "AnyMapMap",
|
|
50
|
+
collapsed: true,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("returns undefined when neither the own name nor a collapsed Any-wrapper exists", () => {
|
|
55
|
+
// Own name doesn't end in List/Map at all.
|
|
56
|
+
expect(resolveStoredClassName("somethingWeird", "map")).toBeUndefined();
|
|
57
|
+
// Own name ends in Map, but the element isn't itself a list/set/map, so there is no
|
|
58
|
+
// "AnyXMap" candidate to fall back to.
|
|
59
|
+
expect(resolveStoredClassName("weirdMap", "struct")).toBeUndefined();
|
|
60
|
+
expect(resolveStoredClassName("weirdMap", "simple")).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// A minimal stand-in for a non-complex, non-collection AttributeTypeModel whose
|
|
65
|
+
// typeModelType is neither "list", "set", "map", nor "simple"/"struct" - i.e. a shape the
|
|
66
|
+
// generator's collapse logic has no candidate class name for. Used to exercise the
|
|
67
|
+
// defensive plain-getter fallback in AttributeModel.getterType without needing a real
|
|
68
|
+
// (currently nonexistent) unsupported shape.
|
|
69
|
+
class UnresolvableStubTypeModel implements AttributeTypeModel {
|
|
70
|
+
get struct() {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
get isComplex() {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
getStoredClassInitializer(_name: string) {
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
79
|
+
get storedClassType() {
|
|
80
|
+
return "unresolvable";
|
|
81
|
+
}
|
|
82
|
+
get inputTypeDefinition() {
|
|
83
|
+
return "any";
|
|
84
|
+
}
|
|
85
|
+
getAttributeAccessFunction(name: string) {
|
|
86
|
+
return `this.interpolationForAttribute('${name}')`;
|
|
87
|
+
}
|
|
88
|
+
get toTerraformFunction() {
|
|
89
|
+
return "cdktn.anyToTerraform";
|
|
90
|
+
}
|
|
91
|
+
get toHclTerraformFunction() {
|
|
92
|
+
return "cdktn.anyToHclTerraform";
|
|
93
|
+
}
|
|
94
|
+
get typeModelType() {
|
|
95
|
+
return "unresolvable-shape";
|
|
96
|
+
}
|
|
97
|
+
get hasReferenceClass() {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
get isTokenizable() {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
get isStoredClassUnavailable() {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
describe("AttributeModel.getterType loud fallback", () => {
|
|
109
|
+
test("falls back to a plain getter and logs a debug breadcrumb when no stored class (not even a collapsed Any-wrapper) is available", () => {
|
|
110
|
+
const debugSpy = jest.spyOn(logger, "debug").mockImplementation();
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
// A map whose element is itself an unrecognized shape: own composed name
|
|
114
|
+
// ("unresolvableMap") isn't in the supported set, and the element's typeModelType
|
|
115
|
+
// isn't "list"/"set"/"map", so there is no "AnyXMap" candidate either.
|
|
116
|
+
const type = new MapAttributeTypeModel(new UnresolvableStubTypeModel());
|
|
117
|
+
expect(type.isStoredClassUnavailable).toBe(true);
|
|
118
|
+
|
|
119
|
+
const attribute = new AttributeModel({
|
|
120
|
+
storageName: "_weirdAttribute",
|
|
121
|
+
name: "weirdAttribute",
|
|
122
|
+
type,
|
|
123
|
+
optional: false,
|
|
124
|
+
computed: true,
|
|
125
|
+
terraformName: "weird_attribute",
|
|
126
|
+
terraformFullName: "test_resource.weird_attribute",
|
|
127
|
+
provider: false,
|
|
128
|
+
required: false,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(attribute.getterType).toEqual({ _type: "plain" });
|
|
132
|
+
expect(attribute.storedClassBoundaryKind).toEqual("fallback");
|
|
133
|
+
|
|
134
|
+
expect(debugSpy).toHaveBeenCalledTimes(1);
|
|
135
|
+
const [message] = debugSpy.mock.calls[0];
|
|
136
|
+
expect(message).toContain("test_resource.weird_attribute");
|
|
137
|
+
expect(message).toContain("unresolvableMap");
|
|
138
|
+
|
|
139
|
+
// Repeated access must not spam the logger.
|
|
140
|
+
void attribute.getterType;
|
|
141
|
+
void attribute.getterType;
|
|
142
|
+
expect(debugSpy).toHaveBeenCalledTimes(1);
|
|
143
|
+
} finally {
|
|
144
|
+
debugSpy.mockRestore();
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
});
|
|
@@ -609,3 +609,78 @@ test("case-insensitive base name collision", async () => {
|
|
|
609
609
|
expect(output).toMatchSnapshot(file);
|
|
610
610
|
}
|
|
611
611
|
});
|
|
612
|
+
|
|
613
|
+
test("deeply nested (unsupported) collection attribute types", async () => {
|
|
614
|
+
// Regression test for https://github.com/open-constructs/cdk-terrain/issues/11:
|
|
615
|
+
// computed attributes whose type nests list/set/map more than two levels deep (e.g.
|
|
616
|
+
// map(map(list(string)))) must not generate a reference to a "cdktn.*" stored class
|
|
617
|
+
// that doesn't exist (e.g. "StringListMapMap"). Instead of falling straight back to a
|
|
618
|
+
// plain, untyped getter, the generator collapses these into the nearest typed
|
|
619
|
+
// "Any"-wrapper that does exist (e.g. "AnyMapMap"), preserving typed navigation for the
|
|
620
|
+
// outer layers. Only shapes with no available stored class at all fall back to a plain
|
|
621
|
+
// getter.
|
|
622
|
+
const code = new CodeMaker();
|
|
623
|
+
const workdir = tmp("deeply-nested-collections.test");
|
|
624
|
+
const spec = JSON.parse(
|
|
625
|
+
fs.readFileSync(
|
|
626
|
+
path.join(
|
|
627
|
+
__dirname,
|
|
628
|
+
"fixtures",
|
|
629
|
+
"deeply-nested-collections.test.fixture.json",
|
|
630
|
+
),
|
|
631
|
+
"utf-8",
|
|
632
|
+
),
|
|
633
|
+
);
|
|
634
|
+
new TerraformProviderGenerator(code, spec).generateAll();
|
|
635
|
+
await code.save(workdir);
|
|
636
|
+
|
|
637
|
+
const output = fs.readFileSync(
|
|
638
|
+
path.join(
|
|
639
|
+
workdir,
|
|
640
|
+
"providers/test/data-deeply-nested-collections/index.ts",
|
|
641
|
+
),
|
|
642
|
+
"utf-8",
|
|
643
|
+
);
|
|
644
|
+
expect(output).toMatchSnapshot();
|
|
645
|
+
|
|
646
|
+
// None of the unsupported nested attributes should reference a non-existent "cdktn.*"
|
|
647
|
+
// wrapper class.
|
|
648
|
+
expect(output).not.toContain("StringListMapMap");
|
|
649
|
+
expect(output).not.toContain("StringMapMapList");
|
|
650
|
+
expect(output).not.toContain("NumberListMapList");
|
|
651
|
+
expect(output).not.toContain("StringListMapMapMap");
|
|
652
|
+
|
|
653
|
+
// Unsupported triple nestings collapse to the nearest typed "Any"-wrapper instead of
|
|
654
|
+
// falling back to a plain getter.
|
|
655
|
+
expect(output).toContain('new cdktn.AnyMapMap(this, "map_map_list_string")');
|
|
656
|
+
expect(output).toContain(
|
|
657
|
+
'new cdktn.AnyMapList(this, "list_map_map_string", false)',
|
|
658
|
+
);
|
|
659
|
+
expect(output).toContain(
|
|
660
|
+
'new cdktn.AnyMapList(this, "set_map_list_number", true)',
|
|
661
|
+
);
|
|
662
|
+
expect(output).toContain(
|
|
663
|
+
'new cdktn.AnyMapMap(this, "map_map_map_list_string")',
|
|
664
|
+
);
|
|
665
|
+
|
|
666
|
+
// A supported double nesting (map(list(string))) must still emit its stored class.
|
|
667
|
+
expect(output).toContain('new cdktn.StringListMap(this, "map_list_string")');
|
|
668
|
+
|
|
669
|
+
// map(map(number)) / map(map(bool)) are now directly supported by new core classes.
|
|
670
|
+
expect(output).toContain('new cdktn.NumberMapMap(this, "map_map_number")');
|
|
671
|
+
expect(output).toContain('new cdktn.BooleanMapMap(this, "map_map_bool")');
|
|
672
|
+
|
|
673
|
+
// map(map(string)) is pre-existing, unchanged support.
|
|
674
|
+
expect(output).toContain('new cdktn.StringMapMap(this, "map_map_string")');
|
|
675
|
+
|
|
676
|
+
// Collapsed getters get a JSDoc documenting the Terraform type and the collapse
|
|
677
|
+
// boundary.
|
|
678
|
+
expect(output).toContain("Terraform type: `map(map(list(string)))`");
|
|
679
|
+
expect(output).toContain(
|
|
680
|
+
"it is exposed as `AnyMapMap` and values below that boundary are untyped tokens",
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
// Supported, non-collapsed attributes must NOT get this JSDoc (avoids snapshot churn).
|
|
684
|
+
expect(output).not.toContain("Terraform type: `map(list(string))`");
|
|
685
|
+
expect(output).not.toContain("Terraform type: `map(map(string))`");
|
|
686
|
+
});
|