@jujulego/jill 2.5.2 → 3.0.0-alpha.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.
Files changed (100) hide show
  1. package/dist/TaskName.js +33 -0
  2. package/dist/TaskName.js.map +1 -0
  3. package/dist/inked.js +62 -0
  4. package/dist/inked.js.map +1 -0
  5. package/dist/list.ink.js +49 -0
  6. package/dist/list.ink.js.map +1 -0
  7. package/dist/main.js +20 -38
  8. package/dist/main.js.map +1 -1
  9. package/dist/parser.js +1879 -0
  10. package/dist/parser.js.map +1 -0
  11. package/dist/planner.service.js +46 -0
  12. package/dist/planner.service.js.map +1 -0
  13. package/dist/task-exec.ink.js +538 -0
  14. package/dist/task-exec.ink.js.map +1 -0
  15. package/dist/task-plan.ink.js +113 -0
  16. package/dist/task-plan.ink.js.map +1 -0
  17. package/dist/tree.ink.js +184 -0
  18. package/dist/tree.ink.js.map +1 -0
  19. package/dist/tsconfig.build.tsbuildinfo +1 -1
  20. package/package.json +50 -53
  21. package/dist/ajv.config.d.ts +0 -3
  22. package/dist/commands/each.d.ts +0 -25
  23. package/dist/commands/exec.d.ts +0 -26
  24. package/dist/commands/group.d.ts +0 -16
  25. package/dist/commands/list.d.ts +0 -30
  26. package/dist/commands/run.d.ts +0 -24
  27. package/dist/commands/tree.d.ts +0 -6
  28. package/dist/commons/context.service.d.ts +0 -23
  29. package/dist/commons/git.service.d.ts +0 -62
  30. package/dist/commons/logger/log.gateway.d.ts +0 -18
  31. package/dist/commons/logger/parameters.d.ts +0 -2
  32. package/dist/commons/logger/thread.gateway.d.ts +0 -13
  33. package/dist/commons/logger/types.d.ts +0 -2
  34. package/dist/commons/logger.service.d.ts +0 -1
  35. package/dist/config/config-loader.d.ts +0 -4
  36. package/dist/config/config-options.d.ts +0 -5
  37. package/dist/config/types.d.ts +0 -8
  38. package/dist/config/utils.d.ts +0 -5
  39. package/dist/constants.d.ts +0 -1
  40. package/dist/core.plugin-Bxu0Sx70.js +0 -642
  41. package/dist/core.plugin-Bxu0Sx70.js.map +0 -1
  42. package/dist/core.plugin.d.ts +0 -2
  43. package/dist/filters/affected.filter.d.ts +0 -12
  44. package/dist/filters/pipeline.d.ts +0 -11
  45. package/dist/filters/private.filter.d.ts +0 -7
  46. package/dist/filters/scripts.filter.d.ts +0 -8
  47. package/dist/index.d.ts +0 -45
  48. package/dist/index.js +0 -35
  49. package/dist/index.js.map +0 -1
  50. package/dist/ink-command-S3TpJLFi.js +0 -2082
  51. package/dist/ink-command-S3TpJLFi.js.map +0 -1
  52. package/dist/ink.config.d.ts +0 -3
  53. package/dist/inversify.config.d.ts +0 -4
  54. package/dist/jill.application-CGujSe1_.js +0 -639
  55. package/dist/jill.application-CGujSe1_.js.map +0 -1
  56. package/dist/jill.application.d.ts +0 -19
  57. package/dist/main.d.ts +0 -1
  58. package/dist/middlewares/load-project.d.ts +0 -21
  59. package/dist/middlewares/load-workspace.d.ts +0 -20
  60. package/dist/modules/command.d.ts +0 -20
  61. package/dist/modules/ink-command.d.ts +0 -11
  62. package/dist/modules/middleware.d.ts +0 -8
  63. package/dist/modules/module.d.ts +0 -7
  64. package/dist/modules/plugin-loader.service.d.ts +0 -10
  65. package/dist/modules/plugin.d.ts +0 -14
  66. package/dist/modules/service.d.ts +0 -8
  67. package/dist/modules/task-command.d.ts +0 -14
  68. package/dist/project/project.d.ts +0 -27
  69. package/dist/project/project.repository.d.ts +0 -15
  70. package/dist/project/types.d.ts +0 -1
  71. package/dist/project/workspace.d.ts +0 -41
  72. package/dist/tasks/command-task.d.ts +0 -15
  73. package/dist/tasks/errors.d.ts +0 -4
  74. package/dist/tasks/script-task.d.ts +0 -27
  75. package/dist/tasks/task-expression.service.d.ts +0 -25
  76. package/dist/tasks/task-manager.config.d.ts +0 -3
  77. package/dist/types.d.ts +0 -11
  78. package/dist/ui/hooks/useFlatTaskTree.d.ts +0 -14
  79. package/dist/ui/hooks/useIsVerbose.d.ts +0 -1
  80. package/dist/ui/hooks/useStdoutDimensions.d.ts +0 -4
  81. package/dist/ui/layout.d.ts +0 -5
  82. package/dist/ui/list.d.ts +0 -5
  83. package/dist/ui/static-logs.d.ts +0 -1
  84. package/dist/ui/task-name.d.ts +0 -5
  85. package/dist/ui/task-spinner.d.ts +0 -5
  86. package/dist/ui/task-tree-completed.d.ts +0 -5
  87. package/dist/ui/task-tree-full-spinner.d.ts +0 -5
  88. package/dist/ui/task-tree-scrollable-spinner.d.ts +0 -5
  89. package/dist/ui/task-tree-spinner.d.ts +0 -5
  90. package/dist/ui/task-tree-stats.d.ts +0 -5
  91. package/dist/ui/workspace-tree.d.ts +0 -8
  92. package/dist/utils/events.d.ts +0 -3
  93. package/dist/utils/exit.d.ts +0 -4
  94. package/dist/utils/import.d.ts +0 -4
  95. package/dist/utils/json.d.ts +0 -2
  96. package/dist/utils/streams.d.ts +0 -3
  97. package/dist/utils/string.d.ts +0 -2
  98. package/dist/utils/worker-cache.d.ts +0 -4
  99. package/dist/workspace-tree-CyjZrimj.js +0 -1120
  100. package/dist/workspace-tree-CyjZrimj.js.map +0 -1
