@tsed/cli-core 7.0.0-beta.9 → 7.0.0-rc.2

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.
@@ -1,5 +1,6 @@
1
1
  import "@tsed/logger-std";
2
2
  import { join, resolve } from "node:path";
3
+ import { PromptCancelledError } from "@tsed/cli-prompts";
3
4
  import { constant, inject, injector } from "@tsed/di";
4
5
  import { $asyncEmit } from "@tsed/hooks";
5
6
  import chalk from "chalk";
@@ -88,6 +89,10 @@ export class CliCore {
88
89
  await cliService.parseArgs(constant("argv"));
89
90
  }
90
91
  catch (er) {
92
+ if (er instanceof PromptCancelledError) {
93
+ console.log(chalk.yellow("Prompt cancelled."));
94
+ return this;
95
+ }
91
96
  throw new CliError({ origin: er, cli: this });
92
97
  }
93
98
  return this;
package/lib/esm/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import "./utils/patchCommander.js";
2
- import Inquirer from "inquirer";
3
2
  export * from "./CliCore.js";
4
3
  export * from "./decorators/index.js";
5
4
  export * from "./fn/command.js";
@@ -7,8 +6,9 @@ export * from "./interfaces/index.js";
7
6
  export * from "./packageManagers/index.js";
8
7
  export * from "./services/index.js";
9
8
  export * from "./utils/index.js";
9
+ export * from "@tsed/cli-prompts";
10
+ export * from "@tsed/cli-tasks";
10
11
  export * from "@tsed/core";
11
12
  export * from "@tsed/di";
12
13
  export * from "@tsed/logger";
13
14
  export * from "@tsed/normalize-path";
14
- export { Inquirer };
@@ -1,2 +1 @@
1
- import "inquirer-autocomplete-prompt";
2
- import AutocompletePrompt from "inquirer-autocomplete-prompt";
1
+ export {};
@@ -1,4 +1,3 @@
1
- import { Type } from "@tsed/core";
2
1
  export * from "./CliDefaultOptions.js";
3
2
  export * from "./CommandData.js";
4
3
  export * from "./CommandMetadata.js";
@@ -6,4 +5,3 @@ export * from "./CommandOptions.js";
6
5
  export * from "./CommandProvider.js";
7
6
  export * from "./PackageJson.js";
8
7
  export * from "./ProjectPreferences.js";
9
- export * from "./Tasks.js";
@@ -1,4 +1,4 @@
1
- import { Inject, inject, injectable, injectMany } from "@tsed/di";
1
+ import { inject, injectable, injectMany } from "@tsed/di";
2
2
  import { EMPTY, throwError } from "rxjs";
3
3
  import { catchError } from "rxjs/operators";
4
4
  import { ProjectPackageJson } from "../services/ProjectPackageJson.js";
@@ -39,6 +39,13 @@ export class PackageManagersModule {
39
39
  this.projectPackageJson.rewrite = true;
40
40
  return packageManager.init(options);
41
41
  }
42
+ task(title, ctx = {}) {
43
+ return {
44
+ title,
45
+ type: "progress",
46
+ task: () => this.install(ctx)
47
+ };
48
+ }
42
49
  install(options = {}) {
43
50
  const packageManager = this.get(options.packageManager);
44
51
  options.packageManager = packageManager.name;
@@ -52,16 +59,10 @@ export class PackageManagersModule {
52
59
  GH_TOKEN: this.projectPackageJson.GH_TOKEN
53
60
  }
54
61
  };
