task-pipeliner 0.3.15 → 0.3.16
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/README.ko.md +1 -1
- package/README.md +1 -1
- package/dist/index.cjs +178 -203
- package/dist/index.d.cts +9 -0
- package/package.json +1 -1
package/README.ko.md
CHANGED
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,180 +1,79 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var
|
|
3
|
-
${
|
|
4
|
-
`;await(0,
|
|
5
|
-
`)
|
|
6
|
-
`),
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
"use strict";var $n=Object.create;var He=Object.defineProperty;var Rn=Object.getOwnPropertyDescriptor;var Cn=Object.getOwnPropertyNames;var En=Object.getPrototypeOf,Tn=Object.prototype.hasOwnProperty;var Dn=(t,e)=>()=>(t&&(e=t(t=0)),e);var io=(t,e)=>{for(var o in e)He(t,o,{get:e[o],enumerable:!0})},ao=(t,e,o,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Cn(e))!Tn.call(t,n)&&n!==o&&He(t,n,{get:()=>e[n],enumerable:!(r=Rn(e,n))||r.enumerable});return t};var T=(t,e,o)=>(o=t!=null?$n(En(t)):{},ao(e||!t||!t.__esModule?He(o,"default",{value:t,enumerable:!0}):o,t)),On=t=>ao(He({},"__esModule",{value:!0}),t);var uo={};io(uo,{DAEMON_DIR:()=>ge,getDaemonErrorLogPath:()=>yt,getDaemonPid:()=>St,getDaemonStartTime:()=>co,getDaemonStatus:()=>M,isDaemonRunning:()=>q,readDaemonErrorLog:()=>xt,removeDaemonPid:()=>Te,saveDaemonPid:()=>Mn,writeDaemonError:()=>bt});function In(t){try{return process.kill(t,0),!0}catch{return!1}}async function St(){try{if(!(0,ue.existsSync)(J))return null;let t=await(0,O.readFile)(J,"utf-8"),e=parseInt(t.trim(),10);return isNaN(e)?(await(0,O.unlink)(J),null):In(e)?e:(await(0,O.unlink)(J),null)}catch(t){if(t instanceof Error&&"code"in t&&t.code==="ENOENT")return null;throw t}}async function q(){return await St()!==null}async function Mn(){await(0,O.mkdir)(ge,{recursive:!0}),await(0,O.writeFile)(J,process.pid.toString(),"utf-8");let t=new Date().toISOString();await(0,O.writeFile)(Ce,t,"utf-8")}async function bt(t){try{await(0,O.mkdir)(ge,{recursive:!0});let e=`${new Date().toISOString()} ${t.message}
|
|
3
|
+
${t.stack??""}
|
|
4
|
+
`;await(0,O.writeFile)(_e,e,"utf-8")}catch{}}async function Te(){try{(0,ue.existsSync)(J)&&await(0,O.unlink)(J),(0,ue.existsSync)(Ce)&&await(0,O.unlink)(Ce)}catch{}}async function co(){try{if((0,ue.existsSync)(Ce)){let e=(await(0,O.readFile)(Ce,"utf-8")).trim();if(e)return e}if((0,ue.existsSync)(J)){let t=await(0,O.stat)(J);return new Date(t.mtime).toISOString()}return null}catch{return null}}function yt(){return _e}async function xt(){try{return(0,ue.existsSync)(_e)&&(await(0,O.readFile)(_e,"utf-8")).trim()||null}catch{return null}}async function M(){let t=await St(),e=t?await co():null;return{running:t!==null,pid:t,startTime:e}}var ue,O,lo,Ee,ge,J,Ce,_e,pe=Dn(()=>{"use strict";ue=require("fs"),O=require("fs/promises"),lo=require("os"),Ee=require("path"),ge=(0,Ee.join)((0,lo.homedir)(),".pipeliner","daemon"),J=(0,Ee.join)(ge,"scheduler.pid"),Ce=(0,Ee.join)(ge,"scheduler.started");_e=(0,Ee.join)(ge,"error.log")});var js={};io(js,{createProgram:()=>cn});module.exports=On(js);var ln=require("commander");var ur=require("fs"),pr=require("fs/promises"),mr=require("os"),dr=require("path");pe();var we=T(require("boxen"),1),F=T(require("chalk"),1),d={success:t=>F.default.green(t),error:t=>F.default.red(t),warning:t=>F.default.yellow(t),info:t=>F.default.blue(t),accent:t=>F.default.cyan(t),muted:t=>F.default.gray(t),subtle:t=>F.default.dim(t),plain:t=>F.default.white(t),strong:t=>F.default.bold(t)},y={successLine:t=>d.success(`
|
|
5
|
+
\u2713 ${t}`),errorLine:t=>d.error(`
|
|
6
|
+
\u2717 ${t}`),warningLine:t=>d.warning(`
|
|
7
|
+
\u26A0 ${t}`),cancelledLine:()=>d.warning(`
|
|
8
|
+
\u2717 Cancelled`)},ze={borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0}},me={panel:(t,e={})=>(0,we.default)(t,{...ze,...e}),error:(t,e={})=>(0,we.default)(t,{...ze,borderColor:"red",...e}),warning:(t,e={})=>(0,we.default)(t,{...ze,borderColor:"yellow",...e}),info:(t,e={})=>(0,we.default)(t,{...ze,borderColor:"cyan",...e})},p=F.default,N=we.default;function po(t,e,o,r={}){let{borderColor:n="cyan",isNested:s=!1}=r,i;e!==void 0&&(i=o?`line ${e} in ${o}`:`line ${e}`);let a=s?`\u2502 ${t}`:`> ${t}`;return me.panel(a,{title:i,borderColor:n})}function mo(t){return me.error(`\u2717 ${t}`)}function fo(t){return me.warning(`> Starting parallel execution (${t} branches)`)}function Ue(t,e=!1,o){let r=t?"\u2713 Completed":"\u2717 Failed",n=t?d.success(r):d.error(r);if(o!==void 0){let s=Se(o);return`${n} ${d.muted(`(${s})`)}`}return n}function ho(t){let e=t?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return t?d.success(e):d.error(e)}function go(t,e=!1){return`${e?"| \u2502 ":"\u2502 "}${t}`}function Se(t){return`${(t/1e3).toFixed(3)}s`}function So(t){let e=[],o=new Map;for(let n of t){let s;n.context.branchIndex!==void 0&&n.context.stepIndex>=1e3?s=Math.floor(n.context.stepIndex/1e3):s=n.context.stepIndex,o.has(s)||o.set(s,[]);let i=o.get(s);i&&i.push(n)}let r=Array.from(o.keys()).sort((n,s)=>n-s);for(let n of r){let s=o.get(n);if(s){let i=s.filter(a=>a.context.branchIndex!==void 0&&a.context.stepIndex>=1e3);if(i.length>0){i.sort((l,c)=>{let m=l.context.branchIndex??-1,h=c.context.branchIndex??-1;return m-h}),e.push(i);let a=s.filter(l=>(l.context.branchIndex===void 0||l.context.stepIndex<1e3)&&!("parallel"in l.step));a.length>0&&(a.sort((l,c)=>l.context.stepIndex-c.context.stepIndex),e.push(a))}else s.sort((a,l)=>a.context.stepIndex-l.context.stepIndex),e.push(s)}}return e}function bo(t){let e=0;for(let o of t)o.length>1?e+=Math.max(...o.map(r=>r.duration)):e+=o[0].duration;return e}function wo(t){let e=t.step,o=28;if("run"in e){let r=t.resolvedCommand??e.run;return r.length>o?`${r.substring(0,o-2)}..`:r}else if("choose"in e){let r=e.choose.message;return r.length>o?`${r.substring(0,o-2)}..`:r}else if("prompt"in e){let r=e.prompt.message;return r.length>o?`${r.substring(0,o-2)}..`:r}else{if("parallel"in e)return"Parallel";if("fail"in e){let r=e.fail.message;return r.length>o?`${r.substring(0,o-2)}..`:r}}return"Unknown"}function yo(t){return t.reduce((e,o)=>o.duration>e.duration?o:e)}function xo(t){let e=[],o=0;for(let r=0;r<t.length;r++){let n=t[r];if(n.some(a=>a.context.branchIndex!==void 0&&a.context.stepIndex>=1e3)&&n.length>=1&&n.length>0){let a=n,l=a.map(m=>({name:wo(m),startTime:o,duration:m.duration})),c=Math.max(...a.map(m=>m.duration));e.push({stepNumber:r+1,name:"Parallel",startTime:o,duration:c,isParallel:!0,parallelBranches:l}),o+=c}else{let a=n[0],c=wo(a)||"Unknown";e.push({stepNumber:r+1,name:c,startTime:o,duration:a.duration,isParallel:!1}),o+=a.duration}}return e}var kt=T(require("string-width"),1);function vt(t,e){return Ye(t)<=e}function Pt(t,e){if(t===0)return p.gray;let o=t/e;return o>=.8?p.red:o>=.5?p.yellow:p.green}function $t(t,e,o,r,n,s,i=!1,a=0,l=1,c=!1){let m=t/o,g=(t+e)/o,f=Math.round(m*r),w=Math.round(g*r);if(l>1&&e===0){let I=a*1e-4;f=Math.round((m+I)*r),w=f+1}else w<=f&&(w=f+1);f=Math.max(0,Math.min(f,r-1)),w=Math.max(f+1,Math.min(w,r));let S;if(i)S=p.cyan;else if(c)S=p.blue;else if(n===0)S=p.gray;else{let I=n/s;I>=.8?S=p.red:I>=.5?S=p.yellow:S=p.green}let b=g>=.99||w>=r?r:w,x="";for(let I=0;I<f;I++)x+=p.gray("\u2591");let P=b-f,E="\u2588".repeat(P);x+=S(E);let D=r-b;for(let I=0;I<D;I++)x+=p.gray("\u2591");return x}function Ye(t){return(0,kt.default)(t)}function be(t,e){if(Ye(t)<=e)return t;let n=e-2;if(n<1)return"..";let s=/\u001b\[[0-9;]*m/g,i=[],a;for(;(a=s.exec(t))!==null;)i.push(a[0]);let l=t.replace(s,""),c="",m=0;for(let h=0;h<l.length;h++){let g=l[h],f=(0,kt.default)(g);if(m+f>n)break;c+=g,m+=f}return c+="..",i.length>0&&c.length>0?i[0]+c+(i[i.length-1]??""):c}function te(t,e){let o=Ye(t);return o>=e?be(t,e):t+" ".repeat(e-o)}function H(t,e){let o=Ye(t);return o>=e?be(t,e):" ".repeat(e-o)+t}function ko(t,e,o){let r=process.stdout.columns||80,n=36,s=4,i=36,a=8,l=8,m=i+a+l+9,g=r-n-s-m,S=Math.max(40,Math.max(0,g-5)),v=[],b=2+i+3+a+3+l+3+S+2,x=r-n-8,P=($,R,X=!1)=>{let Re=$.replace(/\u001b\[[0-9;]*m/g,"").split("").reduce((Y,Q)=>Y+(Q.charCodeAt(0)>255?2:1),0);if(Re===R)return $;if(Re>R)return be($,R);let ie=R-Re;if(X){let Y=$.lastIndexOf("\u2524"),Q=$.lastIndexOf("\u253C",Y-1);if(Q>0&&Y>Q){let Ae=$.slice(0,Q+1),gt=$.slice(Q+1,Y),Ve=$.slice(Y);return Ae+gt+"\u2500".repeat(ie)+Ve}return $.slice(0,-1)+"\u2500".repeat(ie)+$.slice(-1)}let Fe=$.lastIndexOf("\u2502");return Fe>0?$.slice(0,Fe)+" ".repeat(ie)+$.slice(Fe):$+" ".repeat(ie)},E="\u2500".repeat(i),D="\u2500".repeat(a),I="\u2500".repeat(l),pt="\u2500".repeat(S),mt=`\u250C\u2500${E}\u2500\u252C\u2500${D}\u2500\u252C\u2500${I}\u2500\u252C\u2500${pt}\u2500\u2510`;mt=P(mt,b,!0),v.push(mt);let un=te("Step / Task",i),pn=H("Start",a),mn=te("Duration",l),dn=te("Timeline",S),dt=`\u2502 ${p.bold(un)} \u2502 ${p.bold(pn)} \u2502 ${p.bold(mn)} \u2502 ${p.bold(dn)} \u2502`;dt=P(dt,b),v.push(dt);let fn="\u2500".repeat(i),hn="\u2500".repeat(a),gn="\u2500".repeat(l),wn="\u2500".repeat(S),ft=`\u251C\u2500${fn}\u2500\u253C\u2500${hn}\u2500\u253C\u2500${gn}\u2500\u253C\u2500${wn}\u2500\u2524`;ft=P(ft,b,!0),v.push(ft);let je=new Map;for(let $=0;$<t.length;$++){let R=t[$],X=Math.round(R.startTime);je.has(X)||je.set(X,[]),je.get(X)?.push($)}for(let $=0;$<t.length;$++){let R=t[$],X=(R.startTime/1e3).toFixed(1),Re=(R.duration/1e3).toFixed(1),ie=`${p.cyan(`Step ${R.stepNumber}`)}: ${R.name}`,Y=Pt(R.duration,o)(`${Re}s`),Q=Math.round(R.startTime),Ae=je.get(Q)??[],gt=Ae.indexOf($),Ve=$t(R.startTime,R.duration,e,S,R.duration,o,!1,gt,Ae.length,R.isParallel),ae=`\u2502 ${te(ie,i)} \u2502 ${H(`${X}s`,a)} \u2502 ${H(Y,l)} \u2502 ${Ve} \u2502`;if(ae=P(ae,b),!vt(ae,x)){let le=be(ie,i);ae=`\u2502 ${te(le,i)} \u2502 ${H(`${X}s`,a)} \u2502 ${H(Y,l)} \u2502 ${Ve} \u2502`,ae=P(ae,b)}if(v.push(ae),R.isParallel&&R.parallelBranches&&R.parallelBranches.length>0)for(let le=0;le<R.parallelBranches.length;le++){let ee=R.parallelBranches[le],oo=(ee.startTime/1e3).toFixed(1),kn=(ee.duration/1e3).toFixed(1),ro=$t(ee.startTime,ee.duration,e,S,ee.duration,o,!0,0,1,!1),no=le===0?"\u2502 \u23A7 ":le===R.parallelBranches.length-1?"\u2502 \u23A9 ":"\u2502 \u251C ",wt=i-3,vn=te(p.blue(ee.name),wt),so=Pt(ee.duration,o)(`${kn}s`),ce=`${no}${vn} \u2502 ${H(`${oo}s`,a)} \u2502 ${H(so,l)} \u2502 ${ro} \u2502`;if(ce=P(ce,b),!vt(ce,x)){let Pn=be(p.blue(ee.name),wt-3);ce=`${no}${te(Pn,wt)} \u2502 ${H(`${oo}s`,a)} \u2502 ${H(so,l)} \u2502 ${ro} \u2502`,ce=P(ce,b)}v.push(ce)}}let Sn="\u2500".repeat(i),bn="\u2500".repeat(a),yn="\u2500".repeat(l),xn="\u2500".repeat(S),ht=`\u2514\u2500${Sn}\u2500\u2534\u2500${bn}\u2500\u2534\u2500${yn}\u2500\u2534\u2500${xn}\u2500\u2518`;return ht=P(ht,b,!0),v.push(ht),v.join(`
|
|
9
|
+
`)}function Je(t){if(t.records.length===0)return"";let e=So(t.records),o=bo(e),r=(o/1e3).toFixed(1),n=yo(t.records),s=t.records.indexOf(n)+1,i=(n.duration/1e3).toFixed(1),a=xo(e),l=ko(a,o,n.duration),m=`${`${p.bold("Workflow Summary")}
|
|
10
|
+
${p.cyan(`Workflow finished in ${r}s`)}
|
|
11
|
+
${p.yellow(`Slowest step: Step ${s} (${i}s)`)}`}
|
|
10
12
|
|
|
11
|
-
${
|
|
12
|
-
${(
|
|
13
|
-
|
|
14
|
-
`)
|
|
15
|
-
`)
|
|
16
|
-
`)}return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`)
|
|
20
|
-
|
|
21
|
-
`),
|
|
22
|
-
`)
|
|
23
|
-
`)
|
|
24
|
-
`),
|
|
25
|
-
`)
|
|
26
|
-
`)}),e.
|
|
27
|
-
`)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
13
|
+
${l}`;return`
|
|
14
|
+
${N(m,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"})}`}var Rt=class{showStepFooter(e,o){let r=Ue(e,!1,o);console.log(r)}showTotalExecutionTime(e){let o=Se(e);console.log(p.cyan(`
|
|
15
|
+
Total execution time: ${o}`))}showTimeline(e){let o=Je(e);o&&console.log(o)}};function Ct(){return new Rt}var Co=T(require("inquirer"),1);var vo=T(require("readline"),1);async function Po(t,e,o){return new Promise(r=>{let n="",s=0,i=[...e],a=0,l=vo.createInterface({input:process.stdin,output:process.stdout,terminal:!1});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdout.write("\x1B[?25l");let c=()=>{let f=o,w=0,S=i.length;if(i.length>f){let D=Math.floor(f/2);w=Math.max(0,s-D),S=Math.min(i.length,w+f),S===i.length&&(w=Math.max(0,S-f))}let v=n?d.muted(` Filter: ${n}`)+d.muted(` (${i.length}/${e.length})`):d.muted(" Type to filter, \u2191\u2193 to navigate, Enter to select"),b=[d.accent(`? ${t}`),v,""];if(i.length===0)b.push(d.warning(" No matches found"));else{w>0&&b.push(d.muted(` \u2191 ${w} more above`));for(let D=w;D<S;D++){let I=i[D];b.push(D===s?d.accent(`\u276F ${I.label}`):d.plain(` ${I.label}`))}S<i.length&&b.push(d.muted(` \u2193 ${i.length-S} more below`))}let x=b.length,P=a>0?a:0,E=P>0?`\x1B[${P}A\x1B[0J`:"";process.stdout.write(`${E}${b.join(`
|
|
16
|
+
`)}
|
|
17
|
+
`),a=x},m=()=>{let f=n.toLowerCase();i=f?e.filter(w=>w.label.toLowerCase().includes(f)):[...e],s>=i.length&&(s=Math.max(0,i.length-1))},h=f=>{let w=f.toString();if(w===""&&(g(),process.exit(0)),w==="\r"||w===`
|
|
18
|
+
`){i.length>0&&(g(),r(i[s]));return}if(w==="\x1B"&&f.length===1){n&&(n="",m(),c());return}if(w==="\x1B[A"){i.length>0&&(s=s>0?s-1:i.length-1,c());return}if(w==="\x1B[B"){i.length>0&&(s=s<i.length-1?s+1:0,c());return}if(w==="\x7F"||w==="\b"){n.length>0&&(n=n.slice(0,-1),m(),c());return}w.length===1&&w>=" "&&w<="~"&&(n+=w,m(),c())},g=()=>{process.stdin.removeListener("data",h),process.stdin.isTTY&&process.stdin.setRawMode(!1),l.close(),process.stdout.write("\x1B[?25h")};c(),process.stdin.on("data",h)})}var $o=T(require("inquirer"),1),De=class{async prompt(e,o){let{value:r}=await $o.default.prompt([{type:"input",name:"value",message:d.accent(e),default:o}]);return r}};var Ro=15,W=class{searchable;constructor(e=!1){this.searchable=e}async prompt(e,o){if(this.searchable)return Po(e,o,Ro);let{choice:r}=await Co.default.prompt([{type:"list",name:"choice",message:d.accent(e),choices:o.map(s=>({name:s.label,value:s.id})),pageSize:Ro}]),n=o.find(s=>s.id===r);if(!n)throw new Error(`Invalid choice: ${r}`);return n}};var Et=class{choicePrompt=new W;textPrompt=new De;async choose(e,o){return this.choicePrompt.prompt(e,o)}async text(e,o){return this.textPrompt.prompt(e,o)}};function Tt(){return new Et}var Dt=class{showSchedulerStart(e){if(e){console.log("\u{1F680} Starting scheduler daemon in background...");return}let o=p.bold("\u{1F680} Starting workflow scheduler...");console.log(N(o,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"}))}showSchedulerStarted(e,o,r){if(e){if(!r){let s=[p.green("\u2713 Scheduler daemon started"),"",p.gray(`PID: ${o}`),p.dim(" tp schedule stop stop daemon"),p.dim(" tp schedule status check status")].join(`
|
|
19
|
+
`);console.log(`${N(s,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},borderColor:"green"})}
|
|
20
|
+
`)}return}let n=[p.green("\u2713 Scheduler is running"),p.dim(" Press Ctrl+C to stop")].join(`
|
|
21
|
+
`);console.log(N(n,{borderStyle:"round",padding:{top:0,bottom:0,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"green"}))}showSchedulerStopping(e){e||console.log(`
|
|
22
|
+
\u23F9 Stopping scheduler...`)}showNoEnabledSchedules(){console.log(p.gray(` No enabled schedules to load.
|
|
23
|
+
`))}showScheduleStartFailed(e,o){console.error(p.red(` \u2717 Failed to start schedule ${e}:`),o)}showInvalidCronExpression(e,o){console.error(` \u2717 Invalid cron expression for schedule ${e}: ${o}`)}showCronScheduleFailed(e,o,r){console.error(` \u2717 Cron schedule failed for ${e} (timezone: ${o??"local"}).`,r instanceof Error?r.message:r)}showScheduledWorkflowStart(e,o){console.log(`
|
|
24
|
+
\u23F0 Running scheduled workflow: ${e}`),console.log(` Time: ${new Date().toISOString()}`),o&&console.log(` Profile: ${o}`)}showScheduledWorkflowCompleted(e){console.log(`\u2713 Scheduled workflow completed: ${e}
|
|
25
|
+
`)}showScheduledWorkflowFailed(e,o){console.error(`\u2717 Scheduled workflow failed: ${e}`),console.error(` Error: ${o instanceof Error?o.message:String(o)}
|
|
26
|
+
`)}};function Ot(){return new Dt}var It=class{createStepHeaderBox(e,o,r,n={}){return po(e,o,r,n)}createStepFooterMessage(e,o,r){return Ue(e,o,r)}createErrorBox(e){return mo(e)}formatNestedLine(e,o){return go(e,o)}createParallelHeaderBox(e){return fo(e)}createParallelFooterMessage(e){return ho(e)}};function Mt(){return new It}var A=require("fs/promises"),Eo=require("os"),de=require("path"),To=T(require("dayjs"),1),ye=(0,de.join)((0,Eo.homedir)(),".pipeliner","workflow-history"),xe=class{constructor(){}async saveHistory(e){await(0,A.mkdir)(ye,{recursive:!0});let o=(0,To.default)().format("YYYY-MM-DD_HH-mm-ss"),r=Math.random().toString(36).slice(2,6),n=(0,de.join)(ye,`workflow-${o}-${r}.json`);return await(0,A.writeFile)(n,JSON.stringify(e,null,2),{encoding:"utf8"}),n}async clearAllHistories(){await(0,A.rm)(ye,{recursive:!0,force:!0})}async removeHistory(e){await(0,A.rm)((0,de.join)(ye,e),{force:!0})}async getHistoryNames(){try{let o=(await(0,A.readdir)(ye)).map(r=>(0,de.basename)(r));return o.sort((r,n)=>{let s=l=>{let c=l.match(/workflow-(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})-/);return c?c[1]:""},i=s(r),a=s(n);return i===a?n.localeCompare(r):a.localeCompare(i)}),o}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async getHistory(e){let o=await(0,A.readFile)((0,de.join)(ye,e),{encoding:"utf8"});return JSON.parse(o)}};var qe=class{records=[];initialTimestamp=Date.now();recordStartTimestamp=Date.now();constructor(){this.records=[]}recordStart(){this.recordStartTimestamp=Date.now()}recordEnd(e,o,r,n,s){let i=this.getDuration();return this.records.push({step:e,context:o,output:r,duration:i,status:n,...s}),i}reset(){this.records=[],this.initialTimestamp=Date.now()}async save(){let e=new xe,o={initialTimestamp:this.initialTimestamp,records:this.records};return await e.saveHistory(o)}getDuration(){return Date.now()-this.recordStartTimestamp}getHistory(){return{initialTimestamp:this.initialTimestamp,records:this.records}}};var Wt=require("child_process");function Do(t,e,o){if(o&&o.length>0){let i=o[0],a=[...o.slice(1),t],l={stdio:["inherit","pipe","pipe"]};return e&&(l.cwd=e),(0,Wt.spawn)(i,a,l)}let r=process.env.SHELL??(process.platform==="win32"?"cmd.exe":"/bin/sh"),n=process.platform==="win32"?"/c":"-c",s={stdio:["inherit","pipe","pipe"]};return e&&(s.cwd=e),(0,Wt.spawn)(r,[n,t],s)}function Oo(t,e){let o=e+t,r=[],n=o;for(;n.includes(`
|
|
27
|
+
`);){let s=n.indexOf(`
|
|
28
|
+
`),i=n.substring(0,s);n=n.substring(s+1),r.push(i)}return{lines:r,remaining:n}}var Ge=class{outputPort;constructor(e){this.outputPort=e?.outputPort??{createStepHeaderBox:o=>o,createStepFooterMessage:(o,r,n)=>o?`\u2713 Completed (${n??0}ms)`:`\u2717 Failed (${n??0}ms)`,createErrorBox:o=>o,formatNestedLine:o=>o,createParallelHeaderBox:o=>`Starting parallel execution (${o} branches)`,createParallelFooterMessage:o=>o?"All parallel branches completed":"Some parallel branches failed"}}async run(e,o,r,n,s=!1,i=!1,a,l,c,m,h){return s?this.runBuffered(e,c,m,h):this.runRealtime(e,r??e,i,a,l,c,m,h)}async runBuffered(e,o,r,n){return new Promise(s=>{let i=this.spawnWithShell(e,o,n),a=[],l=[],c="",m="",h=null;r&&r>0&&(h=setTimeout(()=>{i.kill("SIGTERM");let g=`Command timed out after ${r} seconds`;l.push(g),s({success:!1,stdout:a,stderr:l})},r*1e3)),i.stdout?.on("data",g=>{let f=g.toString(),{lines:w,remaining:S}=this.processStreamBuffer(f,c);a.push(...w),c=S}),i.stderr?.on("data",g=>{let f=g.toString(),{lines:w,remaining:S}=this.processStreamBuffer(f,m);l.push(...w),m=S}),i.on("close",g=>{h&&clearTimeout(h),c.trim()&&a.push(c),m.trim()&&l.push(m),s({success:g===0,stdout:a,stderr:l})}),i.on("error",g=>{h&&clearTimeout(h);let f=`Error: ${g.message}`;s({success:!1,stdout:a,stderr:[...l,f]})})})}async runRealtime(e,o,r,n,s,i,a,l){let c=r?"green":"cyan",m=this.outputPort.createStepHeaderBox(o,n,s,{borderColor:c});console.log(m);let h=Date.now();return new Promise(g=>{let f=this.spawnWithShell(e,i,l),w="",S="",v=null;a&&a>0&&(v=setTimeout(()=>{f.kill("SIGTERM");let b=`Command timed out after ${a} seconds`,x=this.outputPort.createErrorBox(b);console.error(x);let P=Date.now()-h,E=this.outputPort.createStepFooterMessage(!1,!1,P);console.log(E),g(!1)},a*1e3)),f.stdout?.on("data",b=>{let x=b.toString(),{lines:P,remaining:E}=this.processStreamBuffer(x,w);P.forEach(D=>process.stdout.write(`\u2502 ${D}
|
|
29
|
+
`)),w=E}),f.stderr?.on("data",b=>{let x=b.toString(),{lines:P,remaining:E}=this.processStreamBuffer(x,S);P.forEach(D=>process.stderr.write(`\u2502 ${D}
|
|
30
|
+
`)),S=E}),f.on("close",b=>{v&&clearTimeout(v),w.trim()&&process.stdout.write(`\u2502 ${w}
|
|
31
|
+
`),S.trim()&&process.stderr.write(`\u2502 ${S}
|
|
32
|
+
`);let x=b===0,P=Date.now()-h,E=this.outputPort.createStepFooterMessage(x,!1,P);console.log(E),g(x)}),f.on("error",b=>{v&&clearTimeout(v);let x=this.outputPort.createErrorBox(`Error: ${b.message}`);console.error(x),g(!1)})})}createSpawnOptions(e){let o={stdio:["inherit","pipe","pipe"],shell:!0};return e&&(o.cwd=e),o}spawnWithShell(e,o,r){return Do(e,o,r)}processStreamBuffer(e,o){return Oo(e,o)}formatNestedOutput(e,o){if(o){e.split(`
|
|
33
|
+
`).forEach(r=>{r.trim()&&console.log(`| ${r}`)});return}console.log(e)}displayBufferedOutput(e,o,r=!1,n,s){let i=this.outputPort.createStepHeaderBox(o,n,s,{borderColor:"cyan",isNested:r});this.formatNestedOutput(i,r),e.stdout.forEach(l=>{let c=this.outputPort.formatNestedLine(l,r);process.stdout.write(`${c}
|
|
34
|
+
`)}),e.stderr.forEach(l=>{let c=this.outputPort.formatNestedLine(l,r);process.stderr.write(`${c}
|
|
35
|
+
`)});let a=this.outputPort.createStepFooterMessage(e.success,r);console.log(a)}};var Io=require("fs"),Mo=require("path"),fe=class{constructor(e){this.workspace=e}evaluate(e){return"var"in e||"has"in e?this.evaluateVarExists(e):"file"in e?this.evaluateFileExists(e):"choice"in e?this.evaluateChoice(e):"all"in e?this.evaluateAll(e):"any"in e?this.evaluateAny(e):"not"in e?this.evaluateNot(e):!1}evaluateVarExists(e){if(e.has)return this.workspace.hasVariable(e.has)||this.workspace.hasFact(e.has);if(!e.var)return!1;if(typeof e.var=="object"){for(let[r,n]of Object.entries(e.var)){let s=this.workspace.getVariable(r),i=this.workspace.getFact(r),a=s??(i!==void 0?i.toString():void 0);if(a===void 0||a!==n)return!1}return!0}let o=e.var;return this.workspace.hasVariable(o)||this.workspace.hasFact(o)}evaluateFileExists(e){try{let o=e.file.trim(),r=(0,Mo.resolve)(process.cwd(),o);return(0,Io.existsSync)(r)}catch{return!1}}evaluateChoice(e){return this.workspace.hasChoice(e.choice)}evaluateAll(e){return e.all.every(o=>this.evaluate(o))}evaluateAny(e){return e.any.some(o=>this.evaluate(o))}evaluateNot(e){return!this.evaluate(e.not)}};function Wn(t,e,o){if(e.hasVariable(t))return e.getVariable(t)??o;if(e.hasFact(t)){let r=e.getFact(t);return typeof r=="string"?r:String(r)}return e.hasChoice(t)?e.getChoice(t)??o:o}function V(t,e){let o=/\{\{\s*(\w+)\s*\}\}/g;return t.replace(o,(r,n)=>Wn(n,e,r))}var Ze=class t{state;constructor(){this.state={facts:new Map,choices:new Map,variables:new Map,stepResults:new Map,lastStepIndex:-1}}hasFact(e){return this.state.facts.has(e)}getFact(e){return this.state.facts.get(e)}setFact(e,o){this.state.facts.set(e,o)}getFactStatus(e){if(!this.hasFact(e))return"pending";let o=this.getFact(e);return o===!1||o==="failed"?"failed":"ready"}getAllFacts(){return new Map(this.state.facts)}hasChoice(e){return this.state.choices.has(e)}getChoice(e){return this.state.choices.get(e)}setChoice(e,o){this.state.choices.set(e,o)}hasVariable(e){return this.state.variables.has(e)}getVariable(e){return this.state.variables.get(e)}setVariable(e,o){this.state.variables.set(e,o)}getAllVariables(){return new Map(this.state.variables)}setStepResult(e,o,r){this.state.stepResults.set(e,{success:o,exitCode:r}),this.state.lastStepIndex=e}getStepResult(e){return this.state.stepResults.get(e)}getLastStepResult(){if(this.state.lastStepIndex!==-1)return this.state.stepResults.get(this.state.lastStepIndex)}clone(){let e=new t;return e.state.facts=new Map(this.state.facts),e.state.choices=new Map(this.state.choices),e.state.variables=new Map(this.state.variables),e.state.stepResults=new Map(this.state.stepResults),e.state.lastStepIndex=this.state.lastStepIndex,e}};var oe=require("path");function Wo(t){if(!t.baseDir)return t._filePath?(0,oe.dirname)(t._filePath):void 0;if((0,oe.isAbsolute)(t.baseDir))return t.baseDir;if(t._filePath){let e=(0,oe.dirname)(t._filePath);return(0,oe.resolve)(e,t.baseDir)}return(0,oe.resolve)(process.cwd(),t.baseDir)}function Bo(t,e,o){let r={workspace:o,stepIndex:t};return e._lineNumbers&&(r.lineNumber=e._lineNumbers.get(t)),e._fileName&&(r.fileName=e._fileName),r}function No(t){return t.branchIndex===void 0?t.stepIndex:Math.floor(t.stepIndex/1e3)}function Ke(t,e){if("run"in t)return{resolvedCommand:V(t.run.trim(),e)};if("choose"in t){let o=t.choose.as&&e.hasVariable(t.choose.as)?e.getVariable(t.choose.as):t.choose.options.find(r=>e.getChoice(r.id))?.id;return o!==void 0?{choiceValue:o}:void 0}if("prompt"in t){let o=e.getFact(t.prompt.as);return o!==void 0?{promptValue:o}:void 0}}function Lo(t){let e=t instanceof Error?t.message:String(t);return{success:!1,stdout:[],stderr:[e]}}var Bt=require("jsonpath-plus"),jo=require("yaml");function Fo(t,e){try{let o=e.join(`
|
|
36
|
+
`);if(!("regex"in t)&&!("json"in t)&&!("yaml"in t)&&!("yml"in t)&&!("kv"in t)&&!("after"in t)&&!("before"in t)&&!("line"in t))return o;if("regex"in t){let r=new RegExp(t.regex),n=o.match(r);return n&&n[1]?n[1]:null}if("json"in t)try{let r=JSON.parse(o),n=(0,Bt.JSONPath)({path:t.json,json:r});if(n&&n.length>0){let s=n[0];return typeof s=="string"?s:JSON.stringify(s)}return null}catch{return null}if("yaml"in t||"yml"in t)try{let r=(0,jo.parse)(o),n="yaml"in t?t.yaml:t.yml,s=(0,Bt.JSONPath)({path:n,json:r});if(s&&s.length>0){let i=s[0];return typeof i=="string"?i:JSON.stringify(i)}return null}catch{return null}if("kv"in t&&typeof t.kv=="string"){let r=t.kv.trim();if(!r)return null;for(let n of e){let s=n.trim();if(!s||s.startsWith("#"))continue;let i=`^${r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\s*=\\s*(.+)$`,a=s.match(new RegExp(i));if(a&&a[1])return a[1].trim().replace(/^["']|["']$/g,"")}return null}if("after"in t||"before"in t){let r="after"in t?t.after:"",n="before"in t?t.before:void 0;if(r){let s=o.indexOf(r);if(s===-1)return null;let i=s+r.length,a=o.length;if(n){let l=o.indexOf(n,i);if(l===-1)return null;a=l}return o.substring(i,a).trim()}if(n){let s=o.indexOf(n);return s===-1?null:o.substring(0,s).trim()}}if("line"in t){let{from:r,to:n}=t.line,s=Math.max(0,r-1),i=Math.min(e.length,n);return s>=e.length||i<=s||s<0||n<r?null:e.slice(s,i).join(`
|
|
37
|
+
`)}return null}catch{return null}}async function Ao(t,e,o,r,n){let{workspace:s,taskRunner:i,baseDir:a,globalShell:l,calculateBaseStepIndex:c}=t,m=c(o),h=V(e.run.trim(),s),g=e.shell??l,f=e.retry??0,w=f==="Infinity"||f===1/0,S=typeof f=="number"?f:0,v=e.timeout,b=!1,x=0,P=e.run.trim()!==h?`${h}
|
|
38
|
+
(template: ${e.run})`:h;for(;w||x<=S;){let E=await i.run(h,m,P,o.branchIndex,r,n,o.lineNumber,o.fileName,a,v,g),D=typeof E=="boolean"?E:E.success;if(b=E,D||!w&&x>=S)break;if(x++,w||x<=S){let I=Math.min(1e3*Math.pow(2,x-1),1e4);await new Promise(pt=>setTimeout(pt,I))}}return b}async function Vo(t,e,o,r,n){let s=await Ao(t,{run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},o,r,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:Vo(t,e.onError,o,r,n)}async function Ho(t,e,o,r=!1,n=!1){let{workspace:s}=t,i=!!(r===!0||e.captures&&e.captures.length>0),a=await Ao(t,{run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},o,i,n),l=typeof a=="boolean"?a:a.success;if(s.setStepResult(o.stepIndex,l),i&&typeof a=="object"&&"stdout"in a){let h=V(e.run.trim(),s),g=e.run.trim()!==h?`${h}
|
|
39
|
+
(template: ${e.run})`:h;t.taskRunner.displayBufferedOutput(a,g,!1,o.lineNumber,o.fileName)}if(e.captures&&typeof a=="object"&&"stdout"in a){let h=a.stdout||[];for(let g of e.captures){let f=Fo(g,h);f!==null&&g.as&&s.setVariable(g.as,f)}}if(l||!e.onError)return a;let c={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await Vo(t,c,o,r,n)}function Oe(t){let e=t;return"choose"in e&&(e.choose===null||e.choose===void 0)&&"message"in e&&"options"in e?{choose:{message:e.message,options:e.options,as:e.as},when:e.when}:"prompt"in e&&(e.prompt===null||e.prompt===void 0)&&"message"in e&&"as"in e?{prompt:{message:e.message,as:e.as,default:e.default,validate:e.validate},when:e.when}:"parallel"in e&&Array.isArray(e.parallel)?{...e,parallel:e.parallel.map(o=>Oe(o))}:t}var Nt=T(require("log-update"),1);function Bn(t,e,o){return e.parallel.map((r,n)=>({workspace:t.workspace.clone(),stepIndex:o.stepIndex*1e3+n,branchIndex:n,lineNumber:o.lineNumber,fileName:o.fileName}))}function _o(t,e){return"run"in t?t.run:"choose"in t?`Choose: ${t.choose.message}`:"prompt"in t?`Prompt: ${t.prompt.message}`:"fail"in t?`Fail: ${t.fail.message}`:`Branch ${e+1}`}function Nn(t,e){let o=0;for(let r=0;r<t.length;r++){let n=t[r],s=e[r];n.when&&!new fe(s.workspace).evaluate(n.when)||o++}return o}function Xe(t,e,o=!1){let r=t.map(n=>{let s=n.index+1,i="",a="";switch(n.status){case"pending":i="\u25CB",a=`Branch ${s}: ${n.name} - Pending`;break;case"running":i=e,a=`Branch ${s}: ${n.name} - Running...`;break;case"success":i="\u2713",a=`Branch ${s}: ${n.name} - Completed`;break;case"failed":i="\u2717",a=`Branch ${s}: ${n.name} - Failed${n.error?`: ${n.error}`:""}`;break}return`${i} ${a}`});(0,Nt.default)(r.join(`
|
|
40
|
+
`))}async function Ln(t,e,o,r){let n=[],s=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],i=0;for(let m=0;m<o.length;m++){let h=o[m],g=r[m];if(h.when&&!new fe(g.workspace).evaluate(h.when))continue;let f=e(h,m);n.push({index:m,name:f,status:"pending"})}let a=setInterval(()=>{i=(i+1)%s.length,Xe(n,s[i])},100),l=n.map(async m=>{let{index:h}=m,g=o[h],f=r[h];m.status="running";try{let w=await t.executeStep(g,f,!0);if(m.status="success",Xe(n,s[i]),t.recordBranch){let S="run"in g?{resolvedCommand:g.run}:void 0;t.recordBranch(g,f,w,"success",S)}return{index:h,result:w,context:f}}catch(w){f.workspace.setStepResult(f.stepIndex,!1);let S=w instanceof Error?w.message:String(w);if(m.status="failed",m.error=S,Xe(n,s[i]),t.recordBranch){let v="run"in g?{resolvedCommand:g.run}:void 0;t.recordBranch(g,f,void 0,"failure",v)}return{index:h,error:w,context:f}}}),c=await Promise.all(l);return clearInterval(a),Xe(n,"",!0),Nt.default.done(),c}function jn(t,e,o,r,n){let s=!0,i=!1;console.log("");for(let l of o){if(!l)continue;i=!0;let{index:c,result:m,error:h,context:g}=l;if(h){s=!1;let f=`Branch ${c+1} failed: ${h instanceof Error?h.message:String(h)}`,w=t.outputPort.createErrorBox(f);console.error(w)}else if(m&&typeof m=="object"&&"stdout"in m){let f=m;if(s=s&&f.success,f.stdout.length>0||f.stderr.length>0||!f.success){let w=r[c],S=e(w,c);t.taskRunner.displayBufferedOutput(f,S,!1,g.lineNumber,g.fileName)}}}i||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let a=t.outputPort.createParallelFooterMessage(s);return console.log(a),s}function Fn(t,e){for(let o of e){let r=o.workspace.getAllFacts(),n=o.workspace.getAllVariables();for(let[s,i]of r)t.workspace.setFact(s,i);for(let[s,i]of n)t.workspace.setVariable(s,i)}}async function zo(t,e,o){let r=Bn(t,e,o),n=Nn(e.parallel,r),s=t.outputPort.createParallelHeaderBox(n);console.log(s);let i=await Ln(t,_o,e.parallel,r),a=jn(t,_o,i,e.parallel,o);if(t.setStepResult(o.stepIndex,a),!a){let l=o.lineNumber?` (line ${o.lineNumber})`:"";throw new Error(`Parallel step ${o.stepIndex}${l} failed: one or more branches failed`)}Fn(t,r)}async function Lt(t,e,o,r={}){let n=Oe(e),s=r.bufferOutput??!1,i=r.hasWhenCondition??!1;if("run"in n){let a=await Ho({workspace:t.workspace,taskRunner:t.taskRunner,baseDir:t.baseDir,globalShell:t.globalShell,calculateBaseStepIndex:l=>t.calculateBaseStepIndex(l)},n,o,s,i);return s&&typeof a=="object"&&"stdout"in a,a}if("choose"in n){await An(t,n,o);return}if("prompt"in n){await Vn(t,n,o);return}if("parallel"in n){await zo({outputPort:t.taskRunOutputPort,workspace:t.workspace,taskRunner:t.taskRunner,executeStep:(a,l,c)=>Lt(t,a,l,{bufferOutput:c,hasWhenCondition:!!a.when}),setStepResult:(a,l)=>t.workspace.setStepResult(a,l),recordBranch:t.recorder?(a,l,c,m,h)=>{t.recorder?.recordStart();let g=h??t.getRecordResolved(a);t.recorder?.recordEnd(a,l,c,m,g)}:void 0},n,o);return}if("fail"in n){await Hn(n);return}}async function An(t,e,o){let r=e.choose.as,n=e.choose.options.map(a=>a.id);if(r&&t.workspace.hasVariable(r)){let a=t.workspace.getVariable(r)??"";if(n.includes(a)){t.workspace.setChoice(a,a),t.workspace.setStepResult(o.stepIndex,!0);return}}let s=await t.choicePrompt.prompt(e.choose.message,e.choose.options);if(!s?.id)throw new Error(`Invalid choice result: ${JSON.stringify(s)}`);let i=r??s.id;t.workspace.setChoice(s.id,s.id),t.workspace.setVariable(i,s.id),t.workspace.setStepResult(o.stepIndex,!0)}async function Vn(t,e,o){let r=e.prompt.as;if(t.workspace.hasVariable(r)){let a=t.workspace.getVariable(r)??"";t.workspace.setFact(r,a),t.workspace.setStepResult(o.stepIndex,!0);return}let n=V(e.prompt.message,t.workspace),s=e.prompt.default?V(e.prompt.default,t.workspace):void 0,i=await t.textPrompt.prompt(n,s);t.workspace.setVariable(r,i),t.workspace.setFact(r,i),t.workspace.setStepResult(o.stepIndex,!0)}async function Hn(t){let e=new Error(t.fail.message);throw e.stack=void 0,e}function Ie(t){return"run"in t}function _n(t,e){return Ie(e)?typeof t=="boolean"?t:t&&typeof t=="object"&&"success"in t?t.success:!1:!0}function Uo(t,e,o,r){if(!Ie(t))return _n(o,t);let n=r.getStepResult(e);return n?n.success:!0}function Yo(t,e,o,r){if(Ie(t)){if(t.continue===!1){let n=e.lineNumber?` (line ${e.lineNumber})`:"",s=r?`Step ${o}${n} completed, but workflow stopped due to continue: false`:`Step ${o}${n} failed`;throw new Error(s)}if(!r&&t.continue!==!0){let n=e.lineNumber?` (line ${e.lineNumber})`:"";throw new Error(`Step ${o}${n} failed`)}}}var Qe=class{workspace;taskRunner;taskRunOutputPort;executionOutputPort;baseDir;globalShell;choicePrompt;textPrompt;constructor(e){this.workspace=e.workspace??new Ze,this.taskRunner=e.taskRunner??new Ge({outputPort:e.taskRunOutputPort}),this.taskRunOutputPort=e.taskRunOutputPort,this.executionOutputPort=e.executionOutputPort,this.choicePrompt={prompt:(o,r)=>e.promptPort.choose(o,r)},this.textPrompt={prompt:(o,r)=>e.promptPort.text(o,r)}}evaluateStepCondition(e){return e.when?new fe(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return No(e)}async executeChooseStep(e,o){let r=e.choose.as,n=e.choose.options.map(a=>a.id);if(r&&this.workspace.hasVariable(r)){let a=this.workspace.getVariable(r)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(o.stepIndex,!0);return}}let s=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!s?.id)throw new Error(`Invalid choice result: ${JSON.stringify(s)}`);let i=r??s.id;this.workspace.setChoice(s.id,s.id),this.workspace.setVariable(i,s.id),this.workspace.setStepResult(o.stepIndex,!0)}async executePromptStep(e,o){let r=e.prompt.as;if(this.workspace.hasVariable(r)){let a=this.workspace.getVariable(r)??"";this.workspace.setFact(r,a),this.workspace.setStepResult(o.stepIndex,!0);return}let n=V(e.prompt.message,this.workspace),s=e.prompt.default?V(e.prompt.default,this.workspace):void 0,i=await this.textPrompt.prompt(n,s);this.workspace.setVariable(r,i),this.workspace.setFact(r,i),this.workspace.setStepResult(o.stepIndex,!0)}async executeFailStep(e){let o=new Error(e.fail.message);throw o.stack=void 0,o}applyExecutionVariables(e){if(!(!e?.executionVars||Object.keys(e.executionVars).length===0))for(let[o,r]of Object.entries(e.executionVars))this.workspace.setVariable(o,r)}handleStepResult(e,o,r,n,s){let i=Uo(e,r,n,this.workspace),a=i?"success":"failure",l=Ke(e,this.workspace),c=s.recordEnd(e,o,n,a,l);if(!Ie(e)){this.executionOutputPort.showStepFooter(i,c);return}Yo(e,o,r,i)}handleStepError(e,o,r,n,s){this.workspace.setStepResult(r,!1);let i=Lo(n),a=Ke(e,this.workspace);s.recordEnd(e,o,i,"failure",a)}async execute(e,o){this.applyExecutionVariables(o),this.baseDir=Wo(e),this.globalShell=e.shell;let r=new qe,n=Date.now();for(let a=0;a<e.steps.length;a++){let l=e.steps[a],c=Bo(a,e,this.workspace),m=!!l.when;if(this.evaluateStepCondition(l)){r.recordStart();try{let h=await Lt({workspace:this.workspace,taskRunner:this.taskRunner,taskRunOutputPort:this.taskRunOutputPort,choicePrompt:this.choicePrompt,textPrompt:this.textPrompt,baseDir:this.baseDir,globalShell:this.globalShell,recorder:r,calculateBaseStepIndex:g=>this.calculateBaseStepIndex(g),getRecordResolved:g=>Ke(g,this.workspace)},l,c,{bufferOutput:!1,hasWhenCondition:m});"parallel"in l||this.handleStepResult(l,c,a,h,r)}catch(h){throw"parallel"in l||this.handleStepError(l,c,a,h,r),h}}}let s=Date.now()-n;this.executionOutputPort.showTotalExecutionTime(s);let i=r.getHistory();this.executionOutputPort.showTimeline(i),await r.save(),r.reset()}};var ar=require("fs/promises"),lr=require("path");var tr=require("yaml"),or=require("zod");var u=require("zod"),zn=u.z.object({file:u.z.string()}),Un=u.z.object({var:u.z.union([u.z.string(),u.z.record(u.z.string(),u.z.string())]).optional(),has:u.z.string().optional()}),Yn=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),Jn=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),qn=u.z.object({choice:u.z.string()}),Gn=u.z.union([zn,qn,Un,Yn,Jn]),_=u.z.lazy(()=>u.z.union([Gn,u.z.object({all:u.z.array(_)}),u.z.object({any:u.z.array(_)}),u.z.object({not:_})])),Jo=u.z.lazy(()=>u.z.object({run:u.z.string(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),onError:Jo.optional()})),Zn=u.z.object({as:u.z.string()}),Kn=u.z.object({regex:u.z.string(),as:u.z.string()}),Xn=u.z.object({json:u.z.string(),as:u.z.string()}),Qn=u.z.object({yaml:u.z.string(),as:u.z.string()}),es=u.z.object({yml:u.z.string(),as:u.z.string()}),ts=u.z.object({kv:u.z.string(),as:u.z.string()}),os=u.z.object({after:u.z.string(),as:u.z.string()}),rs=u.z.object({before:u.z.string(),as:u.z.string()}),ns=u.z.object({after:u.z.string(),before:u.z.string(),as:u.z.string()}),ss=u.z.object({line:u.z.object({from:u.z.number(),to:u.z.number()}),as:u.z.string()}),is=u.z.union([Kn,Xn,Qn,es,ts,ns,os,rs,ss,Zn]),qo=u.z.object({run:u.z.string(),when:_.optional(),timeout:u.z.number().optional(),retry:u.z.union([u.z.number(),u.z.literal("Infinity")]).optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),continue:u.z.boolean().optional(),onError:Jo.optional(),captures:u.z.array(is).optional()}),as=u.z.object({choose:u.z.object({message:u.z.string(),options:u.z.array(u.z.object({id:u.z.string(),label:u.z.string()})),as:u.z.string().optional()}),when:_.optional()}),ls=u.z.object({prompt:u.z.object({message:u.z.string(),as:u.z.string(),default:u.z.string().optional(),validate:u.z.string().optional()}),when:_.optional()});function Go(t){if(!t||typeof t!="object")return{found:!1};let e=t;if("choose"in e)return{found:!0,type:"choose"};if("prompt"in e)return{found:!0,type:"prompt"};if("parallel"in e&&Array.isArray(e.parallel))for(let o of e.parallel){let r=Go(o);if(r.found)return r}return{found:!1}}var Zo=u.z.lazy(()=>u.z.union([qo,u.z.object({parallel:u.z.array(u.z.lazy(()=>Zo)),when:_.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:_.optional()})]).superRefine((t,e)=>{let o=Go(t);o.found&&e.addIssue({code:u.z.ZodIssueCode.custom,message:`'${o.type}' step is not allowed inside 'parallel' block (user input cannot run in parallel)`})})),cs=u.z.lazy(()=>u.z.union([qo,as,ls,u.z.object({parallel:u.z.array(Zo),when:_.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:_.optional()})])),us=u.z.object({name:u.z.string().min(1,"Profile name must be non-empty"),var:u.z.record(u.z.string(),u.z.union([u.z.string(),u.z.number(),u.z.boolean()]).transform(String))}),ps=u.z.object({name:u.z.string().optional(),baseDir:u.z.string().optional(),shell:u.z.array(u.z.string()).min(1,"shell must have at least one element").optional(),profiles:u.z.array(us).optional(),steps:u.z.array(cs).min(1,"Workflow must have at least one step")});function Ko(t){return ps.parse(t)}function jt(t){if(t.length===0)return"";let e=[];for(let o=0;o<t.length;o++){let r=t[o],n=t[o+1];r==="steps"&&typeof n=="number"?(e.push(`step ${n+1}`),o++):r==="parallel"&&typeof n=="number"?(e.push(`parallel branch ${n+1}`),o++):typeof r=="string"&&r!=="steps"&&r!=="parallel"&&e.push(r)}return e.length>0?` (${e.join(" \u2192 ")})`:""}function C(t,e,o){let r=o?`
|
|
41
|
+
Reason: ${o}`:"";throw new Error(`Invalid workflow structure:
|
|
42
|
+
- ${e} (step ${t+1})${r}`)}function Xo(t,e,o=!1,r=[]){let n=["run","choose","prompt","parallel","fail"],s=n.find(i=>i in t);if(!s){let i=Object.keys(t).filter(a=>a!=="when");C(e,`Unknown step type. Found keys: [${i.join(", ")}]. Valid types: ${n.join(", ")}`)}if(s==="run"){let i=t.run;if(typeof i!="string"&&C(e,"'run' must be a string command"),i===""&&C(e,"'run' command cannot be empty"),"shell"in t&&t.shell!==void 0){Array.isArray(t.shell)||C(e,"'shell' must be an array");let a=t.shell;a.length===0&&C(e,"'shell' cannot be empty","Shell configuration must have at least one element (program name)");for(let l=0;l<a.length;l++)typeof a[l]!="string"&&C(e,`'shell[${l}]' must be a string`)}}if(s==="choose"){if(o){let l=r.join(" \u2192 ");throw new Error(`Invalid workflow structure:
|
|
31
43
|
- 'choose' step is not allowed inside 'parallel' block (step ${e+1}, ${l})
|
|
32
|
-
Reason: User input prompts cannot run in parallel`)}let
|
|
44
|
+
Reason: User input prompts cannot run in parallel`)}let i=t.choose;(!i||typeof i!="object")&&C(e,"'choose' must be an object with 'message' and 'options'");let a=i;(!a.message||typeof a.message!="string")&&C(e,"'choose.message' is required and must be a string"),Array.isArray(a.options)||C(e,"'choose.options' is required and must be an array"),a.options.length===0&&C(e,"'choose.options' cannot be empty","At least one option is required");for(let l=0;l<a.options.length;l++){let c=a.options[l];(!c||typeof c!="object")&&C(e,`'choose.options[${l}]' must be an object with 'id' and 'label'`),(!c.id||typeof c.id!="string")&&C(e,`'choose.options[${l}].id' is required and must be a string`),(!c.label||typeof c.label!="string")&&C(e,`'choose.options[${l}].label' is required and must be a string`)}}if(s==="prompt"){if(o){let l=r.join(" \u2192 ");throw new Error(`Invalid workflow structure:
|
|
33
45
|
- 'prompt' step is not allowed inside 'parallel' block (step ${e+1}, ${l})
|
|
34
|
-
Reason: User input prompts cannot run in parallel`)}let
|
|
35
|
-
- Workflow must be an object`);let e=
|
|
46
|
+
Reason: User input prompts cannot run in parallel`)}let i=t.prompt;(!i||typeof i!="object")&&C(e,"'prompt' must be an object with 'message' and 'as'");let a=i;(!a.message||typeof a.message!="string")&&C(e,"'prompt.message' is required and must be a string"),(!a.as||typeof a.as!="string")&&C(e,"'prompt.as' is required and must be a string","The 'as' field specifies the variable name to store the user's input")}if(s==="parallel"){let i=t.parallel;Array.isArray(i)||C(e,"'parallel' must be an array of steps"),i.length===0&&C(e,"'parallel' cannot be empty","At least one step is required");for(let a=0;a<i.length;a++){let l=i[a];(!l||typeof l!="object")&&C(e,`'parallel[${a}]' must be a valid step object`);let c=[...r,`branch ${a+1}`];Xo(l,e,!0,c)}}if(s==="fail"){let i=t.fail;(!i||typeof i!="object")&&C(e,"'fail' must be an object with 'message'");let a=i;(!a.message||typeof a.message!="string")&&C(e,"'fail.message' is required and must be a string")}}function Qo(t){if(!t||typeof t!="object")throw new Error(`Invalid workflow structure:
|
|
47
|
+
- Workflow must be an object`);let e=t;if("name"in e&&e.name!==void 0&&typeof e.name!="string")throw new Error(`Invalid workflow structure:
|
|
36
48
|
- 'name' must be a string`);if("shell"in e&&e.shell!==void 0){if(!Array.isArray(e.shell))throw new Error(`Invalid workflow structure:
|
|
37
49
|
- 'shell' must be an array`);if(e.shell.length===0)throw new Error(`Invalid workflow structure:
|
|
38
50
|
- 'shell' cannot be empty
|
|
39
|
-
Reason: Shell configuration must have at least one element (program name)`);for(let
|
|
40
|
-
- 'shell[${
|
|
51
|
+
Reason: Shell configuration must have at least one element (program name)`);for(let o=0;o<e.shell.length;o++)if(typeof e.shell[o]!="string")throw new Error(`Invalid workflow structure:
|
|
52
|
+
- 'shell[${o}]' must be a string`)}if(!("steps"in e))throw new Error(`Invalid workflow structure:
|
|
41
53
|
- 'steps' is required`);if(!Array.isArray(e.steps))throw new Error(`Invalid workflow structure:
|
|
42
54
|
- 'steps' must be an array`);if(e.steps.length===0)throw new Error(`Invalid workflow structure:
|
|
43
55
|
- 'steps' cannot be empty
|
|
44
|
-
Reason: Workflow must have at least one step`);for(let
|
|
45
|
-
- Step ${
|
|
46
|
-
`);throw new Error(`Invalid workflow structure:
|
|
47
|
-
${s}`)}throw r}}extractStepLineNumbers(e){let t=new Map,r=e.split(`
|
|
48
|
-
`),s=0,i=!1;for(let n=0;n<r.length;n++){let a=r[n].trim();if(a==="steps:"||a.startsWith("steps:")){i=!0;continue}i&&a.startsWith("-")&&t.set(s++,n+1)}return t}},$t=class{parse(e){let t;try{t=JSON.parse(e)}catch(r){throw new Error(`Invalid JSON format: ${r instanceof Error?r.message:String(r)}`)}if(t&&typeof t=="object"&&"steps"in t){let r=t;Array.isArray(r.steps)&&(r.steps=r.steps.map(s=>Et(s)))}yo(t);try{return vt(t)}catch(r){if(r instanceof Rt.ZodError){let s=r.issues.map(i=>wo(i,t)).filter(i=>i!==null).join(`
|
|
56
|
+
Reason: Workflow must have at least one step`);for(let o=0;o<e.steps.length;o++){let r=e.steps[o];if(!r||typeof r!="object")throw new Error(`Invalid workflow structure:
|
|
57
|
+
- Step ${o+1} must be an object`);Xo(r,o)}}function ms(t,e){try{let o=e;for(let s of t)if(typeof s!="symbol")if(o&&typeof o=="object")o=o[s];else return null;if(!o||typeof o!="object")return null;let n=Object.keys(o);if(n.length>0){let s=["run","choose","prompt","parallel","fail"];if(!n.some(a=>s.includes(a)))return`Unknown step type. Found keys: [${n.join(", ")}]. Valid types: run, choose, prompt, parallel, fail`}return null}catch{return null}}function er(t,e){let o=t.path;if(t.code==="custom"){let n=jt(o);return` - ${t.message}${n}`}if(t.message==="Invalid input"){let n=jt(o),s=ms(o,e);return s?` - ${s}${n}`:` - Invalid step type${n}`}let r=jt(o);return` - ${t.message}${r}`}function ds(t){if(!t||typeof t!="object"||!("steps"in t))return t;let e=t;return Array.isArray(e.steps)&&(e.steps=e.steps.map(o=>Oe(o))),t}function fs(t){Qo(t);try{return Ko(t)}catch(e){if(e instanceof or.ZodError){let o=e.issues.map(r=>er(r,t)).filter(r=>r!==null).join(`
|
|
49
58
|
`);throw new Error(`Invalid workflow structure:
|
|
50
|
-
${
|
|
51
|
-
`),
|
|
52
|
-
`);
|
|
53
|
-
`)}}
|
|
54
|
-
`)
|
|
55
|
-
|
|
56
|
-
`)
|
|
57
|
-
|
|
58
|
-
`)}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`)}function yn(o){return typeof o=="object"&&o!==null&&"success"in o&&"stdout"in o&&"stderr"in o}function Sn(o){if(o.stdout.length>0){let e=o.stdout.map(t=>v.default.gray(` ${t}`)).join(`
|
|
63
|
-
`);console.log(v.default.green(" Output:")),console.log(e)}if(o.stderr.length>0){let e=o.stderr.map(t=>v.default.gray(` ${t}`)).join(`
|
|
64
|
-
`);console.log(v.default.red(" Errors:")),console.log(e)}}var Qo=require("commander");var Fo=require("child_process"),Ke=require("fs"),Wo=require("fs/promises"),B=require("path"),Vo=x(require("boxen"),1),D=x(require("chalk"),1),Qe=x(require("inquirer"),1),Ho=x(require("node-cron"),1);ge();var Co=require("fs/promises"),Do=require("path"),To=require("yaml"),Io=require("zod");var F=require("zod"),xn=F.z.object({name:F.z.string().min(1,"Schedule name must be non-empty"),cron:F.z.string().min(1,"Cron expression is required"),workflow:F.z.string().min(1,"Workflow path is required"),baseDir:F.z.string().optional(),timezone:F.z.union([F.z.string(),F.z.number()]).transform(String).optional(),silent:F.z.boolean().optional(),profile:F.z.string().optional()}),vn=F.z.object({schedules:F.z.array(xn).min(1,"Schedule file must have at least one schedule")});function Po(o){return vn.parse(o)}async function Mo(o){let e=await(0,Co.readFile)(o,"utf-8"),t=(0,Do.extname)(o).toLowerCase(),r;try{if(t===".yaml"||t===".yml")r=(0,To.parse)(e);else if(t===".json")r=JSON.parse(e);else throw new Error(`Unsupported file format: ${t}. Use .yaml, .yml, or .json`)}catch(s){if(s instanceof Error&&s.message.startsWith("Unsupported"))throw s;let i=t===".json"?"JSON":"YAML";throw new Error(`Invalid ${i} format: ${s instanceof Error?s.message:String(s)}`)}try{return Po(r)}catch(s){if(s instanceof Io.ZodError){let i=s.issues.map(n=>` - ${n.message} (${n.path.join(".")})`).join(`
|
|
65
|
-
`);throw new Error(`Invalid schedule file structure:
|
|
66
|
-
${i}`)}throw s}}var No=x(require("boxen"),1),E=x(require("chalk"),1),jo=x(require("cronstrue"),1),Tt=x(require("dayjs"),1),It=x(require("node-cron"),1);function Mt(o){try{return jo.default.toString(o)}catch{return null}}function kn(o){if(!It.default.validate(o.cron))return null;try{let e={},t=Ge(o.timezone);t&&(e.timezone=t);let r=It.default.createTask(o.cron,()=>{},e),s=r.getNextRun();return r.destroy(),s}catch{return null}}function ee(o,e){let t=o,{daemonRunning:r,emphasizeState:s}=e,i=t.enabled?s?E.default.bold.green("ENABLED"):E.default.green("enabled"):s?E.default.bold.gray("DISABLED"):E.default.gray("disabled"),n=r&&t.enabled,a=n?E.default.green("\u25CF active"):E.default.gray("\u25CB inactive"),l=s?t.enabled?E.default.bold.green(" [ENABLED]"):E.default.bold.gray(" [DISABLED]"):"",c=E.default.bold(t.name??t.workflowPath),d=kn(t),f=d?(0,Tt.default)(d).format("YYYY-MM-DD HH:mm:ss"):E.default.dim("\u2014"),m=t.lastRun?(0,Tt.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):E.default.dim("never"),p=Mt(t.cron),h=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,g=h??"local",b=p?`${t.cron} ${E.default.dim(`\u2192 ${p} (${g})`)}`:t.cron,y=[[E.default.gray("Enabled"),i],[E.default.gray("Cron"),b],[E.default.gray("Timezone"),h??E.default.dim("local")],[E.default.gray("Workflow"),t.workflowPath],...t.profile?[[E.default.gray("Profile"),E.default.cyan(t.profile)]]:[],...t.silent?[[E.default.gray("Silent"),E.default.yellow("yes")]]:[],[E.default.gray("Last run"),m],[E.default.gray("Next run"),f]],S=[`${c} ${a}${l}`,...y.map(([I,M])=>` ${I.padEnd(10)} ${M}`)].join(`
|
|
67
|
-
`);return(0,No.default)(S,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:n?"green":"gray"})}var q=require("fs"),L=require("path"),Nt=require("url"),Ao={};function Bo(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function Oo(){return"0.3.15"}function Xe(o){let e=o?(0,L.resolve)(o):process.cwd(),t=50,r=0;for(;r<t;){let s=(0,L.resolve)(e,"tp");try{if((0,q.existsSync)(s)&&(0,q.statSync)(s).isDirectory())return s}catch{}let i=(0,L.dirname)(e);if(i===e)break;e=i,r++}return null}function Lo(o){let e={};for(let t of o){let r=t.indexOf("=");if(r===-1)throw new Error(`Invalid -v/--var format: "${t}". Use key=value (e.g. -v version=1.0.0).`);let s=t.slice(0,r).trim(),i=t.slice(r+1).trim();if(!s)throw new Error(`Invalid -v/--var format: key is empty in "${t}". Use key=value.`);e[s]=i}return e}function jt(o,e){let t=e.workflow;if((0,B.isAbsolute)(t))return t;let r=e.baseDir?(0,B.resolve)(e.baseDir):(0,B.dirname)(o);return(0,B.resolve)(r,t)}function _o(o,e="plain"){let t=o.name??"(no alias)",r=(0,B.basename)(o.workflowPath),s=Mt(o.cron)??o.cron,i=e==="color"?o.enabled?D.default.green("Enabled"):D.default.dim("Disabled"):o.enabled?"\u2713":"\u2717";return`${t} \xB7 ${r} \xB7 ${o.cron} \xB7 ${s} \xB7 ${i}`}async function Uo(o){let e=new V;if(!o){let l=Xe();l||(console.error(D.default.red(`
|
|
68
|
-
\u2717 No tp directory found`)),process.exit(1));let c=(0,B.join)(l,"schedules");(0,Ke.existsSync)(c)||(console.error(D.default.red(`
|
|
69
|
-
\u2717 No schedules directory found at ${c}`)),process.exit(1));let f=(await(0,Wo.readdir)(c)).filter(g=>{let b=(0,B.extname)(g).toLowerCase();return[".yaml",".yml",".json"].includes(b)});f.length===0&&(console.error(D.default.red(`
|
|
70
|
-
\u2717 No schedule files found in ${c}`)),process.exit(1));let m=f.map(g=>({id:(0,B.join)(c,g),label:g}));o=(await new O(!0).prompt("Select a schedule file to add",m)).id}let t=(0,B.resolve)(o);(0,Ke.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let r;try{r=await Mo(t)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),process.exit(1)}let s=r.schedules.filter(l=>!Ho.default.validate(l.cron));if(s.length>0){console.error("\u2717 Invalid cron expression(s):");for(let l of s)console.error(` - ${l.name}: "${l.cron}"`);process.exit(1)}let i=r.schedules.filter(l=>{let c=jt(t,l);return!(0,Ke.existsSync)(c)});if(i.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of i){let c=jt(t,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}process.exit(1)}console.log(`
|
|
71
|
-
Found ${r.schedules.length} schedule(s) in file.
|
|
72
|
-
`);let n=[];for(let l of r.schedules){let{alias:c}=await Qe.default.prompt([{type:"input",name:"alias",message:`Alias for "${l.name}" (press Enter to use as-is):`,default:l.name}]),d=await e.addSchedule({name:c,workflowPath:jt(t,l),cron:l.cron,enabled:!0,timezone:l.timezone,silent:l.silent,profile:l.profile});n.push(d)}let a=await j();console.log(`
|
|
73
|
-
\u2713 Added ${n.length} schedule(s) successfully
|
|
74
|
-
`);for(let l of n)console.log(ee(l,{daemonRunning:a.running}));console.log(D.default.dim(' Tip: Run "tp schedule start" to start the scheduler daemon'))}async function zo(){let o=new V,e=await o.loadSchedules();if(e.length===0){console.log("No schedules found");return}let t=e.map(c=>({id:c.id,label:_o(c)})),i=(await new O(!0).prompt("Select schedule to remove:",t)).id,n=e.find(c=>c.id===i),{confirm:a}=await Qe.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove this schedule?",default:!1}]);if(!a){console.log("Cancelled");return}let l=await o.removeSchedule(i);if(l&&n){let c=await j();console.log(`
|
|
75
|
-
\u2713 Schedule removed
|
|
76
|
-
`),console.log(ee(n,{daemonRunning:c.running}))}else console.log(l?"\u2713 Schedule removed successfully":"\u2717 Schedule not found")}async function At(){let e=await new V().loadSchedules();if(e.length===0){let n=[D.default.gray("No schedules registered."),"",D.default.dim(" tp schedule add <schedule.yaml> add from a schedule file")].join(`
|
|
77
|
-
`);console.log(`
|
|
78
|
-
${(0,Vo.default)(n,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"})}
|
|
79
|
-
`);return}let t=await j(),r=t.running?D.default.green("\u25CF running"):D.default.gray("\u25CB stopped"),s=e.filter(n=>n.enabled).length,i=D.default.bold("\u{1F4C5} Workflow Schedules");console.log(i),console.log([D.default.gray(" Daemon: "),r,D.default.gray(` \xB7 Schedules: ${s}/${e.length} enabled`)].join(""));for(let n of e)console.log(ee(n,{daemonRunning:t.running}));console.log(D.default.dim(" Tip: tp schedule start \u2014 run scheduler daemon; tp schedule status \u2014 view live status"))}async function Yo(o){if(await Y()){let e=await j();console.error(`\u2717 Scheduler daemon is already running (PID: ${e.pid})`),console.error(' Run "tp schedule stop" to stop it first'),process.exit(1)}if(o)if(process.env.TP_DAEMON_MODE==="true")try{let{saveDaemonPid:e}=await Promise.resolve().then(()=>(ge(),_t));await e(),await new Q().start(!0),await new Promise(()=>{})}catch(e){await pt(e instanceof Error?e:new Error(String(e))),process.exit(1)}else{let e=process.argv.slice(1);(0,Fo.spawn)(process.argv[0],e,{detached:!0,stdio:"ignore",env:{...process.env,TP_DAEMON_MODE:"true"}}).unref();let r=3,s=800,i=!1;for(let n=0;n<r;n++)if(await new Promise(a=>setTimeout(a,s)),await Y()){i=!0;break}if(i){let n=await j();console.log(`\u2713 Scheduler daemon started in background (PID: ${n.pid})`),console.log(' Run "tp schedule stop" to stop the daemon'),console.log(' Run "tp schedule status" to check daemon status')}else{console.error("\u2717 Failed to start scheduler daemon");let n=await mt();n?(console.error(D.default.dim(" Last error from daemon:")),console.error(D.default.red(n.split(`
|
|
80
|
-
`).map(a=>` ${a}`).join(`
|
|
81
|
-
`)))):console.error(D.default.dim(` Check ${dt()} for details`)),process.exit(1)}process.exit(0)}else await new Q().start(!1,{onScheduleStarted:t=>console.log(ee(t,{daemonRunning:!0}))}),await new Promise(()=>{})}async function Jo(){let o=await j();if(!o.running){console.log("Scheduler daemon is not running");return}console.log(`Stopping scheduler daemon (PID: ${o.pid})...`);let t=await new Q().stopDaemon();console.log(t?"\u2713 Scheduler daemon stopped":"\u2717 Failed to stop scheduler daemon (process may have already exited)")}async function qo(){let o=new V,e=await o.loadSchedules();if(e.length===0){console.log("No schedules found");return}let t=e.map(m=>({id:m.id,label:_o(m,"color")})),i=(await new O(!0).prompt("Select schedule to toggle:",t)).id,n=e.find(m=>m.id===i);if(!n){console.log("\u2717 Schedule not found");return}let a=!n.enabled;await o.toggleSchedule(i,a);let l=await j(),c={...n,enabled:a},d=a?D.default.bold.green("ENABLED"):D.default.bold.gray("DISABLED"),f=a?D.default.dim(" (will run at the times shown below)"):D.default.dim(" (will not run until you enable it again)");console.log(`
|
|
82
|
-
\u2713 Schedule is now ${d}${f}
|
|
83
|
-
`),console.log(ee(c,{daemonRunning:l.running,emphasizeState:!0}))}async function Go(){let o=new V,e=await o.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{confirm:t}=await Qe.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to remove all ${e.length} schedule(s)?`,default:!1}]);if(!t){console.log("Cancelled");return}await o.saveSchedules([]),console.log(`\u2713 Removed all ${e.length} schedule(s)`)}var Bt=x(require("boxen"),1),$=x(require("chalk"),1),et=x(require("dayjs"),1),Me=x(require("log-update"),1);ge();function $n(o){if(!o)return"Unknown";let e=(0,et.default)(o),r=(0,et.default)().diff(e,"second"),s=Math.floor(r/86400),i=Math.floor(r%86400/3600),n=Math.floor(r%3600/60),a=r%60,l=[];return s>0&&l.push(`${s}d`),i>0&&l.push(`${i}h`),n>0&&l.push(`${n}m`),(a>0||l.length===0)&&l.push(`${a}s`),l.join(" ")}function Rn(o,e){return ee(o,{daemonRunning:e})}async function Zo(){let o=await j(),t=await new V().loadSchedules(),r=[],s;if(o.running&&o.pid){let n=$n(o.startTime),a=o.startTime?(0,et.default)(o.startTime).format("YYYY-MM-DD HH:mm:ss"):"Unknown";s=[`${$.default.green("\u25CF")} ${$.default.green("active")} ${$.default.gray("(running)")}`,"",`${$.default.gray("Loaded:")} ${$.default.white(a)}`,`${$.default.gray("Active:")} ${$.default.green("active (running)")} since ${$.default.white(a)}`,`${$.default.gray("PID:")} ${$.default.white(o.pid.toString())}`,`${$.default.gray("Uptime:")} ${$.default.white(n)}`].join(`
|
|
84
|
-
`)}else s=[`${$.default.red("\u25CF")} ${$.default.red("inactive")} ${$.default.gray("(dead)")}`,"",`${$.default.gray("Loaded:")} ${$.default.gray("not found")}`,`${$.default.gray("Active:")} ${$.default.red("inactive (dead)")}`].join(`
|
|
85
|
-
`);let i=(0,Bt.default)(s,{title:$.default.bold("task-pipeliner-scheduler.service"),titleAlignment:"left",borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:1,bottom:0,left:0,right:0},borderColor:o.running?"green":"red"});if(r.push(i),t.length>0){let n=t.filter(l=>l.enabled).length,a=$.default.bold(`Schedules: ${n}/${t.length} enabled`);r.push(a);for(let l of t)r.push(Rn(l,o.running))}else{let n=(0,Bt.default)($.default.gray("No schedules configured"),{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"});r.push(n)}return`
|
|
86
|
-
|
|
87
|
-
${r.join(`
|
|
88
|
-
`)}`}function Xo(){process.stdout.write("\x1B[2J\x1B[H")}var En=2,Pn=24;function Cn(){let o=typeof process.stdout.rows=="number"?process.stdout.rows:Pn;return Math.max(5,o-En)}function Dn(o){let e=o.toString("utf8");return e==="\x1B[A"?"up":e==="\x1B[B"?"down":e==="\x1B[5~"?"pageup":e==="\x1B[6~"?"pagedown":e==="\x1B[H"||e==="\x1B[1~"?"home":e==="\x1B[4~"||e==="\x1B[F"?"end":null}async function Ko(o){if(o){let e=process.stdin.isTTY&&process.stdout.isTTY,t=Cn(),r=!0,s=[],i="",n=0,a=()=>{let f=s.length,m=Math.max(0,f-t);n=Math.min(n,m);let h=s.slice(n,n+t).join(`
|
|
89
|
-
`),g=f>t?$.default.dim(` [${n+1}-${Math.min(n+t,f)}/${f}] \u2191/\u2193 PgUp/PgDn: scroll`):"";(0,Me.default)(`${h}
|
|
90
|
-
${i}${g}`)},l=()=>{r=!1,e&&process.stdin.isTTY&&(process.stdin.setRawMode(!1),process.stdin.pause()),Me.default.done(),process.exit(0)};process.on("SIGINT",l),process.on("SIGTERM",l),e&&process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",f=>{let m=typeof f=="string"?Buffer.from(f,"utf8"):f;if(m.length===1&&m[0]===3){l();return}let p=Dn(m);if(!p||s.length<=t){p&&a();return}let h=Math.max(0,s.length-t);switch(p){case"up":n=Math.max(0,n-1);break;case"down":n=Math.min(h,n+1);break;case"pageup":n=Math.max(0,n-t);break;case"pagedown":n=Math.min(h,n+t);break;case"home":n=0;break;case"end":n=h;break}a()}));let c=async()=>{try{let f=await Zo(),m=await j();if(i=m.running?$.default.gray(`
|
|
91
|
-
Ctrl+C: exit (daemon keeps running)`):$.default.gray(`
|
|
92
|
-
Tip: tp schedule start -d to start daemon. Ctrl+C: exit.`),s=f.split(`
|
|
93
|
-
`),e)a();else{let p=m.running?$.default.gray(`
|
|
94
|
-
Press Ctrl+C to exit (daemon keeps running in background)`):$.default.gray(`
|
|
95
|
-
Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit.`);(0,Me.default)(`${f}${p}`)}}catch(f){Me.default.done(),console.error("Error updating status:",f),process.exit(1)}},d=setInterval(async()=>{if(!r){clearInterval(d);return}await c()},1e3);Xo(),await c(),await new Promise(()=>{})}else{Xo();let e=await Zo(),r=(await j()).running?"":$.default.gray(`
|
|
96
|
-
Tip: To start the daemon, run: tp schedule start -d`);console.log(`${e}${r}
|
|
97
|
-
`)}}function er(){let o=new Qo.Command("schedule").description("Manage workflow schedules").action(async()=>{await At()});return o.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON). If no file given, select from nearest tp/schedules directory.").action(async e=>{await Uo(e)}),o.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await zo()}),o.command("remove-all").description("Remove all workflow schedules").action(async()=>{await Go()}),o.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await At()}),o.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await Yo(e.daemon??!1)}),o.command("stop").description("Stop the scheduler daemon").action(async()=>{await Jo()}),o.command("status").description('View daemon and schedule status (does not start the daemon). In live mode, Ctrl+C only exits the status view; the daemon keeps running if it was started with "tp schedule start -d".').option("-n, --no-follow","Show status once and exit (no live refresh)").action(async e=>{let t=e.follow!==!1;await Ko(t)}),o.command("toggle").description("Enable or disable a schedule").action(async()=>{await qo()}),o}var tr=[{filename:"example-hello.yaml",content:`name: Hello World (with choose)
|
|
98
|
-
|
|
99
|
-
# Interactive choice: stored as variable and used in later steps
|
|
100
|
-
steps:
|
|
101
|
-
- run: 'echo "Hello from task-pipeliner"'
|
|
102
|
-
- choose:
|
|
103
|
-
message: "Select action:"
|
|
104
|
-
options:
|
|
105
|
-
- id: greet
|
|
106
|
-
label: "Greet"
|
|
107
|
-
- id: info
|
|
108
|
-
label: "Show info"
|
|
109
|
-
as: action
|
|
110
|
-
- run: 'echo "You chose: {{ action }}"'
|
|
111
|
-
- when:
|
|
112
|
-
var:
|
|
113
|
-
action: greet
|
|
114
|
-
run: 'echo "Hi there! Edit tp/workflows and run: tp run tp/workflows/example-hello.yaml"'
|
|
115
|
-
- when:
|
|
116
|
-
var:
|
|
117
|
-
action: info
|
|
118
|
-
run: 'echo "Tip: Use --profile. See example-build.yaml for profiles."'
|
|
119
|
-
`},{filename:"example-build.yaml",content:`name: Example Build (with profiles and choose)
|
|
120
|
-
|
|
121
|
-
# Profiles: run without prompts via "tp run tp/workflows/example-build.yaml --profile Dev"
|
|
122
|
-
# With profile, choose/prompt are skipped and these variables are used.
|
|
123
|
-
profiles:
|
|
124
|
-
- name: Dev
|
|
125
|
-
var:
|
|
126
|
-
mode: dev
|
|
127
|
-
label: "dev-build"
|
|
128
|
-
- name: Prod
|
|
129
|
-
var:
|
|
130
|
-
mode: prod
|
|
131
|
-
label: "prod-build"
|
|
59
|
+
${o}`)}throw e}}function rr(t,e,o){let r;try{r=o(t)}catch(s){throw new Error(`Invalid ${e} format: ${s instanceof Error?s.message:String(s)}`)}let n=ds(r);return fs(n)}var et=class{parse(e){return rr(e,"YAML",o=>(0,tr.parse)(o))}extractStepLineNumbers(e){let o=new Map,r=e.split(`
|
|
60
|
+
`),n=0,s=!1;for(let i=0;i<r.length;i++){let a=r[i].trim();if(a==="steps:"||a.startsWith("steps:")){s=!0;continue}s&&a.startsWith("-")&&o.set(n++,i+1)}return o}},Ft=class{parse(e){return rr(e,"JSON",o=>JSON.parse(o))}extractStepLineNumbers(e){let o=new Map,r=e.split(`
|
|
61
|
+
`),n=0,s=!1,i=!1;for(let a=0;a<r.length;a++){let c=r[a].trim();if(c.startsWith('"steps"')||c.startsWith("'steps'")){s=!0,c.includes("[")&&(i=!0);continue}if(s&&c==="["){i=!0;continue}if(i&&c==="]"){i=!1,s=!1;continue}i&&c.startsWith("{")&&o.set(n++,a+1)}return o}};function ke(t){switch(t.toLowerCase().split(".").pop()){case"yaml":case"yml":return new et;case"json":return new Ft;default:return new et}}var Vt=T(require("node-cron"),1);pe();var ve=require("fs/promises"),sr=require("os"),At=require("path"),ir=(0,At.join)((0,sr.homedir)(),".pipeliner","schedules"),nr=(0,At.join)(ir,"schedules.json"),z=class{async loadSchedules(){try{let e=await(0,ve.readFile)(nr,"utf-8");return JSON.parse(e).schedules||[]}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async saveSchedules(e){await(0,ve.mkdir)(ir,{recursive:!0}),await(0,ve.writeFile)(nr,JSON.stringify({schedules:e},null,2),"utf-8")}async addSchedule(e){let o=await this.loadSchedules(),r=Math.random().toString(36).slice(2,10),n=new Date().toISOString(),s={id:r,createdAt:n,...e};return o.push(s),await this.saveSchedules(o),s}async removeSchedule(e){let o=await this.loadSchedules(),r=o.length,n=o.filter(s=>s.id!==e);return n.length===r?!1:(await this.saveSchedules(n),!0)}async updateLastRun(e){let o=await this.loadSchedules(),r=o.find(n=>n.id===e);r&&(r.lastRun=new Date().toISOString(),await this.saveSchedules(o))}async toggleSchedule(e,o){let r=await this.loadSchedules(),n=r.find(s=>s.id===e);return n?(n.enabled=o,await this.saveSchedules(r),!0):!1}async getSchedule(e){return(await this.loadSchedules()).find(r=>r.id===e)}};var hs=/^([+-])?(\d{1,2})(?::(\d{2}))?$/;function gs(t){let e=t.trim();if(e===""||e==="0"||e==="+0"||e==="-0")return 0;let o=e.match(hs);if(!o)return null;let r=o[1],n=parseInt(o[2],10);if(n>14)return null;let i=r==="-"?-n:n;return i<-12||i>14?null:i}function ws(t){if(t===0)return"UTC";let e=t>0?"-":"+",o=Math.abs(t);return`Etc/GMT${e}${o}`}function tt(t){if(!t?.trim())return;let e=gs(t);if(e!==null)return ws(e)}var ot=class{scheduleManager;tasks=new Map;startOptions;executorFactory;schedulerOutputPort;constructor(e){this.scheduleManager=e.scheduleManager??new z,this.executorFactory=e.executorFactory,this.schedulerOutputPort=e.schedulerOutputPort}async start(e=!1,o){if(this.startOptions=o,!e&&await q()){let r=await M();throw new Error(`Scheduler daemon is already running (PID: ${r.pid}). Use "tp schedule stop" to stop it first.`)}this.schedulerOutputPort.showSchedulerStart(e),await this.reload(),this.schedulerOutputPort.showSchedulerStarted(e,process.pid,!!process.env.TP_DAEMON_MODE)}async reload(){this.stop();let o=(await this.scheduleManager.loadSchedules()).filter(r=>r.enabled);if(o.length===0){this.schedulerOutputPort.showNoEnabledSchedules();return}for(let r of o)try{this.startSchedule(r)}catch(n){this.schedulerOutputPort.showScheduleStartFailed(r.id,n)}}startSchedule(e){if(!Vt.default.validate(e.cron)){this.schedulerOutputPort.showInvalidCronExpression(e.id,e.cron);return}let o={},r=tt(e.timezone);r&&(o.timezone=r);let n;try{n=Vt.default.schedule(e.cron,async()=>{await this.executeSchedule(e)},o)}catch(s){throw this.schedulerOutputPort.showCronScheduleFailed(e.id,r,s),s}this.tasks.set(e.id,n),this.startOptions?.onScheduleStarted?.(e)}async executeSchedule(e){let o=e.name??e.workflowPath;e.silent||this.schedulerOutputPort.showScheduledWorkflowStart(o,e.profile);try{let r=(0,lr.resolve)(e.workflowPath),n=ke(r),s=await(0,ar.readFile)(r,"utf-8"),i=n.parse(s);i._filePath=r,i._fileName=r.split(/[/\\]/).pop()??"workflow";let a=this.executorFactory.createExecutor(),l={};if(e.profile){if(!i.profiles)throw new Error(`Profile "${e.profile}" not found: no profiles defined in workflow`);let c=i.profiles.find(m=>m.name===e.profile);if(!c)throw new Error(`Profile "${e.profile}" not found. Available profiles: ${i.profiles.map(m=>m.name).join(", ")}`);l.executionVars={...c.var}}await a.execute(i,l),await this.scheduleManager.updateLastRun(e.id),e.silent||this.schedulerOutputPort.showScheduledWorkflowCompleted(o)}catch(r){e.silent||this.schedulerOutputPort.showScheduledWorkflowFailed(o,r)}}stop(){for(let e of this.tasks.values())e.stop();this.tasks.clear()}async shutdown(e){this.schedulerOutputPort.showSchedulerStopping(e),this.stop(),await Te()}async stopDaemon(){let e=await M();if(!e.running||!e.pid)return!1;let o=e.pid;try{if(process.kill(o,"SIGTERM"),await new Promise(r=>setTimeout(r,1e3)),await q()){try{process.kill(o,"SIGKILL")}catch{}await new Promise(r=>setTimeout(r,500))}return await Te(),!0}catch{return await Te(),!1}}};function rt(){return new Qe({promptPort:Tt(),executionOutputPort:Ct(),taskRunOutputPort:Mt()})}function cr(){return{createExecutor:()=>rt()}}function re(){return new ot({executorFactory:cr(),schedulerOutputPort:Ot()})}var Me=class extends Error{exitCode;handled;constructor(e,o=1,r=!1){super(e),this.name="CliCommandError",this.exitCode=o,this.handled=r}};function k(t=1){throw new Me("",t,!0)}async function ne(t){await t()}var We=(0,dr.join)((0,mr.homedir)(),".pipeliner");function fr(t){t.command("clean").description("Remove all data in ~/.pipeliner (schedules, daemon state, workflow history). Use after upgrades if data is incompatible.").action(()=>ne(async()=>{if((await new W().prompt(`This will remove all data in ${d.warning(We)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(y.cancelledLine());return}try{if(await q()){let r=await M();console.log(d.muted(`Stopping scheduler daemon (PID: ${r.pid})...`)),await re().stopDaemon(),console.log(d.muted(" Daemon stopped"))}(0,ur.existsSync)(We)?(await(0,pr.rm)(We,{recursive:!0}),console.log(y.successLine(`Removed ${We}`))):console.log(d.muted(`
|
|
62
|
+
${We} does not exist (already clean)`))}catch(r){let n=r instanceof Error?r.message:String(r);console.error(y.errorLine(`Clean failed: ${n}`)),k(1)}}))}var br=T(require("dayjs"),1);function hr(t){return"run"in t?"Run":"choose"in t?"Choose":"prompt"in t?"Prompt":"parallel"in t?"Parallel":"fail"in t?"Fail":"Unknown"}function gr(t){let e=t.step,o=[];if("run"in e){let r=t.resolvedCommand,n=r??e.run;o.push(`Command: ${d.warning(n)}`),r&&r!==e.run&&o.push(`${d.muted("Template:")} ${d.muted(e.run)}`)}else if("choose"in e){if(o.push(`Message: ${d.warning(e.choose.message)}`),t.choiceValue!==void 0){let r=e.choose.options.find(n=>n.id===t.choiceValue)?.label??t.choiceValue;o.push(`${d.muted("Selected:")} ${d.accent(t.choiceValue)}${r!==t.choiceValue?` (${r})`:""}`)}}else"prompt"in e?(o.push(`Message: ${d.warning(e.prompt.message)} | Variable: ${d.accent(e.prompt.as)}`),t.promptValue!==void 0&&o.push(`${d.muted("Entered:")} ${d.accent(String(t.promptValue))}`)):"parallel"in e?o.push(`Parallel execution with ${e.parallel.length} branches`):"fail"in e?o.push(`Error: ${d.error(e.fail.message)}`):o.push("Unknown step type");return o.join(`
|
|
63
|
+
`)}function wr(t){return typeof t=="object"&&t!==null&&"success"in t&&"stdout"in t&&"stderr"in t}function Sr(t){if(t.stdout.length>0){let e=t.stdout.map(o=>d.muted(` ${o}`)).join(`
|
|
64
|
+
`);console.log(d.success(" Output:")),console.log(e)}if(t.stderr.length>0){let e=t.stderr.map(o=>d.muted(` ${o}`)).join(`
|
|
65
|
+
`);console.log(d.error(" Errors:")),console.log(e)}}function yr(t,e){console.log();let o=t.records.reduce((c,m)=>c+m.duration,0),r=t.records.filter(c=>c.status==="success").length,n=t.records.filter(c=>c.status==="failure").length,s=(0,br.default)(t.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),i=Se(o),a=[d.strong("Workflow Execution History"),"",`${d.accent("File:")} ${e}`,`${d.accent("Started:")} ${s}`,`${d.accent("Total Duration:")} ${i}`,`${d.accent("Total Steps:")} ${t.records.length}`,`${d.success("\u2713 Successful:")} ${r}`,n>0?`${d.error("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
|
|
66
|
+
`);console.log(me.info(a)),t.records.forEach((c,m)=>{Ss(c,m+1,t.records.length)});let l=Je(t);l&&console.log(l),console.log()}function Ss(t,e,o){let r=hr(t.step),n=gr(t),s=t.status==="success"?d.success("\u2713"):d.error("\u2717"),i=t.status==="success"?d.success("Success"):d.error("Failed"),a=Se(t.duration),l=[`${s} ${d.strong(`Step ${e}/${o}`)} - ${d.accent(r)}`,`${d.muted("Duration:")} ${a} | ${d.muted("Status:")} ${i}`,"",d.plain(n)].join(`
|
|
67
|
+
`);console.log(me.panel(l,{borderColor:t.status==="success"?"green":"red"})),wr(t.output)&&Sr(t.output)}function xr(t){t.command("history").description("Manage workflow execution history").action(()=>ne(async()=>{let o=new W,r=new W(!0),n=await o.prompt("Select an action",[{id:"show",label:"Show - View and select a history to view"},{id:"remove",label:"Remove - Delete a specific history file"},{id:"remove-all",label:"Remove All - Delete all history files"}]);n?.id||(console.error(y.errorLine("Invalid choice")),k(1));let s=new xe;switch(n.id){case"show":{let i=await s.getHistoryNames();if(i.length===0){console.log(y.warningLine("No history found"));return}let a=await r.prompt("Select a history to view",i.map(l=>({id:l,label:l})));a?.id||(console.error(y.errorLine("Invalid choice")),k(1));try{let l=await s.getHistory(a.id);yr(l,a.id)}catch(l){let c=l instanceof Error?l.message:String(l);console.error(y.errorLine(`Failed to load history: ${c}`)),k(1)}break}case"remove":{let i=await s.getHistoryNames();if(i.length===0){console.log(y.warningLine("No history found"));return}let a=await r.prompt("Select a history to remove",i.map(l=>({id:l,label:l})));a?.id||(console.error(y.errorLine("Invalid choice")),k(1));try{await s.removeHistory(a.id),console.log(y.successLine(`Removed history: ${a.id}`))}catch(l){let c=l instanceof Error?l.message:String(l);console.error(y.errorLine(`Failed to remove history: ${c}`)),k(1)}break}case"remove-all":{if((await o.prompt("Are you sure you want to remove all histories?",[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(y.cancelledLine());return}try{await s.clearAllHistories(),console.log(y.successLine("All histories removed"))}catch(a){let l=a instanceof Error?a.message:String(a);console.error(y.errorLine(`Failed to remove histories: ${l}`)),k(1)}break}default:console.error(y.errorLine(`Unknown action: ${n.id}`)),k(1)}}))}var kr=require("child_process"),vr=require("util");var bs=(0,vr.promisify)(kr.exec);function Pr(t){t.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
|
|
68
|
+
Examples:
|
|
69
|
+
$ tp open generator
|
|
70
|
+
$ tp open docs
|
|
132
71
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
- id: dev
|
|
139
|
-
label: "Development"
|
|
140
|
-
- id: prod
|
|
141
|
-
label: "Production"
|
|
142
|
-
as: mode
|
|
143
|
-
- run: 'echo "Mode: {{ mode }}"'
|
|
144
|
-
- prompt:
|
|
145
|
-
message: "Enter build label"
|
|
146
|
-
as: label
|
|
147
|
-
default: "default"
|
|
148
|
-
- run: 'echo "Label: {{ label }}"'
|
|
149
|
-
- when:
|
|
150
|
-
var:
|
|
151
|
-
mode: dev
|
|
152
|
-
run: 'echo "Dev-only step (e.g. npm run build:dev)"'
|
|
153
|
-
- when:
|
|
154
|
-
var:
|
|
155
|
-
mode: prod
|
|
156
|
-
run: 'echo "Prod-only step (e.g. npm run build)"'
|
|
157
|
-
- run: 'echo "Done. Replace run steps with real commands."'
|
|
158
|
-
`}],or=[{filename:"example-daily.yaml",content:`schedules:
|
|
159
|
-
# Runs at 09:00 daily; interactive choose is skipped in scheduled runs (no TTY)
|
|
160
|
-
- name: Daily Hello
|
|
161
|
-
cron: "0 9 * * *"
|
|
162
|
-
workflow: ../workflows/example-hello.yaml
|
|
163
|
-
`},{filename:"example-hourly.yaml",content:`schedules:
|
|
164
|
-
# With profile: choose/prompt are skipped and profile vars used (good for cron)
|
|
165
|
-
- name: Hourly Build (Dev)
|
|
166
|
-
cron: "0 * * * *"
|
|
167
|
-
workflow: ../workflows/example-build.yaml
|
|
168
|
-
profile: Dev
|
|
169
|
-
- name: Nightly Build (Prod)
|
|
170
|
-
cron: "0 2 * * *"
|
|
171
|
-
workflow: ../workflows/example-build.yaml
|
|
172
|
-
profile: Prod
|
|
173
|
-
`}];var tt=require("fs"),rr=require("fs/promises"),je=require("path"),Ne=x(require("chalk"),1);async function nr(){let o=Xe();if(!o)return console.error(Ne.default.red(`
|
|
174
|
-
\u2717 No tp directory found`)),null;let e=(0,je.join)(o,"workflows");if(!(0,tt.existsSync)(e))return console.error(Ne.default.red(`
|
|
175
|
-
\u2717 No workflows directory found at ${e}`)),null;try{let r=(await(0,rr.readdir)(e)).filter(a=>{let l=(0,je.extname)(a).toLowerCase();return[".yaml",".yml",".json"].includes(l)});if(r.length===0)return console.error(Ne.default.red(`
|
|
176
|
-
\u2717 No workflow files found in tp/workflows`)),null;let s=await Promise.all(r.map(async a=>{let l=(0,je.join)(e,a);try{let c=ke(l),d=(0,tt.readFileSync)(l,"utf-8"),m=c.parse(d).name??"Untitled";return{id:l,label:`${a} - ${m}`}}catch{return{id:l,label:a}}}));return(await new O(!0).prompt("Select a workflow to run",s))?.id??null}catch(t){let r=t instanceof Error?t.message:String(t);return console.error(Ne.default.red(`
|
|
177
|
-
\u2717 Failed to read tp directory: ${r}`)),null}}function sr(o){return o.split("/").pop()??o}var Ae=(0,G.join)((0,ar.homedir)(),".pipeliner"),Tn=(0,lr.promisify)(ir.exec),re=new cr.Command;re.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
|
|
72
|
+
Targets:
|
|
73
|
+
generator Open the visual workflow generator (https://task-pipeliner-generator.racgoo.com/)
|
|
74
|
+
docs Open the documentation site (https://task-pipeliner.racgoo.com/)`).action(e=>ne(async()=>{let r={generator:"https://task-pipeliner-generator.racgoo.com/",docs:"https://task-pipeliner.racgoo.com/"}[e.toLowerCase()];r||(console.error(y.errorLine(`Invalid target: ${e}`)),console.log(d.warning(`
|
|
75
|
+
Valid targets:`)),console.log(d.warning(" \u2022 generator - Open the visual workflow generator")),console.log(d.warning(" \u2022 docs - Open the documentation site")),k(1));try{let n=process.platform,s;n==="darwin"?s=`open "${r}"`:n==="win32"?s=`start "${r}"`:s=`xdg-open "${r}"`,await bs(s),console.log(y.successLine(`Opening ${e==="generator"?"generator":"documentation"} in browser...`)),console.log(d.info(` ${r}`))}catch(n){let s=n instanceof Error?n.message:String(n);console.error(y.errorLine(`Failed to open browser: ${s}`)),console.log(d.warning(`
|
|
76
|
+
Please visit manually: ${r}`)),k(1)}}))}var ys="task-pipeliner",xs=`A powerful task pipeline runner with condition-based workflow execution.
|
|
178
77
|
|
|
179
78
|
Define workflows in YAML or JSON files with conditional execution, parallel tasks,
|
|
180
79
|
interactive prompts, variable substitution, and cron-based scheduling.
|
|
@@ -231,7 +130,7 @@ Quick Start:
|
|
|
231
130
|
|
|
232
131
|
Note: After upgrading to a new version, if you see compatibility issues (e.g. schedules or daemon), run "tp clean" to reset ~/.pipeliner data.
|
|
233
132
|
|
|
234
|
-
|
|
133
|
+
`,ks=`
|
|
235
134
|
Examples:
|
|
236
135
|
$ tp setup
|
|
237
136
|
$ tp run workflow.yaml
|
|
@@ -254,7 +153,7 @@ Resources:
|
|
|
254
153
|
\u{1F4DA} Documentation: https://task-pipeliner.racgoo.com/
|
|
255
154
|
\u{1F3A8} Visual Generator: https://task-pipeliner-generator.racgoo.com/
|
|
256
155
|
|
|
257
|
-
See README.md for complete DSL reference.`);
|
|
156
|
+
See README.md for complete DSL reference.`;function $r(t,e){return t.name(ys).description(xs).version(e).addHelpText("after",ks)}var Mr=require("fs"),Wr=require("path");var st=require("fs"),Dr=require("fs/promises"),Be=require("path");var Z=require("fs"),B=require("path"),Ht=require("url"),Rr={};function Cr(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function Er(){return"0.3.16"}function nt(t){let e=t?(0,B.resolve)(t):process.cwd(),o=50,r=0;for(;r<o;){let n=(0,B.resolve)(e,"tp");try{if((0,Z.existsSync)(n)&&(0,Z.statSync)(n).isDirectory())return n}catch{}let s=(0,B.dirname)(e);if(s===e)break;e=s,r++}return null}function Tr(t){let e={};for(let o of t){let r=o.indexOf("=");if(r===-1)throw new Error(`Invalid -v/--var format: "${o}". Use key=value (e.g. -v version=1.0.0).`);let n=o.slice(0,r).trim(),s=o.slice(r+1).trim();if(!n)throw new Error(`Invalid -v/--var format: key is empty in "${o}". Use key=value.`);e[n]=s}return e}async function Or(){let t=nt();if(!t)return console.error(y.errorLine("No tp directory found")),null;let e=(0,Be.join)(t,"workflows");if(!(0,st.existsSync)(e))return console.error(y.errorLine(`No workflows directory found at ${e}`)),null;try{let r=(await(0,Dr.readdir)(e)).filter(a=>{let l=(0,Be.extname)(a).toLowerCase();return[".yaml",".yml",".json"].includes(l)});if(r.length===0)return console.error(y.errorLine("No workflow files found in tp/workflows")),null;let n=await Promise.all(r.map(async a=>{let l=(0,Be.join)(e,a);try{let c=ke(l),m=(0,st.readFileSync)(l,"utf-8"),g=c.parse(m).name??"Untitled";return{id:l,label:`${a} - ${g}`}}catch{return{id:l,label:a}}}));return(await new W(!0).prompt("Select a workflow to run",n))?.id??null}catch(o){let r=o instanceof Error?o.message:String(o);return console.error(y.errorLine(`Failed to read tp directory: ${r}`)),null}}function Ir(t){return t.split("/").pop()??t}function Br(t){t.command("run").description("Run a workflow from a YAML or JSON file").argument("[file]","Path to the workflow file (YAML or JSON, relative or absolute). If omitted, will select from workflows in the nearest tp/workflows directory.").option("-s, --silent","Run in silent mode (suppress console output)").option("-p, --profile <name>","Run in profile mode (use profile name)").option("-v, --var <pair>","Set variable (key=value). Overrides profile. Can repeat.",(e,o)=>{let r=o??[];return r.push(e),r},[]).addHelpText("after",`
|
|
258
157
|
Examples:
|
|
259
158
|
$ tp run workflow.yaml
|
|
260
159
|
$ tp run workflow.json
|
|
@@ -281,40 +180,116 @@ Workflow File Structure:
|
|
|
281
180
|
\u2022 all/any/not: Combine conditions
|
|
282
181
|
|
|
283
182
|
Supported formats: YAML (.yaml, .yml) and JSON (.json)
|
|
284
|
-
See README.md for complete DSL documentation.`).action(
|
|
285
|
-
|
|
286
|
-
`)),await new ve().execute(i,{executionVars:d}),console.log(w.default.green(`
|
|
287
|
-
\u2713 Workflow completed successfully`))}catch(t){let r=t instanceof Error?t.message:String(t);console.error(w.default.red(`
|
|
288
|
-
\u2717 Workflow failed: ${r}`)),process.exit(1)}});re.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
|
|
289
|
-
Examples:
|
|
290
|
-
$ tp open generator
|
|
291
|
-
$ tp open docs
|
|
183
|
+
See README.md for complete DSL documentation.`).action((e,o)=>ne(async()=>{try{let r=e??await Or()??null;r||(console.error(y.errorLine("No workflow file found")),k(1)),o.silent&&Cr();let n=ke(r);console.log(d.info(`Loading workflow from ${r}...`));let s=(0,Mr.readFileSync)(r,"utf-8"),i=n.parse(s);if(!i.steps||!Array.isArray(i.steps))throw new Error("Invalid workflow: steps array is required");let a={};if(o.profile){let f=o.profile.trim();if(!i.profiles?.length)throw new Error(`Profile "${f}" requested but workflow has no "profiles" defined. Add a "profiles" section to your workflow file.`);let w=i.profiles.find(S=>S.name===f);if(!w){let S=i.profiles.map(v=>v.name).join(", ");throw new Error(`Profile "${f}" not found. Available profile(s): ${S}`)}a={...w.var}}let l=o.var??[],c=l.length>0?Tr(l):{},m={...a,...c},h=Object.keys(m).length>0?m:void 0;i._lineNumbers=n.extractStepLineNumbers(s),i._fileName=Ir(r),i._filePath=(0,Wr.resolve)(r),console.log(d.success(`Starting workflow execution...
|
|
184
|
+
`)),await rt().execute(i,{executionVars:h}),console.log(y.successLine("Workflow completed successfully"))}catch(r){let n=r instanceof Error?r.message:String(r);console.error(y.errorLine(`Workflow failed: ${n}`)),k(1)}}))}var Ne=require("fs"),$e=require("fs/promises"),Pe=require("path");var vs=[{filename:"example-hello.yaml",content:`name: Hello World (with choose)
|
|
292
185
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
186
|
+
# Interactive choice: stored as variable and used in later steps
|
|
187
|
+
steps:
|
|
188
|
+
- run: 'echo "Hello from task-pipeliner"'
|
|
189
|
+
- choose:
|
|
190
|
+
message: "Select action:"
|
|
191
|
+
options:
|
|
192
|
+
- id: greet
|
|
193
|
+
label: "Greet"
|
|
194
|
+
- id: info
|
|
195
|
+
label: "Show info"
|
|
196
|
+
as: action
|
|
197
|
+
- run: 'echo "You chose: {{ action }}"'
|
|
198
|
+
- when:
|
|
199
|
+
var:
|
|
200
|
+
action: greet
|
|
201
|
+
run: 'echo "Hi there! Edit tp/workflows and run: tp run tp/workflows/example-hello.yaml"'
|
|
202
|
+
- when:
|
|
203
|
+
var:
|
|
204
|
+
action: info
|
|
205
|
+
run: 'echo "Tip: Use --profile. See example-build.yaml for profiles."'
|
|
206
|
+
`},{filename:"example-build.yaml",content:`name: Example Build (with profiles and choose)
|
|
207
|
+
|
|
208
|
+
# Profiles: run without prompts via "tp run tp/workflows/example-build.yaml --profile Dev"
|
|
209
|
+
# With profile, choose/prompt are skipped and these variables are used.
|
|
210
|
+
profiles:
|
|
211
|
+
- name: Dev
|
|
212
|
+
var:
|
|
213
|
+
mode: dev
|
|
214
|
+
label: "dev-build"
|
|
215
|
+
- name: Prod
|
|
216
|
+
var:
|
|
217
|
+
mode: prod
|
|
218
|
+
label: "prod-build"
|
|
219
|
+
|
|
220
|
+
steps:
|
|
221
|
+
- run: 'echo "Build workflow started..."'
|
|
222
|
+
- choose:
|
|
223
|
+
message: "Select mode (or run with --profile Dev/Prod to skip):"
|
|
224
|
+
options:
|
|
225
|
+
- id: dev
|
|
226
|
+
label: "Development"
|
|
227
|
+
- id: prod
|
|
228
|
+
label: "Production"
|
|
229
|
+
as: mode
|
|
230
|
+
- run: 'echo "Mode: {{ mode }}"'
|
|
231
|
+
- prompt:
|
|
232
|
+
message: "Enter build label"
|
|
233
|
+
as: label
|
|
234
|
+
default: "default"
|
|
235
|
+
- run: 'echo "Label: {{ label }}"'
|
|
236
|
+
- when:
|
|
237
|
+
var:
|
|
238
|
+
mode: dev
|
|
239
|
+
run: 'echo "Dev-only step (e.g. npm run build:dev)"'
|
|
240
|
+
- when:
|
|
241
|
+
var:
|
|
242
|
+
mode: prod
|
|
243
|
+
run: 'echo "Prod-only step (e.g. npm run build)"'
|
|
244
|
+
- run: 'echo "Done. Replace run steps with real commands."'
|
|
245
|
+
`}],Ps=[{filename:"example-daily.yaml",content:`schedules:
|
|
246
|
+
# Runs at 09:00 daily; interactive choose is skipped in scheduled runs (no TTY)
|
|
247
|
+
- name: Daily Hello
|
|
248
|
+
cron: "0 9 * * *"
|
|
249
|
+
workflow: ../workflows/example-hello.yaml
|
|
250
|
+
`},{filename:"example-hourly.yaml",content:`schedules:
|
|
251
|
+
# With profile: choose/prompt are skipped and profile vars used (good for cron)
|
|
252
|
+
- name: Hourly Build (Dev)
|
|
253
|
+
cron: "0 * * * *"
|
|
254
|
+
workflow: ../workflows/example-build.yaml
|
|
255
|
+
profile: Dev
|
|
256
|
+
- name: Nightly Build (Prod)
|
|
257
|
+
cron: "0 2 * * *"
|
|
258
|
+
workflow: ../workflows/example-build.yaml
|
|
259
|
+
profile: Prod
|
|
260
|
+
`}];function Nr(t){t.command("setup").description("Create tp directory with workflows and schedules folders and add 2 example files in each (echo-based dummies). Run from project root for easy initial setup.").action(async()=>{let e=process.cwd(),o=(0,Pe.join)(e,"tp"),r=(0,Pe.join)(o,"workflows"),n=(0,Pe.join)(o,"schedules");(0,Ne.existsSync)(o)?console.log(d.muted(`
|
|
261
|
+
tp directory already exists at ${o}`)):(await(0,$e.mkdir)(o,{recursive:!0}),console.log(y.successLine(`Created ${o}`)));let s=async(a,l)=>{(0,Ne.existsSync)(a)?console.log(d.muted(` ${l} already exists`)):(await(0,$e.mkdir)(a,{recursive:!0}),console.log(d.success(`\u2713 Created ${l}`)))};await s(r,"tp/workflows"),await s(n,"tp/schedules");let i=[];for(let{filename:a,content:l}of vs){let c=(0,Pe.join)(r,a);(0,Ne.existsSync)(c)?console.log(d.muted(` Skipped (exists): tp/workflows/${a}`)):(await(0,$e.writeFile)(c,l,"utf-8"),i.push(`tp/workflows/${a}`))}for(let{filename:a,content:l}of Ps){let c=(0,Pe.join)(n,a);(0,Ne.existsSync)(c)?console.log(d.muted(` Skipped (exists): tp/schedules/${a}`)):(await(0,$e.writeFile)(c,l,"utf-8"),i.push(`tp/schedules/${a}`))}i.length>0&&(console.log(y.successLine(`Added ${i.length} example file(s):`)),i.forEach(a=>console.log(d.subtle(` ${a}`)))),console.log(d.subtle(`
|
|
262
|
+
Next: tp run tp/workflows/example-hello.yaml | tp schedule add tp/schedules/example-daily.yaml | tp schedule list`)),console.log()})}var sn=require("commander");var at=require("fs"),zr=require("fs/promises"),he=require("path");var jr=require("fs/promises"),Fr=require("path"),Ar=require("yaml"),Vr=require("zod");var L=require("zod"),$s=L.z.object({name:L.z.string().min(1,"Schedule name must be non-empty"),cron:L.z.string().min(1,"Cron expression is required"),workflow:L.z.string().min(1,"Workflow path is required"),baseDir:L.z.string().optional(),timezone:L.z.union([L.z.string(),L.z.number()]).transform(String).optional(),silent:L.z.boolean().optional(),profile:L.z.string().optional()}),Rs=L.z.object({schedules:L.z.array($s).min(1,"Schedule file must have at least one schedule")});function Lr(t){return Rs.parse(t)}async function Hr(t){let e=await(0,jr.readFile)(t,"utf-8"),o=(0,Fr.extname)(t).toLowerCase(),r;try{if(o===".yaml"||o===".yml")r=(0,Ar.parse)(e);else if(o===".json")r=JSON.parse(e);else throw new Error(`Unsupported file format: ${o}. Use .yaml, .yml, or .json`)}catch(n){if(n instanceof Error&&n.message.startsWith("Unsupported"))throw n;let s=o===".json"?"JSON":"YAML";throw new Error(`Invalid ${s} format: ${n instanceof Error?n.message:String(n)}`)}try{return Lr(r)}catch(n){if(n instanceof Vr.ZodError){let s=n.issues.map(i=>` - ${i.message} (${i.path.join(".")})`).join(`
|
|
263
|
+
`);throw new Error(`Invalid schedule file structure:
|
|
264
|
+
${s}`)}throw n}}var Ur=T(require("inquirer"),1),Yr=T(require("node-cron"),1);var _r=T(require("cronstrue"),1),_t=T(require("dayjs"),1),zt=T(require("node-cron"),1);function Ut(t){try{return _r.default.toString(t)}catch{return null}}function Cs(t){if(!zt.default.validate(t.cron))return null;try{let e={},o=tt(t.timezone);o&&(e.timezone=o);let r=zt.default.createTask(t.cron,()=>{},e),n=r.getNextRun();return r.destroy(),n}catch{return null}}function j(t,e){let o=t,{daemonRunning:r,emphasizeState:n}=e,s=o.enabled?n?p.bold.green("ENABLED"):p.green("enabled"):n?p.bold.gray("DISABLED"):p.gray("disabled"),i=r&&o.enabled,a=i?p.green("\u25CF active"):p.gray("\u25CB inactive"),l=n?o.enabled?p.bold.green(" [ENABLED]"):p.bold.gray(" [DISABLED]"):"",c=p.bold(o.name??o.workflowPath),m=Cs(o),h=m?(0,_t.default)(m).format("YYYY-MM-DD HH:mm:ss"):p.dim("\u2014"),g=o.lastRun?(0,_t.default)(o.lastRun).format("YYYY-MM-DD HH:mm:ss"):p.dim("never"),f=Ut(o.cron),w=o.timezone?o.timezone.startsWith("+")||o.timezone.startsWith("-")?`UTC${o.timezone}`:`UTC+${o.timezone}`:null,S=w??"local",v=f?`${o.cron} ${p.dim(`\u2192 ${f} (${S})`)}`:o.cron,b=[[p.gray("Enabled"),s],[p.gray("Cron"),v],[p.gray("Timezone"),w??p.dim("local")],[p.gray("Workflow"),o.workflowPath],...o.profile?[[p.gray("Profile"),p.cyan(o.profile)]]:[],...o.silent?[[p.gray("Silent"),p.yellow("yes")]]:[],[p.gray("Last run"),g],[p.gray("Next run"),h]],x=[`${c} ${a}${l}`,...b.map(([E,D])=>` ${E.padEnd(10)} ${D}`)].join(`
|
|
265
|
+
`);return N(x,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:i?"green":"gray"})}pe();var K=require("path");function Le(t,e){let o=e.workflow;if((0,K.isAbsolute)(o))return o;let r=e.baseDir?(0,K.resolve)(e.baseDir):(0,K.dirname)(t);return(0,K.resolve)(r,o)}function Yt(t,e="plain"){let o=t.name??"(no alias)",r=(0,K.basename)(t.workflowPath),n=Ut(t.cron)??t.cron,s=e==="color"?t.enabled?p.green("Enabled"):p.dim("Disabled"):t.enabled?"\u2713":"\u2717";return`${o} \xB7 ${r} \xB7 ${t.cron} \xB7 ${n} \xB7 ${s}`}function se(){return new z}async function U(){return M()}async function it(t,e,o="plain"){let n=await new W(!0).prompt(e,t.map(i=>({id:i.id,label:Yt(i,o)})));return t.find(i=>i.id===n.id)}async function Jt(t){let e=se();if(!t){let l=nt();l||(console.error(p.red(`
|
|
266
|
+
\u2717 No tp directory found`)),k(1));let c=(0,he.join)(l,"schedules");(0,at.existsSync)(c)||(console.error(p.red(`
|
|
267
|
+
\u2717 No schedules directory found at ${c}`)),k(1));let h=(await(0,zr.readdir)(c)).filter(S=>{let v=(0,he.extname)(S).toLowerCase();return[".yaml",".yml",".json"].includes(v)});h.length===0&&(console.error(p.red(`
|
|
268
|
+
\u2717 No schedule files found in ${c}`)),k(1));let g=h.map(S=>({id:(0,he.join)(c,S),label:S}));t=(await new W(!0).prompt("Select a schedule file to add",g)).id}let o=(0,he.resolve)(t);(0,at.existsSync)(o)||(console.error(`\u2717 File not found: ${o}`),k(1));let r;try{r=await Hr(o)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),k(1)}let n=r.schedules.filter(l=>!Yr.default.validate(l.cron));if(n.length>0){console.error("\u2717 Invalid cron expression(s):");for(let l of n)console.error(` - ${l.name}: "${l.cron}"`);k(1)}let s=r.schedules.filter(l=>{let c=Le(o,l);return!(0,at.existsSync)(c)});if(s.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of s){let c=Le(o,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}k(1)}console.log(`
|
|
269
|
+
Found ${r.schedules.length} schedule(s) in file.
|
|
270
|
+
`);let i=[];for(let l of r.schedules){let{alias:c}=await Ur.default.prompt([{type:"input",name:"alias",message:`Alias for "${l.name}" (press Enter to use as-is):`,default:l.name}]),m=await e.addSchedule({name:c,workflowPath:Le(o,l),cron:l.cron,enabled:!0,timezone:l.timezone,silent:l.silent,profile:l.profile});i.push(m)}let a=await U();console.log(`
|
|
271
|
+
\u2713 Added ${i.length} schedule(s) successfully
|
|
272
|
+
`);for(let l of i)console.log(j(l,{daemonRunning:a.running}));console.log(p.dim(' Tip: Run "tp schedule start" to start the scheduler daemon'))}async function lt(){let e=await se().loadSchedules();if(e.length===0){let i=[p.gray("No schedules registered."),"",p.dim(" tp schedule add <schedule.yaml> add from a schedule file")].join(`
|
|
273
|
+
`);console.log(`
|
|
274
|
+
${N(i,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"})}
|
|
275
|
+
`);return}let o=await U(),r=o.running?p.green("\u25CF running"):p.gray("\u25CB stopped"),n=e.filter(i=>i.enabled).length,s=p.bold("\u{1F4C5} Workflow Schedules");console.log(s),console.log([p.gray(" Daemon: "),r,p.gray(` \xB7 Schedules: ${n}/${e.length} enabled`)].join(""));for(let i of e)console.log(j(i,{daemonRunning:o.running}));console.log(p.dim(" Tip: tp schedule start \u2014 run scheduler daemon; tp schedule status \u2014 view live status"))}var Jr=T(require("inquirer"),1);async function qt(){let t=new z,e=await t.loadSchedules();if(e.length===0){console.log("No schedules found");return}let{confirm:o}=await Jr.default.prompt([{type:"confirm",name:"confirm",message:`Are you sure you want to remove all ${e.length} schedule(s)?`,default:!1}]);if(!o){console.log("Cancelled");return}await t.saveSchedules([]),console.log(`\u2713 Removed all ${e.length} schedule(s)`)}var qr=T(require("inquirer"),1);async function Gt(){let t=se(),e=await t.loadSchedules();if(e.length===0){console.log("No schedules found");return}let o=await it(e,"Select schedule to remove:");if(!o){console.log("\u2717 Schedule not found");return}let r=o.id,{confirm:n}=await qr.default.prompt([{type:"confirm",name:"confirm",message:"Are you sure you want to remove this schedule?",default:!1}]);if(!n){console.log("Cancelled");return}if(await t.removeSchedule(r)){let i=await U();console.log(`
|
|
276
|
+
\u2713 Schedule removed
|
|
277
|
+
`),console.log(j(o,{daemonRunning:i.running}))}else console.log("\u2717 Schedule not found")}var Gr=require("child_process");pe();async function Zt(t){let{scheduler:e,daemonMode:o}=t;await new Promise(r=>{let n=!1,s=async()=>{if(!n){n=!0,process.off("SIGINT",s),process.off("SIGTERM",s);try{await e.shutdown(o)}finally{r()}}};process.on("SIGINT",s),process.on("SIGTERM",s)})}async function Kt(t){if(await q()){let o=await M();console.error(`\u2717 Scheduler daemon is already running (PID: ${o.pid})`),console.error(' Run "tp schedule stop" to stop it first'),k(1)}if(t){if(process.env.TP_DAEMON_MODE==="true"){try{let{saveDaemonPid:l}=await Promise.resolve().then(()=>(pe(),uo));await l();let c=re();await c.start(!0),await Zt({scheduler:c,daemonMode:!0})}catch(l){await bt(l instanceof Error?l:new Error(String(l))),k(1)}return}let o=process.argv.slice(1);(0,Gr.spawn)(process.argv[0],o,{detached:!0,stdio:"ignore",env:{...process.env,TP_DAEMON_MODE:"true"}}).unref();let n=3,s=800,i=!1;for(let l=0;l<n;l++)if(await new Promise(c=>setTimeout(c,s)),await q()){i=!0;break}if(i){let l=await M();console.log(`\u2713 Scheduler daemon started in background (PID: ${l.pid})`),console.log(' Run "tp schedule stop" to stop the daemon'),console.log(' Run "tp schedule status" to check daemon status');return}console.error("\u2717 Failed to start scheduler daemon");let a=await xt();a?(console.error(p.dim(" Last error from daemon:")),console.error(p.red(a.split(`
|
|
278
|
+
`).map(l=>` ${l}`).join(`
|
|
279
|
+
`)))):console.error(p.dim(` Check ${yt()} for details`)),k(1)}let e=re();await e.start(!1,{onScheduleStarted:o=>console.log(j(o,{daemonRunning:!0}))}),await Zt({scheduler:e,daemonMode:!1})}async function Xt(){let t=await U();if(!t.running){console.log("Scheduler daemon is not running");return}console.log(`Stopping scheduler daemon (PID: ${t.pid})...`);let o=await re().stopDaemon();console.log(o?"\u2713 Scheduler daemon stopped":"\u2717 Failed to stop scheduler daemon (process may have already exited)")}async function Qt(){let t=se(),e=await t.loadSchedules();if(e.length===0){console.log("No schedules found");return}let o=await it(e,"Select schedule to toggle:","color");if(!o){console.log("\u2717 Schedule not found");return}let r=o.id,n=!o.enabled;await t.toggleSchedule(r,n);let s=await U(),i={...o,enabled:n},a=n?p.bold.green("ENABLED"):p.bold.gray("DISABLED"),l=n?p.dim(" (will run at the times shown below)"):p.dim(" (will not run until you enable it again)");console.log(`
|
|
280
|
+
\u2713 Schedule is now ${a}${l}
|
|
281
|
+
`),console.log(j(i,{daemonRunning:s.running,emphasizeState:!0}))}pe();var to=T(require("log-update"),1);var ct=T(require("dayjs"),1);function Zr(t){if(!t)return"Unknown";let e=(0,ct.default)(t),r=(0,ct.default)().diff(e,"second"),n=Math.floor(r/86400),s=Math.floor(r%86400/3600),i=Math.floor(r%3600/60),a=r%60,l=[];return n>0&&l.push(`${n}d`),s>0&&l.push(`${s}h`),i>0&&l.push(`${i}m`),(a>0||l.length===0)&&l.push(`${a}s`),l.join(" ")}function Kr(t,e){return j(t,{daemonRunning:e})}function Es(t){if(t.running&&t.pid){let e=Zr(t.startTime),o=t.startTime?(0,ct.default)(t.startTime).format("YYYY-MM-DD HH:mm:ss"):"Unknown";return[`${p.green("\u25CF")} ${p.green("active")} ${p.gray("(running)")}`,"",`${p.gray("Loaded:")} ${p.white(o)}`,`${p.gray("Active:")} ${p.green("active (running)")} since ${p.white(o)}`,`${p.gray("PID:")} ${p.white(t.pid.toString())}`,`${p.gray("Uptime:")} ${p.white(e)}`].join(`
|
|
282
|
+
`)}return[`${p.red("\u25CF")} ${p.red("inactive")} ${p.gray("(dead)")}`,"",`${p.gray("Loaded:")} ${p.gray("not found")}`,`${p.gray("Active:")} ${p.red("inactive (dead)")}`].join(`
|
|
283
|
+
`)}function Ts(t){return N(Es(t),{title:p.bold("task-pipeliner-scheduler.service"),titleAlignment:"left",borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:1,bottom:0,left:0,right:0},borderColor:t.running?"green":"red"})}function Ds(t,e){if(t.length>0){let r=t.filter(i=>i.enabled).length,n=p.bold(`Schedules: ${r}/${t.length} enabled`),s=t.map(i=>Kr(i,e));return[n,...s]}return[N(p.gray("No schedules configured"),{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"gray"})]}function Xr(t,e){let o=[];return o.push(Ts(t)),o.push(...Ds(e,t.running)),`
|
|
284
|
+
|
|
285
|
+
${o.join(`
|
|
286
|
+
`)}`}function eo(){process.stdout.write("\x1B[2J\x1B[H")}var Qr=T(require("log-update"),1),Os=2,Is=24;function en(){let t=typeof process.stdout.rows=="number"?process.stdout.rows:Is;return Math.max(5,t-Os)}function tn(t){let e=t.toString("utf8");return e==="\x1B[A"?"up":e==="\x1B[B"?"down":e==="\x1B[5~"?"pageup":e==="\x1B[6~"?"pagedown":e==="\x1B[H"||e==="\x1B[1~"?"home":e==="\x1B[4~"||e==="\x1B[F"?"end":null}function ut(t,e){let o=e.lines.length,r=Math.max(0,o-t),n=Math.min(e.scrollOffset,r),s={...e,scrollOffset:n},i=s.lines.slice(s.scrollOffset,s.scrollOffset+t).join(`
|
|
287
|
+
`),a=o>t?p.dim(` [${s.scrollOffset+1}-${Math.min(s.scrollOffset+t,o)}/${o}] \u2191/\u2193 PgUp/PgDn: scroll`):"";return(0,Qr.default)(`${i}
|
|
288
|
+
${s.footer}${a}`),s}function on(t,e,o,r){let n=Math.max(0,o-e);switch(t){case"up":return Math.max(0,r-1);case"down":return Math.min(n,r+1);case"pageup":return Math.max(0,r-e);case"pagedown":return Math.min(n,r+e);case"home":return 0;case"end":return n;default:return r}}async function rn(){let t=await M(),o=await new z().loadSchedules();return Xr(t,o)}function Ms(t){return t.running?p.gray(`
|
|
289
|
+
Press Ctrl+C to exit (daemon keeps running in background)`):p.gray(`
|
|
290
|
+
Tip: To start the daemon, run: tp schedule start -d. Press Ctrl+C to exit.`)}function Ws(t){return t.running?p.gray(`
|
|
291
|
+
Ctrl+C: exit (daemon keeps running)`):p.gray(`
|
|
292
|
+
Tip: tp schedule start -d to start daemon. Ctrl+C: exit.`)}function Bs(t,e,o,r){if(!(process.stdin.isTTY&&process.stdout.isTTY))return()=>{};process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf8");let n=s=>{let i=typeof s=="string"?Buffer.from(s,"utf8"):s;if(i.length===1&&i[0]===3){r();return}let a=tn(i);if(!a)return;let l=e();if(l.lines.length<=t){let h=ut(t,l);o(h);return}let c=on(a,t,l.lines.length,l.scrollOffset),m=ut(t,{...l,scrollOffset:c});o(m)};return process.stdin.on("data",n),()=>{process.stdin.off("data",n)}}async function Ns(t,e,o){let r=await rn(),n=await M(),s={lines:r.split(`
|
|
293
|
+
`),footer:Ws(n),scrollOffset:o.scrollOffset};return t?ut(e,s):((0,to.default)(`${r}${Ms(n)}`),s)}async function Ls(){let t=process.stdin.isTTY&&process.stdout.isTTY,e=en(),o=!0,r={lines:[],footer:"",scrollOffset:0},n,s=new Promise(g=>{n=g}),i={removeInputListener:()=>{}},a=()=>{i.interval&&(clearInterval(i.interval),i.interval=void 0),i.signalHandler&&(process.off("SIGINT",i.signalHandler),process.off("SIGTERM",i.signalHandler),i.signalHandler=void 0),i.removeInputListener(),t&&process.stdin.isTTY&&(process.stdin.setRawMode(!1),process.stdin.pause()),to.default.done()},l=()=>{o&&(o=!1,a(),n?.())},c=g=>{o&&(o=!1,a(),console.error("Error updating status:",g),process.exitCode=1,n?.())},m=()=>{l()};i.signalHandler=m,process.on("SIGINT",m),process.on("SIGTERM",m),i.removeInputListener=Bs(e,()=>r,g=>{r=g},l);let h=async()=>{try{r=await Ns(t,e,r)}catch(g){c(g)}};i.interval=setInterval(()=>{o&&h()},1e3),eo(),await h(),await s}async function nn(t){if(t){await Ls();return}eo();let e=await rn(),r=(await M()).running?"":p.gray(`
|
|
294
|
+
Tip: To start the daemon, run: tp schedule start -d`);console.log(`${e}${r}
|
|
295
|
+
`)}function an(){let t=new sn.Command("schedule").description("Manage workflow schedules").action(async()=>{await lt()});return t.command("add [scheduleFile]").description("Add schedules from a schedule file (YAML or JSON). If no file given, select from nearest tp/schedules directory.").action(async e=>{await Jt(e)}),t.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await Gt()}),t.command("remove-all").description("Remove all workflow schedules").action(async()=>{await qt()}),t.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await lt()}),t.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await Kt(e.daemon??!1)}),t.command("stop").description("Stop the scheduler daemon").action(async()=>{await Xt()}),t.command("status").description('View daemon and schedule status (does not start the daemon). In live mode, Ctrl+C only exits the status view; the daemon keeps running if it was started with "tp schedule start -d".').option("-n, --no-follow","Show status once and exit (no live refresh)").action(async e=>{let o=e.follow!==!1;await nn(o)}),t.command("toggle").description("Enable or disable a schedule").action(async()=>{await Qt()}),t}function cn(){let t=new ln.Command;return $r(t,Er()),Br(t),Pr(t),t.addCommand(an()),Nr(t),xr(t),fr(t),t}typeof require<"u"&&typeof module<"u"&&require.main===module&&cn().parseAsync().catch(e=>{if(e instanceof Me){!e.handled&&e.message&&console.error(e.message),process.exitCode=e.exitCode;return}let o=e instanceof Error?e.message:String(e);console.error(o),process.exitCode=1});0&&(module.exports={createProgram});
|
package/dist/index.d.cts
CHANGED