@tsed/cli 7.0.0-alpha.1 → 7.0.0-alpha.10

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 (88) hide show
  1. package/lib/esm/bin/tsed.js +23 -2
  2. package/lib/esm/commands/generate/GenerateCmd.js +8 -11
  3. package/lib/esm/commands/index.js +2 -1
  4. package/lib/esm/commands/init/InitCmd.js +14 -11
  5. package/lib/esm/commands/init/config/FeaturesPrompt.js +40 -19
  6. package/lib/esm/commands/init/mappers/mapToContext.js +4 -0
  7. package/lib/esm/commands/init/prompts/getFeaturesPrompt.js +0 -12
  8. package/lib/esm/commands/init/utils/hasFeature.js +3 -0
  9. package/lib/esm/commands/template/CreateTemplateCommand.js +101 -0
  10. package/lib/esm/fn/taskOutput.js +7 -0
  11. package/lib/esm/index.js +3 -1
  12. package/lib/esm/processors/transformConfigFile.js +100 -21
  13. package/lib/esm/processors/transformIndexFile.js +0 -5
  14. package/lib/esm/processors/transformServerFile.js +0 -4
  15. package/lib/esm/services/CliProjectService.js +16 -12
  16. package/lib/esm/services/CliTemplatesService.js +67 -15
  17. package/lib/esm/services/ProjectClient.js +24 -1
  18. package/lib/esm/services/mappers/addContextMethods.js +17 -0
  19. package/lib/esm/services/mappers/mapDefaultTemplateOptions.js +7 -1
  20. package/lib/esm/templates/barrels.template.js +7 -2
  21. package/lib/esm/templates/controller.template.js +24 -25
  22. package/lib/esm/templates/decorator.template.js +26 -24
  23. package/lib/esm/templates/docker-compose.template.js +2 -2
  24. package/lib/esm/templates/dockerfile.template.js +5 -5
  25. package/lib/esm/templates/index.command.template.js +6 -2
  26. package/lib/esm/templates/index.config.utils.template.js +1 -1
  27. package/lib/esm/templates/index.js +1 -1
  28. package/lib/esm/templates/index.logger.template.js +5 -2
  29. package/lib/esm/templates/middleware.template.js +16 -14
  30. package/lib/esm/templates/new-template.template.js +67 -0
  31. package/lib/esm/templates/readme.template.js +3 -3
  32. package/lib/esm/templates/tsconfig.spec.template.js +6 -5
  33. package/lib/esm/utils/defineTemplate.js +2 -2
  34. package/lib/tsconfig.esm.tsbuildinfo +1 -1
  35. package/lib/types/bin/tsed.d.ts +1 -1
  36. package/lib/types/commands/generate/GenerateCmd.d.ts +1 -36
  37. package/lib/types/commands/index.d.ts +2 -1
  38. package/lib/types/commands/init/config/FeaturesPrompt.d.ts +13 -5
  39. package/lib/types/commands/init/prompts/getFeaturesPrompt.d.ts +0 -6
  40. package/lib/types/commands/init/utils/hasFeature.d.ts +1 -0
  41. package/lib/types/commands/template/CreateTemplateCommand.d.ts +62 -0
  42. package/lib/types/fn/taskOutput.d.ts +1 -0
  43. package/lib/types/index.d.ts +3 -1
  44. package/lib/types/interfaces/GenerateCmdContext.d.ts +2 -0
  45. package/lib/types/interfaces/RenderDataContext.d.ts +2 -0
  46. package/lib/types/pipes/SymbolNamePipe.d.ts +1 -1
  47. package/lib/types/services/CliProjectService.d.ts +3 -2
  48. package/lib/types/services/CliTemplatesService.d.ts +9 -3
  49. package/lib/types/services/ProjectClient.d.ts +4 -0
  50. package/lib/types/services/mappers/addContextMethods.d.ts +12 -0
  51. package/lib/types/templates/asyncFactory.template.d.ts +15 -1
  52. package/lib/types/templates/barrels.template.d.ts +15 -1
  53. package/lib/types/templates/command.template.d.ts +15 -1
  54. package/lib/types/templates/config.template.d.ts +15 -1
  55. package/lib/types/templates/controller.template.d.ts +16 -1
  56. package/lib/types/templates/decorator.template.d.ts +16 -1
  57. package/lib/types/templates/docker-compose.template.d.ts +15 -1
  58. package/lib/types/templates/exception-filter.template.d.ts +15 -1
  59. package/lib/types/templates/factory.template.d.ts +15 -1
  60. package/lib/types/templates/index.command.template.d.ts +15 -1
  61. package/lib/types/templates/index.config.utils.template.d.ts +15 -1
  62. package/lib/types/templates/index.controller.template.d.ts +15 -1
  63. package/lib/types/templates/index.d.ts +1 -1
  64. package/lib/types/templates/index.logger.template.d.ts +15 -1
  65. package/lib/types/templates/index.template.d.ts +15 -1
  66. package/lib/types/templates/interceptor.template.d.ts +15 -1
  67. package/lib/types/templates/interface.template.d.ts +15 -1
  68. package/lib/types/templates/middleware.template.d.ts +16 -1
  69. package/lib/types/templates/model.template.d.ts +15 -1
  70. package/lib/types/templates/module.template.d.ts +15 -1
  71. package/lib/types/templates/new-template.template.d.ts +9 -0
  72. package/lib/types/templates/pipe.template.d.ts +15 -1
  73. package/lib/types/templates/prisma.service.template.d.ts +15 -1
  74. package/lib/types/templates/readme.template.d.ts +15 -1
  75. package/lib/types/templates/repository.template.d.ts +15 -1
  76. package/lib/types/templates/response-filter.template.d.ts +15 -1
  77. package/lib/types/templates/server.template.d.ts +15 -1
  78. package/lib/types/templates/service.template.d.ts +15 -1
  79. package/lib/types/templates/tsconfig.spec.template.d.ts +15 -1
  80. package/lib/types/templates/value.template.d.ts +15 -1
  81. package/lib/types/utils/defineTemplate.d.ts +31 -3
  82. package/package.json +10 -10
  83. package/templates/tsconfig.json +11 -0
  84. package/templates/tsconfig.node.json +1 -1
  85. package/lib/esm/Cli.js +0 -57
  86. package/lib/esm/templates/tsconfig.template.js +0 -31
  87. package/lib/types/Cli.d.ts +0 -26
  88. package/lib/types/templates/tsconfig.template.d.ts +0 -2
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import "@swc-node/register/esm-register";
2
3
  import { register } from "node:module";
