@tsed/cli-core 7.0.0-beta.12 → 7.0.0-beta.13

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/index.js CHANGED
@@ -7,6 +7,7 @@ export * from "./packageManagers/index.js";
7
7
  export * from "./services/index.js";
8
8
  export * from "./utils/index.js";
9
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";
@@ -5,4 +5,3 @@ export * from "./CommandOptions.js";
5
5
  export * from "./CommandProvider.js";
6
6
  export * from "./PackageJson.js";
7
7
  export * from "./ProjectPreferences.js";
8
- 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,12 +1,12 @@
1
1
  import { PromptRunner } from "@tsed/cli-prompts";
2
+ import { concat, tasks as tasksRunner } from "@tsed/cli-tasks";
2
3
  import { classOf, isArrowFn } from "@tsed/core";
3
- 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";
4
5
  import { $asyncAlter, $asyncEmit } from "@tsed/hooks";
5
6
  import { pascalCase } from "change-case";
6
7
  import { Argument, Command } from "commander";
7
8
  import { v4 } from "uuid";
8
9
  import { PackageManagersModule } from "../packageManagers/index.js";
9
- import { createSubTasks, createTasksRunner } from "../utils/createTasksRunner.js";
10
10
  import { getCommandMetadata } from "../utils/getCommandMetadata.js";
11
11
  import { mapCommanderOptions, validate } from "../utils/index.js";
12
12
  import { mapCommanderArgs } from "../utils/mapCommanderArgs.js";
@@ -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
  /**
@@ -106,30 +103,13 @@ export class CliService {
106
103
  const provider = this.commands.get(cmdName);
107
104
  const instance = inject(provider.token);
108
105
  data = this.mapData(cmdName, data, $ctx);
109
- const tasks = [];
110
- tasks.push(...((await instance.$exec(data)) || []));
111
- tasks.push(...(await $asyncAlter(`$alter${pascalCase(cmdName)}Tasks`, [], [data])));
112
- return tasks.map((opts) => {
113
- return {
114
- ...opts,
115
- task: async (arg, task) => {
116
- context().set("currentTask", task);
117
- const result = await opts.task(arg, task);
118
- context().delete("currentTask");
119
- return result;
120
- }
121
- };
122
- });
106
+ return concat(await instance.$exec(data), await $asyncAlter(`$alter${pascalCase(cmdName)}Tasks`, [], [data]));
123
107
  }
124
108
  async getPostInstallTasks(cmdName, data) {
125
109
  const provider = this.commands.get(cmdName);
126
110
  const instance = inject(provider.token);
127
111
  data = this.mapData(cmdName, data, getContext());
128
- return [
129
- ...(instance.$postInstall ? await instance.$postInstall(data) : []),
130
- ...(await $asyncAlter(`$alter${pascalCase(cmdName)}PostInstallTasks`, [], [data])),
131
- ...(instance.$afterPostInstall ? await instance.$afterPostInstall(data) : [])
132
- ];
112
+ return concat(await instance.$postInstall?.(data), await $asyncAlter(`$alter${pascalCase(cmdName)}PostInstallTasks`, [], [data]), await instance.$afterPostInstall?.(data));
133
113
  }
134
114
  createCommand(metadata) {
135
115
  const { name, description, alias, inputSchema } = metadata;
@@ -207,7 +187,7 @@ export class CliService {
207
187
  else {
208
188
  logger().level = "info";
209
189
  }
210
- data.bindLogger = $ctx.get("command")?.bindLogger;
190
+ data.logger = logger();
211
191
  $ctx.set("data", data);
212
192
  return data;
213
193
  }
@@ -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, ...opts } = Store.from(token)?.get("command");
4
4
  return {
5
5
  name,
6
6
  inputSchema,
@@ -8,7 +8,6 @@ export function getCommandMetadata(token) {
8
8
  description,
9
9
  enableFeatures: enableFeatures || [],
10
10
  disableReadUpPkg: !!disableReadUpPkg,
11
- bindLogger,
12
11
  ...opts,
13
12
  getOptions() {
14
13
  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,11 +34,10 @@ 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;
38
37
  } | {
39
38
  $prompt: any;
40
39
  $exec: any;
41
- handler: (data: Input) => import("../interfaces/Tasks.js").Tasks | Promise<import("../interfaces/Tasks.js").Tasks> | any | Promise<any>;
40
+ handler: (data: Input) => import("@tsed/cli-tasks").MaybePromise<void | import("../interfaces/index.js").Task<Input>[]>;
42
41
  prompt?(initialOptions: Partial<Input>): import("@tsed/cli-prompts").PromptQuestion[] | Promise<import("@tsed/cli-prompts").PromptQuestion[]>;
43
42
  name: string;
44
43
  alias?: string;
@@ -53,6 +52,5 @@ export declare function command<Input>(options: CommandOptions<Input>): TsED.Pro
53
52
  allowUnknownOption?: boolean;
54
53
  enableFeatures?: string[];
55
54
  disableReadUpPkg?: boolean;
56
- bindLogger?: boolean;
57
55
  }>> | TsED.ClassProviderBuilder<Type<CommandProvider<Input>>>;
58
56
  export {};
@@ -7,6 +7,7 @@ export * from "./packageManagers/index.js";
7
7
  export * from "./services/index.js";
8
8
  export * from "./utils/index.js";
9
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";
@@ -7,7 +7,6 @@ declare global {
7
7
  export interface CommandData extends TsED.InitialCommandData {
8
8
  commandName?: string;
9
9
  verbose?: boolean;
10
- bindLogger?: boolean;
11
10
  rawArgs?: string[];
12
11
  [key: string]: any;
13
12
  }
@@ -2,7 +2,6 @@ import type { BaseCommandOptions, CommandArg, CommandOpts } from "./CommandOptio
2
2
  export interface CommandMetadata extends Omit<BaseCommandOptions<any>, "args" | "options" | "allowUnknownOption"> {
3
3
  enableFeatures: string[];
4
4
  disableReadUpPkg: boolean;
5
- bindLogger: boolean;
6
5
  getOptions(): {
7
6
  /**
8
7
  * CommandProvider arguments
@@ -1,9 +1,9 @@
1
1
  import type { PromptQuestion } from "@tsed/cli-prompts";
2
+ import type { MaybePromise, Task } from "@tsed/cli-tasks";
2
3
  import { Type } from "@tsed/core";
3
4
  import type { TokenProvider } from "@tsed/di";
4
5
  import type { JsonSchema } from "@tsed/schema";
5
6
  import type { CommandProvider } from "./CommandProvider.js";
6
- import type { Tasks } from "./Tasks.js";
7
7
  export interface CommandArg {
8
8
  /**
9
9
  * Description of the argument
@@ -79,10 +79,9 @@ export interface BaseCommandOptions<Input> {
79
79
  allowUnknownOption?: boolean;
80
80
  enableFeatures?: string[];
81
81
  disableReadUpPkg?: boolean;
82
- bindLogger?: boolean;
83
82
  }
84
83
  interface FunctionalCommandOptions<Input> extends BaseCommandOptions<Input> {
85
- handler: (data: Input) => Tasks | Promise<Tasks> | any | Promise<any>;
84
+ handler: (data: Input) => MaybePromise<Task<Input>[] | void>;
86
85
  prompt?(initialOptions: Partial<Input>): PromptQuestion[] | Promise<PromptQuestion[]>;
87
86
  [key: string]: any;
88
87
  }
@@ -1,5 +1,5 @@
1
1
  import type { PromptQuestion } from "@tsed/cli-prompts";
2
- import type { Tasks } from "./Tasks.js";
2
+ import type { MaybePromise, Task } from "@tsed/cli-tasks";
3
3
  export interface CommandProvider<Ctx = any> {
4
4
  /**
5
5
  * Hook to create the main prompt for the command. Refer to {@link PromptQuestion}
@@ -16,11 +16,11 @@ export interface CommandProvider<Ctx = any> {
16
16
  * Run a command
17
17
  * @param ctx
18
18
  */
