@jujulego/jill 3.0.0-alpha.7 → 3.0.0-alpha.8

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/dist/main.js CHANGED
@@ -1,10 +1,10 @@
1
- ;{try{(function(){var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="423e1769-82e8-4ede-89c9-d0cfbda3929d",e._sentryDebugIdIdentifier="sentry-dbid-423e1769-82e8-4ede-89c9-d0cfbda3929d");})();}catch(e){}};!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e.SENTRY_RELEASE={id:"3.0.0-alpha.7"};}catch(e){}}();import { token$, inject$, asyncScope$ } from '@kyrielle/injector';
1
+ ;{try{(function(){var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="928a37d5-5913-4d87-9031-9d670b857132",e._sentryDebugIdIdentifier="sentry-dbid-928a37d5-5913-4d87-9031-9d670b857132");})();}catch(e){}};!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e.SENTRY_RELEASE={id:"3.0.0-alpha.8"};}catch(e){}}();import { token$, inject$, asyncScope$ } from '@kyrielle/injector';
2
2
  import { startSpan, getActiveSpan, updateSpanName, getRootSpan, startInactiveSpan, captureException } from '@sentry/node';
3
3
  import process$1 from 'node:process';
4
4
  import { hideBin } from 'yargs/helpers';
5
- import { pipe$, waitFor$, filter$, map$, collect$, asyncIterator$, var$, observable$, off$, once$, flow$ } from 'kyrielle';
5
+ import { pipe$, waitFor$, filter$, map$, collect$, asyncIterator$, var$, flow$ } from 'kyrielle';
6
6
  import yargs from 'yargs';
7
- import { TaskManager, scheduler$, isWorkloadEnded, WorkloadState, plan, spawn$, SpawnTask, GroupTask, TaskSet, ParallelGroup, FallbackGroup, SequenceGroup } from '@jujulego/tasks';
7
+ import { scheduler$, isWorkloadEnded, WorkloadState, spawn$, sequenceFlow$, parallelFlow$, fallbackFlow$ } from '@jujulego/tasks';
8
8
  import { logger$, withTimestamp, withLabel, qLogDelay, LogLevel, LogGateway, logDelay$, toStderr } from '@kyrielle/logger';
9
9
  import fs from 'node:fs';
10
10
  import { PathScurry } from 'path-scurry';
@@ -15,7 +15,7 @@ import { Glob } from 'glob';
15
15
  import normalize from 'normalize-package-data';
16
16
  import { satisfies, compare, parse } from 'semver';
17
17
  import moo from 'moo';
18
- import cp from 'node:child_process';
18
+ import { spawn } from 'node:child_process';
19
19
  import chalk from 'chalk';
20
20
  import slugify from 'slugify';
21
21
  import { qjson, qprop, q$, defineQuickFormat, qerror, qarg, qwrap } from '@jujulego/quick-tag';
@@ -24,14 +24,16 @@ import os from 'node:os';
24
24
  import { cosmiconfig, defaultLoaders } from 'cosmiconfig';
25
25
  import { chalkTemplateStderr } from 'chalk-template';
26
26
 
27
- var version = "3.0.0-alpha.7";
27
+ var version = "3.0.0-alpha.8";
28
28
 
29
29
  function trace(fun, opts) {
30
30
  const name = typeof opts === 'string' ? opts : opts.name;
31
- const use = typeof opts === 'object' ? opts.use : (_, r)=>r;
31
+ const op = typeof opts === 'object' ? opts.op : undefined;
32
+ const use = typeof opts === 'object' && opts.use || ((_, r)=>r);
32
33
  return function(...args) {
33
34
  return pipe$(startSpan({
34
- name
35
+ name,
36
+ op
35
37
  }, ()=>fun.call(this, ...args)), (r)=>use(name, r));
36
38
  };
37
39
  }
@@ -45,27 +47,19 @@ function instrument(opts) {
45
47
  });
46
48
  };
47
49
  }
48
- function traceAsyncGenerator(name, generator) {
49
- const instrumented = {
50
- ...generator,
51
- next: async ()=>startSpan({
52
- name,
53
- op: 'iterator.next'
54
- }, ()=>generator.next()),
55
- [Symbol.asyncIterator]: ()=>instrumented
56
- };
57
- return instrumented;
58
- }
59
50
  function traceImport(name, loader) {
60
51
  return startSpan({
61
- name: `load ${name}`,
52
+ name: name,
62
53
  op: 'resource.script'
63
54
  }, loader);
64
55
  }
65
56
 