55
- const errorPipe = () => catchError((error) => {
56
- if (error.stderr.startsWith("error Your lockfile needs to be updated")) {
57
- return throwError(new Error(`yarn.lock file is outdated. Run ${packageManager.name}, commit the updated lockfile and try again.`));
58
- }
59
- return throwError(error);
60
- });
61
62
  return [
62
63
  {
63
64
  title: "Write package.json",
64
- enabled: () => this.projectPackageJson.rewrite,
65
+ skip: () => !this.projectPackageJson.rewrite,
65
66
  task: () => {
66
67
  this.projectPackageJson.write();
67
68
  }
@@ -69,22 +70,27 @@ export class PackageManagersModule {
69
70
  {
70
71
  title: `Installing dependencies using ${packageManager.name}`,
71
72
  skip: () => !this.projectPackageJson.reinstall,
72
- task: () => packageManager.install(options) // .pipe(errorPipe())
73
+ task: () => packageManager.install(options)
73
74
  },
74
75
  {
75
76
  title: `Add dependencies using ${packageManager.name}`,
76
- skip: () => !deps.length,
77
- task: () => packageManager.add(deps, options) //.pipe(errorPipe())
77
+ enabled: !!deps.length,
78
+ task: () => packageManager.add(deps, options)
78
79
  },
79
80
  {
80
81
  title: `Add devDependencies using ${packageManager.name}`,
81
- skip: () => !devDeps.length,
82
- task: () => packageManager.addDev(devDeps, options) //.pipe(errorPipe())
82
+ enabled: !!devDeps.length,
83
+ task: () => packageManager.addDev(devDeps, options)
84
+ },
85
+ {
86
+ title: `Installing dependencies using ${packageManager.name}`,
87
+ skip: () => !this.projectPackageJson.reinstall,
88
+ task: () => packageManager.install(options)
83
89
  },
84
90
  {
85
91
  title: "Refresh",
86
92
  task: () => {
87
- this.projectPackageJson.refresh();
93
+ return this.projectPackageJson.refresh();
88
94
  }
89
95
  }
90
96
  ];
@@ -2,9 +2,7 @@ import { constant, inject, injectable } from "@tsed/di";
2
2
  import { $asyncEmit } from "@tsed/hooks";
3
3
  import chalk from "chalk";
4
4
  import { PackageManagersModule } from "../packageManagers/PackageManagersModule.js";
5
- import { createSubTasks } from "../utils/createTasksRunner.js";
6
5
  import { loadPlugins } from "../utils/loadPlugins.js";
7
- import { CliHooks } from "./CliHooks.js";
8
6
  import { NpmRegistryClient } from "./NpmRegistryClient.js";
9
7
  import { ProjectPackageJson } from "./ProjectPackageJson.js";
10
8
  function mapPlugins({ package: { name, description = "", ...otherProps } }) {
@@ -36,15 +34,7 @@ export class CliPlugins {
36
34
  }
37
35
  };
38
36
  });
39
- return [
40
- ...tasks,
41
- {
42
- title: "Install",
43
- task: createSubTasks(() => {
44
- return this.packageManagers.install(ctx);
45
- }, { ...ctx, concurrent: false })
46
- }
47
- ];
37
+ return [...tasks, this.packageManagers.task("Install dependencies", ctx)];
48
38
  }
