task-pipeliner 0.2.10 → 0.2.12

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 조건 기반 작업 파이프라인 실행기로 아름다운 CLI 출력을 제공합니다
4
4
 
5
- **버전:** 0.2.10
5
+ **버전:** 0.2.12
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
@@ -29,30 +29,101 @@
29
29
 
30
30
  ## 리소스
31
31
 
32
+ ### 문서 및 도구
33
+
32
34
  - 📚 **[문서](https://task-pipeliner.racgoo.com/)** - 완전한 DSL 참조 및 가이드
33
- - 🎨 **[시각적 생성기](https://task-pipeliner-generator.racgoo.com/)** - 브라우저에서 시각적으로 워크플로우 생성
35
+ - 🎨 **[워크플로우 생성기](https://task-pipeliner-generator.racgoo.com/)** - 브라우저에서 시각적으로 워크플로우 생성
36
+
37
+ ### 저장소 및 패키지 관리자
38
+
34
39
  - 💻 **[GitHub](https://github.com/racgoo/task-pipeliner)** - 소스 코드 및 이슈 추적
35
40
  - 📦 **[npm](https://www.npmjs.com/package/task-pipeliner)** - npm 레지스트리 패키지
36
- > **CLI 명령어**:
37
- ```bash
38
- tp run workflow.yaml # 워크플로우 실행
39
- tp run workflow.yaml --silent # 사일런트 모드로 실행 (모든 콘솔 출력 억제)
40
- tp run workflow.yaml -s # 사일런트 모드 짧은 형식
41
- tp open generator # 시각적 생성기 열기
42
- tp open docs # 문서 열기
43
- tp history # 워크플로우 실행 히스토리 보기
44
- tp history show # 특정 히스토리 선택하여 보기
45
- tp history remove # 특정 히스토리 삭제
46
- tp history remove-all # 모든 히스토리 삭제
47
- ```
41
+ - 🍺 **[Homebrew](https://github.com/racgoo/homebrew-task-pipeliner)** - macOS/Linux용 Homebrew 탭
42
+ - 🪟 **[Scoop](https://github.com/racgoo/scoop-task-pipeliner)** - Windows용 Scoop 버킷
43
+
44
+ ### CLI 명령어
45
+
46
+ **워크플로우 실행:**
47
+ ```bash
48
+ tp run workflow.yaml # 워크플로우 실행
49
+ tp run # 가장 가까운 tp 디렉토리에서 워크플로우 선택하여 실행
50
+ tp run workflow.yaml --silent # 사일런트 모드로 실행 (모든 콘솔 출력 억제)
51
+ tp run workflow.yaml -s # 사일런트 모드 짧은 형식
52
+ ```
53
+
54
+ **리소스 열기:**
55
+ ```bash
56
+ tp open generator # 시각적 생성기 열기
57
+ tp open docs # 문서 열기
58
+ ```
59
+
60
+ **히스토리 관리:**
61
+ ```bash
62
+ tp history # 워크플로우 실행 히스토리 보기
63
+ tp history show # 특정 히스토리 선택하여 보기
64
+ tp history remove # 특정 히스토리 삭제
65
+ tp history remove-all # 모든 히스토리 삭제
66
+ ```
48
67
 
49
68
  ## 🚀 빠른 시작
50
69
 
51
70
  ### 설치
52
71
 
53
- #### 전역 설치
72
+ #### Homebrew (macOS/Linux)
73
+
74
+ macOS와 Linux에서 가장 쉬운 설치 방법은 Homebrew를 사용하는 것입니다:
75
+
76
+ ```bash
77
+ # 탭(저장소) 추가
78
+ brew tap racgoo/task-pipeliner
79
+
80
+ # task-pipeliner 설치
81
+ brew install task-pipeliner
82
+ ```
83
+
84
+ 설치 후 다음 명령으로 실행할 수 있습니다:
85
+ ```bash
86
+ task-pipeliner run workflow.yaml
87
+ # 또는 짧은 별칭 사용
88
+ tp run workflow.yaml
89
+ ```
90
+
91
+ **업데이트:**
92
+ ```bash
93
+ # 먼저 Homebrew의 패키지 레지스트리를 업데이트합니다
94
+ brew update
95
+
96
+ # 그 다음 task-pipeliner를 업그레이드합니다
97
+ brew upgrade task-pipeliner
98
+ ```
99
+
100
+ #### Scoop (Windows)
101
+
102
+ Windows에서 Scoop을 사용하여 설치:
103
+
104
+ ```bash
105
+ # 버킷(저장소) 추가
106
+ scoop bucket add task-pipeliner https://github.com/racgoo/scoop-task-pipeliner
107
+
108
+ # task-pipeliner 설치
109
+ scoop install task-pipeliner
110
+ ```
54
111
 
55
- 전역으로 설치하면 `task-pipeliner` 또는 `tp` 명령을 직접 사용할 수 있습니다:
112
+ 설치 다음 명령으로 실행할 수 있습니다:
113
+ ```bash
114
+ task-pipeliner run workflow.yaml
115
+ # 또는 짧은 별칭 사용
116
+ tp run workflow.yaml
117
+ ```
118
+
119
+ **업데이트:**
120
+ ```bash
121
+ scoop update task-pipeliner
122
+ ```
123
+
124
+ #### 전역 설치 (npm)
125
+
126
+ npm을 사용하여 전역으로 설치하면 `task-pipeliner` 또는 `tp` 명령을 직접 사용할 수 있습니다:
56
127
 
57
128
  ```bash
58
129
  npm install -g task-pipeliner
@@ -177,6 +248,29 @@ tp run workflow.yaml --silent
177
248
  tp run workflow.yaml -s
178
249
  ```
179
250
 
251
+ **`tp` 디렉토리 사용하기 (권장):**
252
+
253
+ 더 나은 조직화를 위해 프로젝트에 `tp` 디렉토리를 만들고 모든 워크플로우 파일을 그곳에 배치할 수 있습니다. 파일을 지정하지 않고 `tp run`을 실행하면 task-pipeliner가 자동으로 가장 가까운 `tp` 디렉토리(현재 디렉토리부터 시작하여 상위로 탐색)를 찾아 대화형으로 워크플로우를 선택할 수 있게 해줍니다.
254
+
255
+ ```bash
256
+ # tp 디렉토리를 만들고 워크플로우 파일 추가
257
+ mkdir tp
258
+ mv workflow.yaml tp/
259
+
260
+ # 파일을 지정하지 않고 실행 - 대화형 선택
261
+ tp run
262
+ ```
263
+
264
+ 이 기능은:
265
+ 1. 가장 가까운 `tp` 디렉토리를 찾습니다 (현재 디렉토리 또는 상위 디렉토리)
266
+ 2. 해당 디렉토리의 모든 워크플로우 파일 (`.yaml`, `.yml`, `.json`)을 나열합니다
267
+ 3. 다음 기능을 제공하는 대화형 검색 가능한 메뉴를 표시합니다:
268
+ - 타이핑하여 실시간으로 워크플로우 필터링
269
+ - 화살표 키 (↑↓)로 탐색
270
+ - Enter를 눌러 선택하고 실행
271
+
272
+ 대화형 메뉴는 파일 이름과 워크플로우의 `name` (YAML/JSON 내용에서)을 모두 표시하여 쉽게 식별할 수 있습니다.
273
+
180
274
  **사일런트 모드:**
181
275
  `--silent` (또는 `-s`) 플래그는 워크플로우 실행 중 모든 콘솔 출력을 억제합니다. 다음 경우에 유용합니다:
182
276
  - 종료 코드만 필요한 CI/CD 파이프라인
@@ -355,7 +449,7 @@ steps:
355
449
 
356
450
  #### 2. `choose` - 사용자 선택
357
451
 
358
- 옵션 목록에서 사용자가 선택하도록 프롬프트를 표시합니다.
452
+ 옵션 목록에서 사용자가 선택하도록 프롬프트를 표시합니다. 선택 메뉴에는 **실시간 검색 기능**이 포함되어 있어 타이핑으로 옵션을 필터링할 수 있습니다.
359
453
 
360
454
  **문법:**
361
455
  ```yaml
@@ -381,6 +475,13 @@ steps:
381
475
  - 제공 시: 선택된 `id`가 이 변수 이름으로 저장됩니다
382
476
  - `when` (선택): `Condition` - 조건이 충족될 때만 선택 프롬프트 표시
383
477
 
478
+ **대화형 기능:**
479
+ - **실시간 검색**: 타이핑하여 옵션을 즉시 필터링 - 매칭되는 옵션만 표시됩니다
480
+ - **화살표 키 탐색**: ↑↓ 키를 사용하여 옵션 간 탐색
481
+ - **Enter로 선택**: Enter를 눌러 선택 확인
482
+ - **Backspace**: 검색어에서 문자 제거
483
+ - **Escape**: 검색어를 지우고 모든 옵션 표시
484
+
384
485
  **예제:**
385
486
  ```yaml
386
487
  # 기본 선택
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > A powerful, condition-based task pipeline runner with beautiful CLI output
4
4
 
5
- **Version:** 0.2.10
5
+ **Version:** 0.2.12
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
@@ -29,30 +29,101 @@
29
29
 
30
30
  ## 🔗 Resources
31
31
 
32
+ ### Documentation & Tools
33
+
32
34
  - 📚 **[Documentation](https://task-pipeliner.racgoo.com/)** - Complete DSL reference and guides
33
35
  - 🎨 **[Visual Generator](https://task-pipeliner-generator.racgoo.com/)** - Create workflows visually in your browser
36
+
37
+ ### Repositories & Package Managers
38
+
34
39
  - 💻 **[GitHub](https://github.com/racgoo/task-pipeliner)** - Source code and issue tracking
35
40
  - 📦 **[npm](https://www.npmjs.com/package/task-pipeliner)** - Package on npm registry
36
- - 💻 **CLI Commands**:
37
- ```bash
38
- tp run workflow.yaml # Run a workflow
39
- tp run workflow.yaml --silent # Run in silent mode (suppress all console output)
40
- tp run workflow.yaml -s # Short form for silent mode
41
- tp open generator # Open visual generator
42
- tp open docs # Open documentation
43
- tp history # View workflow execution history
44
- tp history show # Select and view a specific history
45
- tp history remove # Remove a specific history
46
- tp history remove-all # Remove all histories
47
- ```
41
+ - 🍺 **[Homebrew](https://github.com/racgoo/homebrew-task-pipeliner)** - Homebrew tap for macOS/Linux
42
+ - 🪟 **[Scoop](https://github.com/racgoo/scoop-task-pipeliner)** - Scoop bucket for Windows
43
+
44
+ ### CLI Commands
45
+
46
+ **Run Workflows:**
47
+ ```bash
48
+ tp run workflow.yaml # Run a workflow
49
+ tp run # Select and run a workflow from nearest tp directory
50
+ tp run workflow.yaml --silent # Run in silent mode (suppress all console output)
51
+ tp run workflow.yaml -s # Short form for silent mode
52
+ ```
53
+
54
+ **Open Resources:**
55
+ ```bash
56
+ tp open generator # Open visual generator
57
+ tp open docs # Open documentation
58
+ ```
59
+
60
+ **History Management:**
61
+ ```bash
62
+ tp history # View workflow execution history
63
+ tp history show # Select and view a specific history
64
+ tp history remove # Remove a specific history
65
+ tp history remove-all # Remove all histories
66
+ ```
48
67
 
49
68
  ## 🚀 Quick Start
50
69
 
51
70
  ### Installation
52
71
 
53
- #### Global Installation
72
+ #### Homebrew (macOS/Linux)
73
+
74
+ Install using Homebrew for the easiest setup on macOS and Linux:
75
+
76
+ ```bash
77
+ # Add the tap (repository)
78
+ brew tap racgoo/task-pipeliner
79
+
80
+ # Install task-pipeliner
81
+ brew install task-pipeliner
82
+ ```
83
+
84
+ After installation, you can run:
85
+ ```bash
86
+ task-pipeliner run workflow.yaml
87
+ # or use the short alias
88
+ tp run workflow.yaml
89
+ ```
90
+
91
+ **Updating:**
92
+ ```bash
93
+ # Update Homebrew's package registry first
94
+ brew update
95
+
96
+ # Then upgrade task-pipeliner
97
+ brew upgrade task-pipeliner
98
+ ```
99
+
100
+ #### Scoop (Windows)
101
+
102
+ Install using Scoop on Windows:
103
+
104
+ ```bash
105
+ # Add the bucket (repository)
106
+ scoop bucket add task-pipeliner https://github.com/racgoo/scoop-task-pipeliner
107
+
108
+ # Install task-pipeliner
109
+ scoop install task-pipeliner
110
+ ```
54
111
 
55
- Install globally to use `task-pipeliner` or `tp` commands directly:
112
+ After installation, you can run:
113
+ ```bash
114
+ task-pipeliner run workflow.yaml
115
+ # or use the short alias
116
+ tp run workflow.yaml
117
+ ```
118
+
119
+ **Updating:**
120
+ ```bash
121
+ scoop update task-pipeliner
122
+ ```
123
+
124
+ #### Global Installation (npm)
125
+
126
+ Install globally using npm to use `task-pipeliner` or `tp` commands directly:
56
127
 
57
128
  ```bash
58
129
  npm install -g task-pipeliner
@@ -177,6 +248,29 @@ tp run workflow.yaml --silent
177
248
  tp run workflow.yaml -s
178
249
  ```
179
250
 
251
+ **Using the `tp` Directory (Recommended):**
252
+
253
+ For better organization, you can create a `tp` directory in your project and place all workflow files there. When you run `tp run` without specifying a file, task-pipeliner will automatically search for the nearest `tp` directory (starting from the current directory and traversing up) and let you select a workflow interactively.
254
+
255
+ ```bash
256
+ # Create a tp directory and add workflow files
257
+ mkdir tp
258
+ mv workflow.yaml tp/
259
+
260
+ # Run without specifying a file - interactive selection
261
+ tp run
262
+ ```
263
+
264
+ This will:
265
+ 1. Find the nearest `tp` directory (current directory or any parent directory)
266
+ 2. List all workflow files (`.yaml`, `.yml`, `.json`) in that directory
267
+ 3. Show an interactive, searchable menu where you can:
268
+ - Type to filter workflows in real-time
269
+ - Use arrow keys (↑↓) to navigate
270
+ - Press Enter to select and run
271
+
272
+ The interactive menu displays both the filename and the workflow's `name` (from the YAML/JSON content) for easy identification.
273
+
180
274
  **Silent Mode:**
181
275
  The `--silent` (or `-s`) flag suppresses all console output during workflow execution. This is useful for:
182
276
  - CI/CD pipelines where you only need exit codes
@@ -355,7 +449,7 @@ steps:
355
449
 
356
450
  #### 2. `choose` - User Choice
357
451
 
358
- Prompt user to select from a list of options.
452
+ Prompt user to select from a list of options. The choice menu includes a **real-time search feature** that allows you to filter options by typing.
359
453
 
360
454
  **Syntax:**
361
455
  ```yaml
@@ -381,6 +475,13 @@ steps:
381
475
  - If provided: selected `id` is stored in this variable name
382
476
  - `when` (optional): `Condition` - Show choice prompt only if condition is met
383
477
 
478
+ **Interactive Features:**
479
+ - **Real-time search**: Type to filter options instantly - only matching options are shown
480
+ - **Arrow key navigation**: Use ↑↓ keys to navigate through options
481
+ - **Enter to select**: Press Enter to confirm your choice
482
+ - **Backspace**: Remove characters from search term
483
+ - **Escape**: Clear search term and show all options
484
+
384
485
  **Examples:**
385
486
  ```yaml
386
487
  # Basic choice
package/dist/index.cjs CHANGED
@@ -1,23 +1,24 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Me=Object.create;var le=Object.defineProperty;var Ne=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var Te=Object.getPrototypeOf,Be=Object.prototype.hasOwnProperty;var De=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ie(e))!Be.call(n,o)&&o!==t&&le(n,o,{get:()=>e[o],enumerable:!(r=Ne(e,o))||r.enumerable});return n};var b=(n,e,t)=>(t=n!=null?Me(Te(n)):{},De(e||!n||!n.__esModule?le(t,"default",{value:n,enumerable:!0}):t,n));var ve=require("child_process"),Re=require("fs"),Ce=require("path"),$e=require("util"),ie=b(require("boxen"),1),u=b(require("chalk"),1),Ee=require("commander"),Pe=b(require("dayjs"),1);var I=require("path"),he=b(require("chalk"),1),Z=b(require("log-update"),1);var K=b(require("chalk"),1),Q=b(require("inquirer"),1),T=class{async prompt(e,t){let{choice:r}=await Q.default.prompt([{type:"list",name:"choice",message:K.default.cyan(e),choices:t.map(s=>({name:s.label,value:s.id}))}]),o=t.find(s=>s.id===r);if(!o)throw new Error(`Invalid choice: ${r}`);return o}},H=class{async prompt(e,t){let{value:r}=await Q.default.prompt([{type:"input",name:"value",message:K.default.cyan(e),default:t}]);return r}};var V=b(require("boxen"),1),B=b(require("chalk"),1);function ee(n,e,t,r={}){let{borderColor:o="cyan",isNested:s=!1}=r,a;e!==void 0&&(t?a=`line ${e} in ${t}`:a=`line ${e}`);let i=s?`\u2502 ${n}`:`> ${n}`;return(0,V.default)(i,{title:a,borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:o})}function D(n,e=!1,t){let r=n?"\u2713 Completed":"\u2717 Failed",o=n?B.default.green(r):B.default.red(r);if(t!==void 0){let s=A(t);return`${o} ${B.default.gray(`(${s})`)}`}return o}function _(n){return(0,V.default)(`\u2717 ${n}`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"red"})}function ce(n){return(0,V.default)(`> Starting parallel execution (${n} branches)`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"yellow"})}function ue(n){let e=n?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return n?B.default.green(e):B.default.red(e)}function te(n,e=!1){return`${e?"| \u2502 ":"\u2502 "}${n}`}function A(n){return`${(n/1e3).toFixed(3)}s`}var pe=require("fs"),me=require("path"),j=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,o]of Object.entries(e.var)){let s=this.workspace.getVariable(r),a=this.workspace.getFact(r),i=s??(a!==void 0?a.toString():void 0);if(i===void 0||i!==o)return!1}return!0}let t=e.var;return this.workspace.hasVariable(t)||this.workspace.hasFact(t)}evaluateFileExists(e){try{let t=e.file.trim(),r=(0,me.resolve)(process.cwd(),t);return(0,pe.existsSync)(r)}catch{return!1}}evaluateChoice(e){return this.workspace.hasChoice(e.choice)}evaluateAll(e){return e.all.every(t=>this.evaluate(t))}evaluateAny(e){return e.any.some(t=>this.evaluate(t))}evaluateNot(e){return!this.evaluate(e.not)}};var S=require("fs/promises"),fe=require("os"),N=require("path"),de=b(require("dayjs"),1),L=(0,N.join)((0,fe.homedir)(),".pipeliner","workflow-history"),F=class{constructor(){}async saveHistory(e){await(0,S.mkdir)(L,{recursive:!0});let t=(0,de.default)().format("YYYY-MM-DD_HH-mm-ss"),r=Math.random().toString(36).slice(2,6),o=(0,N.join)(L,`workflow-${t}-${r}.json`);return await(0,S.writeFile)(o,JSON.stringify(e,null,2),{encoding:"utf8"}),o}async clearAllHistories(){await(0,S.rm)(L,{recursive:!0,force:!0})}async removeHistory(e){await(0,S.rm)((0,N.join)(L,e),{force:!0})}async getHistoryNames(){try{let t=(await(0,S.readdir)(L)).map(r=>(0,N.basename)(r));return t.sort((r,o)=>{let s=p=>{let c=p.match(/workflow-(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})-/);return c?c[1]:""},a=s(r),i=s(o);return a===i?o.localeCompare(r):i.localeCompare(a)}),t}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async getHistory(e){let t=await(0,S.readFile)((0,N.join)(L,e),{encoding:"utf8"});return JSON.parse(t)}};var J=class{records=[];initialTimestamp=Date.now();recordStartTimestamp=Date.now();constructor(){this.records=[]}recordStart(){this.recordStartTimestamp=Date.now()}recordEnd(e,t,r,o){let s=this.getDuration();return this.records.push({step:e,context:t,output:r,duration:s,status:o}),s}reset(){this.records=[],this.initialTimestamp=Date.now()}async save(){let e=new F,t={initialTimestamp:this.initialTimestamp,records:this.records};return await e.saveHistory(t)}getDuration(){return Date.now()-this.recordStartTimestamp}};var Y=class{async run(e,t,r,o,s=!1,a=!1,i,p,c,m){return s?this.runBuffered(e,c,m):this.runRealtime(e,r||e,a,i,p,c,m)}async runBuffered(e,t,r){let{spawn:o}=await import("child_process"),[s,...a]=this.parseCommand(e),i=this.createSpawnOptions(t);return new Promise((p,c)=>{let m=o(s,a,i),h=[],f=[],d="",w="",v=null;r&&r>0&&(v=setTimeout(()=>{m.kill("SIGTERM");let g=`Command timed out after ${r} seconds`;f.push(g),p({success:!1,stdout:h,stderr:f})},r*1e3)),m.stdout?.on("data",g=>{let y=g.toString(),{lines:$,remaining:R}=this.processStreamBuffer(y,d);h.push(...$),d=R}),m.stderr?.on("data",g=>{let y=g.toString(),{lines:$,remaining:R}=this.processStreamBuffer(y,w);f.push(...$),w=R}),m.on("close",g=>{v&&clearTimeout(v),d.trim()&&h.push(d),w.trim()&&f.push(w),p({success:g===0,stdout:h,stderr:f})}),m.on("error",g=>{v&&clearTimeout(v);let y=`Error: ${g.message}`;p({success:!1,stdout:h,stderr:[...f,y]})})})}async runRealtime(e,t,r,o,s,a,i){let{spawn:p}=await import("child_process"),[c,...m]=this.parseCommand(e),h=this.createSpawnOptions(a),d=ee(t,o,s,{borderColor:r?"green":"cyan"});console.log(d);let w=Date.now();return new Promise(v=>{let g=p(c,m,h),y="",$="",R=null;i&&i>0&&(R=setTimeout(()=>{g.kill("SIGTERM");let C=`Command timed out after ${i} seconds`,k=_(C);console.error(k);let P=Date.now()-w,M=D(!1,!1,P);console.log(M),v(!1)},i*1e3)),g.stdout?.on("data",C=>{let k=C.toString(),{lines:P,remaining:M}=this.processStreamBuffer(k,y);P.forEach(q=>process.stdout.write(`\u2502 ${q}
3
- `)),y=M}),g.stderr?.on("data",C=>{let k=C.toString(),{lines:P,remaining:M}=this.processStreamBuffer(k,$);P.forEach(q=>process.stderr.write(`\u2502 ${q}
4
- `)),$=M}),g.on("close",C=>{R&&clearTimeout(R),y.trim()&&process.stdout.write(`\u2502 ${y}
5
- `),$.trim()&&process.stderr.write(`\u2502 ${$}
6
- `);let k=C===0,P=Date.now()-w,M=D(k,!1,P);console.log(M),v(k)}),g.on("error",C=>{R&&clearTimeout(R);let k=_(`Error: ${C.message}`);console.error(k),v(!1)})})}parseCommand(e){let t=e.split(" ");return[t[0],...t.slice(1)]}createSpawnOptions(e){let t={stdio:["inherit","pipe","pipe"],shell:!0};return e&&(t.cwd=e),t}processStreamBuffer(e,t){let r=t+e,o=[],s=r;for(;s.includes(`
7
- `);){let a=s.indexOf(`
8
- `),i=s.substring(0,a);s=s.substring(a+1),o.push(i)}return{lines:o,remaining:s}}formatNestedOutput(e,t){t?e.split(`
9
- `).forEach(r=>{r.trim()&&console.log(`| ${r}`)}):console.log(e)}displayBufferedOutput(e,t,r=!1,o,s){let a=ee(t,o,s,{borderColor:"cyan",isNested:r});this.formatNestedOutput(a,r),e.stdout.forEach(p=>{let c=te(p,r);process.stdout.write(`${c}
10
- `)}),e.stderr.forEach(p=>{let c=te(p,r);process.stderr.write(`${c}
11
- `)});let i=D(e.success,r);console.log(i)}};function Ae(n,e,t){if(e.hasVariable(n))return e.getVariable(n)||t;if(e.hasFact(n)){let r=e.getFact(n);return typeof r=="string"?r:String(r)}return e.hasChoice(n)&&e.getChoice(n)||t}function U(n,e){let t=/\{\{(\w+)\}\}/g;return n.replace(t,(r,o)=>Ae(o,e,r))}var z=class n{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,t){this.state.facts.set(e,t)}getFactStatus(e){if(!this.hasFact(e))return"pending";let t=this.getFact(e);return t===!1||t==="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,t){this.state.choices.set(e,t)}hasVariable(e){return this.state.variables.has(e)}getVariable(e){return this.state.variables.get(e)}setVariable(e,t){this.state.variables.set(e,t)}getAllVariables(){return new Map(this.state.variables)}setStepResult(e,t,r){this.state.stepResults.set(e,{success:t,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 n;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 G=class n{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;constructor(){this.workspace=new z,this.taskRunner=new Y,this.choicePrompt=new T,this.textPrompt=new H}resolveBaseDir(e){if(e.baseDir)if((0,I.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,I.dirname)(e._filePath);this.baseDir=(0,I.resolve)(t,e.baseDir)}else this.baseDir=(0,I.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let r={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(r.lineNumber=t._lineNumbers.get(e)),t._fileName&&(r.fileName=t._fileName),r}evaluateStepCondition(e){return e.when?new j(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/n.PARALLEL_STEP_INDEX_MULTIPLIER)}isRunStep(e){return"run"in e}async execute(e){this.resolveBaseDir(e);let t=new J,r=Date.now();for(let a=0;a<e.steps.length;a++){let i=e.steps[a],p=this.createStepContext(a,e),c=!!i.when;if(this.evaluateStepCondition(i)){t.recordStart();try{let m=await this.executeStep(i,p,!1,c);this.handleStepResult(i,p,a,m,t)}catch(m){throw this.handleStepError(i,p,a,m,t),m}}}let o=Date.now()-r,s=A(o);console.log(he.default.cyan(`
12
- Total execution time: ${s}`)),await t.save(),t.reset()}isStepSuccessful(e,t){return"run"in t?typeof e=="boolean"?e:e&&typeof e=="object"&&"success"in e?e.success:!1:!0}handleStepResult(e,t,r,o,s){let a=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(r);return c?c.success:!0})():this.isStepSuccessful(o,e),i=a?"success":"failure",p=s.recordEnd(e,t,o,i);if(!this.isRunStep(e)){let c=D(a,!1,p);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",m=a?`Step ${r}${c} completed, but workflow stopped due to continue: false`:`Step ${r}${c} failed`;throw new Error(m)}if(!a&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${r}${c} failed`)}}}handleStepError(e,t,r,o,s){this.workspace.setStepResult(r,!1);let a=o instanceof Error?o.message:String(o),i={success:!1,stdout:[],stderr:[a]};s.recordEnd(e,t,i,"failure")}fixMalformedStep(e){let r=e;return"choose"in e&&r.choose===null&&"message"in e&&"options"in e?{choose:{message:r.message,options:r.options,as:r.as},when:r.when}:"prompt"in e&&r.prompt===null&&"message"in e&&"as"in e?{prompt:{message:r.message,as:r.as,default:r.default},when:r.when}:e}async executeStep(e,t,r=!1,o=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,r,o);return r&&typeof s=="object"&&"stdout"in s,s}if("choose"in e){await this.executeChooseStep(e,t);return}if("prompt"in e){await this.executePromptStep(e,t);return}if("parallel"in e){await this.executeParallelStep(e,t);return}if("fail"in e){await this.executeFailStep(e,t);return}}async executeSingleRun(e,t,r=!1,o=!1){let s=this.calculateBaseStepIndex(t),a=U(e.run,this.workspace),i=e.retry??0,p=e.timeout,c=!1,m=0;for(;m<=i;){let h=await this.taskRunner.run(a,s,a,t.branchIndex,r,o,t.lineNumber,t.fileName,this.baseDir,p),f=typeof h=="boolean"?h:h.success;if(c=h,f||m>=i)break;if(m++,m<=i){let d=Math.min(1e3*Math.pow(2,m-1),1e4);await new Promise(w=>setTimeout(w,d))}}return c}async executeRunStep(e,t,r=!1,o=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry},t,r,o),a=typeof s=="boolean"?s:s.success;if(this.workspace.setStepResult(t.stepIndex,a),a||!e.onError)return s;let i={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await this.executeRunChain(i,t,r,o)}async executeRunChain(e,t,r,o){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry},t,r,o);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,r,o)}async executeChooseStep(e,t){let r=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!r?.id)throw new Error(`Invalid choice result: ${JSON.stringify(r)}`);let o=e.choose.as??r.id;this.workspace.setChoice(r.id,r.id),this.workspace.setVariable(o,r.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let r=U(e.prompt.message,this.workspace),o=e.prompt.default?U(e.prompt.default,this.workspace):void 0,s=await this.textPrompt.prompt(r,o);this.workspace.setVariable(e.prompt.as,s),this.workspace.setFact(e.prompt.as,s),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((r,o)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*n.PARALLEL_STEP_INDEX_MULTIPLIER+o,branchIndex:o,lineNumber:t.lineNumber,fileName:t.fileName}))}getBranchDisplayName(e,t){return"run"in e?e.run:"choose"in e?`Choose: ${e.choose.message}`:"prompt"in e?`Prompt: ${e.prompt.message}`:"fail"in e?`Fail: ${e.fail.message}`:`Branch ${t+1}`}async executeParallelBranches(e,t){let r=[],o=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let c=0;c<e.length;c++){let m=e[c],h=t[c];if(m.when&&!new j(h.workspace).evaluate(m.when))continue;let f=this.getBranchDisplayName(m,c);r.push({index:c,name:f,status:"pending"})}let a=setInterval(()=>{s=(s+1)%o.length,this.updateParallelBranchesDisplay(r,o[s])},100),i=r.map(async c=>{let{index:m}=c,h=e[m],f=t[m];c.status="running";try{let d=await this.executeStep(h,f,!0);return c.status="success",this.updateParallelBranchesDisplay(r,o[s]),{index:m,result:d,context:f}}catch(d){f.workspace.setStepResult(f.stepIndex,!1);let w=d instanceof Error?d.message:String(d);return c.status="failed",c.error=w,this.updateParallelBranchesDisplay(r,o[s]),{index:m,error:d,context:f}}}),p=await Promise.all(i);return clearInterval(a),this.updateParallelBranchesDisplay(r,"",!0),Z.default.done(),p}updateParallelBranchesDisplay(e,t,r=!1){let o=e.map(s=>{let a=s.index+1,i="",p="";switch(s.status){case"pending":i="\u25CB",p=`Branch ${a}: ${s.name} - Pending`;break;case"running":i=t,p=`Branch ${a}: ${s.name} - Running...`;break;case"success":i="\u2713",p=`Branch ${a}: ${s.name} - Completed`;break;case"failed":i="\u2717",p=`Branch ${a}: ${s.name} - Failed${s.error?`: ${s.error}`:""}`;break}return`${i} ${p}`});r?(0,Z.default)(o.join(`
13
- `)):(0,Z.default)(o.join(`
14
- `))}displayParallelResults(e,t,r){let o=!0,s=!1;console.log("");for(let i of e){if(!i)continue;s=!0;let{index:p,result:c,error:m,context:h}=i;if(m){o=!1;let f=`Branch ${p+1} failed: ${m instanceof Error?m.message:String(m)}`,d=_(f);console.error(d)}else if(c&&typeof c=="object"&&"stdout"in c){let f=c;if(o=o&&f.success,f.stdout.length>0||f.stderr.length>0||!f.success){let d=t[p],w=this.getBranchDisplayName(d,p);this.taskRunner.displayBufferedOutput(f,w,!1,h.lineNumber,h.fileName)}}}s||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let a=ue(o);return console.log(a),o}mergeParallelResults(e){for(let t of e){let r=t.workspace.getAllFacts(),o=t.workspace.getAllVariables();for(let[s,a]of r)this.workspace.setFact(s,a);for(let[s,a]of o)this.workspace.setVariable(s,a)}}countExecutableBranches(e,t){let r=0;for(let o=0;o<e.length;o++){let s=e[o],a=t[o];s.when&&!new j(a.workspace).evaluate(s.when)||r++}return r}async executeParallelStep(e,t){let r=this.createParallelContexts(e,t),o=this.countExecutableBranches(e.parallel,r),s=ce(o);console.log(s);let a=await this.executeParallelBranches(e.parallel,r),i=this.displayParallelResults(a,e.parallel,t);if(this.workspace.setStepResult(t.stepIndex,i),!i){let p=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Parallel step ${t.stepIndex}${p} failed: one or more branches failed`)}this.mergeParallelResults(r)}async executeFailStep(e,t){let r=new Error(e.fail.message);throw r.stack=void 0,r}};var be=require("yaml"),ne=require("zod");var l=require("zod"),je=l.z.object({file:l.z.string()}),Le=l.z.object({var:l.z.union([l.z.string(),l.z.record(l.z.string(),l.z.string())]).optional(),has:l.z.string().optional()}),Fe=l.z.object({status:l.z.object({fact:l.z.string(),is:l.z.enum(["ready","failed","pending"])})}),We=l.z.object({step:l.z.object({success:l.z.boolean()}).optional(),last_step:l.z.enum(["success","failure"]).optional()}),_e=l.z.object({choice:l.z.string()}),Oe=l.z.union([je,_e,Le,Fe,We]),E=l.z.lazy(()=>l.z.union([Oe,l.z.object({all:l.z.array(E)}),l.z.object({any:l.z.array(E)}),l.z.object({not:E})])),ge=l.z.lazy(()=>l.z.object({run:l.z.string(),timeout:l.z.number().optional(),retry:l.z.number().optional(),onError:ge.optional()})),He=l.z.object({run:l.z.string(),when:E.optional(),timeout:l.z.number().optional(),retry:l.z.number().optional(),continue:l.z.boolean().optional(),onError:ge.optional()}),Ve=l.z.object({choose:l.z.object({message:l.z.string(),options:l.z.array(l.z.object({id:l.z.string(),label:l.z.string()})),as:l.z.string().optional()}),when:E.optional()}),Je=l.z.object({prompt:l.z.object({message:l.z.string(),as:l.z.string(),default:l.z.string().optional(),validate:l.z.string().optional()}),when:E.optional()}),we=l.z.lazy(()=>l.z.union([He,Ve,Je,l.z.object({parallel:l.z.array(we),when:E.optional()}),l.z.object({fail:l.z.object({message:l.z.string()}),when:E.optional()})])),Ye=l.z.object({name:l.z.string().optional(),baseDir:l.z.string().optional(),steps:l.z.array(we).min(1,"Workflow must have at least one step")});function re(n){return Ye.parse(n)}function se(n){let e=n;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(t=>se(t))}:n}var X=class{parse(e){let t;try{t=(0,be.parse)(e)}catch(r){throw new Error(`Invalid YAML 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(o=>se(o)))}try{return re(t)}catch(r){if(r instanceof ne.ZodError){let o=r.issues.map(s=>{let a=s.path.length>0?` at ${s.path.join(".")}`:"";return` - ${s.message}${a}`}).join(`
2
+ "use strict";var Ie=Object.create;var pe=Object.defineProperty;var De=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var je=Object.getPrototypeOf,Fe=Object.prototype.hasOwnProperty;var Le=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ae(e))!Fe.call(s,o)&&o!==t&&pe(s,o,{get:()=>e[o],enumerable:!(r=De(e,o))||r.enumerable});return s};var x=(s,e,t)=>(t=s!=null?Ie(je(s)):{},Le(e||!s||!s.__esModule?pe(t,"default",{value:s,enumerable:!0}):t,s));var Pe=require("child_process"),ce=require("fs"),Me=require("fs/promises"),O=require("path"),Ne=require("util"),ue=x(require("boxen"),1),u=x(require("chalk"),1),Te=require("commander"),Be=x(require("dayjs"),1);var D=require("path"),xe=x(require("chalk"),1),X=x(require("log-update"),1);var fe=x(require("readline"),1),S=x(require("chalk"),1),ee=x(require("inquirer"),1),me=15,B=class{searchable;constructor(e=!1){this.searchable=e}async prompt(e,t){if(this.searchable)return this.promptWithSearch(e,t);let{choice:r}=await ee.default.prompt([{type:"list",name:"choice",message:S.default.cyan(e),choices:t.map(n=>({name:n.label,value:n.id})),pageSize:me}]),o=t.find(n=>n.id===r);if(!o)throw new Error(`Invalid choice: ${r}`);return o}async promptWithSearch(e,t){return new Promise(r=>{let o="",n=0,i=[...t],a=fe.createInterface({input:process.stdin,output:process.stdout,terminal:!0});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdout.write("\x1B[?1049h"),process.stdout.write("\x1B[?25l");let p=()=>{process.stdout.write("\x1B[H\x1B[2J"),console.log(S.default.cyan(`? ${e}`));let d=o?S.default.gray(` Filter: ${o}`)+S.default.gray(` (${i.length}/${t.length})`):S.default.gray(" Type to filter, \u2191\u2193 to navigate, Enter to select");console.log(d),console.log();let f=me,h=0,g=i.length;if(i.length>f){let b=Math.floor(f/2);h=Math.max(0,n-b),g=Math.min(i.length,h+f),g===i.length&&(h=Math.max(0,g-f))}if(i.length===0)console.log(S.default.yellow(" No matches found"));else{h>0&&console.log(S.default.gray(` \u2191 ${h} more above`));for(let b=h;b<g;b++){let w=i[b];console.log(b===n?S.default.cyan(`\u276F ${w.label}`):S.default.white(` ${w.label}`))}g<i.length&&console.log(S.default.gray(` \u2193 ${i.length-g} more below`))}},l=()=>{let d=o.toLowerCase();i=d?t.filter(f=>f.label.toLowerCase().includes(d)):[...t],n>=i.length&&(n=Math.max(0,i.length-1))},m=()=>{process.stdin.isTTY&&process.stdin.setRawMode(!1),a.close(),process.stdout.write("\x1B[?25h"),process.stdout.write("\x1B[?1049l")};p(),process.stdin.on("data",d=>{let f=d.toString();if(f===""&&(m(),process.exit(0)),f==="\r"||f===`
3
+ `){i.length>0&&(m(),r(i[n]));return}if(f==="\x1B"&&d.length===1){o&&(o="",l(),p());return}if(f==="\x1B[A"){i.length>0&&(n=n>0?n-1:i.length-1,p());return}if(f==="\x1B[B"){i.length>0&&(n=n<i.length-1?n+1:0,p());return}if(f==="\x7F"||f==="\b"){o.length>0&&(o=o.slice(0,-1),l(),p());return}f.length===1&&f>=" "&&f<="~"&&(o+=f,l(),p())})})}},J=class{async prompt(e,t){let{value:r}=await ee.default.prompt([{type:"input",name:"value",message:S.default.cyan(e),default:t}]);return r}};var Y=x(require("boxen"),1),A=x(require("chalk"),1);function te(s,e,t,r={}){let{borderColor:o="cyan",isNested:n=!1}=r,i;e!==void 0&&(t?i=`line ${e} in ${t}`:i=`line ${e}`);let a=n?`\u2502 ${s}`:`> ${s}`;return(0,Y.default)(a,{title:i,borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:o})}function j(s,e=!1,t){let r=s?"\u2713 Completed":"\u2717 Failed",o=s?A.default.green(r):A.default.red(r);if(t!==void 0){let n=F(t);return`${o} ${A.default.gray(`(${n})`)}`}return o}function H(s){return(0,Y.default)(`\u2717 ${s}`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"red"})}function de(s){return(0,Y.default)(`> Starting parallel execution (${s} branches)`,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"yellow"})}function he(s){let e=s?"\u2713 All parallel branches completed":"\u2717 Some parallel branches failed";return s?A.default.green(e):A.default.red(e)}function re(s,e=!1){return`${e?"| \u2502 ":"\u2502 "}${s}`}function F(s){return`${(s/1e3).toFixed(3)}s`}var ge=require("fs"),we=require("path"),L=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,o]of Object.entries(e.var)){let n=this.workspace.getVariable(r),i=this.workspace.getFact(r),a=n??(i!==void 0?i.toString():void 0);if(a===void 0||a!==o)return!1}return!0}let t=e.var;return this.workspace.hasVariable(t)||this.workspace.hasFact(t)}evaluateFileExists(e){try{let t=e.file.trim(),r=(0,we.resolve)(process.cwd(),t);return(0,ge.existsSync)(r)}catch{return!1}}evaluateChoice(e){return this.workspace.hasChoice(e.choice)}evaluateAll(e){return e.all.every(t=>this.evaluate(t))}evaluateAny(e){return e.any.some(t=>this.evaluate(t))}evaluateNot(e){return!this.evaluate(e.not)}};var v=require("fs/promises"),be=require("os"),I=require("path"),ye=x(require("dayjs"),1),W=(0,I.join)((0,be.homedir)(),".pipeliner","workflow-history"),_=class{constructor(){}async saveHistory(e){await(0,v.mkdir)(W,{recursive:!0});let t=(0,ye.default)().format("YYYY-MM-DD_HH-mm-ss"),r=Math.random().toString(36).slice(2,6),o=(0,I.join)(W,`workflow-${t}-${r}.json`);return await(0,v.writeFile)(o,JSON.stringify(e,null,2),{encoding:"utf8"}),o}async clearAllHistories(){await(0,v.rm)(W,{recursive:!0,force:!0})}async removeHistory(e){await(0,v.rm)((0,I.join)(W,e),{force:!0})}async getHistoryNames(){try{let t=(await(0,v.readdir)(W)).map(r=>(0,I.basename)(r));return t.sort((r,o)=>{let n=p=>{let l=p.match(/workflow-(\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2})-/);return l?l[1]:""},i=n(r),a=n(o);return i===a?o.localeCompare(r):a.localeCompare(i)}),t}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return[];throw e}}async getHistory(e){let t=await(0,v.readFile)((0,I.join)(W,e),{encoding:"utf8"});return JSON.parse(t)}};var U=class{records=[];initialTimestamp=Date.now();recordStartTimestamp=Date.now();constructor(){this.records=[]}recordStart(){this.recordStartTimestamp=Date.now()}recordEnd(e,t,r,o){let n=this.getDuration();return this.records.push({step:e,context:t,output:r,duration:n,status:o}),n}reset(){this.records=[],this.initialTimestamp=Date.now()}async save(){let e=new _,t={initialTimestamp:this.initialTimestamp,records:this.records};return await e.saveHistory(t)}getDuration(){return Date.now()-this.recordStartTimestamp}};var z=class{async run(e,t,r,o,n=!1,i=!1,a,p,l,m){return n?this.runBuffered(e,l,m):this.runRealtime(e,r||e,i,a,p,l,m)}async runBuffered(e,t,r){let{spawn:o}=await import("child_process"),[n,...i]=this.parseCommand(e),a=this.createSpawnOptions(t);return new Promise((p,l)=>{let m=o(n,i,a),d=[],f=[],h="",g="",b=null;r&&r>0&&(b=setTimeout(()=>{m.kill("SIGTERM");let w=`Command timed out after ${r} seconds`;f.push(w),p({success:!1,stdout:d,stderr:f})},r*1e3)),m.stdout?.on("data",w=>{let k=w.toString(),{lines:P,remaining:$}=this.processStreamBuffer(k,h);d.push(...P),h=$}),m.stderr?.on("data",w=>{let k=w.toString(),{lines:P,remaining:$}=this.processStreamBuffer(k,g);f.push(...P),g=$}),m.on("close",w=>{b&&clearTimeout(b),h.trim()&&d.push(h),g.trim()&&f.push(g),p({success:w===0,stdout:d,stderr:f})}),m.on("error",w=>{b&&clearTimeout(b);let k=`Error: ${w.message}`;p({success:!1,stdout:d,stderr:[...f,k]})})})}async runRealtime(e,t,r,o,n,i,a){let{spawn:p}=await import("child_process"),[l,...m]=this.parseCommand(e),d=this.createSpawnOptions(i),h=te(t,o,n,{borderColor:r?"green":"cyan"});console.log(h);let g=Date.now();return new Promise(b=>{let w=p(l,m,d),k="",P="",$=null;a&&a>0&&($=setTimeout(()=>{w.kill("SIGTERM");let C=`Command timed out after ${a} seconds`,R=H(C);console.error(R);let N=Date.now()-g,T=j(!1,!1,N);console.log(T),b(!1)},a*1e3)),w.stdout?.on("data",C=>{let R=C.toString(),{lines:N,remaining:T}=this.processStreamBuffer(R,k);N.forEach(Q=>process.stdout.write(`\u2502 ${Q}
4
+ `)),k=T}),w.stderr?.on("data",C=>{let R=C.toString(),{lines:N,remaining:T}=this.processStreamBuffer(R,P);N.forEach(Q=>process.stderr.write(`\u2502 ${Q}
5
+ `)),P=T}),w.on("close",C=>{$&&clearTimeout($),k.trim()&&process.stdout.write(`\u2502 ${k}
6
+ `),P.trim()&&process.stderr.write(`\u2502 ${P}
7
+ `);let R=C===0,N=Date.now()-g,T=j(R,!1,N);console.log(T),b(R)}),w.on("error",C=>{$&&clearTimeout($);let R=H(`Error: ${C.message}`);console.error(R),b(!1)})})}parseCommand(e){let t=e.split(" ");return[t[0],...t.slice(1)]}createSpawnOptions(e){let t={stdio:["inherit","pipe","pipe"],shell:!0};return e&&(t.cwd=e),t}processStreamBuffer(e,t){let r=t+e,o=[],n=r;for(;n.includes(`
8
+ `);){let i=n.indexOf(`
9
+ `),a=n.substring(0,i);n=n.substring(i+1),o.push(a)}return{lines:o,remaining:n}}formatNestedOutput(e,t){t?e.split(`
10
+ `).forEach(r=>{r.trim()&&console.log(`| ${r}`)}):console.log(e)}displayBufferedOutput(e,t,r=!1,o,n){let i=te(t,o,n,{borderColor:"cyan",isNested:r});this.formatNestedOutput(i,r),e.stdout.forEach(p=>{let l=re(p,r);process.stdout.write(`${l}
11
+ `)}),e.stderr.forEach(p=>{let l=re(p,r);process.stderr.write(`${l}
12
+ `)});let a=j(e.success,r);console.log(a)}};function We(s,e,t){if(e.hasVariable(s))return e.getVariable(s)||t;if(e.hasFact(s)){let r=e.getFact(s);return typeof r=="string"?r:String(r)}return e.hasChoice(s)&&e.getChoice(s)||t}function Z(s,e){let t=/\{\{(\w+)\}\}/g;return s.replace(t,(r,o)=>We(o,e,r))}var G=class s{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,t){this.state.facts.set(e,t)}getFactStatus(e){if(!this.hasFact(e))return"pending";let t=this.getFact(e);return t===!1||t==="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,t){this.state.choices.set(e,t)}hasVariable(e){return this.state.variables.has(e)}getVariable(e){return this.state.variables.get(e)}setVariable(e,t){this.state.variables.set(e,t)}getAllVariables(){return new Map(this.state.variables)}setStepResult(e,t,r){this.state.stepResults.set(e,{success:t,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 s;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 q=class s{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;constructor(){this.workspace=new G,this.taskRunner=new z,this.choicePrompt=new B,this.textPrompt=new J}resolveBaseDir(e){if(e.baseDir)if((0,D.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,D.dirname)(e._filePath);this.baseDir=(0,D.resolve)(t,e.baseDir)}else this.baseDir=(0,D.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let r={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(r.lineNumber=t._lineNumbers.get(e)),t._fileName&&(r.fileName=t._fileName),r}evaluateStepCondition(e){return e.when?new L(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/s.PARALLEL_STEP_INDEX_MULTIPLIER)}isRunStep(e){return"run"in e}async execute(e){this.resolveBaseDir(e);let t=new U,r=Date.now();for(let i=0;i<e.steps.length;i++){let a=e.steps[i],p=this.createStepContext(i,e),l=!!a.when;if(this.evaluateStepCondition(a)){t.recordStart();try{let m=await this.executeStep(a,p,!1,l);this.handleStepResult(a,p,i,m,t)}catch(m){throw this.handleStepError(a,p,i,m,t),m}}}let o=Date.now()-r,n=F(o);console.log(xe.default.cyan(`
13
+ Total execution time: ${n}`)),await t.save(),t.reset()}isStepSuccessful(e,t){return"run"in t?typeof e=="boolean"?e:e&&typeof e=="object"&&"success"in e?e.success:!1:!0}handleStepResult(e,t,r,o,n){let i=this.isRunStep(e)?(()=>{let l=this.workspace.getStepResult(r);return l?l.success:!0})():this.isStepSuccessful(o,e),a=i?"success":"failure",p=n.recordEnd(e,t,o,a);if(!this.isRunStep(e)){let l=j(i,!1,p);console.log(l)}if(this.isRunStep(e)){if(e.continue===!1){let l=t.lineNumber?` (line ${t.lineNumber})`:"",m=i?`Step ${r}${l} completed, but workflow stopped due to continue: false`:`Step ${r}${l} failed`;throw new Error(m)}if(!i&&e.continue!==!0){let l=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${r}${l} failed`)}}}handleStepError(e,t,r,o,n){this.workspace.setStepResult(r,!1);let i=o instanceof Error?o.message:String(o),a={success:!1,stdout:[],stderr:[i]};n.recordEnd(e,t,a,"failure")}fixMalformedStep(e){let r=e;return"choose"in e&&r.choose===null&&"message"in e&&"options"in e?{choose:{message:r.message,options:r.options,as:r.as},when:r.when}:"prompt"in e&&r.prompt===null&&"message"in e&&"as"in e?{prompt:{message:r.message,as:r.as,default:r.default},when:r.when}:e}async executeStep(e,t,r=!1,o=!1){if(e=this.fixMalformedStep(e),"run"in e){let n=await this.executeRunStep(e,t,r,o);return r&&typeof n=="object"&&"stdout"in n,n}if("choose"in e){await this.executeChooseStep(e,t);return}if("prompt"in e){await this.executePromptStep(e,t);return}if("parallel"in e){await this.executeParallelStep(e,t);return}if("fail"in e){await this.executeFailStep(e,t);return}}async executeSingleRun(e,t,r=!1,o=!1){let n=this.calculateBaseStepIndex(t),i=Z(e.run,this.workspace),a=e.retry??0,p=e.timeout,l=!1,m=0;for(;m<=a;){let d=await this.taskRunner.run(i,n,i,t.branchIndex,r,o,t.lineNumber,t.fileName,this.baseDir,p),f=typeof d=="boolean"?d:d.success;if(l=d,f||m>=a)break;if(m++,m<=a){let h=Math.min(1e3*Math.pow(2,m-1),1e4);await new Promise(g=>setTimeout(g,h))}}return l}async executeRunStep(e,t,r=!1,o=!1){let n=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry},t,r,o),i=typeof n=="boolean"?n:n.success;if(this.workspace.setStepResult(t.stepIndex,i),i||!e.onError)return n;let a={run:e.onError.run,timeout:e.onError.timeout,retry:e.onError.retry,onError:e.onError.onError??void 0};return await this.executeRunChain(a,t,r,o)}async executeRunChain(e,t,r,o){let n=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry},t,r,o);return(typeof n=="boolean"?n:n.success)||!e.onError?n:this.executeRunChain(e.onError,t,r,o)}async executeChooseStep(e,t){let r=await this.choicePrompt.prompt(e.choose.message,e.choose.options);if(!r?.id)throw new Error(`Invalid choice result: ${JSON.stringify(r)}`);let o=e.choose.as??r.id;this.workspace.setChoice(r.id,r.id),this.workspace.setVariable(o,r.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let r=Z(e.prompt.message,this.workspace),o=e.prompt.default?Z(e.prompt.default,this.workspace):void 0,n=await this.textPrompt.prompt(r,o);this.workspace.setVariable(e.prompt.as,n),this.workspace.setFact(e.prompt.as,n),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((r,o)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*s.PARALLEL_STEP_INDEX_MULTIPLIER+o,branchIndex:o,lineNumber:t.lineNumber,fileName:t.fileName}))}getBranchDisplayName(e,t){return"run"in e?e.run:"choose"in e?`Choose: ${e.choose.message}`:"prompt"in e?`Prompt: ${e.prompt.message}`:"fail"in e?`Fail: ${e.fail.message}`:`Branch ${t+1}`}async executeParallelBranches(e,t){let r=[],o=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],n=0;for(let l=0;l<e.length;l++){let m=e[l],d=t[l];if(m.when&&!new L(d.workspace).evaluate(m.when))continue;let f=this.getBranchDisplayName(m,l);r.push({index:l,name:f,status:"pending"})}let i=setInterval(()=>{n=(n+1)%o.length,this.updateParallelBranchesDisplay(r,o[n])},100),a=r.map(async l=>{let{index:m}=l,d=e[m],f=t[m];l.status="running";try{let h=await this.executeStep(d,f,!0);return l.status="success",this.updateParallelBranchesDisplay(r,o[n]),{index:m,result:h,context:f}}catch(h){f.workspace.setStepResult(f.stepIndex,!1);let g=h instanceof Error?h.message:String(h);return l.status="failed",l.error=g,this.updateParallelBranchesDisplay(r,o[n]),{index:m,error:h,context:f}}}),p=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(r,"",!0),X.default.done(),p}updateParallelBranchesDisplay(e,t,r=!1){let o=e.map(n=>{let i=n.index+1,a="",p="";switch(n.status){case"pending":a="\u25CB",p=`Branch ${i}: ${n.name} - Pending`;break;case"running":a=t,p=`Branch ${i}: ${n.name} - Running...`;break;case"success":a="\u2713",p=`Branch ${i}: ${n.name} - Completed`;break;case"failed":a="\u2717",p=`Branch ${i}: ${n.name} - Failed${n.error?`: ${n.error}`:""}`;break}return`${a} ${p}`});r?(0,X.default)(o.join(`
14
+ `)):(0,X.default)(o.join(`
15
+ `))}displayParallelResults(e,t,r){let o=!0,n=!1;console.log("");for(let a of e){if(!a)continue;n=!0;let{index:p,result:l,error:m,context:d}=a;if(m){o=!1;let f=`Branch ${p+1} failed: ${m instanceof Error?m.message:String(m)}`,h=H(f);console.error(h)}else if(l&&typeof l=="object"&&"stdout"in l){let f=l;if(o=o&&f.success,f.stdout.length>0||f.stderr.length>0||!f.success){let h=t[p],g=this.getBranchDisplayName(h,p);this.taskRunner.displayBufferedOutput(f,g,!1,d.lineNumber,d.fileName)}}}n||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let i=he(o);return console.log(i),o}mergeParallelResults(e){for(let t of e){let r=t.workspace.getAllFacts(),o=t.workspace.getAllVariables();for(let[n,i]of r)this.workspace.setFact(n,i);for(let[n,i]of o)this.workspace.setVariable(n,i)}}countExecutableBranches(e,t){let r=0;for(let o=0;o<e.length;o++){let n=e[o],i=t[o];n.when&&!new L(i.workspace).evaluate(n.when)||r++}return r}async executeParallelStep(e,t){let r=this.createParallelContexts(e,t),o=this.countExecutableBranches(e.parallel,r),n=de(o);console.log(n);let i=await this.executeParallelBranches(e.parallel,r),a=this.displayParallelResults(i,e.parallel,t);if(this.workspace.setStepResult(t.stepIndex,a),!a){let p=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Parallel step ${t.stepIndex}${p} failed: one or more branches failed`)}this.mergeParallelResults(r)}async executeFailStep(e,t){let r=new Error(e.fail.message);throw r.stack=void 0,r}};var ve=require("yaml"),se=require("zod");var c=require("zod"),_e=c.z.object({file:c.z.string()}),Oe=c.z.object({var:c.z.union([c.z.string(),c.z.record(c.z.string(),c.z.string())]).optional(),has:c.z.string().optional()}),He=c.z.object({status:c.z.object({fact:c.z.string(),is:c.z.enum(["ready","failed","pending"])})}),Ve=c.z.object({step:c.z.object({success:c.z.boolean()}).optional(),last_step:c.z.enum(["success","failure"]).optional()}),Je=c.z.object({choice:c.z.string()}),Ye=c.z.union([_e,Je,Oe,He,Ve]),M=c.z.lazy(()=>c.z.union([Ye,c.z.object({all:c.z.array(M)}),c.z.object({any:c.z.array(M)}),c.z.object({not:M})])),Se=c.z.lazy(()=>c.z.object({run:c.z.string(),timeout:c.z.number().optional(),retry:c.z.number().optional(),onError:Se.optional()})),Ue=c.z.object({run:c.z.string(),when:M.optional(),timeout:c.z.number().optional(),retry:c.z.number().optional(),continue:c.z.boolean().optional(),onError:Se.optional()}),ze=c.z.object({choose:c.z.object({message:c.z.string(),options:c.z.array(c.z.object({id:c.z.string(),label:c.z.string()})),as:c.z.string().optional()}),when:M.optional()}),Ze=c.z.object({prompt:c.z.object({message:c.z.string(),as:c.z.string(),default:c.z.string().optional(),validate:c.z.string().optional()}),when:M.optional()}),ke=c.z.lazy(()=>c.z.union([Ue,ze,Ze,c.z.object({parallel:c.z.array(ke),when:M.optional()}),c.z.object({fail:c.z.object({message:c.z.string()}),when:M.optional()})])),Ge=c.z.object({name:c.z.string().optional(),baseDir:c.z.string().optional(),steps:c.z.array(ke).min(1,"Workflow must have at least one step")});function oe(s){return Ge.parse(s)}function ie(s){let e=s;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(t=>ie(t))}:s}var K=class{parse(e){let t;try{t=(0,ve.parse)(e)}catch(r){throw new Error(`Invalid YAML 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(o=>ie(o)))}try{return oe(t)}catch(r){if(r instanceof se.ZodError){let o=r.issues.map(n=>{let i=n.path.length>0?` at ${n.path.join(".")}`:"";return` - ${n.message}${i}`}).join(`
15
16
  `);throw new Error(`Invalid workflow structure:
16
17
  ${o}`)}throw r}}extractStepLineNumbers(e){let t=new Map,r=e.split(`
17
- `),o=0,s=!1;for(let a=0;a<r.length;a++){let i=r[a].trim();if(i==="steps:"||i.startsWith("steps:")){s=!0;continue}s&&i.startsWith("-")&&t.set(o++,a+1)}return t}},oe=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(o=>se(o)))}try{return re(t)}catch(r){if(r instanceof ne.ZodError){let o=r.issues.map(s=>{let a=s.path.length>0?` at ${s.path.join(".")}`:"";return` - ${s.message}${a}`}).join(`
18
+ `),o=0,n=!1;for(let i=0;i<r.length;i++){let a=r[i].trim();if(a==="steps:"||a.startsWith("steps:")){n=!0;continue}n&&a.startsWith("-")&&t.set(o++,i+1)}return t}},ne=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(o=>ie(o)))}try{return oe(t)}catch(r){if(r instanceof se.ZodError){let o=r.issues.map(n=>{let i=n.path.length>0?` at ${n.path.join(".")}`:"";return` - ${n.message}${i}`}).join(`
18
19
  `);throw new Error(`Invalid workflow structure:
19
20
  ${o}`)}throw r}}extractStepLineNumbers(e){let t=new Map,r=e.split(`
20
- `),o=0,s=!1,a=!1;for(let i=0;i<r.length;i++){let c=r[i].trim();if(c.startsWith('"steps"')||c.startsWith("'steps'")){s=!0,c.includes("[")&&(a=!0);continue}if(s&&c==="["){a=!0;continue}if(a&&c==="]"){a=!1,s=!1;continue}a&&c.startsWith("{")&&t.set(o++,i+1)}return t}};function ye(n){switch(n.toLowerCase().split(".").pop()){case"yaml":case"yml":return new X;case"json":return new oe;default:return new X}}var W=require("fs"),x=require("path"),ae=require("url"),Se={};function xe(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function ke(){return"0.2.10"}var Ue=(0,$e.promisify)(ve.exec),O=new Ee.Command;O.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
21
+ `),o=0,n=!1,i=!1;for(let a=0;a<r.length;a++){let l=r[a].trim();if(l.startsWith('"steps"')||l.startsWith("'steps'")){n=!0,l.includes("[")&&(i=!0);continue}if(n&&l==="["){i=!0;continue}if(i&&l==="]"){i=!1,n=!1;continue}i&&l.startsWith("{")&&t.set(o++,a+1)}return t}};function ae(s){switch(s.toLowerCase().split(".").pop()){case"yaml":case"yml":return new K;case"json":return new ne;default:return new K}}var E=require("fs"),y=require("path"),le=require("url"),Re={};function $e(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function Ce(){return"0.2.12"}function Ee(s){let e=s?(0,y.resolve)(s):process.cwd(),t=50,r=0;for(;r<t;){let o=(0,y.resolve)(e,"tp");try{if((0,E.existsSync)(o)&&(0,E.statSync)(o).isDirectory())return o}catch{}let n=(0,y.dirname)(e);if(n===e)break;e=n,r++}return null}var Xe=(0,Ne.promisify)(Pe.exec),V=new Te.Command;V.name("task-pipeliner").description(`A powerful task pipeline runner with condition-based workflow execution.
21
22
 
22
23
  Define workflows in YAML or JSON files with conditional execution, parallel tasks,
23
24
  interactive prompts, and variable substitution.
@@ -55,7 +56,7 @@ Quick Start:
55
56
  tp history remove # Remove a specific history
56
57
  tp history remove-all # Remove all histories
57
58
 
58
- `).version(ke()).addHelpText("after",`
59
+ `).version(Ce()).addHelpText("after",`
59
60
  Examples:
60
61
  $ tp run workflow.yaml
61
62
  $ tp run examples/simple-project/workflow.yaml
@@ -68,12 +69,13 @@ Resources:
68
69
  \u{1F4DA} Documentation: https://task-pipeliner.racgoo.com/
69
70
  \u{1F3A8} Visual Generator: https://task-pipeliner-generator.racgoo.com/
70
71
 
71
- See README.md for complete DSL reference.`);O.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)").option("-s, --silent","Run in silent mode (suppress console output)").addHelpText("after",`
72
+ See README.md for complete DSL reference.`);V.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 search for workflows in the nearest tp directory.").option("-s, --silent","Run in silent mode (suppress console output)").addHelpText("after",`
72
73
  Examples:
73
74
  $ tp run workflow.yaml
74
75
  $ tp run workflow.json
75
76
  $ tp run ./my-workflow.yaml
76
77
  $ tp run examples/simple-project/workflow.json
78
+ $ tp run # Select from workflows in nearest tp directory
77
79
  $ tp run workflow.yaml --silent
78
80
  $ tp run workflow.yaml -s
79
81
 
@@ -92,36 +94,40 @@ Workflow File Structure:
92
94
  \u2022 all/any/not: Combine conditions
93
95
 
94
96
  Supported formats: YAML (.yaml, .yml) and JSON (.json)
95
- See README.md for complete DSL documentation.`).action(async(n,e)=>{e.silent&&xe();try{let t=ye(n);console.log(u.default.blue(`Loading workflow from ${n}...`));let r=(0,Re.readFileSync)(n,"utf-8"),o=t.parse(r);if(!o.steps||!Array.isArray(o.steps))throw new Error("Invalid workflow: steps array is required");o._lineNumbers=t.extractStepLineNumbers(r),o._fileName=Ze(n),o._filePath=(0,Ce.resolve)(n),console.log(u.default.green(`Starting workflow execution...
96
- `)),await new G().execute(o),console.log(u.default.green(`
97
+ See README.md for complete DSL documentation.`).action(async(s,e)=>{try{let t=s??await Ke()??null;t||(console.error(u.default.red(`
98
+ \u2717 No workflow file found`)),process.exit(1)),e.silent&&$e();let r=ae(t);console.log(u.default.blue(`Loading workflow from ${t}...`));let o=(0,ce.readFileSync)(t,"utf-8"),n=r.parse(o);if(!n.steps||!Array.isArray(n.steps))throw new Error("Invalid workflow: steps array is required");n._lineNumbers=r.extractStepLineNumbers(o),n._fileName=Qe(t),n._filePath=(0,O.resolve)(t),console.log(u.default.green(`Starting workflow execution...
99
+ `)),await new q().execute(n),console.log(u.default.green(`
97
100
  \u2713 Workflow completed successfully`))}catch(t){let r=t instanceof Error?t.message:String(t);console.error(u.default.red(`
98
- \u2717 Workflow failed: ${r}`)),process.exit(1)}});O.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
101
+ \u2717 Workflow failed: ${r}`)),process.exit(1)}});V.command("open").description("Open generator or docs website in browser").argument("<target>",'Target to open: "generator" or "docs"').addHelpText("after",`
99
102
  Examples:
100
103
  $ tp open generator
101
104
  $ tp open docs
102
105
 
103
106
  Targets:
104
107
  generator Open the visual workflow generator (https://task-pipeliner-generator.racgoo.com/)
105
- docs Open the documentation site (https://task-pipeliner.racgoo.com/)`).action(async n=>{let t={generator:"https://task-pipeliner-generator.racgoo.com/",docs:"https://task-pipeliner.racgoo.com/"}[n.toLowerCase()];t||(console.error(u.default.red(`
106
- \u2717 Invalid target: ${n}`)),console.log(u.default.yellow(`
107
- Valid targets:`)),console.log(u.default.yellow(" \u2022 generator - Open the visual workflow generator")),console.log(u.default.yellow(" \u2022 docs - Open the documentation site")),process.exit(1));try{let r=process.platform,o;r==="darwin"?o=`open "${t}"`:r==="win32"?o=`start "${t}"`:o=`xdg-open "${t}"`,await Ue(o),console.log(u.default.green(`
108
- \u2713 Opening ${n==="generator"?"generator":"documentation"} in browser...`)),console.log(u.default.blue(` ${t}`))}catch(r){let o=r instanceof Error?r.message:String(r);console.error(u.default.red(`
108
+ docs Open the documentation site (https://task-pipeliner.racgoo.com/)`).action(async s=>{let t={generator:"https://task-pipeliner-generator.racgoo.com/",docs:"https://task-pipeliner.racgoo.com/"}[s.toLowerCase()];t||(console.error(u.default.red(`
109
+ \u2717 Invalid target: ${s}`)),console.log(u.default.yellow(`
110
+ Valid targets:`)),console.log(u.default.yellow(" \u2022 generator - Open the visual workflow generator")),console.log(u.default.yellow(" \u2022 docs - Open the documentation site")),process.exit(1));try{let r=process.platform,o;r==="darwin"?o=`open "${t}"`:r==="win32"?o=`start "${t}"`:o=`xdg-open "${t}"`,await Xe(o),console.log(u.default.green(`
111
+ \u2713 Opening ${s==="generator"?"generator":"documentation"} in browser...`)),console.log(u.default.blue(` ${t}`))}catch(r){let o=r instanceof Error?r.message:String(r);console.error(u.default.red(`
109
112
  \u2717 Failed to open browser: ${o}`)),console.log(u.default.yellow(`
110
- Please visit manually: ${t}`)),process.exit(1)}});var ze=O.command("history").description("Manage workflow execution history");ze.action(async()=>{let n=new T,e=await n.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"}]);e?.id||(console.error(u.default.red(`
111
- \u2717 Invalid choice`)),process.exit(1));let t=new F;switch(e.id){case"show":{let r=await t.getHistoryNames();if(r.length===0){console.log(u.default.yellow(`
112
- \u26A0 No history found`));return}let o=await n.prompt("Select a history to view",r.map(s=>({id:s,label:s})));o?.id||(console.error(u.default.red(`
113
- \u2717 Invalid choice`)),process.exit(1));try{let s=await t.getHistory(o.id);Ge(s,o.id)}catch(s){let a=s instanceof Error?s.message:String(s);console.error(u.default.red(`
114
- \u2717 Failed to load history: ${a}`)),process.exit(1)}break}case"remove":{let r=await t.getHistoryNames();if(r.length===0){console.log(u.default.yellow(`
115
- \u26A0 No history found`));return}let o=await n.prompt("Select a history to remove",r.map(s=>({id:s,label:s})));o?.id||(console.error(u.default.red(`
113
+ Please visit manually: ${t}`)),process.exit(1)}});var qe=V.command("history").description("Manage workflow execution history");qe.action(async()=>{let s=new B,e=await s.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"}]);e?.id||(console.error(u.default.red(`
114
+ \u2717 Invalid choice`)),process.exit(1));let t=new _;switch(e.id){case"show":{let r=await t.getHistoryNames();if(r.length===0){console.log(u.default.yellow(`
115
+ \u26A0 No history found`));return}let o=await s.prompt("Select a history to view",r.map(n=>({id:n,label:n})));o?.id||(console.error(u.default.red(`
116
+ \u2717 Invalid choice`)),process.exit(1));try{let n=await t.getHistory(o.id);et(n,o.id)}catch(n){let i=n instanceof Error?n.message:String(n);console.error(u.default.red(`
117
+ \u2717 Failed to load history: ${i}`)),process.exit(1)}break}case"remove":{let r=await t.getHistoryNames();if(r.length===0){console.log(u.default.yellow(`
118
+ \u26A0 No history found`));return}let o=await s.prompt("Select a history to remove",r.map(n=>({id:n,label:n})));o?.id||(console.error(u.default.red(`
116
119
  \u2717 Invalid choice`)),process.exit(1));try{await t.removeHistory(o.id),console.log(u.default.green(`
117
- \u2713 Removed history: ${o.id}`))}catch(s){let a=s instanceof Error?s.message:String(s);console.error(u.default.red(`
118
- \u2717 Failed to remove history: ${a}`)),process.exit(1)}break}case"remove-all":{if((await n.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(u.default.yellow(`
120
+ \u2713 Removed history: ${o.id}`))}catch(n){let i=n instanceof Error?n.message:String(n);console.error(u.default.red(`
121
+ \u2717 Failed to remove history: ${i}`)),process.exit(1)}break}case"remove-all":{if((await s.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(u.default.yellow(`
119
122
  \u2717 Cancelled`));return}try{await t.clearAllHistories(),console.log(u.default.green(`
120
- \u2713 All histories removed`))}catch(o){let s=o instanceof Error?o.message:String(o);console.error(u.default.red(`
121
- \u2717 Failed to remove histories: ${s}`)),process.exit(1)}break}default:console.error(u.default.red(`
122
- \u2717 Unknown action: ${e.id}`)),process.exit(1)}});function Ze(n){return n.split("/").pop()??n}function Ge(n,e){console.log(`
123
- `);let t=n.records.reduce((c,m)=>c+m.duration,0),r=n.records.filter(c=>c.status==="success").length,o=n.records.filter(c=>c.status==="failure").length,s=(0,Pe.default)(n.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),i=A(t),p=[u.default.bold("Workflow Execution History"),"",`${u.default.cyan("File:")} ${e}`,`${u.default.cyan("Started:")} ${s}`,`${u.default.cyan("Total Duration:")} ${i}`,`${u.default.cyan("Total Steps:")} ${n.records.length}`,`${u.default.green("\u2713 Successful:")} ${r}`,o>0?`${u.default.red("\u2717 Failed:")} ${o}`:""].filter(Boolean).join(`
124
- `);console.log((0,ie.default)(p,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:"cyan"})),n.records.forEach((c,m)=>{Xe(c,m+1,n.records.length)}),console.log("")}function Xe(n,e,t){let r=qe(n.step),o=Ke(n.step),s=n.status==="success"?u.default.green("\u2713"):u.default.red("\u2717"),a=n.status==="success"?u.default.green("Success"):u.default.red("Failed"),i=A(n.duration),p=[`${s} ${u.default.bold(`Step ${e}/${t}`)} - ${u.default.cyan(r)}`,`${u.default.gray("Duration:")} ${i} | ${u.default.gray("Status:")} ${a}`,"",u.default.white(o)].join(`
125
- `);console.log((0,ie.default)(p,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:n.status==="success"?"green":"red"})),Qe(n.output)&&et(n.output)}function qe(n){return"run"in n?"Run":"choose"in n?"Choose":"prompt"in n?"Prompt":"parallel"in n?"Parallel":"fail"in n?"Fail":"Unknown"}function Ke(n){return"run"in n?`Command: ${u.default.yellow(n.run)}`:"choose"in n?`Message: ${u.default.yellow(n.choose.message)}`:"prompt"in n?`Message: ${u.default.yellow(n.prompt.message)} | Variable: ${u.default.cyan(n.prompt.as)}`:"parallel"in n?`Parallel execution with ${n.parallel.length} branches`:"fail"in n?`Error: ${u.default.red(n.fail.message)}`:"Unknown step type"}function Qe(n){return typeof n=="object"&&n!==null&&"success"in n&&"stdout"in n&&"stderr"in n}function et(n){if(n.stdout.length>0){let e=n.stdout.map(t=>u.default.gray(` ${t}`)).join(`
126
- `);console.log(u.default.green(" Output:")),console.log(e)}if(n.stderr.length>0){let e=n.stderr.map(t=>u.default.gray(` ${t}`)).join(`
127
- `);console.log(u.default.red(" Errors:")),console.log(e)}}O.parse();
123
+ \u2713 All histories removed`))}catch(o){let n=o instanceof Error?o.message:String(o);console.error(u.default.red(`
124
+ \u2717 Failed to remove histories: ${n}`)),process.exit(1)}break}default:console.error(u.default.red(`
125
+ \u2717 Unknown action: ${e.id}`)),process.exit(1)}});async function Ke(){let s=Ee();if(!s)return console.error(u.default.red(`
126
+ \u2717 No tp directory found`)),null;try{let t=(await(0,Me.readdir)(s)).filter(i=>{let a=(0,O.extname)(i).toLowerCase();return[".yaml",".yml",".json"].includes(a)});if(t.length===0)return console.error(u.default.red(`
127
+ \u2717 No workflow files found in ${s}`)),null;let r=await Promise.all(t.map(async i=>{let a=(0,O.join)(s,i);try{let p=ae(a),l=(0,ce.readFileSync)(a,"utf-8"),d=p.parse(l).name??"Untitled";return{id:a,label:`${i} - ${d}`}}catch{return{id:a,label:i}}}));return(await new B(!0).prompt("Select a workflow to run",r)).id}catch(e){let t=e instanceof Error?e.message:String(e);return console.error(u.default.red(`
128
+ \u2717 Failed to read tp directory: ${t}`)),null}}function Qe(s){return s.split("/").pop()??s}function et(s,e){console.log(`
129
+ `);let t=s.records.reduce((l,m)=>l+m.duration,0),r=s.records.filter(l=>l.status==="success").length,o=s.records.filter(l=>l.status==="failure").length,n=(0,Be.default)(s.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=F(t),p=[u.default.bold("Workflow Execution History"),"",`${u.default.cyan("File:")} ${e}`,`${u.default.cyan("Started:")} ${n}`,`${u.default.cyan("Total Duration:")} ${a}`,`${u.default.cyan("Total Steps:")} ${s.records.length}`,`${u.default.green("\u2713 Successful:")} ${r}`,o>0?`${u.default.red("\u2717 Failed:")} ${o}`:""].filter(Boolean).join(`
130
+ `);console.log((0,ue.default)(p,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:"cyan"})),s.records.forEach((l,m)=>{tt(l,m+1,s.records.length)}),console.log("")}function tt(s,e,t){let r=rt(s.step),o=ot(s.step),n=s.status==="success"?u.default.green("\u2713"):u.default.red("\u2717"),i=s.status==="success"?u.default.green("Success"):u.default.red("Failed"),a=F(s.duration),p=[`${n} ${u.default.bold(`Step ${e}/${t}`)} - ${u.default.cyan(r)}`,`${u.default.gray("Duration:")} ${a} | ${u.default.gray("Status:")} ${i}`,"",u.default.white(o)].join(`
131
+ `);console.log((0,ue.default)(p,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:s.status==="success"?"green":"red"})),nt(s.output)&&st(s.output)}function rt(s){return"run"in s?"Run":"choose"in s?"Choose":"prompt"in s?"Prompt":"parallel"in s?"Parallel":"fail"in s?"Fail":"Unknown"}function ot(s){return"run"in s?`Command: ${u.default.yellow(s.run)}`:"choose"in s?`Message: ${u.default.yellow(s.choose.message)}`:"prompt"in s?`Message: ${u.default.yellow(s.prompt.message)} | Variable: ${u.default.cyan(s.prompt.as)}`:"parallel"in s?`Parallel execution with ${s.parallel.length} branches`:"fail"in s?`Error: ${u.default.red(s.fail.message)}`:"Unknown step type"}function nt(s){return typeof s=="object"&&s!==null&&"success"in s&&"stdout"in s&&"stderr"in s}function st(s){if(s.stdout.length>0){let e=s.stdout.map(t=>u.default.gray(` ${t}`)).join(`
132
+ `);console.log(u.default.green(" Output:")),console.log(e)}if(s.stderr.length>0){let e=s.stderr.map(t=>u.default.gray(` ${t}`)).join(`
133
+ `);console.log(u.default.red(" Errors:")),console.log(e)}}V.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeliner",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "A task pipeline runner with condition-based workflow execution",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",