66
57
  function command$5(module) {
67
- const name = getCommandName(module);
68
- const handler = trace(module.handler, 'cli.handler');
58
+ const name = commandName(module);
59
+ const handler = trace(module.handler, {
60
+ name: commandName(module),
61
+ op: 'cli.handler'
62
+ });
69
63
  return (parser)=>parser.command({
70
64
  ...module,
71
65
  async handler (args) {
@@ -77,7 +71,7 @@ function command$5(module) {
77
71
  }
78
72
  });
79
73
  }
80
- function getCommandName(module) {
74
+ function commandName(module) {
81
75
  if (!module.command) {
82
76
  return '[unknown]';
83
77
  }
@@ -97,47 +91,6 @@ const LOGGER = token$('Logger', ()=>logger$(withTimestamp()));
97
91
  const PATH_SCURRY = token$('PathScurry', ()=>new PathScurry('/', {
98
92
  fs
99
93
  }));
100
- /** @deprecated */ const TASK_MANAGER = token$('TaskManager', async ()=>{
101
- const manager = new TaskManager({
102
- jobs: (await inject$(CONFIG, asyncScope$())).jobs,
103
- logger: inject$(LOGGER)
104
- });
105
- let rootSpan = getActiveSpan();
106
- if (rootSpan) rootSpan = getRootSpan(rootSpan);
107
- const spans = new Map();
108
- manager.events$.on('added', (task)=>{
109
- // Main span
110
- const span = startInactiveSpan({
111
- name: task.name,
112
- parentSpan: (task.group && spans.get(task.group.id)) ?? rootSpan,
113
- op: 'task'
114
- });
115
- task.events$.on('completed', ({ status })=>{
116
- span.setStatus({
117
- code: status === 'done' ? 1 : 2
118
- });
119
- span.end();
120
- });
121
- spans.set(task.id, span);
122
- // Status spans
123
- let statusSpan = startInactiveSpan({
124
- name: task.status,
125
- parentSpan: span,
126
- op: 'task.status'
127
- });
128
- task.events$.on('status', ({ status })=>{
129
- statusSpan.end();
130
- if (!task.completed) {
131
- statusSpan = startInactiveSpan({
132
- name: status,
133
- parentSpan: span,
134
- op: 'task.status'
135
- });
136
- }
137
- });
138
- });
139
- return manager;
140
- });
141
94
  const SCHEDULER = token$('Scheduler', async ()=>{
142
95
  const config = await inject$(CONFIG, asyncScope$());
143
96
  const logger = inject$(LOGGER);
@@ -163,40 +116,44 @@ const SCHEDULER = token$('Scheduler', async ()=>{
163
116
  });
164
117
  // Status spans
165
118
  let stateSpan;
166
- const sub = job.state$.subscribe((state)=>{
167
- stateSpan?.end();
168
- if (isWorkloadEnded(state)) {
169
- jobSpan.setAttribute('job.final_state', state);
170
- jobSpan.setStatus({
171
- code: state === WorkloadState.Succeeded ? 1 : 2
172
- });
173
- jobSpan.end();
174
- sub.unsubscribe();
175
- } else {
176
- stateSpan = startInactiveSpan({
177
- op: 'job.state',
178
- name: state,
179
- parentSpan: jobSpan
180
- });
119
+ let subscription;
120
+ job.state$.subscribe({
121
+ start: (sub)=>{
122
+ subscription = sub;
123
+ },
124
+ next: (state)=>{
125
+ stateSpan?.end();
126
+ if (isWorkloadEnded(state)) {
127
+ jobSpan.setAttribute('job.final_state', state);
128
+ jobSpan.setAttribute('job.duration', job.duration().seconds());
129
+ jobSpan.setStatus({
130
+ code: state === WorkloadState.Succeeded ? 1 : 2
131
+ });
132
+ jobSpan.end();
133
+ subscription.unsubscribe();
134
+ } else {
135
+ stateSpan = startInactiveSpan({
136
+ op: 'job.state',
137
+ name: state,
138
+ parentSpan: jobSpan
139
+ });
140
+ }
181
141
  }
182
142
  });
183
143
  });
184
144
  return scheduler;
185
145
  });
186
146
 
187
- // Utils
188
- function printJson(data, stream = process.stdout) {
189
- if (stream.isTTY) {
190
- stream.write(JSON.stringify(data, null, 2));
191
- } else {
192
- stream.write(JSON.stringify(data));
193
- }
194
- }
195
-
196
147
  // Utils
197
148
  function executeCommand(module) {
198
- const prepare = trace(module.prepare, 'cli.prepare');
199
- const execute = module.execute && trace(module.execute, 'cli.execute');
149
+ const prepare = trace(module.prepare, {
150
+ name: commandName(module),
151
+ op: 'cli.prepare'
152
+ });
153
+ const execute = module.execute && trace(module.execute, {
154
+ name: commandName(module),
155
+ op: 'cli.execute'
156
+ });
200
157
  return command$5({
201
158
  ...module,
202
159
  builder (base) {
@@ -208,23 +165,14 @@ function executeCommand(module) {
208
165
  }
209
166
  },
210
167
  async handler (args) {
211
- const tasks = await prepare(args);
212
- if (args.plan) {
213
- if (args.planMode === 'json') {
214
- printJson(Array.from(plan(tasks)));
215
- } else {
216
- const { default: TaskPlanInk } = await traceImport('TaskPlanInk', ()=>import('./task-plan.ink.js'));
217
- await TaskPlanInk({
218
- tasks
219
- });
220
- }
221
- } else {
168
+ const job = await prepare(args) ?? null;
169
+ if (args.plan) ; else {
222
170
  if (execute) {
223
- await execute(args, tasks);
224
- } else if (tasks.tasks.length > 0) {
225
- const { default: TaskExecInk } = await traceImport('TaskExecInk', ()=>import('./task-exec.ink.js'));
226
- await TaskExecInk({
227
- tasks,
171
+ await execute(args, job);
172
+ } else if (job) {
173
+ const { default: JobExecInk } = await traceImport('JobExecInk', ()=>import('./job-exec.ink.js'));
174
+ await JobExecInk({
175
+ job,
228
176
  verbose: [
229
177
  'verbose',
230
178
  'debug'
@@ -239,9 +187,12 @@ function executeCommand(module) {
239
187
  }
240
188
  });
241
189
  }
242
- function planCommand(module, tasks$) {
190
+ function planCommand(module, job$) {
243
191
  if ('prepare' in module) {
244
- const prepare = trace(module.prepare, 'cli.prepare');
192
+ const prepare = trace(module.prepare, {
193
+ name: commandName(module),
194
+ op: 'cli.prepare'
195
+ });
245
196
  return command$5({
246
197
  ...module,
247
198
  builder (base) {
@@ -253,7 +204,7 @@ function planCommand(module, tasks$) {
253
204
  }
254
205
  },
255
206
  async handler (args) {
256
- tasks$.mutate(await prepare(args));
207
+ job$.mutate(await prepare(args) ?? null);
257
208
  }
258
209
  });
259
210
  } else {
@@ -305,30 +256,30 @@ class ClientError extends Error {
305
256
  }
306
257
  }
307
258
 
308
- var _dec$4, _dec1$3, _dec2$1, _initProto$4;
309
- _dec$4 = instrument('GitService.isAffected'), _dec1$3 = instrument('GitService.listBranches'), _dec2$1 = instrument('GitService.listTags');
259
+ var _dec$2, _dec1$1, _dec2, _initProto$2;
260
+ _dec$2 = instrument('GitService.isAffected'), _dec1$1 = instrument('GitService.listBranches'), _dec2 = instrument('GitService.listTags');
310
261
  class GitService {
311
262
  static{
312
- ({ e: [_initProto$4] } = _(this, [
263
+ ({ e: [_initProto$2] } = _(this, [
313
264
  [
314
- _dec$4,
265
+ _dec$2,
315
266
  2,
316
267
  "isAffected"
317
268
  ],
318
269
  [
319
- _dec1$3,
270
+ _dec1$1,
320
271
  2,
321
272
  "listBranches"
322
273
  ],
323
274
  [
324
- _dec2$1,
275
+ _dec2,
325
276
  2,
326
277
  "listTags"
327
278
  ]
328
279
  ], []));
329
280
  }
330
281
  // Attributes
331
- _scheduler = (_initProto$4(this), inject$(SCHEDULER));
282
+ _scheduler = (_initProto$2(this), inject$(SCHEDULER));
332
283
  _logger = inject$(LOGGER);
333
284
  // Methods
334
285
  /**
@@ -493,83 +444,37 @@ async function with$(lock, fn) {
493
444
  }
494
445
  }
495
446
 
496
- // Utils
497
- async function* combine(...generators) {
498
- for (const gen of generators){
499
- yield* gen;
500
- }
501
- }
502
- function streamLines$(task, stream = 'stdout') {
503
- return observable$((observer, signal)=>{
504
- const off = off$();
505
- let current = '';
506
- // End
507
- off.add(once$(task.events$, 'completed', ()=>{
508
- if (current) observer.next(current);
509
- observer.complete();
510
- off.unsubscribe();
511
- }));
512
- // Abort
513
- signal.addEventListener('abort', ()=>off.unsubscribe(), {
514
- once: true
515
- });
516
- // Steam
517
- off.add(task.events$.on(`stream.${stream}`, (chunk)=>{
518
- const data = current + chunk.data.toString('utf-8');
519
- const lines = data.split(/\r?\n/);
520
- current = lines.pop() ?? '';
521
- for (const line of lines){
522
- observer.next(line);
523
- }
524
- }));
525
- });
526
- }
527
-
528
- // Class
529
- class CommandTask extends SpawnTask {
530
- workspace;
531
- // Constructor
532
- constructor(workspace, command, args, opts = {}){
533
- let cmd = command;
534
- if (opts.superCommand) {
535
- if (typeof opts.superCommand === 'string') {
536
- opts.superCommand = [
537
- opts.superCommand
538
- ];
539
- }
540
- if (opts.superCommand.length > 0) {
541
- cmd = opts.superCommand[0];
542
- args = [
543
- ...opts.superCommand.slice(1),
544
- command,
545
- ...args
546
- ];
547
- }
447
+ function command$(workspace, cmd, args, opts = {}) {
448
+ const { superCommand, logger = inject$(LOGGER), ...rest } = opts;
449
+ // Apply super command
450
+ if (superCommand) {
451
+ if (typeof superCommand === 'string') {
452
+ args = [
453
+ cmd,
454
+ ...args
455
+ ];
456
+ cmd = superCommand;
457
+ } else if (superCommand.length) {
458
+ args = [
459
+ ...superCommand.slice(1),
460
+ cmd,
461
+ ...args
462
+ ];
463
+ cmd = superCommand[0];
464
+ }
465
+ }
466
+ // Prepare job
467
+ const job = spawn$(cmd, args, {
468
+ ...rest,
469
+ cwd: workspace.root,
470
+ env: {
471
+ FORCE_COLOR: '1',
472
+ ...rest.env
548
473
  }
549
- super(cmd, args, {
550
- workspace,
551
- command
552
- }, {
553
- ...opts,
554
- cwd: workspace.root,
555
- env: {
556
- FORCE_COLOR: '1',
557
- ...opts.env
558
- }
559
- }), this.workspace = workspace;
560
- this._logStreams();
561
- }
562
- // Methods
563
- _logStreams() {
564
- const off = off$(streamLines$(this, 'stdout').subscribe((line)=>this.logger$.info(line)), streamLines$(this, 'stderr').subscribe((line)=>this.logger$.info(line)));
565
- once$(this.events$, 'completed', ()=>{
566
- off.unsubscribe();
567
- });
568
- }
569
- }
570
- // Utils
571
- function isCommandCtx(ctx) {
572
- return 'workspace' in ctx && 'command' in ctx;
474
+ });
475
+ job.stdout.on('data', (data)=>logger.info(data.toString('utf-8').trimEnd()));
476
+ job.stderr.on('data', (data)=>logger.info(data.toString('utf-8').trimEnd()));
477
+ return job;
573
478
  }
574
479
 
575
480
  // Utils
@@ -603,173 +508,84 @@ function splitCommandLine(line) {
603
508
  return parts;
604
509
  }
605
510
 
606
- // Class
607
- class ScriptTask extends GroupTask {
608
- workspace;
609
- script;
610
- args;
611
- // Attributes
612
- _preHookTasks = null;
613
- _postHookTasks = null;
614
- _scriptTasks = null;
615
- _runHooks;
616
- // Constructor
617
- constructor(workspace, script, args, opts){
618
- super(script, {
619
- workspace,
620
- script
621
- }, opts), this.workspace = workspace, this.script = script, this.args = args;
622
- this._runHooks = opts?.runHooks ?? true;
623
- }
624
- // Methods
625
- async _runScript(script, args) {
626
- const line = this.workspace.getScript(script);
627
- if (!line) {
628
- return null;
629
- }
630
- // Create command task for script
631
- const [command, ...commandArgs] = splitCommandLine(line);
632
- const set = new TaskSet();
633
- if (!command) {
634
- return set;
635
- }
636
- if (command === 'jill') {
637
- const argv = commandArgs.map((arg)=>arg.replace(/^["'](.+)["']$/, '$1'));
638
- const { PlannerService } = await import('./planner.service.js');
639
- const plannerService = inject$(PlannerService);
640
- const tasks = await plannerService.plan(argv, this.workspace.root);
641
- if (tasks) {
642
- return tasks;
643
- }
644
- }
645
- const pm = await this.workspace.project.packageManager();
646
- set.add(new CommandTask(this.workspace, command, [
647
- ...commandArgs,
648
- ...args
649
- ], {
650
- logger: this.logger$,
651
- superCommand: pm === 'yarn' ? [
652
- 'yarn',
653
- 'exec'
654
- ] : undefined
655
- }));
656
- return set;
657
- }
658
- async prepare() {
659
- // Prepare script run
660
- this._scriptTasks = await this._runScript(this.script, this.args);
661
- if (!this._scriptTasks) {
662
- throw new ScriptNotFound(`No script ${this.script} in ${this.workspace.name}`);
663
- }
664
- // Prepare hooks run
665
- if (this._runHooks) {
666
- this._preHookTasks = await this._runScript(`pre${this.script}`, []);
667
- this._postHookTasks = await this._runScript(`post${this.script}`, []);
668
- }
669
- // Add tasks to group
670
- if (this._preHookTasks) {
671
- this.logger$.verbose(`found pre-hook script "pre${this.script}"`);
672
- for (const tsk of this._preHookTasks){
673
- this.add(tsk);
674
- }
675
- }
676
- for (const tsk of this._scriptTasks){
677
- this.add(tsk);
678
- }
679
- if (this._postHookTasks) {
680
- this.logger$.verbose(`found post-hook script "post${this.script}"`);
681
- for (const tsk of this._postHookTasks){
682
- this.add(tsk);
683
- }
684
- }
685
- }
686
- async *onOrchestrate() {
687
- if (!this._scriptTasks) {
688
- throw new Error('ScriptTask needs to be prepared. Call prepare before starting it');
689
- }
690
- // Run pre-hook
691
- if (this._preHookTasks) {
692
- yield* this._preHookTasks;
693
- if (await this._hasFailed(this._preHookTasks)) {
694
- return this.setStatus('failed');
695
- }
696
- }
697
- // Run script
698
- yield* this._scriptTasks;
699
- if (await this._hasFailed(this._scriptTasks)) {
700
- return this.setStatus('failed');
701
- }
702
- // Run post-hook
703
- if (this._postHookTasks) {
704
- yield* this._postHookTasks;
705
- if (await this._hasFailed(this._postHookTasks)) {
706
- return this.setStatus('failed');
707
- }
708
- }
709
- this.setStatus('done');
710
- }
711
- async _hasFailed(set) {
712
- const results = await waitFor$(set.events$, 'finished');
713
- return results.failed > 0;
714
- }
715
- async onStop() {
716
- if (!this._scriptTasks) return;
717
- for (const tsk of this._scriptTasks){
718
- await tsk.stop();
719
- }
720
- }
721
- complexity(cache = new Map()) {
722
- let complexity = super.complexity(cache);
723
- if (this._scriptTasks) {
724
- complexity += this._scriptTasks.tasks.reduce((cpl, tsk)=>cpl + tsk.complexity(cache), 0);
725
- }
726
- cache.set(this.id, complexity);
727
- return complexity;
728
- }
729
- // Properties
730
- get project() {
731
- return this.workspace.project;
732
- }
511
+ async function runScript$(workspace, script, args, opts = {}) {
512
+ // Run script itself
513
+ const jobs = [
514
+ await planScript$(workspace, script, args, opts)
515
+ ];
516
+ if (!jobs[0]) {
517
+ throw new ScriptNotFound(`No script ${script} in ${workspace.name}`);
518
+ }
519
+ // Run hooks
520
+ if (opts.runHooks) {
521
+ jobs.unshift(await planScript$(workspace, `pre${script}`, [], opts));
522
+ jobs.push(await planScript$(workspace, `post${script}`, [], opts));
523
+ }
524
+ // Prepare workflow
525
+ const flow = pipe$(jobs, filter$((job)=>job !== null), collect$(sequenceFlow$({
526
+ label: script,
527
+ type: 'script'
528
+ })));
529
+ return {
530
+ ...flow,
531
+ script,
532
+ workspace
533
+ };
733
534
  }
734
535
  // Utils
735
- function isScriptCtx(ctx) {
736
- return 'workspace' in ctx && 'script' in ctx;
536
+ async function planScript$(workspace, script, args, opts) {
537
+ // Load script
538
+ const line = workspace?.getScript(script);
539
+ if (!line) {
540
+ return null;
541
+ }
542
+ // Parse script
543
+ const [command, ...commandArgs] = splitCommandLine(line);
544
+ if (!command) {
545
+ return null;
546
+ }
547
+ if (command === 'jill') {
548
+ const argv = commandArgs.map((arg)=>arg.replace(/^["'](.+)["']$/, '$1'));
549
+ const { PlannerService } = await import('./planner.service.js');
550
+ const plannerService = inject$(PlannerService);
551
+ const job = await plannerService.plan(argv, workspace.root);
552
+ if (job) {
553
+ return job;
554
+ }
555
+ }
556
+ // Run command
557
+ const pm = await workspace.project.packageManager();
558
+ return command$(workspace, command, [
559
+ ...commandArgs,
560
+ ...args
561
+ ], {
562
+ logger: opts.logger,
563
+ superCommand: pm === 'yarn' ? [
564
+ 'yarn',
565
+ 'exec'
566
+ ] : undefined
567
+ });
737
568
  }
738
569
  class ScriptNotFound extends ClientError {
739
570
  name = 'ScriptNotFound';
740
571
  }
741
572
 
742
- var _dec$3, _dec1$2, _initProto$3;
743
- _dec$3 = instrument({
744
- name: 'Workspace.dependencies',
745
- use: traceAsyncGenerator
746
- }), _dec1$2 = instrument({
747
- name: 'Workspace.devDependencies',
748
- use: traceAsyncGenerator
749
- });
573
+ // Utils
574
+ async function* combine(...generators) {
575
+ for (const gen of generators){
576
+ yield* gen;
577
+ }
578
+ }
579
+
750
580
  class Workspace {
751
581
  manifest;
752
582
  project;
753
- static{
754
- ({ e: [_initProto$3] } = _(this, [
755
- [
756
- _dec$3,
757
- 2,
758
- "dependencies"
759
- ],
760
- [
761
- _dec1$2,
762
- 2,
763
- "devDependencies"
764
- ]
765
- ], []));
766
- }
767
583
  // Attributes
768
- _affectedCache = (_initProto$3(this), new Map());
584
+ _affectedCache = new Map();
769
585
  _logger;
770
586
  _git = inject$(GitService);
771
587
  _root;
772
- _tasks = new Map();
588
+ _jobs = new Map();
773
589
  // Constructor
774
590
  constructor(root, manifest, project){
775
591
  this.manifest = manifest;
@@ -778,7 +594,7 @@ class Workspace {
778
594
  this._logger = inject$(LOGGER).child(withLabel(manifest.name));
779
595
  }
780
596
  // Methods
781
- async _buildDependencies(task, opts) {
597
+ async _buildDependencies(job, opts) {
782
598
  const generators = [];
783
599
  switch(opts.buildDeps ?? 'all'){
784
600
  case 'all':
@@ -791,7 +607,7 @@ class Workspace {
791
607
  for await (const dep of combine(...generators)){
792
608
  const build = await dep.build(opts);
793
609
  if (build) {
794
- task.dependsOn(build);
610
+ job.dependsOn(build);
795
611
  }
796
612
  }
797
613
  }
@@ -856,15 +672,15 @@ class Workspace {
856
672
  }
857
673
  async build(opts = {}) {
858
674
  const script = opts.buildScript ?? 'build';
859
- const task = await this.run(script, [], opts);
860
- if (!task) {
675
+ const job = await this.run(script, [], opts);
676
+ if (!job) {
861
677
  this._logger.warning(`will not be built (no "${script}" script found)`);
862
678
  }
863
- return task;
679
+ return job;
864
680
  }
865
681
  async exec(command, args = [], opts = {}) {
866
682
  const pm = await this.project.packageManager();
867
- const task = new CommandTask(this, command, args, {
683
+ const job = command$(this, command, args, {
868
684
  ...opts,
869
685
  logger: this._logger.child(withLabel(`${this.name}$${command}`)),
870
686
  superCommand: pm === 'yarn' ? [
@@ -872,8 +688,8 @@ class Workspace {
872
688
  'exec'
873
689
  ] : undefined
874
690
  });
875
- await this._buildDependencies(task, opts);
876
- return task;
691
+ await this._buildDependencies(job, opts);
692
+ return job;
877
693
  }
878
694
  getScript(script) {
879
695
  const { scripts = {} } = this.manifest;
@@ -885,19 +701,18 @@ class Workspace {
885
701
  return null;
886
702
  }
887
703
  // Create task if it doesn't exist yet
888
- let task = this._tasks.get(script);
889
- if (!task) {
704
+ let job = this._jobs.get(script);
705
+ if (!job) {
890
706
  const config = await inject$(CONFIG, asyncScope$());
891
- task = new ScriptTask(this, script, args, {
707
+ job = await runScript$(this, script, args, {
892
708
  ...opts,
893
709
  logger: this._logger.child(withLabel(`${this.name}#${script}`)),
894
710
  runHooks: config.hooks
895
711
  });
896
- await task.prepare();
897
- await this._buildDependencies(task, opts);
898
- this._tasks.set(script, task);
712
+ await this._buildDependencies(job, opts);
713
+ this._jobs.set(script, job);
899
714
  }
900
- return task;
715
+ return job;
901
716
  }
902
717
  toJSON() {
903
718
  return {
@@ -921,43 +736,9 @@ class Workspace {
921
736
  }
922
737
  }
923
738
 
924
- var _dec$2, _dec1$1, _dec2, _dec3, _dec4, _initProto$2;
925
- _dec$2 = instrument('Project.currentWorkspace'), _dec1$1 = instrument('Project.mainWorkspace'), _dec2 = instrument('Project.packageManager'), _dec3 = instrument('Project.workspace'), _dec4 = instrument({
926
- name: 'Project.workspaces',
927
- use: traceAsyncGenerator
928
- });
929
739
  class Project {
930
- static{
931
- ({ e: [_initProto$2] } = _(this, [
932
- [
933
- _dec$2,
934
- 2,
935
- "currentWorkspace"
936
- ],
937
- [
938
- _dec1$1,
939
- 2,
940
- "mainWorkspace"
941
- ],
942
- [
943
- _dec2,
944
- 2,
945
- "packageManager"
946
- ],
947
- [
948
- _dec3,
949
- 2,
950
- "workspace"
951
- ],
952
- [
953
- _dec4,
954
- 2,
955
- "workspaces"
956
- ]
957
- ], []));
958
- }
959
740
  // Attributes
960
- _isFullyLoaded = (_initProto$2(this), false);
741
+ _isFullyLoaded = false;
961
742
  _lock = mutex$();
962
743
  _mainWorkspace;
963
744
  _packageManager;
@@ -1210,7 +991,7 @@ class TaskSyntaxError extends ClientError {
1210
991
  }
1211
992
 
1212
993
  var _dec, _dec1, _initProto;
1213
- _dec = instrument('TaskParserService.parse'), _dec1 = instrument('TaskParserService.buildTask');
994
+ _dec = instrument('TaskParserService.parse'), _dec1 = instrument('TaskParserService.buildJob');
1214
995
  // Service
1215
996
  class TaskParserService {
1216
997
  static{
@@ -1223,7 +1004,7 @@ class TaskParserService {
1223
1004
  [
1224
1005
  _dec1,
1225
1006
  2,
1226
- "buildTask"
1007
+ "buildJob"
1227
1008
  ]
1228
1009
  ], []));
1229
1010
  }
@@ -1410,42 +1191,36 @@ class TaskParserService {
1410
1191
  }
1411
1192
  }
1412
1193
  }
1413
- async buildTask(node, workspace, opts) {
1194
+ async buildJob(node, workspace, opts) {
1414
1195
  if (TaskParserService.isTaskNode(node)) {
1415
- const task = await workspace.run(node.script, node.args, opts);
1416
- if (!task) {
1196
+ const job = await workspace.run(node.script, node.args, opts);
1197
+ if (!job) {
1417
1198
  throw new TaskExpressionError(`Workspace ${workspace.name} have no ${node.script} script`);
1418
1199
  }
1419
- return task;
1200
+ return job;
1420
1201
  } else {
1421
- let group;
1202
+ let flow;
1422
1203
  if (node.operator === '//') {
1423
- group = new ParallelGroup('In parallel', {
1424
- workspace
1425
- }, {
1426
- logger: this._logger
1204
+ flow = parallelFlow$({
1205
+ label: 'In parallel'
1427
1206
  });
1428
1207
  } else if (node.operator === '||') {
1429
- group = new FallbackGroup('Fallbacks', {
1430
- workspace
1431
- }, {
1432
- logger: this._logger
1208
+ flow = fallbackFlow$({
1209
+ label: 'Fallbacks'
1433
1210
  });
1434
1211
  } else {
1435
1212
  if (node.operator === '->' && TaskParserService._sequenceOperatorWarn) {
1436
1213
  this._logger.warn('Sequence operator -> is deprecated in favor of &&. It will be removed in a next major release.');
1437
1214
  TaskParserService._sequenceOperatorWarn = true;
1438
1215
  }
1439
- group = new SequenceGroup('In sequence', {
1440
- workspace
1441
- }, {
1442
- logger: this._logger
1216
+ flow = sequenceFlow$({
1217
+ label: 'In sequence'
1443
1218
  });
1444
1219
  }
1445
1220
  for (const child of node.tasks){
1446
- group.add(await this.buildTask(child, workspace, opts));
1221
+ flow.push(await this.buildJob(child, workspace, opts));
1447
1222
  }
1448
- return group;
1223
+ return flow;
1449
1224
  }
1450
1225
  }
1451
1226
  }
@@ -1535,16 +1310,22 @@ const command$4 = {
1535
1310
  const scripts = Array.from(taskParser.extractScripts(tree));
1536
1311
  // Load workspaces
1537
1312
  const project = loadProject(args);
1538
- const workspaces = pipe$(asyncIterator$(project.workspaces()), hasEveryScript$(scripts), filters.build());
1313
+ const workspaces = await waitFor$(pipe$(asyncIterator$(project.workspaces()), hasEveryScript$(scripts), filters.build(), collect$()));
1314
+ workspaces.sort((a, b)=>a.name.localeCompare(b.name));
1315
+ if (workspaces.length === 0) {
1316
+ return;
1317
+ }
1539
1318
  // Prepare tasks
1540
- const tasks = new TaskSet();
1541
- for await (const wks of workspaces){
1542
- tasks.add(await taskParser.buildTask(tree.roots[0], wks, {
1319
+ const flow = parallelFlow$({
1320
+ label: '[hidden]'
1321
+ });
1322
+ for (const wks of workspaces){
1323
+ flow.push(await taskParser.buildJob(tree.roots[0], wks, {
1543
1324
  buildScript: args.buildScript,
1544
1325
  buildDeps: args.depsMode
1545
1326
  }));
1546
1327
  }
1547
- return tasks;
1328
+ return flow;
1548
1329
  }
1549
1330
  };
1550
1331
 
@@ -1620,51 +1401,68 @@ const command$3 = {
1620
1401
  rest.splice(0, 1);
1621
1402
  }
1622
1403
  // Run script in workspace
1623
- const tasks = new TaskSet();
1624
- tasks.add(await workspace.exec(args.command, rest, {
1404
+ return await workspace.exec(args.command, rest, {
1625
1405
  buildScript: args.buildScript,
1626
1406
  buildDeps: args.depsMode
1627
- }));
1628
- return tasks;
1407
+ });
1629
1408
  },
1630
- async execute (args, tasks) {
1631
- const task = tasks.tasks[0];
1632
- if (task.dependencies.length > 0) {
1633
- const dependencies = new TaskSet();
1634
- for (const dep of task.dependencies){
1635
- dependencies.add(dep);
1636
- }
1409
+ async execute (args, arg) {
1410
+ const job = arg;
1411
+ if (job.dependencies().length > 0) {
1412
+ const dependencies = pipe$(job.dependencies(), collect$(parallelFlow$({
1413
+ label: 'build dependencies'
1414
+ })));
1637
1415
  // Run dependencies first with spinners
1638
- const { default: TaskExecInk } = await traceImport('TaskExecInk', ()=>import('./task-exec.ink.js'));
1639
- await TaskExecInk({
1640
- tasks: dependencies,
1416
+ const { default: JobExecInk } = await traceImport('JobExecInk', ()=>import('./job-exec.ink.js'));
1417
+ await JobExecInk({
1418
+ job: dependencies,
1641
1419
  verbose: [
1642
1420
  'verbose',
1643
1421
  'debug'
1644
1422
  ].includes(args.verbose)
1645
1423
  });
1424
+ if (dependencies.state() !== WorkloadState.Succeeded) {
1425
+ return;
1426
+ }
1646
1427
  } else {
1647
1428
  const logger = inject$(LOGGER);
1648
1429
  logger.verbose('No dependency to build');
1649
1430
  }
1650
- const child = cp.spawn(task.cmd, task.args, {
1651
- stdio: 'inherit',
1652
- cwd: task.cwd,
1653
- env: {
1654
- ...process$1.env,
1655
- ...task.env
1656
- },
1657
- shell: true,
1658
- windowsHide: true
1659
- });
1660
- process$1.exitCode = await new Promise((resolve)=>{
1661
- child.on('close', (code)=>{
1662
- resolve(code ?? 0);
1431
+ await startSpan({
1432
+ op: 'subprocess',
1433
+ name: [
1434
+ job.cmd,
1435
+ ...job.args
1436
+ ].join(' ')
1437
+ }, async ()=>{
1438
+ const child = spawn(job.cmd, job.args, {
1439
+ stdio: 'inherit',
1440
+ cwd: job.cwd,
1441
+ env: {
1442
+ ...process$1.env,
1443
+ ...job.env
1444
+ },
1445
+ shell: true,
1446
+ windowsHide: true
1447
+ });
1448
+ process$1.exitCode = await new Promise((resolve)=>{
1449
+ child.on('close', (code)=>{
1450
+ resolve(code ?? 0);
1451
+ });
1663
1452
  });
1664
1453
  });
1665
1454
  }
1666
1455
  };
1667
1456
 
1457
+ // Utils
1458
+ function printJson(data, stream = process.stdout) {
1459
+ if (stream.isTTY) {
1460
+ stream.write(JSON.stringify(data, null, 2));
1461
+ } else {
1462
+ stream.write(JSON.stringify(data));
1463
+ }
1464
+ }
1465
+
1668
1466
  // Command
1669
1467
  const command$2 = {
1670
1468
  command: 'list',
@@ -1900,12 +1698,10 @@ const command$1 = {
1900
1698
  // Parse task expression
1901
1699
  const taskParser = inject$(TaskParserService);
1902
1700
  const tree = taskParser.parse(expr.join(' '));
1903
- const tasks = new TaskSet();
1904
- tasks.add(await taskParser.buildTask(tree.roots[0], workspace, {
1701
+ return await taskParser.buildJob(tree.roots[0], workspace, {
1905
1702
  buildScript: args.buildScript,
1906
1703
  buildDeps: args.depsMode
1907
- }));
1908
- return tasks;
1704
+ });
1909
1705
  }
1910
1706
  };
1911
1707
 
@@ -2115,8 +1911,8 @@ function baseParser() {
2115
1911
  }
2116
1912
  /**
2117
1913
  * Prepare parser planning commands
2118
- */ function planParser(tasks$) {
2119
- return pipe$(baseParser(), planCommand(command$4, tasks$), planCommand(command$3, tasks$), planCommand(command$2, tasks$), planCommand(command$1, tasks$), planCommand(command, tasks$));
1914
+ */ function planParser(job$) {
1915
+ return pipe$(baseParser(), planCommand(command$4, job$), planCommand(command$3, job$), planCommand(command$2, job$), planCommand(command$1, job$), planCommand(command, job$));
2120
1916
  }
2121
1917
 
2122
1918
  // Bootstrap
@@ -2125,25 +1921,37 @@ const parser = executeParser();
2125
1921
  void startSpan({
2126
1922
  name: 'jill',
2127
1923
  op: 'cli.main',
1924
+ startTime: 0,
2128
1925
  attributes: {
2129
1926
  'cli.argv': argv
2130
1927
  }
2131
- }, ()=>parser.wrap(parser.terminalWidth()).fail((msg, err)=>{
2132
- const logger = inject$(LOGGER);
2133
- if (msg) {
2134
- logger.error(msg);
2135
- } else if (err instanceof ClientError) {
2136
- logger.error(err.message);
2137
- } else {
2138
- captureException(err, {
2139
- tags: {
2140
- handled: false
2141
- }
2142
- });
2143
- logger.error(err.message);
2144
- }
2145
- process$1.exitCode = 1;
2146
- }).parseAsync(argv).catch(()=>{}));
1928
+ }, async ()=>{
1929
+ try {
1930
+ startInactiveSpan({
1931
+ name: 'bootstrap',
1932
+ op: 'cli.bootstrap',
1933
+ startTime: 0
1934
+ }).end();
1935
+ return await parser.wrap(parser.terminalWidth()).fail((msg, err)=>{
1936
+ const logger = inject$(LOGGER);
1937
+ if (msg) {
1938
+ logger.error(msg);
1939
+ } else if (err instanceof ClientError) {
1940
+ logger.error(err.message);
1941
+ } else {
1942
+ captureException(err, {
1943
+ tags: {
1944
+ handled: false
1945
+ }
1946
+ });
1947
+ logger.error(err.message);
1948
+ }
1949
+ process$1.exitCode = 1;
1950
+ }).parseAsync(argv);
1951
+ } catch {
1952
+ // Already handled
1953
+ }
1954
+ });
2147
1955
 
2148
- export { CommandTask as C, LOGGER as L, ScriptTask as S, TASK_MANAGER as T, isScriptCtx as a, CWD as b, capitalize as c, ConfigService as d, instrument as e, isCommandCtx as i, logFormat as l, planParser as p };
1956
+ export { CWD as C, LOGGER as L, SCHEDULER as S, ConfigService as a, capitalize as c, instrument as i, logFormat as l, planParser as p };
2149
1957
  //# sourceMappingURL=main.js.map