@@ -0,0 +1,538 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { inject$ } from '@kyrielle/injector';
3
+ import { waitFor$ } from 'kyrielle';
4
+ import process from 'node:process';
5
+ import { i as isCommandCtx, S as ScriptTask, C as CommandTask, a as isScriptCtx, T as TASK_MANAGER } from './parser.js';
6
+ import { Box, Text, Static, useStdout, useInput, useStdin } from 'ink';
7
+ import { useState, useLayoutEffect, useMemo, useEffect } from 'react';
8
+ import { GroupTask } from '@jujulego/tasks';
9
+ import Spinner from 'ink-spinner';
10
+ import ms from 'pretty-ms';
11
+ import isUnicodeSupported from 'is-unicode-supported';
12
+ import { T as TaskName } from './TaskName.js';
13
+ import { i as inked } from './inked.js';
14
+ import '@kyrielle/logger';
15
+ import 'node:path';
16
+ import 'glob';
17
+ import 'node:fs';
18
+ import 'normalize-package-data';
19
+ import 'semver';
20
+ import 'moo';
21
+ import 'node:child_process';
22
+ import 'chalk';
23
+ import 'slugify';
24
+ import 'yargs';
25
+ import 'yargs/helpers';
26
+ import 'path-scurry';
27
+ import '@jujulego/quick-tag';
28
+ import 'ajv';
29
+ import 'node:os';
30
+ import 'cosmiconfig';
31
+ import 'chalk-template';
32
+
33
+ // Utils
34
+ /**
35
+ * Sorts tasks according to workspace and script, keeping command at the end
36
+ */ function taskComparator(a, b) {
37
+ // 1 - compare kind
38
+ const kindA = a instanceof CommandTask ? 0 : 1;
39
+ const kindB = b instanceof CommandTask ? 0 : 1;
40
+ if (kindA !== kindB) {
41
+ return kindB - kindA;
42
+ }
43
+ // 2 - compare workspaces
44
+ const wksA = 'workspace' in a.context ? a.context.workspace.name : '\uffff';
45
+ const wksB = 'workspace' in b.context ? b.context.workspace.name : '\uffff';
46
+ const wksDiff = wksA.localeCompare(wksB);
47
+ if (wksDiff !== 0) {
48
+ return wksDiff;
49
+ }
50
+ // 1 - compare scripts
51
+ const scriptA = 'script' in a.context ? a.context.script : '\uffff';
52
+ const scriptB = 'script' in b.context ? b.context.script : '\uffff';
53
+ return scriptA.localeCompare(scriptB);
54
+ }
55
+ /**
56
+ * Extract tasks to be printed, with their level in the tree
57
+ */ function* flatTasks(tasks, isVerbose, groupId, level = 0) {
58
+ for (const task of tasks){
59
+ if (task.group?.id !== groupId) {
60
+ continue;
61
+ }
62
+ yield {
63
+ task,
64
+ level
65
+ };
66
+ if (task instanceof GroupTask) {
67
+ const isCommandGroup = task.tasks.some((t)=>!isCommandCtx(t.context));
68
+ const hasFailed = task.tasks.some((t)=>t.status === 'failed');
69
+ const isStarted = task.status === 'running';
70
+ if (isVerbose || isCommandGroup || hasFailed || isStarted) {
71
+ let tasks = task.tasks;
72
+ if (task instanceof ScriptTask) {
73
+ tasks = [
74
+ ...tasks
75
+ ].sort(taskComparator);
76
+ }
77
+ yield* flatTasks(tasks, isVerbose, task.id, level + 1);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ // Hook
83
+ function useFlatTaskTree(manager, isVerbose = false) {
84
+ const [tasks, setTasks] = useState([
85
+ ...manager.tasks
86
+ ].sort(taskComparator));
87
+ const [version, setVersion] = useState(0);
88
+ useLayoutEffect(()=>{
89
+ let dirty = false;
90
+ return manager.events$.on('added', ()=>{
91
+ if (!dirty) {
92
+ dirty = true;
93
+ queueMicrotask(()=>{
94
+ setTasks([
95
+ ...manager.tasks
96
+ ].sort(taskComparator));
97
+ dirty = false;
98
+ });
99
+ }
100
+ }).unsubscribe;
101
+ }, [
102
+ manager
103
+ ]);
104
+ useLayoutEffect(()=>{
105
+ let dirty = false;
106
+ return manager.events$.on('started', ()=>{
107
+ if (!dirty) {
108
+ dirty = true;
109
+ setTimeout(()=>{
110
+ setVersion((old)=>++old);
111
+ dirty = false;
112
+ });
113
+ }
114
+ }).unsubscribe;
115
+ }, [
116
+ manager
117
+ ]);
118
+ useLayoutEffect(()=>{
119
+ let dirty = false;
120
+ return manager.events$.on('completed', ()=>{
121
+ if (!dirty) {
122
+ dirty = true;
123
+ setTimeout(()=>{
124
+ setVersion((old)=>++old);
125
+ dirty = false;
126
+ });
127
+ }
128
+ }).unsubscribe;
129
+ }, [
130
+ manager
131
+ ]);
132
+ return useMemo(()=>{
133
+ return Array.from(flatTasks(tasks, isVerbose));
134
+ }, [
135
+ tasks,
136
+ isVerbose,
137
+ version
138
+ ]); // eslint-disable-line react-hooks/exhaustive-deps
139
+ }
140
+
141
+ const isSupported = !isUnicodeSupported();
142
+ const success = isSupported ? '✔' : '√';
143
+ const error = isSupported ? '✖' : '×';
144
+
145
+ // Components
146
+ function TaskSpinner({ task }) {
147
+ // State
148
+ const [status, setStatus] = useState(task.status);
149
+ const [time, setTime] = useState(task.duration);
150
+ // Effects
151
+ useLayoutEffect(()=>{
152
+ return task.events$.on('status', (event)=>{
153
+ setStatus(event.status);
154
+ }).unsubscribe;
155
+ }, [
156
+ task
157
+ ]);
158
+ useLayoutEffect(()=>{
159
+ return task.events$.on('completed', ({ duration })=>{
160
+ setTime(duration);
161
+ }).unsubscribe;
162
+ }, [
163
+ task
164
+ ]);
165
+ // Render
166
+ const isScriptChild = (isCommandCtx(task.context) && task.group && isScriptCtx(task.group.context)) ?? false;
167
+ switch(status){
168
+ case 'blocked':
169
+ case 'ready':
170
+ case 'starting':
171
+ return /*#__PURE__*/ jsxs(Box, {
172
+ children: [
173
+ /*#__PURE__*/ jsx(Text, {
174
+ color: "grey",
175
+ children: '\u00B7'
176
+ }),
177
+ /*#__PURE__*/ jsx(Box, {
178
+ paddingLeft: 1,
179
+ children: /*#__PURE__*/ jsx(Text, {
180
+ color: "grey",
181
+ wrap: "truncate",
182
+ children: /*#__PURE__*/ jsx(TaskName, {
183
+ task: task,
184
+ withWorkspace: true
185
+ })
186
+ })
187
+ })
188
+ ]
189
+ });
190
+ case 'running':
191
+ return /*#__PURE__*/ jsxs(Box, {
192
+ children: [
193
+ /*#__PURE__*/ jsx(Text, {
194
+ dimColor: isScriptChild,
195
+ children: /*#__PURE__*/ jsx(Spinner, {})
196
+ }),
197
+ /*#__PURE__*/ jsx(Box, {
198
+ paddingLeft: 1,
199
+ children: /*#__PURE__*/ jsx(Text, {
200
+ dimColor: isScriptChild,
201
+ wrap: "truncate",
202
+ children: /*#__PURE__*/ jsx(TaskName, {
203
+ task: task,
204
+ withWorkspace: true
205
+ })
206
+ })
207
+ })
208
+ ]
209
+ });
210
+ case 'done':
211
+ return /*#__PURE__*/ jsxs(Box, {
212
+ children: [
213
+ /*#__PURE__*/ jsx(Text, {
214
+ color: "green",
215
+ children: success
216
+ }),
217
+ /*#__PURE__*/ jsx(Box, {
218
+ paddingLeft: 1,
219
+ children: /*#__PURE__*/ jsx(Text, {
220
+ dimColor: isScriptChild,
221
+ wrap: "truncate",
222
+ children: /*#__PURE__*/ jsx(TaskName, {
223
+ task: task,
224
+ withWorkspace: true
225
+ })
226
+ })
227
+ }),
228
+ /*#__PURE__*/ jsx(Box, {
229
+ paddingLeft: 1,
230
+ flexShrink: 0,
231
+ children: /*#__PURE__*/ jsxs(Text, {
232
+ color: isScriptChild ? 'grey' : 'dim',
233
+ children: [
234
+ "(took ",
235
+ ms(time),
236
+ ")"
237
+ ]
238
+ })
239
+ })
240
+ ]
241
+ });
242
+ case 'failed':
243
+ return /*#__PURE__*/ jsxs(Box, {
244
+ children: [
245
+ /*#__PURE__*/ jsx(Text, {
246
+ color: "red",
247
+ children: error
248
+ }),
249
+ /*#__PURE__*/ jsx(Box, {
250
+ paddingLeft: 1,
251
+ children: /*#__PURE__*/ jsx(Text, {
252
+ dimColor: isScriptChild,
253
+ wrap: "truncate",
254
+ children: /*#__PURE__*/ jsx(TaskName, {
255
+ task: task,
256
+ withWorkspace: true
257
+ })
258
+ })
259
+ }),
260
+ /*#__PURE__*/ jsx(Box, {
261
+ paddingLeft: 1,
262
+ flexShrink: 0,
263
+ children: /*#__PURE__*/ jsxs(Text, {
264
+ color: isScriptChild ? 'grey' : 'dim',
265
+ children: [
266
+ "(took ",
267
+ ms(time),
268
+ ")"
269
+ ]
270
+ })
271
+ })
272
+ ]
273
+ });
274
+ }
275
+ }
276
+
277
+ // Component
278
+ function TaskTreeStats({ manager }) {
279
+ // Follow stats
280
+ const [stats, setStats] = useState(()=>{
281
+ const base = {
282
+ running: 0,
283
+ done: 0,
284
+ failed: 0
285
+ };
286
+ for (const task of manager.tasks){
287
+ switch(task.status){
288
+ case 'starting':
289
+ case 'running':
290
+ base.running += task.weight;
291
+ break;
292
+ case 'done':
293
+ base.done += task.weight;
294
+ break;
295
+ case 'failed':
296
+ base.failed += task.weight;
297
+ break;
298
+ }
299
+ }
300
+ return base;
301
+ });
302
+ useLayoutEffect(()=>{
303
+ return manager.events$.on('started', (task)=>{
304
+ setStats((old)=>({
305
+ ...old,
306
+ running: old.running + task.weight
307
+ }));
308
+ }).unsubscribe;
309
+ }, [
310
+ manager
311
+ ]);
312
+ useLayoutEffect(()=>{
313
+ return manager.events$.on('completed', (task)=>{
314
+ setStats((old)=>({
315
+ running: old.running - task.weight,
316
+ done: task.status === 'done' ? old.done + task.weight : old.done,
317
+ failed: task.status === 'failed' ? old.failed + task.weight : old.failed
318
+ }));
319
+ }).unsubscribe;
320
+ }, [
321
+ manager
322
+ ]);
323
+ // Render
324
+ return /*#__PURE__*/ jsxs(Text, {
325
+ children: [
326
+ stats.running !== 0 && /*#__PURE__*/ jsxs(Fragment, {
327
+ children: [
328
+ /*#__PURE__*/ jsx(Spinner, {
329
+ type: "sand"
330
+ }),
331
+ " ",
332
+ /*#__PURE__*/ jsx(Text, {
333
+ bold: true,
334
+ children: stats.running
335
+ }),
336
+ " running"
337
+ ]
338
+ }),
339
+ stats.running !== 0 && stats.done !== 0 && /*#__PURE__*/ jsx(Fragment, {
340
+ children: ", "
341
+ }),
342
+ stats.done !== 0 && /*#__PURE__*/ jsxs(Text, {
343
+ color: "green",
344
+ children: [
345
+ success,
346
+ " ",
347
+ stats.done,
348
+ " done"
349
+ ]
350
+ }),
351
+ stats.running + stats.done !== 0 && stats.failed !== 0 && /*#__PURE__*/ jsx(Fragment, {
352
+ children: ", "
353
+ }),
354
+ stats.failed !== 0 && /*#__PURE__*/ jsxs(Text, {
355
+ color: "red",
356
+ children: [
357
+ error,
358
+ " ",
359
+ stats.failed,
360
+ " failed"
361
+ ]
362
+ })
363
+ ]
364
+ });
365
+ }
366
+
367
+ // Component
368
+ function TaskTreeCompleted({ manager, verbose }) {
369
+ // Extract all tasks
370
+ const flat = useMemo(()=>{
371
+ return Array.from(flatTasks([
372
+ ...manager.tasks
373
+ ].sort(taskComparator), verbose ?? false));
374
+ }, [
375
+ manager,
376
+ verbose
377
+ ]);
378
+ // Render
379
+ return /*#__PURE__*/ jsxs(Fragment, {
380
+ children: [
381
+ /*#__PURE__*/ jsx(Static, {
382
+ items: flat,
383
+ children: ({ task, level })=>/*#__PURE__*/ jsx(Box, {
384
+ marginLeft: level * 2,
385
+ flexShrink: 0,
386
+ children: /*#__PURE__*/ jsx(TaskSpinner, {
387
+ task: task
388
+ })
389
+ }, task.id)
390
+ }),
391
+ /*#__PURE__*/ jsx(TaskTreeStats, {
392
+ manager: manager
393
+ })
394
+ ]
395
+ });
396
+ }
397
+
398
+ // Component
399
+ function TaskTreeFullSpinner({ manager, verbose }) {
400
+ const flat = useFlatTaskTree(manager, verbose);
401
+ // Render
402
+ return /*#__PURE__*/ jsxs(Fragment, {
403
+ children: [
404
+ /*#__PURE__*/ jsx(Box, {
405
+ flexDirection: "column",
406
+ children: flat.map(({ task, level })=>/*#__PURE__*/ jsx(Box, {
407
+ marginLeft: level * 2,
408
+ flexShrink: 0,
409
+ children: /*#__PURE__*/ jsx(TaskSpinner, {
410
+ task: task
411
+ })
412
+ }, task.id))
413
+ }),
414
+ /*#__PURE__*/ jsx(Text, {
415
+ children: /*#__PURE__*/ jsx(TaskTreeStats, {
416
+ manager: manager
417
+ })
418
+ })
419
+ ]
420
+ });
421
+ }
422
+
423
+ function useStdoutDimensions() {
424
+ const { stdout } = useStdout();
425
+ const [dimensions, setDimensions] = useState({
426
+ columns: stdout.columns ?? Infinity,
427
+ rows: stdout.rows ?? Infinity
428
+ });
429
+ useEffect(()=>{
430
+ const handler = ()=>setDimensions({
431
+ columns: stdout.columns ?? Infinity,
432
+ rows: stdout.rows ?? Infinity
433
+ });
434
+ stdout.on('resize', handler);
435
+ return ()=>{
436
+ stdout.off('resize', handler);
437
+ };
438
+ }, [
439
+ stdout
440
+ ]);
441
+ return dimensions;
442
+ }
443
+
444
+ // Component
445
+ function TaskTreeScrollableSpinner({ manager, verbose }) {
446
+ const { rows: termHeight } = useStdoutDimensions();
447
+ // Extract all tasks
448
+ const flat = useFlatTaskTree(manager, verbose);
449
+ const maxHeight = useMemo(()=>Math.min(termHeight - 4, flat.length), [
450
+ termHeight,
451
+ flat
452
+ ]);
453
+ // Manage scroll
454
+ const [start, setStart] = useState(0);
455
+ const slice = useMemo(()=>flat.slice(start, start + maxHeight), [
456
+ flat,
457
+ start,
458
+ maxHeight
459
+ ]);
460
+ useEffect(()=>{
461
+ if (start + maxHeight > flat.length) {
462
+ setStart(Math.max(flat.length - maxHeight, 0));
463
+ }
464
+ }, [
465
+ start,
466
+ flat,
467
+ maxHeight
468
+ ]);
469
+ useInput((_, key)=>{
470
+ if (key.upArrow) {
471
+ setStart((old)=>Math.max(0, old - 1));
472
+ } else if (key.downArrow) {
473
+ setStart((old)=>Math.min(flat.length - maxHeight, old + 1));
474
+ }
475
+ });
476
+ // Render
477
+ return /*#__PURE__*/ jsxs(Fragment, {
478
+ children: [
479
+ /*#__PURE__*/ jsx(Box, {
480
+ flexDirection: "column",
481
+ children: slice.map(({ task, level })=>/*#__PURE__*/ jsx(Box, {
482
+ marginLeft: level * 2,
483
+ flexShrink: 0,
484
+ children: /*#__PURE__*/ jsx(TaskSpinner, {
485
+ task: task
486
+ })
487
+ }, task.id))
488
+ }),
489
+ /*#__PURE__*/ jsxs(Text, {
490
+ children: [
491
+ /*#__PURE__*/ jsx(TaskTreeStats, {
492
+ manager: manager
493
+ }),
494
+ maxHeight < flat.length && /*#__PURE__*/ jsx(Text, {
495
+ color: "grey",
496
+ children: " - use keyboard arrows to scroll"
497
+ })
498
+ ]
499
+ })
500
+ ]
501
+ });
502
+ }
503
+
504
+ // Component
505
+ function TaskTreeSpinner({ manager, verbose }) {
506
+ const stdin = useStdin();
507
+ if (stdin.isRawModeSupported) {
508
+ return /*#__PURE__*/ jsx(TaskTreeScrollableSpinner, {
509
+ manager: manager,
510
+ verbose: verbose
511
+ });
512
+ } else {
513
+ return /*#__PURE__*/ jsx(TaskTreeFullSpinner, {
514
+ manager: manager,
515
+ verbose: verbose
516
+ });
517
+ }
518
+ }
519
+
520
+ const TaskExecInk = inked(async function*({ tasks, verbose }) {
521
+ const manager = await inject$(TASK_MANAGER);
522
+ yield /*#__PURE__*/ jsx(TaskTreeSpinner, {
523
+ manager: manager,
524
+ verbose: verbose
525
+ });
526
+ tasks.start(manager);
527
+ const results = await waitFor$(tasks.events$, 'finished');
528
+ yield /*#__PURE__*/ jsx(TaskTreeCompleted, {
529
+ manager: manager,
530
+ verbose: verbose
531
+ });
532
+ if (results.failed > 0) {
533
+ process.exitCode = 1;
534
+ }
535
+ });
536
+
537
+ export { TaskExecInk as default };
538
+ //# sourceMappingURL=task-exec.ink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-exec.ink.js","sources":["../src/cli/hooks/useFlatTaskTree.ts","../src/utils/symbols.ts","../src/cli/components/TaskSpinner.tsx","../src/cli/components/TaskTreeStats.tsx","../src/cli/components/TaskTreeCompleted.tsx","../src/cli/components/TaskTreeFullSpinner.tsx","../src/cli/hooks/useStdoutDimensions.ts","../src/cli/components/TaskTreeScrollableSpinner.tsx","../src/cli/components/TaskTreeSpinner.tsx","../src/cli/bases/task-exec.ink.tsx"],"sourcesContent":["import { GroupTask, type Task, type TaskManager } from '@jujulego/tasks';\nimport { useLayoutEffect, useMemo, useState } from 'react';\nimport type { Workspace } from '../../projects/workspace.js';\nimport { CommandTask, isCommandCtx } from '../../tasks/command-task.js';\nimport { ScriptTask } from '../../tasks/script-task.js';\n\n// Types\nexport interface FlatTask {\n task: Task;\n level: number;\n}\n\n// Utils\n/**\n * Sorts tasks according to workspace and script, keeping command at the end\n */\nexport function taskComparator(a: Task, b: Task) {\n // 1 - compare kind\n const kindA = a instanceof CommandTask ? 0 : 1;\n const kindB = b instanceof CommandTask ? 0 : 1;\n\n if (kindA !== kindB) {\n return kindB - kindA;\n }\n\n // 2 - compare workspaces\n const wksA = 'workspace' in a.context ? (a.context.workspace as Workspace).name : '\\uffff';\n const wksB = 'workspace' in b.context ? (b.context.workspace as Workspace).name : '\\uffff';\n const wksDiff = wksA.localeCompare(wksB);\n\n if (wksDiff !== 0) {\n return wksDiff;\n }\n\n // 1 - compare scripts\n const scriptA = 'script' in a.context ? a.context.script as string : '\\uffff';\n const scriptB = 'script' in b.context ? b.context.script as string : '\\uffff';\n\n return scriptA.localeCompare(scriptB);\n}\n\n/**\n * Extract tasks to be printed, with their level in the tree\n */\nexport function* flatTasks(tasks: readonly Task[], isVerbose: boolean, groupId?: string, level = 0): Generator<FlatTask> {\n for (const task of tasks) {\n if (task.group?.id !== groupId) {\n continue;\n }\n\n yield { task, level };\n\n if (task instanceof GroupTask) {\n const isCommandGroup = task.tasks.some((t) => !isCommandCtx(t.context));\n const hasFailed = task.tasks.some((t) => t.status === 'failed');\n const isStarted = task.status === 'running';\n\n if (isVerbose || isCommandGroup || hasFailed || isStarted) {\n let tasks = task.tasks;\n\n if (task instanceof ScriptTask) {\n tasks = [...tasks].sort(taskComparator);\n }\n\n yield* flatTasks(tasks, isVerbose, task.id, level + 1);\n }\n }\n }\n}\n\n// Hook\nexport function useFlatTaskTree(manager: TaskManager, isVerbose: boolean = false): FlatTask[] {\n const [tasks, setTasks] = useState([...manager.tasks].sort(taskComparator));\n const [version, setVersion] = useState(0);\n\n useLayoutEffect(() => {\n let dirty = false;\n\n return manager.events$.on('added', () => {\n if (!dirty) {\n dirty = true;\n\n queueMicrotask(() => {\n setTasks([...manager.tasks].sort(taskComparator));\n dirty = false;\n });\n }\n }).unsubscribe;\n }, [manager]);\n\n useLayoutEffect(() => {\n let dirty = false;\n\n return manager.events$.on('started', () => {\n if (!dirty) {\n dirty = true;\n\n setTimeout(() => {\n setVersion((old) => ++old);\n dirty = false;\n });\n }\n }).unsubscribe;\n }, [manager]);\n\n useLayoutEffect(() => {\n let dirty = false;\n\n return manager.events$.on('completed', () => {\n if (!dirty) {\n dirty = true;\n\n setTimeout(() => {\n setVersion((old) => ++old);\n dirty = false;\n });\n }\n }).unsubscribe;\n }, [manager]);\n\n return useMemo(() => {\n return Array.from(flatTasks(tasks, isVerbose));\n }, [tasks, isVerbose, version]); // eslint-disable-line react-hooks/exhaustive-deps\n}\n","import isUnicodeSupported from 'is-unicode-supported';\n\nconst isSupported = !isUnicodeSupported();\n\nexport const success = isSupported ? '✔' : '√';\nexport const error = isSupported ? '✖' : '×';\n","import { type Task } from '@jujulego/tasks';\nimport { Box, Text } from 'ink';\nimport Spinner from 'ink-spinner';\nimport ms from 'pretty-ms';\nimport { useLayoutEffect, useState } from 'react';\nimport { isCommandCtx } from '../../tasks/command-task.js';\nimport { isScriptCtx } from '../../tasks/script-task.js';\nimport * as symbols from '../../utils/symbols.js';\nimport TaskName from './TaskName.jsx';\n\n// Types\nexport interface TaskSpinnerProps {\n task: Task;\n}\n\n// Components\nexport default function TaskSpinner({ task }: TaskSpinnerProps) {\n // State\n const [status, setStatus] = useState(task.status);\n const [time, setTime] = useState(task.duration);\n\n // Effects\n useLayoutEffect(() => {\n return task.events$.on('status', (event) => {\n setStatus(event.status);\n }).unsubscribe;\n }, [task]);\n\n useLayoutEffect(() => {\n return task.events$.on('completed', ({ duration }) => {\n setTime(duration);\n }).unsubscribe;\n }, [task]);\n\n // Render\n const isScriptChild = (isCommandCtx(task.context) && task.group && isScriptCtx(task.group.context)) ?? false;\n\n switch (status) {\n case 'blocked':\n case 'ready':\n case 'starting':\n return (\n <Box>\n <Text color=\"grey\">{'\\u00B7'}</Text>\n <Box paddingLeft={1}>\n <Text color=\"grey\" wrap=\"truncate\">\n <TaskName task={task} withWorkspace />\n </Text>\n </Box>\n </Box>\n );\n\n case 'running':\n return (\n <Box>\n <Text dimColor={isScriptChild}>\n <Spinner />\n </Text>\n <Box paddingLeft={1}>\n <Text dimColor={isScriptChild} wrap=\"truncate\">\n <TaskName task={task} withWorkspace />\n </Text>\n </Box>\n </Box>\n );\n\n case 'done':\n return (\n <Box>\n <Text color=\"green\">{ symbols.success }</Text>\n <Box paddingLeft={1}>\n <Text dimColor={isScriptChild} wrap=\"truncate\">\n <TaskName task={task} withWorkspace />\n </Text>\n </Box>\n <Box paddingLeft={1} flexShrink={0}>\n <Text color={isScriptChild ? 'grey' : 'dim'}>(took {ms(time)})</Text>\n </Box>\n </Box>\n );\n\n case 'failed':\n return (\n <Box>\n <Text color=\"red\">{ symbols.error }</Text>\n <Box paddingLeft={1}>\n <Text dimColor={isScriptChild} wrap=\"truncate\">\n <TaskName task={task} withWorkspace />\n </Text>\n </Box>\n <Box paddingLeft={1} flexShrink={0}>\n <Text color={isScriptChild ? 'grey' : 'dim'}>(took {ms(time)})</Text>\n </Box>\n </Box>\n );\n }\n}\n","import type { TaskManager } from '@jujulego/tasks';\nimport { Text } from 'ink';\nimport Spinner from 'ink-spinner';\nimport { useLayoutEffect, useState } from 'react';\nimport * as symbols from '../../utils/symbols.js';\n\n// Types\nexport interface TaskTreeStatsProps {\n readonly manager: TaskManager;\n}\n\n// Component\nexport default function TaskTreeStats({ manager }: TaskTreeStatsProps) {\n // Follow stats\n const [stats, setStats] = useState(() => {\n const base = { running: 0, done: 0, failed: 0 };\n \n for (const task of manager.tasks) {\n switch (task.status) {\n case 'starting':\n case 'running':\n base.running += task.weight;\n break;\n\n case 'done':\n base.done += task.weight;\n break;\n\n case 'failed':\n base.failed += task.weight;\n break;\n }\n }\n \n return base;\n });\n\n useLayoutEffect(() => {\n return manager.events$.on('started', (task) => {\n setStats((old) => ({\n ...old,\n running: old.running + task.weight\n }));\n }).unsubscribe;\n }, [manager]);\n\n useLayoutEffect(() => {\n return manager.events$.on('completed', (task) => {\n setStats((old) => ({\n running: old.running - task.weight,\n done: task.status === 'done' ? old.done + task.weight : old.done,\n failed: task.status === 'failed' ? old.failed + task.weight : old.failed,\n }));\n }).unsubscribe;\n }, [manager]);\n\n // Render\n return (\n <Text>\n { (stats.running !== 0) && (\n <><Spinner type=\"sand\" /> <Text bold>{ stats.running }</Text> running</>\n ) }\n { (stats.running !== 0 && stats.done !== 0) && (<>, </>) }\n { (stats.done !== 0) && (\n <Text color=\"green\">{ symbols.success } { stats.done } done</Text>\n ) }\n { (stats.running + stats.done !== 0 && stats.failed !== 0) && (<>, </>) }\n { (stats.failed !== 0) && (\n <Text color=\"red\">{ symbols.error } { stats.failed } failed</Text>\n ) }\n </Text>\n );\n}\n","import type { TaskManager } from '@jujulego/tasks';\nimport { Box, Static } from 'ink';\nimport { useMemo } from 'react';\nimport { flatTasks, taskComparator } from '../hooks/useFlatTaskTree.js';\nimport TaskSpinner from './TaskSpinner.jsx';\nimport TaskTreeStats from './TaskTreeStats.jsx';\n\n// Component\nexport default function TaskTreeCompleted({ manager, verbose }: TaskTreeCompletedProps) {\n // Extract all tasks\n const flat = useMemo(() => {\n return Array.from(flatTasks([...manager.tasks].sort(taskComparator), verbose ?? false));\n }, [manager, verbose]);\n\n // Render\n return (\n <>\n <Static items={flat}>\n { ({ task, level }) => (\n <Box key={task.id} marginLeft={level * 2} flexShrink={0}>\n <TaskSpinner task={task} />\n </Box>\n ) }\n </Static>\n <TaskTreeStats manager={manager} />\n </>\n );\n}\n\n// Types\nexport interface TaskTreeCompletedProps {\n readonly manager: TaskManager;\n readonly verbose?: boolean;\n}\n","import type { TaskManager } from '@jujulego/tasks';\nimport { Box, Text } from 'ink';\nimport { useFlatTaskTree } from '../hooks/useFlatTaskTree.js';\nimport TaskSpinner from './TaskSpinner.jsx';\nimport TaskTreeStats from './TaskTreeStats.jsx';\n\n// Component\nexport default function TaskTreeFullSpinner({ manager, verbose }: TaskTreeFullSpinnerProps) {\n const flat = useFlatTaskTree(manager, verbose);\n\n // Render\n return (\n <>\n <Box flexDirection=\"column\">\n { flat.map(({ task, level }) => (\n <Box key={task.id} marginLeft={level * 2} flexShrink={0}>\n <TaskSpinner task={task} />\n </Box>\n )) }\n </Box>\n <Text>\n <TaskTreeStats manager={manager} />\n </Text>\n </>\n );\n}\n\n// Types\nexport interface TaskTreeFullSpinnerProps {\n readonly manager: TaskManager;\n readonly verbose?: boolean;\n}\n","import { useStdout } from 'ink';\nimport { useEffect, useState } from 'react';\n\nexport function useStdoutDimensions() {\n const { stdout } = useStdout();\n const [dimensions, setDimensions] = useState({\n columns: stdout.columns ?? Infinity,\n rows: stdout.rows ?? Infinity,\n });\n\n useEffect(() => {\n const handler = () => setDimensions({\n columns: stdout.columns ?? Infinity,\n rows: stdout.rows ?? Infinity,\n });\n stdout.on('resize', handler);\n\n return () => {\n stdout.off('resize', handler);\n };\n }, [stdout]);\n\n return dimensions;\n}\n","import { type TaskManager } from '@jujulego/tasks';\nimport { Box, Text, useInput } from 'ink';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useFlatTaskTree } from '../hooks/useFlatTaskTree.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport TaskSpinner from './TaskSpinner.jsx';\nimport TaskTreeStats from './TaskTreeStats.jsx';\n\n// Component\nexport default function TaskTreeScrollableSpinner({ manager, verbose }: TaskTreeScrollableSpinnerProps) {\n const { rows: termHeight } = useStdoutDimensions();\n\n // Extract all tasks\n const flat = useFlatTaskTree(manager, verbose);\n\n const maxHeight = useMemo(\n () => Math.min(termHeight - 4, flat.length),\n [termHeight, flat]\n );\n\n // Manage scroll\n const [start, setStart] = useState(0);\n\n const slice = useMemo(\n () => flat.slice(start, start + maxHeight),\n [flat, start, maxHeight]\n );\n\n useEffect(() => {\n if (start + maxHeight > flat.length) {\n setStart(Math.max(flat.length - maxHeight, 0));\n }\n }, [start, flat, maxHeight]);\n\n useInput((_, key) => {\n if (key.upArrow) {\n setStart((old) => Math.max(0, old - 1));\n } else if (key.downArrow) {\n setStart((old) => Math.min(flat.length - maxHeight, old + 1));\n }\n });\n\n // Render\n return (\n <>\n <Box flexDirection=\"column\">\n { slice.map(({ task, level }) => (\n <Box key={task.id} marginLeft={level * 2} flexShrink={0}>\n <TaskSpinner task={task} />\n </Box>\n )) }\n </Box>\n <Text>\n <TaskTreeStats manager={manager} />\n { (maxHeight < flat.length) && (<Text color=\"grey\"> - use keyboard arrows to scroll</Text>) }\n </Text>\n </>\n );\n}\n\n// Types\nexport interface TaskTreeScrollableSpinnerProps {\n readonly manager: TaskManager;\n readonly verbose?: boolean;\n}\n","import { type TaskManager } from '@jujulego/tasks';\nimport { useStdin } from 'ink';\nimport TaskTreeFullSpinner from './TaskTreeFullSpinner.jsx';\nimport TaskTreeScrollableSpinner from './TaskTreeScrollableSpinner.jsx';\n\n// Component\nexport default function TaskTreeSpinner({ manager, verbose }: TaskTreeSpinnerProps) {\n const stdin = useStdin();\n\n if (stdin.isRawModeSupported) {\n return <TaskTreeScrollableSpinner manager={manager} verbose={verbose} />;\n } else {\n return <TaskTreeFullSpinner manager={manager} verbose={verbose} />;\n }\n}\n\n// Types\nexport interface TaskTreeSpinnerProps {\n readonly manager: TaskManager;\n readonly verbose?: boolean;\n}\n","import type { TaskSet } from '@jujulego/tasks';\nimport { inject$ } from '@kyrielle/injector';\nimport { waitFor$ } from 'kyrielle';\nimport process from 'node:process';\nimport { TASK_MANAGER } from '../../tokens.js';\nimport TaskTreeCompleted from '../components/TaskTreeCompleted.jsx';\nimport TaskTreeSpinner from '../components/TaskTreeSpinner.jsx';\nimport { inked } from '../inked.jsx';\n\nconst TaskExecInk = inked(async function* ({ tasks, verbose }: TaskExecInkProps) {\n const manager = await inject$(TASK_MANAGER);\n\n yield <TaskTreeSpinner manager={manager} verbose={verbose} />;\n tasks.start(manager);\n\n const results = await waitFor$(tasks.events$, 'finished');\n yield <TaskTreeCompleted manager={manager} verbose={verbose} />;\n\n if (results.failed > 0) {\n process.exitCode = 1;\n }\n});\n\nexport default TaskExecInk;\n\n// Types\nexport interface TaskExecInkProps {\n readonly tasks: TaskSet;\n readonly verbose?: boolean;\n}\n"],"names":["taskComparator","a","b","kindA","CommandTask","kindB","wksA","context","workspace","name","wksB","wksDiff","localeCompare","scriptA","script","scriptB","flatTasks","tasks","isVerbose","groupId","level","task","group","id","GroupTask","isCommandGroup","some","t","isCommandCtx","hasFailed","status","isStarted","ScriptTask","sort","useFlatTaskTree","manager","setTasks","useState","version","setVersion","useLayoutEffect","dirty","events$","on","queueMicrotask","unsubscribe","setTimeout","old","useMemo","Array","from","isSupported","isUnicodeSupported","success","error","TaskSpinner","setStatus","time","setTime","duration","event","isScriptChild","isScriptCtx","_jsxs","Box","_jsx","Text","color","paddingLeft","wrap","TaskName","withWorkspace","dimColor","Spinner","symbols","flexShrink","ms","TaskTreeStats","stats","setStats","base","running","done","failed","weight","_Fragment","type","bold","TaskTreeCompleted","verbose","flat","Static","items","marginLeft","TaskTreeFullSpinner","flexDirection","map","useStdoutDimensions","stdout","useStdout","dimensions","setDimensions","columns","Infinity","rows","useEffect","handler","off","TaskTreeScrollableSpinner","termHeight","maxHeight","Math","min","length","start","setStart","slice","max","useInput","_","key","upArrow","downArrow","TaskTreeSpinner","stdin","useStdin","isRawModeSupported","TaskExecInk","inked","inject$","TASK_MANAGER","results","waitFor$","process","exitCode"],"mappings":"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"}