@tsed/cli 7.0.0-alpha.1 → 7.0.0-alpha.3
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/lib/esm/commands/generate/GenerateCmd.js +2 -6
- package/lib/esm/commands/init/InitCmd.js +10 -9
- package/lib/esm/commands/init/config/FeaturesPrompt.js +29 -7
- package/lib/esm/fn/taskOutput.js +7 -0
- package/lib/esm/processors/transformConfigFile.js +100 -21
- package/lib/esm/processors/transformIndexFile.js +0 -5
- package/lib/esm/processors/transformServerFile.js +0 -4
- package/lib/esm/services/CliProjectService.js +14 -9
- package/lib/esm/services/CliTemplatesService.js +3 -2
- package/lib/esm/services/ProjectClient.js +24 -1
- package/lib/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/commands/init/config/FeaturesPrompt.d.ts +1 -0
- package/lib/types/fn/taskOutput.d.ts +1 -0
- package/lib/types/interfaces/RenderDataContext.d.ts +1 -0
- package/lib/types/services/CliProjectService.d.ts +1 -0
- package/lib/types/services/ProjectClient.d.ts +4 -0
- package/package.json +3 -3
|
@@ -53,15 +53,11 @@ export class GenerateCmd {
|
|
|
53
53
|
{
|
|
54
54
|
title: `Generate ${ctx.type} file to '${symbolPath}.ts'`,
|
|
55
55
|
skip: !this.templates.get(type),
|
|
56
|
-
task: () =>
|
|
57
|
-
this.projectService.createFromTemplate(type, ctx);
|
|
58
|
-
}
|
|
56
|
+
task: () => this.projectService.createFromTemplate(type, ctx)
|
|
59
57
|
},
|
|
60
58
|
{
|
|
61
59
|
title: "Transform generated files",
|
|
62
|
-
task: () =>
|
|
63
|
-
return this.projectService.transformFiles(ctx);
|
|
64
|
-
}
|
|
60
|
+
task: () => this.projectService.transformFiles(ctx)
|
|
65
61
|
}
|
|
66
62
|
];
|
|
67
63
|
}
|
|
@@ -7,6 +7,7 @@ import { kebabCase } from "change-case";
|
|
|
7
7
|
import { DEFAULT_TSED_TAGS, TEMPLATE_DIR } from "../../constants/index.js";
|
|
8
8
|
import { exec } from "../../fn/exec.js";
|
|
9
9
|
import { render } from "../../fn/render.js";
|
|
10
|
+
import { taskOutput } from "../../fn/taskOutput.js";
|
|
10
11
|
import { ArchitectureConvention } from "../../interfaces/ArchitectureConvention.js";
|
|
11
12
|
import { PlatformType } from "../../interfaces/index.js";
|
|
12
13
|
import { ProjectConvention } from "../../interfaces/ProjectConvention.js";
|
|
@@ -160,13 +161,11 @@ export class InitCmd {
|
|
|
160
161
|
return [
|
|
161
162
|
{
|
|
162
163
|
title: "Render base files",
|
|
163
|
-
task:
|
|
164
|
-
return this.renderFiles(ctx);
|
|
165
|
-
}
|
|
164
|
+
task: () => this.renderFiles(ctx)
|
|
166
165
|
},
|
|
167
166
|
{
|
|
168
167
|
title: "Alter package json",
|
|
169
|
-
task:
|
|
168
|
+
task: () => {
|
|
170
169
|
return $asyncAlter("$alterPackageJson", this.packageJson, [ctx]);
|
|
171
170
|
}
|
|
172
171
|
},
|
|
@@ -175,7 +174,7 @@ export class InitCmd {
|
|
|
175
174
|
task: createSubTasks(async () => {
|
|
176
175
|
const subTasks = [
|
|
177
176
|
...(await exec("generate", {
|
|
178
|
-
|
|
177
|
+
//...ctx,
|
|
179
178
|
type: "controller",
|
|
180
179
|
route: "rest",
|
|
181
180
|
name: "HelloWorld",
|
|
@@ -183,7 +182,7 @@ export class InitCmd {
|
|
|
183
182
|
})),
|
|
184
183
|
...(ctx.commands
|
|
185
184
|
? await exec("generate", {
|
|
186
|
-
|
|
185
|
+
//...ctx,
|
|
187
186
|
type: "command",
|
|
188
187
|
route: "hello",
|
|
189
188
|
name: "hello"
|
|
@@ -241,6 +240,7 @@ export class InitCmd {
|
|
|
241
240
|
"@tsed/core": ctx.tsedVersion,
|
|
242
241
|
"@tsed/di": ctx.tsedVersion,
|
|
243
242
|
"@tsed/ajv": ctx.tsedVersion,
|
|
243
|
+
"@tsed/config": ctx.tsedVersion,
|
|
244
244
|
"@tsed/exceptions": ctx.tsedVersion,
|
|
245
245
|
"@tsed/schema": ctx.tsedVersion,
|
|
246
246
|
"@tsed/json-mapper": ctx.tsedVersion,
|
|
@@ -259,9 +259,6 @@ export class InitCmd {
|
|
|
259
259
|
"@tsed/barrels": "latest",
|
|
260
260
|
ajv: "latest",
|
|
261
261
|
"cross-env": "latest",
|
|
262
|
-
dotenv: "latest",
|
|
263
|
-
"dotenv-expand": "latest",
|
|
264
|
-
"dotenv-flow": "latest",
|
|
265
262
|
...this.runtimes.get().dependencies(),
|
|
266
263
|
...this.platforms.get(ctx.platform).dependencies(ctx)
|
|
267
264
|
});
|
|
@@ -326,8 +323,11 @@ export class InitCmd {
|
|
|
326
323
|
}
|
|
327
324
|
async renderFiles(ctx) {
|
|
328
325
|
// base files
|
|
326
|
+
let startTime = Date.now();
|
|
329
327
|
await this.baseFiles(ctx);
|
|
328
|
+
taskOutput(`Base files rendered (${Date.now() - startTime}ms)`);
|
|
330
329
|
const files = await $asyncAlter("$alterRenderFiles", [], [ctx]);
|
|
330
|
+
startTime = Date.now();
|
|
331
331
|
const promises = files.map((option) => {
|
|
332
332
|
if (!option) {
|
|
333
333
|
return;
|
|
@@ -350,6 +350,7 @@ export class InitCmd {
|
|
|
350
350
|
}
|
|
351
351
|
});
|
|
352
352
|
await Promise.all(promises);
|
|
353
|
+
taskOutput(`Plugins files rendered (${Date.now() - startTime}ms)`);
|
|
353
354
|
}
|
|
354
355
|
}
|
|
355
356
|
command(InitCmd, {
|
|
@@ -16,6 +16,7 @@ export var FeatureType;
|
|
|
16
16
|
FeatureType["CONFIG_DOTENV"] = "config:dotenv";
|
|
17
17
|
FeatureType["CONFIG_JSON"] = "config:json";
|
|
18
18
|
FeatureType["CONFIG_YAML"] = "config:yaml";
|
|
19
|
+
FeatureType["CONFIG_AWS_SECRETS"] = "config:aws_secrets";
|
|
19
20
|
FeatureType["CONFIG_IOREDIS"] = "config:ioredis";
|
|
20
21
|
FeatureType["CONFIG_MONGO"] = "config:mongo";
|
|
21
22
|
FeatureType["CONFIG_VAULT"] = "config:vault";
|
|
@@ -158,39 +159,59 @@ export const FeaturesMap = {
|
|
|
158
159
|
name: "Envs"
|
|
159
160
|
},
|
|
160
161
|
[FeatureType.CONFIG_DOTENV]: {
|
|
161
|
-
name: "Dotenv"
|
|
162
|
+
name: "Dotenv",
|
|
163
|
+
dependencies: {
|
|
164
|
+
dotenv: "latest",
|
|
165
|
+
"dotenv-expand": "latest",
|
|
166
|
+
"dotenv-flow": "latest"
|
|
167
|
+
}
|
|
162
168
|
},
|
|
163
169
|
[FeatureType.CONFIG_JSON]: {
|
|
164
170
|
name: "JSON"
|
|
165
171
|
},
|
|
166
172
|
[FeatureType.CONFIG_YAML]: {
|
|
167
|
-
name: "YAML"
|
|
173
|
+
name: "YAML",
|
|
174
|
+
dependencies: {
|
|
175
|
+
"js-yaml": "latest"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
[FeatureType.CONFIG_AWS_SECRETS]: {
|
|
179
|
+
name: "AWS Secrets Manager (Premium)",
|
|
180
|
+
dependencies: {
|
|
181
|
+
"@tsedio/config-source-aws-secrets": "latest",
|
|
182
|
+
"@aws-sdk/client-secrets-manager": "latest"
|
|
183
|
+
}
|
|
168
184
|
},
|
|
169
185
|
[FeatureType.CONFIG_IOREDIS]: {
|
|
170
186
|
name: "IORedis (Premium)",
|
|
171
187
|
dependencies: {
|
|
172
|
-
ioredis: "
|
|
173
|
-
"@
|
|
188
|
+
"@tsedio/config-ioredis": "{{tsedVersion}}",
|
|
189
|
+
"@tsed/ioredis": "{{tsedVersion}}",
|
|
190
|
+
ioredis: "latest"
|
|
191
|
+
},
|
|
192
|
+
devDependencies: {
|
|
193
|
+
"@tsedio/testcontainers-redis": "latest"
|
|
174
194
|
}
|
|
175
195
|
},
|
|
176
196
|
[FeatureType.CONFIG_MONGO]: {
|
|
177
197
|
name: "MongoDB (Premium)",
|
|
178
198
|
dependencies: {
|
|
179
199
|
mongodb: "latest",
|
|
180
|
-
"@tsedio/config-mongo": "
|
|
200
|
+
"@tsedio/config-mongo": "latest"
|
|
181
201
|
}
|
|
182
202
|
},
|
|
183
203
|
[FeatureType.CONFIG_VAULT]: {
|
|
184
204
|
name: "Vault (Premium)",
|
|
185
205
|
dependencies: {
|
|
186
|
-
"@tsedio/config-vault": "
|
|
206
|
+
"@tsedio/config-vault": "latest",
|
|
207
|
+
"node-vault": "latest"
|
|
187
208
|
}
|
|
188
209
|
},
|
|
189
210
|
[FeatureType.CONFIG_POSTGRES]: {
|
|
190
211
|
name: "Postgres (Premium)",
|
|
191
212
|
dependencies: {
|
|
192
213
|
pg: "latest",
|
|
193
|
-
"@tsedio/config-postgres": "
|
|
214
|
+
"@tsedio/config-postgres": "latest"
|
|
194
215
|
}
|
|
195
216
|
},
|
|
196
217
|
/// TYPEORM
|
|
@@ -389,6 +410,7 @@ export const FeaturesPrompt = (availableRuntimes, availablePackageManagers) => [
|
|
|
389
410
|
FeatureType.CONFIG_DOTENV,
|
|
390
411
|
FeatureType.CONFIG_JSON,
|
|
391
412
|
FeatureType.CONFIG_YAML,
|
|
413
|
+
FeatureType.CONFIG_AWS_SECRETS,
|
|
392
414
|
FeatureType.CONFIG_IOREDIS,
|
|
393
415
|
FeatureType.CONFIG_MONGO,
|
|
394
416
|
FeatureType.CONFIG_VAULT,
|
|
@@ -1,26 +1,105 @@
|
|
|
1
|
-
import { SyntaxKind } from "ts-morph";
|
|
2
1
|
export function transformConfigFile(project, data) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
if (!data.config && data.commandName === "init") {
|
|
3
|
+
project.addConfigSource("EnvsConfigSource", {
|
|
4
|
+
moduleSpecifier: "@tsedio/config-envs/envs"
|
|
5
|
+
});
|
|
7
6
|
}
|
|
8
7
|
if (data.config) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
if (data.configDotenv) {
|
|
9
|
+
project.addConfigSource("DotenvConfigSource", {
|
|
10
|
+
moduleSpecifier: "@tsedio/config-envs/dotenv"
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
else if (data.configEnvs) {
|
|
14
|
+
project.addConfigSource("EnvsConfigSource", {
|
|
15
|
+
moduleSpecifier: "@tsedio/config-envs/envs"
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (data.configJson) {
|
|
19
|
+
project.addConfigSource("JsonConfigSource", {
|
|
20
|
+
moduleSpecifier: "@tsedio/config-envs/json",
|
|
21
|
+
content: `withOptions(JsonConfigSource, {
|
|
22
|
+
path: "./config.json"
|
|
23
|
+
})`
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (data.configYaml) {
|
|
27
|
+
project.addConfigSource("YamlConfigSource", {
|
|
28
|
+
moduleSpecifier: "@tsedio/config-envs/yaml",
|
|
29
|
+
content: `withOptions(YamlConfigSource, {
|
|
30
|
+
path: "./config.yaml"
|
|
31
|
+
})`
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (data.configAwsSecrets) {
|
|
35
|
+
project.addConfigSource("AwsSecretsConfigSource", {
|
|
36
|
+
moduleSpecifier: "@tsedio/config-source-aws-secrets",
|
|
37
|
+
content: `withOptions(AwsSecretsConfigSource, {
|
|
38
|
+
name: "aws",
|
|
39
|
+
path: "/my-app/config", // Path prefix in Secrets Manager
|
|
40
|
+
region: "us-east-1", // AWS region
|
|
41
|
+
watch: true // Enable secrets watching
|
|
42
|
+
// validationSchema: object({}) // Optional: add a validation schema
|
|
43
|
+
// maxConcurrency: 10
|
|
44
|
+
})`
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (data.configVault) {
|
|
48
|
+
project.addConfigSource("VaultConfigSource", {
|
|
49
|
+
moduleSpecifier: "@tsedio/config-vault",
|
|
50
|
+
content: ` withOptions(VaultConfigSource, {
|
|
51
|
+
name: "vault",
|
|
52
|
+
endpoint: "http://localhost:8200", // Vault server URL
|
|
53
|
+
token: "your-vault-token", // Your Vault token
|
|
54
|
+
secretPath: "secret/data/myapp", // Path to your secret (KV v2 or v1, see below)
|
|
55
|
+
refreshInterval: 10000 // ⏱️ Polling interval in ms (default: 10s)
|
|
56
|
+
// Additional node-vault options
|
|
57
|
+
|
|
58
|
+
// validationSchema: object({}) // Optional: add a validation schema
|
|
59
|
+
})`
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (data.configIoredis) {
|
|
63
|
+
project.addConfigSource("IoredisConfigSource", {
|
|
64
|
+
moduleSpecifier: "@tsedio/config-ioredis",
|
|
65
|
+
content: `withOptions(IoredisConfigSource, {
|
|
66
|
+
name: "redis",
|
|
67
|
+
prefixKey: "my-config", // Optional: All config keys will be prefixed
|
|
68
|
+
url: "redis://localhost:6379" // Or use any Redis/Cluster options
|
|
69
|
+
// validationSchema: object({}) // Optional: add a validation schema
|
|
70
|
+
})`
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (data.configMongo) {
|
|
74
|
+
project.addConfigSource("MongoConfigSource", {
|
|
75
|
+
moduleSpecifier: "@tsedio/config-mongo",
|
|
76
|
+
content: `withOptions(MongoConfigSource, {
|
|
77
|
+
name: "mongo",
|
|
78
|
+
url: "mongodb://localhost:27017", // MongoDB connection URL
|
|
79
|
+
database: "my_database", // Database name
|
|
80
|
+
collection: "config" // Collection used for config storage
|
|
81
|
+
|
|
82
|
+
// Additional MongoDB client options can be provided here
|
|
83
|
+
|
|
84
|
+
// ConfigSource options
|
|
85
|
+
// validationSchema: object({}) // Optional: add a validation schema
|
|
86
|
+
})`
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (data.configPostgres) {
|
|
90
|
+
project.addConfigSource("PostgresConfigSource", {
|
|
91
|
+
moduleSpecifier: "@tsedio/config-postgres",
|
|
92
|
+
content: `withOptions(PostgresConfigSource, {
|
|
93
|
+
name: "postgres",
|
|
94
|
+
connectionString: "postgresql://postgres:postgres@localhost:5432/my_database", // PostgreSQL connection string
|
|
95
|
+
table: "config" // Table used for config storage
|
|
96
|
+
|
|
97
|
+
// Additional PostgresSQL client options can be provided here
|
|
98
|
+
|
|
99
|
+
// ConfigSource options
|
|
100
|
+
// validationSchema: object({}) // Optional: add a validation schema
|
|
101
|
+
})`
|
|
102
|
+
});
|
|
103
|
+
}
|
|
21
104
|
}
|
|
22
|
-
sourceFile.organizeImports();
|
|
23
|
-
sourceFile.formatText({
|
|
24
|
-
indentSize: 2
|
|
25
|
-
});
|
|
26
105
|
}
|
|
@@ -12,7 +12,6 @@ export function transformIndexFile(project, data) {
|
|
|
12
12
|
moduleSpecifier: "@tsed/platform-" + data.platform.toLowerCase(),
|
|
13
13
|
namedImports: [platformName]
|
|
14
14
|
});
|
|
15
|
-
// replace PlatformBuilder with Platform<PlatformType>
|
|
16
15
|
sourceFile.getImportDeclaration((declaration) => declaration.getModuleSpecifierValue() === "@tsed/platform-http")?.remove();
|
|
17
16
|
sourceFile.getDescendantsOfKind(SyntaxKind.Identifier).map((identifier) => {
|
|
18
17
|
if (identifier.getText() === "PlatformBuilder") {
|
|
@@ -21,8 +20,4 @@ export function transformIndexFile(project, data) {
|
|
|
21
20
|
}
|
|
22
21
|
return identifier;
|
|
23
22
|
});
|
|
24
|
-
sourceFile.organizeImports();
|
|
25
|
-
sourceFile.formatText({
|
|
26
|
-
indentSize: 2
|
|
27
|
-
});
|
|
28
23
|
}
|
|
@@ -4,10 +4,8 @@ import { constant, injectable } from "@tsed/di";
|
|
|
4
4
|
import { $asyncAlter } from "@tsed/hooks";
|
|
5
5
|
import { normalizePath } from "@tsed/normalize-path";
|
|
6
6
|
import { globbySync } from "globby";
|
|
7
|
+
import { taskOutput } from "../fn/taskOutput.js";
|
|
7
8
|
import { PlatformsModule } from "../platforms/PlatformsModule.js";
|
|
8
|
-
import { InitExpressPlatform } from "../platforms/supports/InitExpressPlatform.js";
|
|
9
|
-
import { InitFastifyPlatform } from "../platforms/supports/InitFastifyPlatform.js";
|
|
10
|
-
import { InitKoaPlatform } from "../platforms/supports/InitKoaPlatform.js";
|
|
11
9
|
import { transformBinFile } from "../processors/transformBinFile.js";
|
|
12
10
|
import { transformConfigFile } from "../processors/transformConfigFile.js";
|
|
13
11
|
import { transformIndexFile } from "../processors/transformIndexFile.js";
|
|
@@ -28,13 +26,10 @@ export class CliProjectService {
|
|
|
28
26
|
getServerFileName() {
|
|
29
27
|
return this.get().getSource("Server.ts") ? "Server" : "server";
|
|
30
28
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return this.project;
|
|
34
|
-
}
|
|
29
|
+
create() {
|
|
30
|
+
taskOutput("Create typescript project");
|
|
35
31
|
const fs = inject(CliFs);
|
|
36
32
|
this.project = new ProjectClient({
|
|
37
|
-
// tsConfigFilePath: join(this.rootDir, "tsconfig.json"),
|
|
38
33
|
rootDir: this.rootDir
|
|
39
34
|
});
|
|
40
35
|
const files = fs.globSync([join(constant("project.rootDir", process.cwd()), "**/*.ts")]);
|
|
@@ -43,6 +38,11 @@ export class CliProjectService {
|
|
|
43
38
|
overwrite: true
|
|
44
39
|
});
|
|
45
40
|
});
|
|
41
|
+
}
|
|
42
|
+
get() {
|
|
43
|
+
if (!this.project) {
|
|
44
|
+
this.create();
|
|
45
|
+
}
|
|
46
46
|
return this.project;
|
|
47
47
|
}
|
|
48
48
|
async transformFiles(data) {
|
|
@@ -60,11 +60,16 @@ export class CliProjectService {
|
|
|
60
60
|
await $asyncAlter(`$alterProjectFiles`, project, [data]);
|
|
61
61
|
await Promise.all(project.getSourceFiles().map((sourceFile) => {
|
|
62
62
|
sourceFile.organizeImports();
|
|
63
|
+
sourceFile.formatText({
|
|
64
|
+
indentSize: 2
|
|
65
|
+
});
|
|
63
66
|
return sourceFile.save();
|
|
64
67
|
}));
|
|
65
68
|
}
|
|
66
69
|
async createFromTemplate(templateId, ctx) {
|
|
70
|
+
const startTime = Date.now();
|
|
67
71
|
const obj = await this.templates.render(templateId, ctx);
|
|
72
|
+
taskOutput(`Template ${templateId} rendered in ${Date.now() - startTime}ms`);
|
|
68
73
|
const project = this.get();
|
|
69
74
|
if (obj) {
|
|
70
75
|
const sourceFile = await project.createSource(obj.outputPath, obj.content, {
|
|
@@ -88,4 +93,4 @@ export class CliProjectService {
|
|
|
88
93
|
return [...set];
|
|
89
94
|
}
|
|
90
95
|
}
|
|
91
|
-
injectable(
|
|
96
|
+
injectable(CliProjectService);
|
|
@@ -54,10 +54,11 @@ export class CliTemplatesService {
|
|
|
54
54
|
else {
|
|
55
55
|
const from = data.from || TEMPLATE_DIR;
|
|
56
56
|
const fromPath = join(from, templateId.replace("{{srcDir}}", "src"));
|
|
57
|
-
if (this.fs.
|
|
57
|
+
if (await this.fs.fileExists(fromPath)) {
|
|
58
|
+
const content = await inject(CliFs).readFile(fromPath);
|
|
58
59
|
return {
|
|
59
60
|
templateId,
|
|
60
|
-
content
|
|
61
|
+
content,
|
|
61
62
|
outputPath: templateId.replace("{{srcDir}}", constant("project.srcDir", ""))
|
|
62
63
|
};
|
|
63
64
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
2
|
import { CliDockerComposeYaml, CliFs, ProjectPackageJson } from "@tsed/cli-core";
|
|
3
3
|
import { isString } from "@tsed/core";
|
|
4
4
|
import { constant, inject } from "@tsed/di";
|
|
@@ -45,6 +45,7 @@ export class ProjectClient extends Project {
|
|
|
45
45
|
await source.save();
|
|
46
46
|
return source;
|
|
47
47
|
}
|
|
48
|
+
await this.fs.ensureDir(dirname(path));
|
|
48
49
|
await this.fs.writeFile(path, sourceFileText, { encoding: "utf-8" });
|
|
49
50
|
}
|
|
50
51
|
findClassDecorator(sourceFile, name) {
|
|
@@ -136,4 +137,26 @@ export class ProjectClient extends Project {
|
|
|
136
137
|
}
|
|
137
138
|
return undefined;
|
|
138
139
|
}
|
|
140
|
+
addConfigSource(name, { content = name, moduleSpecifier }) {
|
|
141
|
+
const sourceFile = this.configSourceFile;
|
|
142
|
+
const options = this.findConfiguration("config");
|
|
143
|
+
if (!options) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const extendsConfig = this.getPropertyAssignment(options, {
|
|
147
|
+
name: "extends",
|
|
148
|
+
kind: SyntaxKind.ArrayLiteralExpression,
|
|
149
|
+
initializer: "[]"
|
|
150
|
+
});
|
|
151
|
+
const has = extendsConfig.getElements().some((expression) => {
|
|
152
|
+
return expression.getText().includes(name);
|
|
153
|
+
});
|
|
154
|
+
if (!has) {
|
|
155
|
+
sourceFile.addImportDeclaration({
|
|
156
|
+
moduleSpecifier,
|
|
157
|
+
namedImports: [{ name: name }]
|
|
158
|
+
});
|
|
159
|
+
extendsConfig.addElement("\n" + content);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
139
162
|
}
|