3
4
  import { join } from "node:path";
4
5
  import { pathToFileURL } from "node:url";
@@ -14,8 +15,28 @@ register(pathToFileURL(join(import.meta.dirname, `../loaders/alias.hook.${EXT}`)
14
15
  },
15
16
  transferList: []
16
17
  });
17
- const { Cli } = await import("../Cli.js");
18
- Cli.bootstrap({}).catch((error) => {
18
+ const { commands, CliCore, PKG, TEMPLATE_DIR, ArchitectureConvention, ProjectConvention } = await import("../index.js");
19
+ CliCore.bootstrap({
20
+ name: "tsed",
21
+ pkg: PKG,
22
+ templateDir: TEMPLATE_DIR,
23
+ plugins: true,
24
+ updateNotifier: true,
25
+ checkPrecondition: true,
26
+ commands,
27
+ defaultProjectPreferences() {
28
+ return {
29
+ convention: ProjectConvention.DEFAULT,
30
+ architecture: ArchitectureConvention.DEFAULT
31
+ };
32
+ },
33
+ project: {
34
+ reinstallAfterRun: true
35
+ },
36
+ logger: {
37
+ level: "info"
38
+ }
39
+ }).catch((error) => {
19
40
  console.error(error);
20
41
  process.exit(-1);
21
42
  });
@@ -1,14 +1,15 @@
1
1
  import { command, inject, ProjectPackageJson } from "@tsed/cli-core";
2
- import { pascalCase } from "change-case";
3
2
  import { CliProjectService } from "../../services/CliProjectService.js";
4
3
  import { CliTemplatesService } from "../../services/CliTemplatesService.js";
4
+ import { addContextMethods } from "../../services/mappers/addContextMethods.js";
5
5
  import { mapDefaultTemplateOptions } from "../../services/mappers/mapDefaultTemplateOptions.js";
6
6
  const searchFactory = (list) => {
7
+ const items = list.map((item) => ({ name: item.label, value: item.id }));
7
8
  return (_, keyword) => {
8
9
  if (keyword) {
9
- return list.filter((item) => item.label.toLowerCase().includes(keyword.toLowerCase()));
10
+ return items.filter((item) => item.name.toLowerCase().includes(keyword.toLowerCase()));
10
11
  }
11
- return list;
12
+ return items;
12
13
  };
13
14
  };
14
15
  export class GenerateCmd {
@@ -18,7 +19,7 @@ export class GenerateCmd {
18
19
  this.templates = inject(CliTemplatesService);
19
20
  }
20
21
  async $prompt(data) {
21
- data.getName = (state) => data.name || pascalCase(state.name || data.name || state.type || data.type || "");
22
+ data = addContextMethods(data);
22
23
  const templates = this.templates.find();
23
24
  const templatesPrompts = await Promise.all(templates
24
25
  .filter((template) => template.prompts)
@@ -29,7 +30,7 @@ export class GenerateCmd {
29
30
  {
30
31
  type: "autocomplete",
31
32
  name: "type",
32
- message: "Which type of provider?",
33
+ message: "Which template you want to use?",
33
34
  default: data.type,
34
35
  when: () => templates.length > 1,
35
36
  source: searchFactory(this.templates.find(data.type))
@@ -53,15 +54,11 @@ export class GenerateCmd {
53
54
  {
54
55
  title: `Generate ${ctx.type} file to '${symbolPath}.ts'`,
55
56
  skip: !this.templates.get(type),
56
- task: () => {
57
- this.projectService.createFromTemplate(type, ctx);
58
- }
57
+ task: () => this.projectService.createFromTemplate(type, ctx)
59
58
  },
60
59
  {
61
60
  title: "Transform generated files",
62
- task: () => {
63
- return this.projectService.transformFiles(ctx);
64
- }
61
+ task: () => this.projectService.transformFiles(ctx)
65
62
  }
66
63
  ];
67
64
  }
@@ -2,5 +2,6 @@ import { AddCmd } from "./add/AddCmd.js";
2
2
  import { GenerateCmd } from "./generate/GenerateCmd.js";
3
3
  import { InitCmd } from "./init/InitCmd.js";
4
4
  import { RunCmd } from "./run/RunCmd.js";
5
+ import { CreateTemplateCommand } from "./template/CreateTemplateCommand.js";
5
6
  import { UpdateCmd } from "./update/UpdateCmd.js";
6
- export default [AddCmd, InitCmd, GenerateCmd, UpdateCmd, RunCmd];
7
+ export default [AddCmd, InitCmd, GenerateCmd, UpdateCmd, RunCmd, CreateTemplateCommand];
@@ -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";
@@ -119,7 +120,7 @@ export class InitCmd {
119
120
  await createTasksRunner([
120
121
  {
121
122
  title: "Write RC files",
122
- skip: () => !ctx.GH_TOKEN,
123
+ skip: () => !ctx.premium,
123
124
  task: () => {
124
125
  return Promise.all([render(".npmrc", ctx), render(".yarnrc", ctx)]);
125
126
  }
@@ -160,13 +161,11 @@ export class InitCmd {
160
161
  return [
161
162
  {
162
163
  title: "Render base files",
163
- task: async () => {
164
- return this.renderFiles(ctx);
165
- }
164
+ task: () => this.renderFiles(ctx)
166
165
  },
167
166
  {
168
167
  title: "Alter package json",
169
- task: async () => {
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
- ...ctx,
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
- ...ctx,
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,
@@ -255,13 +255,11 @@ export class InitCmd {
255
255
  "@tsed/platform-views": ctx.tsedVersion,
256
256
  "@tsed/platform-multer": ctx.tsedVersion,
257
257
  "@tsed/logger": "latest",
258
+ "@tsed/logger-std": "latest",
258
259
  "@tsed/engines": "latest",
259
260
  "@tsed/barrels": "latest",
260
261
  ajv: "latest",
261
262
  "cross-env": "latest",
262
- dotenv: "latest",
263
- "dotenv-expand": "latest",
264
- "dotenv-flow": "latest",
265
263
  ...this.runtimes.get().dependencies(),
266
264
  ...this.platforms.get(ctx.platform).dependencies(ctx)
267
265
  });
@@ -301,7 +299,7 @@ export class InitCmd {
301
299
  // files with higher priority
302
300
  const promises = [
303
301
  "tsconfig.base.json",
304
- "tsconfig.config.json",
302
+ "tsconfig.json",
305
303
  "tsconfig.spec.json",
306
304
  "tsconfig.node.json",
307
305
  "docker-compose.yml",
@@ -314,6 +312,7 @@ export class InitCmd {
314
312
  "index.config.util",
315
313
  "index.logger",
316
314
  "index.controller",
315
+ ctx.commands && "index.command",
317
316
  "barrels",
318
317
  "readme",
319
318
  `pm2.${pm2}`,
@@ -326,8 +325,11 @@ export class InitCmd {
326
325
  }
327
326
  async renderFiles(ctx) {
328
327
  // base files
328
+ let startTime = Date.now();
329
329
  await this.baseFiles(ctx);
330
+ taskOutput(`Base files rendered (${Date.now() - startTime}ms)`);
330
331
  const files = await $asyncAlter("$alterRenderFiles", [], [ctx]);
332
+ startTime = Date.now();
331
333
  const promises = files.map((option) => {
332
334
  if (!option) {
333
335
  return;
@@ -350,6 +352,7 @@ export class InitCmd {
350
352
  }
351
353
  });
352
354
  await Promise.all(promises);
355
+ taskOutput(`Plugins files rendered (${Date.now() - startTime}ms)`);
353
356
  }
354
357
  }
355
358
  command(InitCmd, {
@@ -1,5 +1,5 @@
1
1
  import { ArchitectureConvention, PlatformType, ProjectConvention } from "../../../interfaces/index.js";
2
- import { hasFeature, hasValue } from "../utils/hasFeature.js";
2
+ import { hasFeature, hasValue, hasValuePremium } from "../utils/hasFeature.js";
3
3
  import { isPlatform } from "../utils/isPlatform.js";
4
4
  export var FeatureType;
5
5
  (function (FeatureType) {
@@ -16,10 +16,11 @@ 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_IOREDIS"] = "config:ioredis";
20
- FeatureType["CONFIG_MONGO"] = "config:mongo";
21
- FeatureType["CONFIG_VAULT"] = "config:vault";
22
- FeatureType["CONFIG_POSTGRES"] = "config:postgres";
19
+ FeatureType["CONFIG_AWS_SECRETS"] = "config:aws_secrets:premium";
20
+ FeatureType["CONFIG_IOREDIS"] = "config:ioredis:premium";
21
+ FeatureType["CONFIG_MONGO"] = "config:mongo:premium";
22
+ FeatureType["CONFIG_VAULT"] = "config:vault:premium";
23
+ FeatureType["CONFIG_POSTGRES"] = "config:postgres:premium";
23
24
  // DOC
24
25
  FeatureType["SWAGGER"] = "swagger";
25
26
  FeatureType["SCALAR"] = "scalar";
@@ -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: "latest",
173
- "@tsedio/config-ioredis": "{{tsedVersion}}"
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": "{{tsedVersion}}"
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": "{{tsedVersion}}"
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": "{{tsedVersion}}"
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,
@@ -431,13 +453,12 @@ export const FeaturesPrompt = (availableRuntimes, availablePackageManagers) => [
431
453
  ],
432
454
  when: hasValue("featuresDB", FeatureType.TYPEORM)
433
455
  },
434
- // {
435
- // type: "password",
436
- // name: "GH_TOKEN",
437
- // message:
438
- // "Enter GH_TOKEN to use the premium @tsedio package or leave blank (see https://tsed.dev/plugins/premium/install-premium-plugins.html)"
439
- // // when: hasValue("featuresDB.type", "prisma")
440
- // },
456
+ {
457
+ type: "password",
458
+ name: "GH_TOKEN",
459
+ message: "Enter GH_TOKEN to use the premium @tsedio package or leave blank (see https://tsed.dev/plugins/premium/install-premium-plugins.html)",
460
+ when: hasValuePremium()
461
+ },
441
462
  {
442
463
  message: "Choose unit framework",
443
464
  type: "list",
@@ -4,6 +4,10 @@ export function mapToContext(options) {
4
4
  options = mapUniqFeatures(options);
5
5
  options.features.forEach((feature) => {
6
6
  const [base, type] = feature.split(":");
7
+ if (feature?.endsWith(":premium")) {
8
+ feature = feature.replace(":premium", "");
9
+ options.premium = true;
10
+ }
7
11
  options[camelCase(base)] = true;
8
12
  type && (options[camelCase(type)] = true);
9
13
  feature && (options[camelCase(feature)] = true);
@@ -18,15 +18,3 @@ export function getFeaturesPrompt(runtimes, availablePackageManagers, options) {
18
18
  });
19
19
  });
20
20
  }
21
- export function getFrameworksPrompt() {
22
- return {
23
- ...FrameworksPrompt,
24
- choices: FrameworksPrompt.choices.map((choice, index) => {
25
- return cleanObject({
26
- ...FeaturesMap[choice],
27
- checked: index === 0,
28
- value: choice
29
- });
30
- })
31
- };
32
- }
@@ -5,3 +5,6 @@ export function hasValue(expression, value) {
5
5
  export function hasFeature(feature) {
6
6
  return (ctx) => !!ctx.features.find((item) => item === feature);
7
7
  }
8
+ export function hasValuePremium() {
9
+ return (ctx) => !!ctx.features.find((item) => item.endsWith(":premium"));
10
+ }
@@ -0,0 +1,101 @@
1
+ import { command, inject, ProjectPackageJson } from "@tsed/cli-core";
2
+ import { snakeCase } from "change-case";
3
+ import { PKG } from "../../constants/index.js";
4
+ import { render } from "../../fn/render.js";
5
+ import { CliTemplatesService } from "../../services/CliTemplatesService.js";
6
+ const searchFactory = (list) => {
7
+ const items = list.map((item) => ({ name: item.label, value: item.id }));
8
+ return (_, keyword) => {
9
+ if (keyword) {
10
+ return items.filter((item) => item.name.toLowerCase().includes(keyword.toLowerCase()));
11
+ }
12
+ return items;
13
+ };
14
+ };
15
+ export class CreateTemplateCommand {
16
+ constructor() {
17
+ this.projectPackageJson = inject(ProjectPackageJson);
18
+ this.templates = inject(CliTemplatesService);
19
+ }
20
+ async $prompt(data) {
21
+ return [
22
+ {
23
+ type: "list",
24
+ name: "from",
25
+ message: "Create a template from existing one?",
26
+ default: "new",
27
+ when: !data.from,
28
+ choices: [
29
+ { name: "No, create a new template", value: "new" },
30
+ { name: "Yes, from existing template", value: "existing" }
31
+ ]
32
+ },
33
+ {
34
+ type: "autocomplete",
35
+ name: "templateId",
36
+ message: "Select the template to use as base",
37
+ default: data.from,
38
+ when: (ctx) => {
39
+ return ctx.from === "existing";
40
+ },
41
+ source: searchFactory(this.templates.find())
42
+ },
43
+ {
44
+ type: "confirm",
45
+ name: "override",
46
+ message: "Would you like to override the selected Ts.ED default template?",
47
+ when: (ctx) => ctx.from !== "new",
48
+ default: !!data.override
49
+ },
50
+ {
51
+ type: "input",
52
+ name: "name",
53
+ message: "Which name?",
54
+ default: data.name,
55
+ when: !data.name
56
+ }
57
+ ];
58
+ }
59
+ $mapContext(ctx) {
60
+ const symbolName = snakeCase(ctx.name).replace(/_/g, "-");
61
+ return {
62
+ ...ctx,
63
+ symbolPath: `./.templates/${symbolName}.template`,
64
+ symbolPathBasename: ".",
65
+ symbolName: symbolName,
66
+ templateId: ctx.orverride ? ctx.templateId : symbolName,
67
+ template: ctx.templateId && this.templates.get(ctx.templateId)
68
+ };
69
+ }
70
+ $exec(ctx) {
71
+ this.projectPackageJson.addDevDependencies({ "@tsed/cli": PKG.version });
72
+ return [
73
+ {
74
+ title: "Generate " + ctx.from === "new" ? `new template ${ctx.templateId}` : `template ${ctx.templateId} from ${ctx.from}`,
75
+ task: async () => {
76
+ await render("new-template", ctx);
77
+ }
78
+ }
79
+ ];
80
+ }
81
+ }
82
+ command(CreateTemplateCommand, {
83
+ name: "template",
84
+ description: "Create a custom template that can be selected in tsed generate command",
85
+ args: {
86
+ name: {
87
+ description: "Name of the class",
88
+ type: String
89
+ }
90
+ },
91
+ options: {
92
+ "--from <from>": {
93
+ type: String,
94
+ description: "Select the template to use as base"
95
+ },
96
+ "--override": {
97
+ type: Boolean,
98
+ description: "Override the existing selected template"
99
+ }
100
+ }
101
+ });
@@ -0,0 +1,7 @@
1
+ import { context } from "@tsed/di";
2
+ export function taskOutput(output) {
3
+ const task = context().get("currentTask");
4
+ if (task) {
5
+ task.output = output;
6
+ }
7
+ }
package/lib/esm/index.js CHANGED
@@ -1,7 +1,8 @@
1
+ import "@tsed/logger-std";
1
2
  import "./templates/index.js";
2
- export * from "./Cli.js";
3
3
  export * from "./commands/add/AddCmd.js";
4
4
  export * from "./commands/generate/GenerateCmd.js";
5
+ export { default as commands } from "./commands/index.js";
5
6
  export * from "./commands/init/config/FeaturesPrompt.js";
6
7
  export * from "./commands/init/config/FeaturesPrompt.js";
7
8
  export * from "./commands/init/InitCmd.js";
@@ -17,3 +18,4 @@ export * from "./services/CliProjectService.js";
17
18
  export * from "./services/CliTemplatesService.js";
18
19
  export * from "./services/ProjectClient.js";
19
20
  export * from "./utils/defineTemplate.js";
21
+ export { CliCore } from "@tsed/cli-core";
@@ -1,26 +1,105 @@
1
- import { SyntaxKind } from "ts-morph";
2
1
  export function transformConfigFile(project, data) {
3
- const sourceFile = project.configSourceFile;
4
- const options = project.findConfiguration("config");
5
- if (!options) {
6
- return;
2
+ if (!data.config && data.commandName === "init") {
3
+ project.addConfigSource("EnvsConfigSource", {
4
+ moduleSpecifier: "@tsed/config/envs"
5
+ });
7
6
  }
8
7
  if (data.config) {
9
- // const extendsConfig = project.getPropertyAssignment(options, {
10
- // name: "extends",
11
- // kind: SyntaxKind.ObjectLiteralExpression,
12
- // initializer: "[]"
13
- // });
14
- //
15
- // if (data.configEnvs) {
16
- // sourceFile.addImportDeclaration({
17
- // moduleSpecifier: "@tsed/config/envs",
18
- // namedImports: [{name: "EnvsConfigSource"}]
19
- // });
20
- // }
8
+ if (data.configDotenv) {
9
+ project.addConfigSource("DotenvConfigSource", {
10
+ moduleSpecifier: "@tsed/config/dotenv"
11
+ });
12
+ }
13
+ else if (data.configEnvs) {
14
+ project.addConfigSource("EnvsConfigSource", {
15
+ moduleSpecifier: "@tsed/config/envs"
16
+ });
17
+ }
18
+ if (data.configJson) {
19
+ project.addConfigSource("JsonConfigSource", {
20
+ moduleSpecifier: "@tsed/config/json",
21
+ content: `withOptions(JsonConfigSource, {
22
+ path: "./config.json"
23
+ })`
24
+ });
25
+ }
26
+ if (data.configYaml) {
27
+ project.addConfigSource("YamlConfigSource", {
28
+ moduleSpecifier: "@tsed/config/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
  }
@@ -57,8 +57,4 @@ export function transformServerFile(project, data) {
57
57
  project.addMountPath("/", "...Object.values(pages)");
58
58
  }
59
59
  }
60
- sourceFile.organizeImports();
61
- sourceFile.formatText({
62
- indentSize: 2
63
- });
64
60
  }