@tsed/cli-tasks 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.
@@ -0,0 +1,270 @@
1
+ import { log, progress, spinner, taskLog } from "@clack/prompts";
2
+ import { contextLogger } from "@tsed/di";
3
+ export class TaskLogger {
4
+ #title;
5
+ #logger;
6
+ #verbose;
7
+ #parent;
8
+ #index;
9
+ constructor(opts) {
10
+ this.#title = opts.title;
11
+ this.type = opts.type;
12
+ this.#parent = opts.parent;
13
+ this.#verbose = opts.verbose;
14
+ this.#logger = this.create({
15
+ ...opts,
16
+ verbose: this.#verbose
17
+ });
18
+ }
19
+ get parent() {
20
+ return this.#parent;
21
+ }
22
+ get isReady() {
23
+ return !!this.#logger;
24
+ }
25
+ get title() {
26
+ return this.#title;
27
+ }
28
+ set title(title) {
29
+ if (title) {
30
+ this.#title = title;
31
+ this.#logger.message?.(title);
32
+ }
33
+ }
34
+ set output(message) {
35
+ if (message) {
36
+ (this.#logger.info || this.#logger.message)?.(message);
37
+ }
38
+ }
39
+ static from(opts) {
40
+ if (opts.parent) {
41
+ switch (opts.parent.type) {
42
+ case "progress":
43
+ return new TaskLogger({
44
+ ...opts,
45
+ type: "progress",
46
+ parent: opts.parent
47
+ });
48
+ case "spinner":
49
+ return opts.parent;
50
+ }
51
+ }
52
+ if (opts.parent) {
53
+ if (opts.parent?.parent) {
54
+ opts.type = opts.type || "group";
55
+ }
56
+ else {
57
+ opts.type = opts.type || "taskLog";
58
+ }
59
+ }
60
+ opts.type = opts.type || "log";
61
+ return new TaskLogger(opts);
62
+ }
63
+ log(message) {
64
+ this.#logger.message(`${this.title} - ${message}`);
65
+ }
66
+ message(message) {
67
+ this.#logger.message(`${this.title} - ${message}`);
68
+ }
69
+ advance() {
70
+ if (this.isReady && this.type === "progress") {
71
+ if (this.isRaw()) {
72
+ this.info(`${this.title} [${this.#index}/${this.parent.max}]`);
73
+ }
74
+ else {
75
+ const it = Math.round((1 / this.parent.max) * 100);
76
+ this.#logger.advance(it, this.title);
77
+ }
78
+ }
79
+ return this;
80
+ }
81
+ start() {
82
+ if (this.isReady) {
83
+ const msg = `${this.title}...`;
84
+ switch (this.type) {
85
+ default:
86
+ this.#logger.message(msg);
87
+ break;
88
+ case "log":
89
+ this.#logger.info(msg);
90
+ break;
91
+ case "progress":
92
+ if (this.isChildProgress()) {
93
+ this.advance();
94
+ }
95
+ else {
96
+ this.#logger.start(this.title);
97
+ }
98
+ break;
99
+ case "spinner":
100
+ this.#logger.start(this.title);
101
+ break;
102
+ }
103
+ }
104
+ return this;
105
+ }
106
+ done() {
107
+ if (this.isReady) {
108
+ const msg = `${this.title} completed`;
109
+ switch (this.type) {
110
+ default:
111
+ this.#logger.success(msg);
112
+ break;
113
+ case "progress":
114
+ if (!this.isChildProgress()) {
115
+ this.#logger.stop(msg);
116
+ }
117
+ break;
118
+ case "spinner":
119
+ this.#logger.stop(msg);
120
+ break;
121
+ }
122
+ }
123
+ return this;
124
+ }
125
+ error(message) {
126
+ if (this.isReady) {
127
+ this.#logger.error(`${this.title} - ${message}`);
128
+ }
129
+ return this;
130
+ }
131
+ info(message) {
132
+ if (this.isReady) {
133
+ switch (this.type) {
134
+ case "log":
135
+ case "taskLog":
136
+ this.#logger.info(`${this.title} - ${message}`);
137
+ break;
138
+ default:
139
+ this.#logger.message(`${this.title} - ${message}`);
140
+ break;
141
+ }
142
+ }
143
+ return this;
144
+ }
145
+ warn(message) {
146
+ if (this.isReady) {
147
+ switch (this.type) {
148
+ case "log":
149
+ case "taskLog":
150
+ this.#logger.warn(`${this.title} - ${message}`);
151
+ break;
152
+ default:
153
+ this.#logger.message(`${this.title} - WARN ${message}`);
154
+ }
155
+ }
156
+ return this;
157
+ }
158
+ skip() {
159
+ if (this.isReady) {
160
+ switch (this.type) {
161
+ default:
162
+ case "log":
163
+ this.#logger.warn(`${this.title} skipped...`);
164
+ break;
165
+ case "group":
166
+ case "taskLog":
167
+ this.#logger.error(`${this.title} skipped...`);
168
+ break;
169
+ case "progress":
170
+ this.advance();
171
+ break;
172
+ case "spinner":
173
+ this.#logger.stop(`${this.title} skipped...`);
174
+ break;
175
+ }
176
+ }
177
+ return this;
178
+ }
179
+ /**
180
+ * @ddeprecated use info or message instead
181
+ * @param message
182
+ */
183
+ report(message) {
184
+ (this.#logger.info || this.#logger.message)?.(message);
185
+ }
186
+ isChildProgress() {
187
+ return this.parent?.type === "progress" && this.type === "progress";
188
+ }
189
+ create(opts) {
190
+ const { type, title, parent } = opts;
191
+ if (this.isRaw()) {
192
+ const success = (message) => {
193
+ !this.isEnvTest() &&
194
+ contextLogger()?.info({
195
+ state: "SUCCESS",
196
+ title,
197
+ message
198
+ });
199
+ };
200
+ const start = (message) => {
201
+ !this.isEnvTest() &&
202
+ contextLogger()?.info({
203
+ title,
204
+ message
205
+ });
206
+ };
207
+ const defaultLogger = {
208
+ message: (message) => {
209
+ !this.isEnvTest() &&
210
+ contextLogger()?.info({
211
+ state: "MSG",
212
+ title,
213
+ message
214
+ });
215
+ },
216
+ stop: success,
217
+ success,
218
+ info: start,
219
+ start,
220
+ warn: (message) => {
221
+ !this.isEnvTest() &&
222
+ contextLogger()?.warn({
223
+ title,
224
+ message
225
+ });
226
+ },
227
+ error: (message) => {
228
+ !this.isEnvTest() &&
229
+ contextLogger()?.error({
230
+ title,
231
+ message
232
+ });
233
+ }
234
+ };
235
+ defaultLogger.message("...");
236
+ return defaultLogger;
237
+ }
238
+ switch (type) {
239
+ case "spinner":
240
+ const spin = spinner();
241
+ spin.message(title);
242
+ return spin;
243
+ case "progress":
244
+ if (parent && this.isChildProgress()) {
245
+ return parent.#logger;
246
+ }
247
+ return progress({
248
+ style: "block",
249
+ max: 100
250
+ });
251
+ case "taskLog":
252
+ return taskLog({
253
+ title: this.title
254
+ });
255
+ case "log":
256
+ return log;
257
+ case "group":
258
+ if (!parent || parent.type !== "taskLog") {
259
+ return log;
260
+ }
261
+ return parent.#logger.group(this.title);
262
+ }
263
+ }
264
+ isRaw() {
265
+ return this.#verbose || this.isEnvTest();
266
+ }
267
+ isEnvTest() {
268
+ return process.env.NODE_ENV === "test";
269
+ }
270
+ }
@@ -0,0 +1,4 @@
1
+ import { context, ContextLogger, contextLogger } from "@tsed/di";
2
+ export function taskLogger() {
3
+ return context().get("TASK_LOGGER") || contextLogger();
4
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./domain/TaskLogger.js";
2
+ export * from "./fn/taskLogger.js";
3
+ export * from "./interfaces/Task.js";
4
+ export * from "./tasks.js";
@@ -0,0 +1 @@
1
+ import { TaskLogger } from "../domain/TaskLogger.js";
@@ -0,0 +1,101 @@
1
+ import { isArray } from "@tsed/core/utils/isArray";
2
+ import { isBoolean } from "@tsed/core/utils/isBoolean";
3
+ import { isFunction } from "@tsed/core/utils/isFunction";
4
+ import { isObservable } from "@tsed/core/utils/isObservable";
5
+ import { isPromise } from "@tsed/core/utils/isPromise";
6
+ import { isString } from "@tsed/core/utils/isString";
7
+ import { context } from "@tsed/di";
8
+ import { TaskLogger } from "./domain/TaskLogger.js";
9
+ export async function tasks(list, ctx, parent) {
10
+ const items = list.filter((task) => isEnabled(task));
11
+ parent && (parent.max = items.length);
12
+ for (let i = 0; i < items.length; i++) {
13
+ const task = items[i];
14
+ const taskLogger = TaskLogger.from({
15
+ index: i,
16
+ title: task.title,
17
+ type: task.type,
18
+ parent,
19
+ verbose: ctx.verbose
20
+ });
21
+ try {
22
+ if (!(await isExecutable(task, ctx))) {
23
+ taskLogger.skip();
24
+ continue;
25
+ }
26
+ taskLogger.start();
27
+ context().set("TASK_LOGGER", taskLogger);
28
+ const result = await resolveTaskResult(task.task(ctx, taskLogger), taskLogger);
29
+ context().delete("TASK_LOGGER");
30
+ if (isArray(result)) {
31
+ await tasks(result, ctx, taskLogger);
32
+ }
33
+ taskLogger.done();
34
+ }
35
+ catch (er) {
36
+ taskLogger.error(er);
37
+ throw er;
38
+ }
39
+ }
40
+ }
41
+ function resolveTaskResult(result, logger) {
42
+ if (!result) {
43
+ return result;
44
+ }
45
+ if (isPromise(result)) {
46
+ return result;
47
+ }
48
+ if (isObservable(result)) {
49
+ return new Promise((resolve, reject) => {
50
+ let subscription;
51
+ subscription = result.subscribe({
52
+ next(value) {
53
+ if (isString(value)) {
54
+ logger.message(value);
55
+ }
56
+ },
57
+ complete() {
58
+ subscription?.unsubscribe?.();
59
+ resolve(undefined);
60
+ },
61
+ error(err) {
62
+ subscription?.unsubscribe?.();
63
+ reject(err);
64
+ }
65
+ });
66
+ });
67
+ }
68
+ return result;
69
+ }
70
+ export async function concat(...args) {
71
+ const tasks = [];
72
+ for (const arg of args) {
73
+ if (isArray(arg)) {
74
+ tasks.push(...arg);
75
+ }
76
+ }
77
+ return tasks;
78
+ }
79
+ function isEnabled(item) {
80
+ return isBoolean(item.enabled) ? item.enabled : true;
81
+ }
82
+ async function isExecutable(item, ctx) {
83
+ if (isFunction(item.enabled)) {
84
+ const isEnable = await item.enabled(ctx);
85
+ if (!isEnable) {
86
+ return false;
87
+ }
88
+ }
89
+ if ("skip" in item) {
90
+ const isSkipped = isFunction(item.skip) ? await item.skip(ctx) : item.skip;
91
+ if (isSkipped) {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ }
97
+ /**
98
+ * @deprecated use tasks function instead
99
+ */
100
+ export const createTasksRunner = tasks;
101
+ export const createSubTasks = tasks;