19
- $exec(ctx: Ctx): Tasks | Promise<Tasks> | any | Promise<any>;
19
+ $exec(ctx: Ctx): MaybePromise<Task<Ctx>[] | void>;
20
20
  /**
21
21
  * Run commands after the npm/yarn install
22
22
  * @param ctx
23
23
  */
24
- $postInstall?(ctx: Ctx): Tasks | Promise<Tasks> | any | Promise<any>;
25
- $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>;
26
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 }?: {
@@ -28,7 +28,7 @@ export declare class CliService {
28
28
  * @param $ctx
29
29
  */
30
30
  runLifecycle(cmdName: string, data: CommandData | undefined, $ctx: DIContext): Promise<Promise<void>>;
31
- exec(cmdName: string, data: any, $ctx: DIContext): Promise<any>;
31
+ exec(cmdName: string, data: any, $ctx: DIContext): Promise<void>;
32
32
  /**
33
33
  * Run prompt for a given command
34
34
  * @param cmdName
@@ -42,7 +42,7 @@ export declare class CliService {
42
42
  * @param data
43
43
  */
44
44
  getTasks(cmdName: string, data: any): Promise<Task[]>;
45
- getPostInstallTasks(cmdName: string, data: any): Promise<any[]>;
45
+ getPostInstallTasks(cmdName: string, data: any): Promise<Task<any>[]>;
46
46
  createCommand(metadata: CommandMetadata): any;
47
47
  load(): void;
48
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.12",
4
+ "version": "7.0.0-beta.13",
5
5
  "type": "module",
6
6
  "main": "./lib/esm/index.js",
7
7
  "source": "./src/index.ts",
@@ -29,11 +29,12 @@
29
29
  "decorators",
30
30
  "commander.js",
31
31
  "prompts",
32
- "listr"
32
+ "clack"
33
33
  ],
34
34
  "dependencies": {
35
35
  "@ts-morph/common": "0.28.0",
36
- "@tsed/cli-prompts": "7.0.0-beta.12",
36
+ "@tsed/cli-prompts": "7.0.0-beta.13",
37
+ "@tsed/cli-tasks": "7.0.0-beta.13",
37
38
  "@tsed/logger": ">=8.0.3",
38
39
  "@tsed/logger-pattern-layout": ">=8.0.3",
39
40
  "@tsed/logger-std": ">=8.0.3",
@@ -48,7 +49,6 @@
48
49
  "fs-extra": "^11.2.0",
49
50
  "globby": "^14.0.2",
50
51
  "js-yaml": "^4.1.0",
51
- "listr2": "^8.2.4",
52
52
  "read-pkg-up": "^11.0.0",
53
53
  "registry-auth-token": "^5.1.0",
54
54
  "registry-url": "^6.0.1",
@@ -62,7 +62,7 @@
62
62
  "uuid": "^10.0.0"
63
63
  },
64
64
  "devDependencies": {
65
- "@tsed/typescript": "7.0.0-beta.12",
65
+ "@tsed/typescript": "7.0.0-beta.13",
66
66
  "@types/commander": "2.12.2",
67
67
  "@types/figures": "3.0.1",
68
68
  "@types/fs-extra": "^11.0.4",
package/readme.md CHANGED
@@ -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>;