49
39
  getKeyword(keyword) {
50
40
  return `@${this.name}/cli-plugin-${this.cleanKeyword(keyword)}`;
@@ -1,20 +1,18 @@
1
+ import { PromptRunner } from "@tsed/cli-prompts";
2
+ import { concat, tasks as tasksRunner } from "@tsed/cli-tasks";
1
3
  import { classOf, isArrowFn } from "@tsed/core";
2
- import { configuration, constant, context, destroyInjector, DIContext, getContext, inject, injectable, injector, logger, Provider, runInContext } from "@tsed/di";
4
+ import { configuration, constant, destroyInjector, DIContext, getContext, inject, injectable, injector, logger, Provider, runInContext } from "@tsed/di";
3
5
  import { $asyncAlter, $asyncEmit } from "@tsed/hooks";
4
6
  import { pascalCase } from "change-case";
5
7
  import { Argument, Command } from "commander";
6
- import Inquirer from "inquirer";
7
- import inquirer_autocomplete_prompt from "inquirer-autocomplete-prompt";
8
8
  import { v4 } from "uuid";
9
9
  import { PackageManagersModule } from "../packageManagers/index.js";
10
- import { createSubTasks, createTasksRunner } from "../utils/createTasksRunner.js";
11
10
  import { getCommandMetadata } from "../utils/getCommandMetadata.js";
12
11
  import { mapCommanderOptions, validate } from "../utils/index.js";
13
12
  import { mapCommanderArgs } from "../utils/mapCommanderArgs.js";
14
13
  import { parseOption } from "../utils/parseOption.js";
15
14
  import { CliHooks } from "./CliHooks.js";
16
15
  import { ProjectPackageJson } from "./ProjectPackageJson.js";
17
- Inquirer.registerPrompt("autocomplete", inquirer_autocomplete_prompt);
18
16
  export class CliService {
19
17
  constructor() {
20
18
  this.reinstallAfterRun = constant("project.reinstallAfterRun", false);
@@ -23,6 +21,7 @@ export class CliService {
23
21
  this.hooks = inject(CliHooks);
24
22
  this.projectPkg = inject(ProjectPackageJson);
25
23
  this.packageManagers = inject(PackageManagersModule);
24
+ this.promptRunner = inject(PromptRunner);
26
25
  this.commands = new Map();
27
26
  }
28
27
  /**
@@ -45,17 +44,18 @@ export class CliService {
45
44
  return runInContext($ctx, async () => {
46
45
  $ctx.set("dispatchCmd", cmdName);
47
46
  await $asyncEmit("$loadPackageJson");
48
- data = await this.prompt(cmdName, data, $ctx);
49
47
  try {
48
+ data = await this.prompt(cmdName, data, $ctx);
50
49
  await this.exec(cmdName, data, $ctx);
50
+ await $asyncEmit("$onFinish", [data]);
51
51
  }
52
52
  catch (er) {
53
53
  await $asyncEmit("$onFinish", [data, er]);
54
- await destroyInjector();
55
54
  throw er;
56
55
  }
57
- await $asyncEmit("$onFinish", [data]);
58
- await destroyInjector();
56
+ finally {
57
+ await destroyInjector();
58
+ }
59
59
  });
60
60
  }
61
61
  async exec(cmdName, data, $ctx) {
@@ -63,14 +63,11 @@ export class CliService {
63
63
  $ctx.set("data", data);
64
64
  if (tasks.length) {
65
65
  if (this.reinstallAfterRun && (this.projectPkg.rewrite || this.projectPkg.reinstall)) {
66
- tasks.push({
67
- title: "Install dependencies",
68
- task: createSubTasks(() => this.packageManagers.install(data), { ...data, concurrent: false })
69
- }, ...(await this.getPostInstallTasks(cmdName, data)));
66
+ tasks.push(this.packageManagers.task("Install dependencies", data), ...(await this.getPostInstallTasks(cmdName, data)));
70
67
  }
71
68
  data = this.mapData(cmdName, data, $ctx);
72
69
  $ctx.set("data", data);
73
- return createTasksRunner(tasks, data);
70
+ return tasksRunner(tasks, data);
74
71
  }
75
72
  }
76
73
  /**
@@ -84,11 +81,12 @@ export class CliService {
84
81
  const instance = inject(provider.token);
85
82
  $ctx.set("data", data);
86
83
  if (instance.$prompt) {
87
- const questions = [...(await instance.$prompt(data))];
88
- if (questions.length) {
84
+ const questions = await instance.$prompt(data);
85
+ if (questions) {
86
+ const answers = await this.promptRunner.run(questions, data);
89
87
  data = {
90
88
  ...data,
91
- ...(await Inquirer.prompt(questions))
89
+ ...answers
92
90
  };
93
91
  }
94
92
  }
@@ -105,30 +103,13 @@ export class CliService {
105
103
  const provider = this.commands.get(cmdName);
106
104
  const instance = inject(provider.token);
107
105
  data = this.mapData(cmdName, data, $ctx);
108
- const tasks = [];
109
- tasks.push(...((await instance.$exec(data)) || []));
110
- tasks.push(...(await $asyncAlter(`$alter${pascalCase(cmdName)}Tasks`, [], [data])));
111
- return tasks.map((opts) => {
112
- return {
113
- ...opts,
114
- task: async (arg, task) => {
115
- context().set("currentTask", task);
116
- const result = await opts.task(arg, task);
117
- context().delete("currentTask");
118
- return result;
119
- }
120
- };
121
- });
106
+ return concat(await instance.$exec(data), await $asyncAlter(`$alter${pascalCase(cmdName)}Tasks`, [], [data]));
122
107
  }
123
108
  async getPostInstallTasks(cmdName, data) {
124
109
  const provider = this.commands.get(cmdName);
125
110
  const instance = inject(provider.token);
126
111
  data = this.mapData(cmdName, data, getContext());
127
- return [
128
- ...(instance.$postInstall ? await instance.$postInstall(data) : []),
129
- ...(await $asyncAlter(`$alter${pascalCase(cmdName)}PostInstallTasks`, [], [data])),
130
- ...(instance.$afterPostInstall ? await instance.$afterPostInstall(data) : [])
131
- ];
112
+ return concat(await instance.$postInstall?.(data), await $asyncAlter(`$alter${pascalCase(cmdName)}PostInstallTasks`, [], [data]), await instance.$afterPostInstall?.(data));
132
113
  }
133
114
  createCommand(metadata) {
134
115
  const { name, description, alias, inputSchema } = metadata;
@@ -206,7 +187,8 @@ export class CliService {
206
187
  else {
207
188
  logger().level = "info";
208
189
  }
209
- data.bindLogger = $ctx.get("command")?.bindLogger;
190
+ data.renderMode = $ctx.get("command")?.renderMode;
191
+ data.logger = logger();
210
192
  $ctx.set("data", data);
211
193
  return data;
212
194
  }
@@ -1,6 +1,6 @@
1
1
  import { isArrowFn, Store } from "@tsed/core";
2
2
  export function getCommandMetadata(token) {
3
- const { name, alias, args = {}, description, options = {}, enableFeatures, disableReadUpPkg, inputSchema, bindLogger = true, ...opts } = Store.from(token)?.get("command");
3
+ const { name, alias, args = {}, description, options = {}, enableFeatures, disableReadUpPkg, inputSchema, renderMode, ...opts } = Store.from(token)?.get("command");
4
4
  return {
5
5
  name,
6
6
  inputSchema,
@@ -8,7 +8,7 @@ export function getCommandMetadata(token) {
8
8
  description,
9
9
  enableFeatures: enableFeatures || [],
10
10
  disableReadUpPkg: !!disableReadUpPkg,
11
- bindLogger,
11
+ renderMode,
12
12
  ...opts,
13
13
  getOptions() {
14
14
  if (inputSchema) {
@@ -1,5 +1,4 @@
1
1
  export * from "./createInjector.js";
2
- export * from "./createTasksRunner.js";
3
2
  export * from "./getCommandMetadata.js";
4
3
  export * from "./getTemplateDirectory.js";
5
4
  export * from "./loadPlugins.js";
@@ -1,3 +1,4 @@
1
+ import { taskLogger } from "@tsed/cli-tasks";
1
2
  import { injector, lazyInject, logger } from "@tsed/di";
2
3
  import chalk from "chalk";
3
4
  import figures from "figures";
@@ -14,13 +15,13 @@ export async function loadPlugins() {
14
15
  .map(async (mod) => {
15
16
  try {
16
17
  if ($inj.settings.get("loaded")) {
17
- logger().info("Try to load ", mod);
18
+ taskLogger().info(`Try to load ${mod}`);
18
19
  await lazyInject(() => fs.importModule(mod, projectPackageJson.cwd));
19
20
  }
20
- logger().info(chalk.green(figures.tick), mod, "module loaded");
21
+ taskLogger().info(`${mod} module loaded`);
21
22
  }
22
23
  catch (er) {
23
- logger().warn(chalk.red(figures.cross), "Fail to load plugin", mod, er.message);
24
+ taskLogger().warn(`Fail to load plugin ${mod} ${er.message}`);
24
25
  }
25
26
  });
26
27
  await all(promises);
@@ -34,12 +34,12 @@ export declare function command<Input>(options: CommandOptions<Input>): TsED.Pro
34
34
  allowUnknownOption?: boolean;
35
35
  enableFeatures?: string[];
36
36
  disableReadUpPkg?: boolean;
37
- bindLogger?: boolean;
37
+ renderMode?: import("@tsed/cli-tasks").TasksOptions["renderMode"];
38
38
  } | {
39
39
  $prompt: any;
40
40
  $exec: any;
41
- prompt?<T extends import("inquirer").Answers = import("inquirer").Answers>(initialOptions: Partial<Input>): import("../interfaces/CommandProvider.js").QuestionOptions<T> | Promise<import("../interfaces/CommandProvider.js").QuestionOptions<T>>;
42
- handler: (data: Input) => import("../interfaces/Tasks.js").Tasks | Promise<import("../interfaces/Tasks.js").Tasks> | any | Promise<any>;
41
+ handler: (data: Input) => import("@tsed/cli-tasks").MaybePromise<void | import("../interfaces/index.js").Task<Input>[]>;
42
+ prompt?(initialOptions: Partial<Input>): import("@tsed/cli-prompts").PromptQuestion[] | Promise<import("@tsed/cli-prompts").PromptQuestion[]>;
43
43
  name: string;
44
44
  alias?: string;
45
45
  description: string;
@@ -53,6 +53,6 @@ export declare function command<Input>(options: CommandOptions<Input>): TsED.Pro
53
53
  allowUnknownOption?: boolean;
54
54
  enableFeatures?: string[];
55
55
  disableReadUpPkg?: boolean;
56
- bindLogger?: boolean;
56
+ renderMode?: import("@tsed/cli-tasks").TasksOptions["renderMode"];
57
57
  }>> | TsED.ClassProviderBuilder<Type<CommandProvider<Input>>>;
58
58
  export {};
@@ -1,5 +1,4 @@
1
1
  import "./utils/patchCommander.js";
2
- import Inquirer from "inquirer";
3
2
  export * from "./CliCore.js";
4
3
  export * from "./decorators/index.js";
5
4
  export * from "./fn/command.js";
@@ -7,8 +6,9 @@ export * from "./interfaces/index.js";
7
6
  export * from "./packageManagers/index.js";
8
7
  export * from "./services/index.js";
9
8
  export * from "./utils/index.js";
9
+ export * from "@tsed/cli-prompts";
10
+ export * from "@tsed/cli-tasks";
10
11
  export * from "@tsed/core";
11
12
  export * from "@tsed/di";
12
13
  export * from "@tsed/logger";
13
14
  export * from "@tsed/normalize-path";
14
- export { Inquirer };
@@ -1,3 +1,4 @@
1
+ import type { TasksOptions } from "@tsed/cli-tasks";
1
2
  declare global {
2
3
  namespace TsED {
3
4
  interface InitialCommandData {
@@ -6,7 +7,8 @@ declare global {
6
7
  }
7
8
  export interface CommandData extends TsED.InitialCommandData {
8
9
  commandName?: string;
9
- verbose?: boolean;
10
- bindLogger?: boolean;
10
+ verbose?: TasksOptions["verbose"];
11
+ renderMode?: TasksOptions["renderMode"];
11
12
  rawArgs?: string[];
13
+ [key: string]: any;
12
14
  }
@@ -1,8 +1,9 @@
1
+ import type { TasksOptions } from "@tsed/cli-tasks";
1
2
  import type { BaseCommandOptions, CommandArg, CommandOpts } from "./CommandOptions.js";
2
3
  export interface CommandMetadata extends Omit<BaseCommandOptions<any>, "args" | "options" | "allowUnknownOption"> {
3
4
  enableFeatures: string[];
4
5
  disableReadUpPkg: boolean;
5
- bindLogger: boolean;
6
+ renderMode?: TasksOptions["renderMode"];
6
7
  getOptions(): {
7
8
  /**
8
9
  * CommandProvider arguments
@@ -1,9 +1,9 @@
1
+ import type { PromptQuestion } from "@tsed/cli-prompts";
2
+ import type { MaybePromise, Task, TasksOptions } from "@tsed/cli-tasks";
1
3
  import { Type } from "@tsed/core";
2
4
  import type { TokenProvider } from "@tsed/di";
3
5
  import type { JsonSchema } from "@tsed/schema";
4
- import type { Answers } from "inquirer";
5
- import type { CommandProvider, QuestionOptions } from "./CommandProvider.js";
6
- import type { Tasks } from "./Tasks.js";
6
+ import type { CommandProvider } from "./CommandProvider.js";
7
7
  export interface CommandArg {
8
8
  /**
9
9
  * Description of the argument
@@ -79,11 +79,11 @@ export interface BaseCommandOptions<Input> {
79
79
  allowUnknownOption?: boolean;
80
80
  enableFeatures?: string[];
81
81
  disableReadUpPkg?: boolean;
82
- bindLogger?: boolean;
82
+ renderMode?: TasksOptions["renderMode"];
83
83
  }
84
84
  interface FunctionalCommandOptions<Input> extends BaseCommandOptions<Input> {
85
- prompt?<T extends Answers = Answers>(initialOptions: Partial<Input>): QuestionOptions<T> | Promise<QuestionOptions<T>>;
86
- handler: (data: Input) => Tasks | Promise<Tasks> | any | Promise<any>;
85
+ handler: (data: Input) => MaybePromise<Task<Input>[] | void>;
86
+ prompt?(initialOptions: Partial<Input>): PromptQuestion[] | Promise<PromptQuestion[]>;
87
87
  [key: string]: any;
88
88
  }
89
89
  export interface ClassCommandOptions<Input> extends BaseCommandOptions<Input> {
@@ -1,20 +1,12 @@
1
- import "inquirer-autocomplete-prompt";
2
- import type { Answers, QuestionCollection } from "inquirer";
3
- import AutocompletePrompt from "inquirer-autocomplete-prompt";
4
- import type { Tasks } from "./Tasks.js";
5
- declare module "inquirer" {
6
- interface QuestionMap<T extends Answers = Answers> {
7
- autocomplete: AutocompletePrompt.AutocompleteQuestionOptions<T>;
8
- }
9
- }
10
- export type QuestionOptions<T extends Answers = Answers> = QuestionCollection<T>;
1
+ import type { PromptQuestion } from "@tsed/cli-prompts";
2
+ import type { MaybePromise, Task } from "@tsed/cli-tasks";
11
3
  export interface CommandProvider<Ctx = any> {
12
4
  /**
13
- * Hook to create the main prompt for the command
14
- * See https://github.com/enquirer/enquirer for more detail on question configuration.
5
+ * Hook to create the main prompt for the command. Refer to {@link PromptQuestion}
6
+ * for supported question attributes.
15
7
  * @param initialOptions
16
8
  */
17
- $prompt?<T extends Answers = Answers>(initialOptions: Partial<Ctx>): QuestionOptions<T> | Promise<QuestionOptions<T>>;
9
+ $prompt?(initialOptions: Partial<Ctx>): PromptQuestion[] | Promise<PromptQuestion[]>;
18
10
  /**
19
11
  * Hook to map options
20
12
  * @param ctx
@@ -24,11 +16,11 @@ export interface CommandProvider<Ctx = any> {
24
16
  * Run a command
25
17
  * @param ctx
26
18
  */
27
- $exec(ctx: Ctx): Tasks | Promise<Tasks> | any | Promise<any>;
19
+ $exec(ctx: Ctx): MaybePromise<Task<Ctx>[] | void>;
28
20
  /**
29
21
  * Run commands after the npm/yarn install
30
22
  * @param ctx
31
23
  */
32
- $postInstall?(ctx: Ctx): Tasks | Promise<Tasks> | any | Promise<any>;
33
- $afterPostInstall?(ctx: Ctx): Tasks | Promise<Tasks> | any | Promise<any>;
24
+ $postInstall?(ctx: Ctx): MaybePromise<Task<Ctx>[] | void>;
25
+ $afterPostInstall?(ctx: Ctx): MaybePromise<Task<Ctx>[] | void>;
34
26
  }
@@ -8,7 +8,7 @@ export * from "./CommandOptions.js";
8
8
  export * from "./CommandProvider.js";
9
9
  export * from "./PackageJson.js";
10
10
  export * from "./ProjectPreferences.js";
11
- export * from "./Tasks.js";
11
+ export type { Task } from "@tsed/cli-tasks";
12
12
  declare global {
13
13
  namespace TsED {
14
14
  interface Configuration {
@@ -1,3 +1,4 @@
1
+ import type { Task } from "@tsed/cli-tasks";
1
2
  import { ProjectPackageJson } from "../services/ProjectPackageJson.js";
2
3
  import { BaseManager, type ManagerCmdOpts } from "./supports/BaseManager.js";
3
4
  export interface InstallOptions {
@@ -8,22 +9,8 @@ export declare class PackageManagersModule {
8
9
  protected projectPackageJson: ProjectPackageJson;
9
10
  protected packageManagers: BaseManager[];
10
11
  init(options?: InstallOptions): Promise<void>;
11
- install(options?: InstallOptions): ({
12
- title: string;
13
- enabled: () => boolean;
14
- task: () => void;
15
- skip?: undefined;
16
- } | {
17
- title: string;
18
- skip: () => boolean;
19
- task: () => import("rxjs").Observable<any>;
20
- enabled?: undefined;
21
- } | {
22
- title: string;
23
- task: () => void;
24
- enabled?: undefined;
25
- skip?: undefined;
26
- })[];
12
+ task(title: string, ctx?: InstallOptions): Task;
13
+ install(options?: InstallOptions): Task[];
27
14
  list(): string[];
28
15
  get(name?: string): BaseManager;
29
16
  runScript(scriptName: string, { ignoreError, ...opts }?: {
@@ -1,3 +1,4 @@
1
+ import { PromptRunner } from "@tsed/cli-prompts";
1
2
  import { DIContext } from "@tsed/di";
2
3
  import { Command } from "commander";
3
4
  import type { CommandData } from "../interfaces/CommandData.js";
@@ -13,6 +14,7 @@ export declare class CliService {
13
14
  protected hooks: CliHooks;
14
15
  protected projectPkg: ProjectPackageJson;
15
16
  protected packageManagers: PackageManagersModule;
17
+ protected promptRunner: PromptRunner;
16
18
  private commands;
17
19
  /**
18
20
  * Parse process.argv and runLifecycle action
@@ -26,7 +28,7 @@ export declare class CliService {
26
28
  * @param $ctx
27
29
  */
28
30
  runLifecycle(cmdName: string, data: CommandData | undefined, $ctx: DIContext): Promise<Promise<void>>;
29
- exec(cmdName: string, data: any, $ctx: DIContext): Promise<any>;
31
+ exec(cmdName: string, data: any, $ctx: DIContext): Promise<void>;
30
32
  /**
31
33
  * Run prompt for a given command
32
34
  * @param cmdName
@@ -40,7 +42,7 @@ export declare class CliService {
40
42
  * @param data
41
43
  */
42
44
  getTasks(cmdName: string, data: any): Promise<Task[]>;
43
- getPostInstallTasks(cmdName: string, data: any): Promise<any[]>;
45
+ getPostInstallTasks(cmdName: string, data: any): Promise<Task<any>[]>;
44
46
  createCommand(metadata: CommandMetadata): any;
45
47
  load(): void;
46
48
  private mapData;
@@ -1,5 +1,4 @@
1
1
  export * from "./createInjector.js";
2
- export * from "./createTasksRunner.js";
3
2
  export * from "./getCommandMetadata.js";
4
3
  export * from "./getTemplateDirectory.js";
5
4
  export * from "./loadPlugins.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tsed/cli-core",
3
3
  "description": "Build your CLI with TypeScript and Decorators",
4
- "version": "7.0.0-beta.9",
4
+ "version": "7.0.0-rc.2",
5
5
  "type": "module",
6
6
  "main": "./lib/esm/index.js",
7
7
  "source": "./src/index.ts",
@@ -28,30 +28,27 @@
28
28
  "api",
29
29
  "decorators",
30
30
  "commander.js",
31
- "inquirer.js",
32
- "listr"
31
+ "prompts",
32
+ "clack"
33
33
  ],
34
34
  "dependencies": {
35
35
  "@ts-morph/common": "0.28.0",
36
+ "@tsed/cli-prompts": "7.0.0-rc.2",
37
+ "@tsed/cli-tasks": "7.0.0-rc.2",
36
38
  "@tsed/logger": ">=8.0.3",
37
39
  "@tsed/logger-pattern-layout": ">=8.0.3",
38
40
  "@tsed/logger-std": ">=8.0.3",
39
41
  "@tsed/normalize-path": ">=8.0.0",
40
- "@types/inquirer": "^9.0.7",
41
42
  "ajv": "^8.17.1",
42
43
  "axios": "^1.7.7",
43
44
  "chalk": "^5.3.0",
44
45
  "change-case": "^5.4.4",
45
46
  "commander": "^12.1.0",
46
- "enquirer": "^2.4.1",
47
47
  "execa": "^8.0.1",
48
48
  "figures": "^6.1.0",
49
49
  "fs-extra": "^11.2.0",
50
50
  "globby": "^14.0.2",
51
- "inquirer": "^9.3.7",
52
- "inquirer-autocomplete-prompt": "^3.0.1",
53
51
  "js-yaml": "^4.1.0",
54
- "listr2": "^8.2.4",
55
52
  "read-pkg-up": "^11.0.0",
56
53
  "registry-auth-token": "^5.1.0",
57
54
  "registry-url": "^6.0.1",
@@ -65,7 +62,7 @@
65
62
  "uuid": "^10.0.0"
66
63
  },
67
64
  "devDependencies": {
68
- "@tsed/typescript": "7.0.0-beta.9",
65
+ "@tsed/typescript": "7.0.0-rc.2",
69
66
  "@types/commander": "2.12.2",
70
67
  "@types/figures": "3.0.1",
71
68
  "@types/fs-extra": "^11.0.4",
@@ -105,6 +102,6 @@
105
102
  "author": "Romain Lenzotti",
106
103
  "license": "MIT",
107
104
  "publishConfig": {
108
- "tag": "beta"
105
+ "tag": "rc"
109
106
  }
110
107
  }
package/readme.md CHANGED
@@ -116,7 +116,7 @@ export class GenerateCmd implements CommandProvider {
116
116
  srcRenderService: SrcRendererService;
117
117
 
118
118
  /**
119
- * Prompt use Inquirer.js to print questions (see Inquirer.js for more details)
119
+ * Prompts run through the Ts.ED prompt runner (powered by `@clack/prompts`) to gather inputs
120
120
  */
121
121
  $prompt(initialOptions: Partial<GenerateCmdContext>) {
122
122
  return [
@@ -152,7 +152,7 @@ export class GenerateCmd implements CommandProvider {
152
152
  }
153
153
 
154
154
  /**
155
- * Perform action like generate files. The tasks returned by $exec method is based on Listr configuration (see Listr documentation on npm)
155
+ * Perform action like generate files. The tasks returned by $exec method rely on the @clack/prompts-powered @tsed/cli-tasks helpers.
156
156
  */
157
157
  async $exec(options: GenerateCmdContext) {
158
158
  const {outputFile, ...data} = options;
@@ -1 +0,0 @@
1
- import {} from "listr2";
@@ -1,40 +0,0 @@
1
- // @ts-ignore
2
- import { isFunction } from "@tsed/core";
3
- import { DefaultRenderer, Listr, ListrLogger, VerboseRenderer } from "listr2";
4
- import { getLogger } from "./createInjector.js";
5
- class CustomLogger extends ListrLogger {
6
- log(level, message, options) {
7
- if (["FAILED"].includes(level)) {
8
- getLogger()?.error(`[${level}]`, message);
9
- }
10
- else {
11
- getLogger()?.info(`[${level}]`, message);
12
- }
13
- }
14
- }
15
- function getOptions({ bindLogger = true, ...ctx }) {
16
- const useRawRenderer = !(!ctx.verbose && !process.env.CI);
17
- return {
18
- silentRendererCondition: process.env.NODE_ENV === "test",
19
- renderer: useRawRenderer ? VerboseRenderer : DefaultRenderer,
20
- rendererOptions: useRawRenderer && bindLogger
21
- ? {
22
- logger: new CustomLogger()
23
- }
24
- : undefined
25
- };
26
- }
27
- export function createTasks(tasks, ctx) {
28
- return new Listr(tasks, getOptions(ctx));
29
- }
30
- export function createSubTasks(tasks, opts) {
31
- return async (ctx, task) => {
32
- if (isFunction(tasks)) {
33
- tasks = await tasks(ctx, task);
34
- }
35
- return task.newListr(tasks, getOptions(opts));
36
- };
37
- }
38
- export function createTasksRunner(tasks, ctx) {
39
- return createTasks(tasks, ctx).run(ctx);
40
- }
@@ -1,8 +0,0 @@
1
- import { type ListrBaseClassOptions, type ListrContext, type ListrTask } from "listr2";
2
- export interface TaskOptions<Ctx = ListrContext> extends ListrBaseClassOptions<Ctx> {
3
- concurrent?: boolean | number;
4
- verbose?: boolean;
5
- bindLogger?: boolean;
6
- }
7
- export type Task = ListrTask<any, any>;
8
- export type Tasks = Task[];
@@ -1,5 +0,0 @@
1
- import { Listr, type ListrTaskWrapper } from "listr2";
2
- import type { TaskOptions, Tasks } from "../interfaces/Tasks.js";
3
- export declare function createTasks(tasks: Tasks, ctx: TaskOptions): Listr<any, any, any>;
4
- export declare function createSubTasks(tasks: Tasks | ((ctx: any, task: any) => Tasks | Promise<Tasks>), opts: TaskOptions): (ctx: any, task: ListrTaskWrapper<any, any, any>) => Promise<Listr<any, any, any>>;
5
- export declare function createTasksRunner(tasks: Tasks, ctx: TaskOptions): Promise<any>;