@cdktn/provider-generator 0.25.0-pre.4 → 0.25.0-pre.40
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/__tests__/edge-provider-schema/builder.js +3 -3
- package/build/__tests__/edge-provider-schema/cli.js +18 -8
- package/build/__tests__/edge-provider-schema.test.js +18 -8
- package/build/__tests__/provider.test.js +18 -8
- package/build/get/__tests__/constructs-maker.test.js +91 -8
- package/build/get/__tests__/generator/complex-computed-types.test.js +18 -8
- package/build/get/__tests__/generator/deep-nested-attributes.test.js +18 -8
- package/build/get/__tests__/generator/description-escaping.test.js +18 -8
- package/build/get/__tests__/generator/empty-provider-resources.test.js +18 -8
- package/build/get/__tests__/generator/ephemeral-resources.test.js +18 -8
- package/build/get/__tests__/generator/export-sharding.test.js +18 -8
- package/build/get/__tests__/generator/import-style.test.js +18 -8
- package/build/get/__tests__/generator/module-generator.test.js +18 -8
- package/build/get/__tests__/generator/nested-types.test.js +18 -8
- package/build/get/__tests__/generator/provider-functions-name-collision.test.d.ts +2 -0
- package/build/get/__tests__/generator/provider-functions-name-collision.test.js +89 -0
- package/build/get/__tests__/generator/provider-functions.test.js +18 -8
- package/build/get/__tests__/generator/provider.test.js +18 -8
- package/build/get/__tests__/generator/resource-types.test.js +18 -8
- package/build/get/__tests__/generator/skipped-attributes.test.js +18 -8
- package/build/get/__tests__/generator/types.test.js +18 -8
- package/build/get/__tests__/generator/versions-file.test.js +18 -8
- package/build/get/__tests__/generator/write-only.test.js +18 -8
- package/build/get/__tests__/target-versions.test.js +18 -8
- package/build/get/__tests__/util.js +20 -11
- package/build/get/constructs-maker.d.ts +17 -0
- package/build/get/constructs-maker.js +68 -10
- package/build/get/generator/emitter/struct-emitter.js +18 -8
- package/build/get/generator/loop-detection.js +2 -3
- package/build/get/generator/models/attribute-model.js +3 -3
- package/build/get/generator/models/attribute-type-model.js +3 -3
- package/build/get/generator/models/provider-function-model.js +3 -4
- package/build/get/generator/models/resource-model.d.ts +3 -1
- package/build/get/generator/models/resource-model.js +16 -10
- package/build/get/generator/models/supported-stored-classes.js +2 -3
- package/build/get/generator/provider-generator.d.ts +15 -1
- package/build/get/generator/provider-generator.js +19 -4
- package/build/get/generator/resource-parser.d.ts +3 -1
- package/build/get/generator/resource-parser.js +16 -7
- package/build/get/generator/sanitized-comments.js +2 -3
- package/build/get/generator/skipped-attributes.js +2 -3
- package/build/index.js +3 -3
- package/build/util.js +3 -4
- package/package.json +9 -9
- package/src/get/__tests__/constructs-maker.test.ts +125 -1
- package/src/get/__tests__/generator/fixtures/provider-functions-name-collision.test.fixture.json +42 -0
- package/src/get/__tests__/generator/provider-functions-name-collision.test.ts +84 -0
- package/src/get/constructs-maker.ts +65 -0
- package/src/get/generator/models/attribute-type-model.ts +1 -2
- package/src/get/generator/models/resource-model.ts +27 -9
- package/src/get/generator/provider-generator.ts +26 -3
- package/src/get/generator/resource-parser.ts +21 -3
- package/tsconfig.json +4 -0
package/src/get/__tests__/generator/fixtures/provider-functions-name-collision.test.fixture.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider_schemas": {
|
|
3
|
+
"registry.terraform.io/hashicorp/example": {
|
|
4
|
+
"resource_schemas": {
|
|
5
|
+
"example_provider_functions": {
|
|
6
|
+
"version": 0,
|
|
7
|
+
"block": {
|
|
8
|
+
"attributes": {
|
|
9
|
+
"id": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description_kind": "plain",
|
|
12
|
+
"computed": true
|
|
13
|
+
},
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description_kind": "plain",
|
|
17
|
+
"optional": true
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"functions": {
|
|
24
|
+
"sum": {
|
|
25
|
+
"description": "Adds up two numbers.",
|
|
26
|
+
"summary": "Sum numbers",
|
|
27
|
+
"return_type": "number",
|
|
28
|
+
"parameters": [
|
|
29
|
+
{
|
|
30
|
+
"name": "a",
|
|
31
|
+
"type": "number"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "b",
|
|
35
|
+
"type": "number"
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright (c) HashiCorp, Inc
|
|
2
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { CodeMaker } from "codemaker";
|
|
6
|
+
import { TerraformProviderGenerator } from "../../generator/provider-generator";
|
|
7
|
+
import { sanitizeClassOrNamespaceName } from "../../generator/resource-parser";
|
|
8
|
+
import { createTmpHelper } from "../util";
|
|
9
|
+
|
|
10
|
+
const tmp = createTmpHelper();
|
|
11
|
+
|
|
12
|
+
// A provider declaring provider-defined functions emits them to
|
|
13
|
+
// providers/<provider>/provider-functions/index.ts. A resource named
|
|
14
|
+
// <provider>_provider_functions maps to that same directory, so without a
|
|
15
|
+
// guard the resource overwrites the functions wrapper and the provider index
|
|
16
|
+
// exports the name twice.
|
|
17
|
+
describe("resource named like the provider functions submodule", () => {
|
|
18
|
+
let workdir: string;
|
|
19
|
+
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
const code = new CodeMaker();
|
|
22
|
+
workdir = tmp("provider-functions-name-collision.test");
|
|
23
|
+
const spec = JSON.parse(
|
|
24
|
+
fs.readFileSync(
|
|
25
|
+
path.join(
|
|
26
|
+
__dirname,
|
|
27
|
+
"fixtures",
|
|
28
|
+
"provider-functions-name-collision.test.fixture.json",
|
|
29
|
+
),
|
|
30
|
+
"utf-8",
|
|
31
|
+
),
|
|
32
|
+
);
|
|
33
|
+
new TerraformProviderGenerator(code, spec).generateAll();
|
|
34
|
+
await code.save(workdir);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const read = (relPath: string) =>
|
|
38
|
+
fs.readFileSync(path.join(workdir, relPath), "utf-8");
|
|
39
|
+
|
|
40
|
+
test("the functions submodule holds the functions wrapper, not the resource", () => {
|
|
41
|
+
const output = read("providers/example/provider-functions/index.ts");
|
|
42
|
+
expect(output).toContain("class ExampleProviderFunctions");
|
|
43
|
+
expect(output).not.toContain("cdktn.TerraformResource");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("the resource is emitted to its own directory", () => {
|
|
47
|
+
const output = read(
|
|
48
|
+
"providers/example/provider-functions-resource/index.ts",
|
|
49
|
+
);
|
|
50
|
+
expect(output).toContain("class ProviderFunctionsResource");
|
|
51
|
+
expect(output).toContain("cdktn.TerraformResource");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("the provider index exports both, without duplicate names", () => {
|
|
55
|
+
const index = read("providers/example/index.ts");
|
|
56
|
+
expect(index).toContain(
|
|
57
|
+
"export * as providerFunctions from './provider-functions/index';",
|
|
58
|
+
);
|
|
59
|
+
expect(index).toContain(
|
|
60
|
+
"export * as providerFunctionsResource from './provider-functions-resource/index';",
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const exportedNames = [...index.matchAll(/export \* as (\w+) from/g)].map(
|
|
64
|
+
(m) => m[1],
|
|
65
|
+
);
|
|
66
|
+
expect(new Set(exportedNames).size).toBe(exportedNames.length);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("sanitizeClassOrNamespaceName", () => {
|
|
71
|
+
test("suffixes a resource named provider_functions", () => {
|
|
72
|
+
expect(sanitizeClassOrNamespaceName("provider_functions")).toBe(
|
|
73
|
+
"provider_functions_resource",
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("still suffixes a resource named provider", () => {
|
|
78
|
+
expect(sanitizeClassOrNamespaceName("provider")).toBe("provider_resource");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("leaves an unrelated resource name alone", () => {
|
|
82
|
+
expect(sanitizeClassOrNamespaceName("function_app")).toBe("function_app");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -315,6 +315,8 @@ export class ConstructsMaker {
|
|
|
315
315
|
private readonly codeMakerOutdir: string;
|
|
316
316
|
private readonly code: CodeMaker;
|
|
317
317
|
private versions: { [providerName: string]: string | undefined };
|
|
318
|
+
/** Resource directory names emitted per provider folder during this run */
|
|
319
|
+
public emittedResourceFolders: { [providerName: string]: string[] };
|
|
318
320
|
|
|
319
321
|
constructor(
|
|
320
322
|
private readonly options: GetOptions,
|
|
@@ -328,6 +330,7 @@ export class ConstructsMaker {
|
|
|
328
330
|
fs.mkdirpSync(this.codeMakerOutdir);
|
|
329
331
|
this.code = new CodeMaker();
|
|
330
332
|
this.versions = {};
|
|
333
|
+
this.emittedResourceFolders = {};
|
|
331
334
|
}
|
|
332
335
|
private async generateTypescriptProvider(
|
|
333
336
|
target: ConstructsMakerProviderTarget,
|
|
@@ -336,10 +339,15 @@ export class ConstructsMaker {
|
|
|
336
339
|
const endTSTimer = logTimespan(`Generate Typescript for ${target.name}`);
|
|
337
340
|
const generator = new TerraformProviderGenerator(this.code, schema, {
|
|
338
341
|
importExtension: this.options.languageOptions?.importExtension,
|
|
342
|
+
targetVersions: this.options.targetVersions,
|
|
339
343
|
});
|
|
340
344
|
generator.generate(target);
|
|
341
345
|
|
|
342
346
|
this.versions = { ...this.versions, ...generator.versions };
|
|
347
|
+
this.emittedResourceFolders = {
|
|
348
|
+
...this.emittedResourceFolders,
|
|
349
|
+
...generator.emittedResourceFolders,
|
|
350
|
+
};
|
|
343
351
|
endTSTimer();
|
|
344
352
|
}
|
|
345
353
|
|
|
@@ -595,6 +603,62 @@ export class ConstructsMaker {
|
|
|
595
603
|
});
|
|
596
604
|
}
|
|
597
605
|
|
|
606
|
+
/**
|
|
607
|
+
* Delete resource directories under `providers/` that this run did not emit, so each provider folder holds
|
|
608
|
+
* exactly the resources in the version it was generated against.
|
|
609
|
+
*
|
|
610
|
+
* Walks only providers present in `emittedResourceFolders`, keeping any provider this run skipped. Within those,
|
|
611
|
+
* removes every subdirectory not emitted and leaves provider-level files (`index.ts`, `lazy-index.ts`) in place.
|
|
612
|
+
* Deletes files, so it must run after `save()` has written the current run's output.
|
|
613
|
+
*
|
|
614
|
+
* TypeScript only: `providers/<name>/<resource>/` maps one-to-one onto the emitted index exports. Other languages
|
|
615
|
+
* co-locate providers and modules in the same folders, which makes a dropped resource indistinguishable from a
|
|
616
|
+
* hand-written construct.
|
|
617
|
+
*/
|
|
618
|
+
public async removeOrphanedResourceFolders() {
|
|
619
|
+
if (!this.isJavascriptTarget) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
for (const [provider, emittedFolders] of Object.entries(
|
|
624
|
+
this.emittedResourceFolders,
|
|
625
|
+
)) {
|
|
626
|
+
const providerFolder = path.resolve(
|
|
627
|
+
this.codeMakerOutdir,
|
|
628
|
+
"providers",
|
|
629
|
+
provider,
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
let entries: string[] = [];
|
|
633
|
+
try {
|
|
634
|
+
entries = await fs.readdir(providerFolder);
|
|
635
|
+
} catch (e) {
|
|
636
|
+
logger.debug(
|
|
637
|
+
`Could not list resource folders in '${providerFolder}': ${e}`,
|
|
638
|
+
);
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const expected = new Set(emittedFolders);
|
|
643
|
+
for (const entry of entries) {
|
|
644
|
+
if (expected.has(entry)) {
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const entryPath = path.resolve(providerFolder, entry);
|
|
649
|
+
if (!fs.statSync(entryPath).isDirectory()) {
|
|
650
|
+
// Leave index.ts / lazy-index.ts and any other provider-level files alone.
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
logger.debug(
|
|
655
|
+
`Removing orphaned resource folder '${entry}' from provider '${provider}': it was not emitted for the current provider version`,
|
|
656
|
+
);
|
|
657
|
+
await fs.remove(entryPath);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
598
662
|
// emits a constraints.json file with a map of the used provider fqpns and version constraints
|
|
599
663
|
// this is used for caching purposes
|
|
600
664
|
private emitConstraintsFile(
|
|
@@ -757,6 +821,7 @@ a NODE_OPTIONS variable, we won't override it. Hence, the provider generation mi
|
|
|
757
821
|
|
|
758
822
|
if (this.isJavascriptTarget) {
|
|
759
823
|
await this.save();
|
|
824
|
+
await this.removeOrphanedResourceFolders();
|
|
760
825
|
}
|
|
761
826
|
|
|
762
827
|
if (!this.isJavascriptTarget || this.options.outputJsii) {
|
|
@@ -215,8 +215,7 @@ export interface CollectionAttributeTypeModel extends AttributeTypeModel {
|
|
|
215
215
|
// into the nearest typed "Any"-wrapper. undefined only defensively - see
|
|
216
216
|
// resolveStoredClassName in supported-stored-classes.ts.
|
|
217
217
|
readonly resolvedStoredClass:
|
|
218
|
-
|
|
219
|
-
| undefined;
|
|
218
|
+
{ name: string; collapsed: boolean } | undefined;
|
|
220
219
|
}
|
|
221
220
|
|
|
222
221
|
export class ListAttributeTypeModel implements CollectionAttributeTypeModel {
|
|
@@ -5,7 +5,11 @@ import path from "path";
|
|
|
5
5
|
import { FQPN, parseFQPN, ProviderName } from "@cdktn/provider-schema";
|
|
6
6
|
import { AttributeModel } from "./attribute-model";
|
|
7
7
|
import { Struct, ConfigStruct } from "./struct";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
Schema,
|
|
10
|
+
TerraformTargetVersions,
|
|
11
|
+
registryForTargetVersions,
|
|
12
|
+
} from "@cdktn/commons";
|
|
9
13
|
import { ProviderFunctionsModel } from "./provider-function-model";
|
|
10
14
|
|
|
11
15
|
// Limit is 1200 to prevent stack size error.
|
|
@@ -25,6 +29,7 @@ interface ResourceModelOptions {
|
|
|
25
29
|
schema: Schema;
|
|
26
30
|
terraformSchemaType: string;
|
|
27
31
|
configStructName: string;
|
|
32
|
+
targetVersions?: TerraformTargetVersions;
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
type DefinitionPath = string;
|
|
@@ -35,6 +40,7 @@ export class ResourceModel {
|
|
|
35
40
|
public baseName: string;
|
|
36
41
|
public provider: ProviderName;
|
|
37
42
|
public fqpn: FQPN;
|
|
43
|
+
private readonly targetVersions?: TerraformTargetVersions;
|
|
38
44
|
public providerVersionConstraint?: string;
|
|
39
45
|
public providerVersion?: string;
|
|
40
46
|
public terraformProviderSource?: string;
|
|
@@ -68,6 +74,7 @@ export class ResourceModel {
|
|
|
68
74
|
this.attributes = options.attributes;
|
|
69
75
|
this.schema = options.schema;
|
|
70
76
|
this.fqpn = options.fqpn;
|
|
77
|
+
this.targetVersions = options.targetVersions;
|
|
71
78
|
this.provider = parseFQPN(options.fqpn).name;
|
|
72
79
|
this.terraformProviderName = this.provider;
|
|
73
80
|
this.fileName = options.fileName;
|
|
@@ -109,15 +116,26 @@ export class ResourceModel {
|
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
public get linkToDocs(): string {
|
|
112
|
-
|
|
119
|
+
// Keyed off the project's declared targets, not the FQPN hostname: that
|
|
120
|
+
// hostname reflects whichever CLI fetched the schema, which would make the
|
|
121
|
+
// generated link differ between a terraform and a tofu `cdktn get`.
|
|
122
|
+
const registry = registryForTargetVersions(this.targetVersions);
|
|
123
|
+
const { namespace, name } = parseFQPN(this.fqpn);
|
|
113
124
|
const version = this.providerVersion || "latest";
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
125
|
+
const kind = this.isProvider
|
|
126
|
+
? "provider"
|
|
127
|
+
: this.isDataSource
|
|
128
|
+
? "data-source"
|
|
129
|
+
: this.isEphemeralResource
|
|
130
|
+
? "ephemeral-resource"
|
|
131
|
+
: "resource";
|
|
132
|
+
return registry.docsUrl(
|
|
133
|
+
namespace,
|
|
134
|
+
name,
|
|
135
|
+
version,
|
|
136
|
+
kind,
|
|
137
|
+
this.terraformDocName,
|
|
138
|
+
);
|
|
121
139
|
}
|
|
122
140
|
|
|
123
141
|
public get isProvider(): boolean {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
logger,
|
|
9
9
|
ProviderSchema,
|
|
10
10
|
TerraformProviderConstraint,
|
|
11
|
+
TerraformTargetVersions,
|
|
11
12
|
} from "@cdktn/commons";
|
|
12
13
|
import { FQPN, parseFQPN, ProviderName } from "@cdktn/provider-schema";
|
|
13
14
|
import {
|
|
@@ -29,6 +30,8 @@ export interface TerraformProviderGeneratorOptions {
|
|
|
29
30
|
* Defaults to "" (CommonJS).
|
|
30
31
|
*/
|
|
31
32
|
readonly importExtension?: string;
|
|
33
|
+
/** Project's declared targetVersions; selects the docs registry. */
|
|
34
|
+
readonly targetVersions?: TerraformTargetVersions;
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
interface ProviderData {
|
|
@@ -107,12 +110,17 @@ export interface ProviderConstraints {
|
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
export class TerraformProviderGenerator {
|
|
110
|
-
private resourceParser
|
|
113
|
+
private resourceParser: ResourceParser;
|
|
111
114
|
private resourceEmitter: ResourceEmitter;
|
|
112
115
|
private structEmitter: StructEmitter;
|
|
113
116
|
private providerFunctionsEmitter: ProviderFunctionsEmitter;
|
|
114
117
|
private readonly importExtension: string;
|
|
115
118
|
public versions: { [fqpn: string]: string | undefined } = {};
|
|
119
|
+
/**
|
|
120
|
+
* Resource directory names emitted per provider folder Used to prune directories
|
|
121
|
+
* left over from a previous provider version.
|
|
122
|
+
*/
|
|
123
|
+
public emittedResourceFolders: { [provider: string]: string[] } = {};
|
|
116
124
|
|
|
117
125
|
constructor(
|
|
118
126
|
private readonly code: CodeMaker,
|
|
@@ -121,6 +129,7 @@ export class TerraformProviderGenerator {
|
|
|
121
129
|
) {
|
|
122
130
|
this.code.indentation = 2;
|
|
123
131
|
this.importExtension = options.importExtension ?? "";
|
|
132
|
+
this.resourceParser = new ResourceParser(options.targetVersions);
|
|
124
133
|
this.resourceEmitter = new ResourceEmitter(this.code, this.importExtension);
|
|
125
134
|
this.structEmitter = new StructEmitter(this.code, this.importExtension);
|
|
126
135
|
this.providerFunctionsEmitter = new ProviderFunctionsEmitter(this.code);
|
|
@@ -298,6 +307,20 @@ export class TerraformProviderGenerator {
|
|
|
298
307
|
|
|
299
308
|
this.emitIndexFile(name, files);
|
|
300
309
|
this.emitLazyIndexFile(name, files);
|
|
310
|
+
|
|
311
|
+
// Record exactly what this run emitted, derived the same way the index
|
|
312
|
+
// files derive their exports, so pruning can never disagree with them.
|
|
313
|
+
this.emittedResourceFolders[name] = files.map((file) =>
|
|
314
|
+
this.resourceFolderName(name, file),
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Map an emitted file path to the resource directory name it lives in, e.g.
|
|
320
|
+
* `providers/mongodbatlas/teams/index.ts` -> `teams`.
|
|
321
|
+
*/
|
|
322
|
+
private resourceFolderName(provider: ProviderName, file: string): string {
|
|
323
|
+
return file.replace(`providers/${provider}/`, "").replace("/index.ts", "");
|
|
301
324
|
}
|
|
302
325
|
|
|
303
326
|
private emitProviderFunctions(
|
|
@@ -333,7 +356,7 @@ export class TerraformProviderGenerator {
|
|
|
333
356
|
this.code.openFile(filePath);
|
|
334
357
|
this.code.line("// generated by cdktn get");
|
|
335
358
|
for (const file of files) {
|
|
336
|
-
const dirName =
|
|
359
|
+
const dirName = this.resourceFolderName(provider, file);
|
|
337
360
|
this.code.line(
|
|
338
361
|
`export * as ${toCamelCase(dirName)} from './${dirName}/index${this.importExtension}';`,
|
|
339
362
|
);
|
|
@@ -348,7 +371,7 @@ export class TerraformProviderGenerator {
|
|
|
348
371
|
this.code.openFile(filePath);
|
|
349
372
|
this.code.line("// generated by cdktn get");
|
|
350
373
|
for (const file of files) {
|
|
351
|
-
const dirName =
|
|
374
|
+
const dirName = this.resourceFolderName(provider, file);
|
|
352
375
|
this.code.line(
|
|
353
376
|
`Object.defineProperty(exports, '${toCamelCase(
|
|
354
377
|
dirName,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
isAttributeNestedType,
|
|
12
12
|
isNestedTypeAttribute,
|
|
13
13
|
Schema,
|
|
14
|
+
TerraformTargetVersions,
|
|
14
15
|
} from "@cdktn/commons";
|
|
15
16
|
import { ProviderName, FQPN, parseFQPN } from "@cdktn/provider-schema";
|
|
16
17
|
import {
|
|
@@ -82,8 +83,17 @@ export function sanitizeClassOrNamespaceName(
|
|
|
82
83
|
isProvider = false,
|
|
83
84
|
) {
|
|
84
85
|
const resourceIsNamedProvider = !isProvider && baseName === "provider";
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
// A resource named `<provider>_provider_functions` maps to the same
|
|
87
|
+
// providers/<provider>/provider-functions/ directory that the provider's
|
|
88
|
+
// functions submodule is emitted to, and would silently overwrite it.
|
|
89
|
+
const resourceIsNamedProviderFunctions =
|
|
90
|
+
!isProvider && baseName === "provider_functions";
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
isReservedClassOrNamespaceName(baseName) ||
|
|
94
|
+
resourceIsNamedProvider ||
|
|
95
|
+
resourceIsNamedProviderFunctions
|
|
96
|
+
) {
|
|
87
97
|
return `${baseName}_resource`;
|
|
88
98
|
} else {
|
|
89
99
|
return baseName;
|
|
@@ -114,6 +124,7 @@ class Parser {
|
|
|
114
124
|
constructor(
|
|
115
125
|
private classNames: string[],
|
|
116
126
|
private usedBaseNames: Map<string, string>,
|
|
127
|
+
private targetVersions?: TerraformTargetVersions,
|
|
117
128
|
) {}
|
|
118
129
|
|
|
119
130
|
private uniqueClassName(className: string): string {
|
|
@@ -285,6 +296,7 @@ class Parser {
|
|
|
285
296
|
terraformSchemaType,
|
|
286
297
|
structs: this.structs,
|
|
287
298
|
configStructName,
|
|
299
|
+
targetVersions: this.targetVersions,
|
|
288
300
|
});
|
|
289
301
|
|
|
290
302
|
return resourceModel;
|
|
@@ -718,6 +730,8 @@ export class ResourceParser {
|
|
|
718
730
|
private uniqueBaseNames: Map<string, string> = new Map();
|
|
719
731
|
private resources: Record<string, ResourceModel> = {};
|
|
720
732
|
|
|
733
|
+
constructor(private readonly targetVersions?: TerraformTargetVersions) {}
|
|
734
|
+
|
|
721
735
|
public parse(
|
|
722
736
|
fqpn: FQPN,
|
|
723
737
|
type: string,
|
|
@@ -729,7 +743,11 @@ export class ResourceParser {
|
|
|
729
743
|
return this.resources[type];
|
|
730
744
|
}
|
|
731
745
|
|
|
732
|
-
const parser = new Parser(
|
|
746
|
+
const parser = new Parser(
|
|
747
|
+
this.uniqueClassnames,
|
|
748
|
+
this.uniqueBaseNames,
|
|
749
|
+
this.targetVersions,
|
|
750
|
+
);
|
|
733
751
|
const resource = parser.resourceFrom(
|
|
734
752
|
fqpn,
|
|
735
753
|
type,
|