task-pipeliner 0.3.4 → 0.3.5

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.3.4
5
+ **버전:** 0.3.5
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
@@ -224,7 +224,7 @@ npx tp run workflow.yaml
224
224
  name: My Workflow
225
225
 
226
226
  steps:
227
- - run: echo "Hello, World!"
227
+ - run: 'echo "Hello, World!"'
228
228
 
229
229
  - choose:
230
230
  message: "무엇을 하시겠습니까?"
@@ -238,12 +238,12 @@ steps:
238
238
  - when:
239
239
  var:
240
240
  action: build
241
- run: npm run build
241
+ run: 'npm run build'
242
242
 
243
243
  - when:
244
244
  var:
245
245
  action: test
246
- run: npm test
246
+ run: 'npm test'
247
247
  ```
248
248
 
249
249
  **JSON 형식 (`workflow.json`):**
@@ -509,12 +509,12 @@ steps: # 필수: 실행할 단계 배열
509
509
  ```yaml
510
510
  # 간단한 명령
511
511
  steps:
512
- - run: npm install
512
+ - run: 'npm install'
513
513
 
514
514
  # 조건이 있는 명령
515
515
  - when:
516
516
  file: ./package.json
517
- run: npm install
517
+ run: 'npm install'
518
518
 
519
519
  # 변수 입력
520
520
  - choose:
@@ -529,55 +529,55 @@ steps:
529
529
  as: version
530
530
 
531
531
  # 변수 치환이 있는 명령
532
- - run: echo "Building {{version}}"
532
+ - run: 'echo "Building {{version}}"'
533
533
 
534
534
  # 타임아웃이 있는 명령 (30초)
535
- - run: npm install
535
+ - run: 'npm install'
536
536
  timeout: 30
537
537
 
538
538
  # 재시도가 있는 명령 (최대 3번 재시도)
539
- - run: npm install
539
+ - run: 'npm install'
540
540
  retry: 3
541
541
 
542
542
  # 무한 재시도 명령 (성공할 때까지 재시도)
543
- - run: npm install
543
+ - run: 'npm install'
544
544
  retry: Infinity
545
545
 
546
546
  # PM2처럼 프로세스 관리: 서버가 죽으면 자동 재시작
547
- - run: node server.js
547
+ - run: 'node server.js'
548
548
  retry: Infinity
549
549
 
550
550
  # 타임아웃과 재시도 모두 사용
551
- - run: npm install
551
+ - run: 'npm install'
552
552
  timeout: 60
553
553
  retry: 2
554
554
 
555
555
  # 실패 시 fallback 명령 실행
556
- - run: pnpm lint
556
+ - run: 'pnpm lint'
557
557
  onError:
558
- run: pnpm lint:fix
558
+ run: 'pnpm lint:fix'
559
559
 
560
560
  # 여러 단계로 이어지는 fallback 체인
561
- - run: step1
561
+ - run: 'step1'
562
562
  onError:
563
- run: step2
563
+ run: 'step2'
564
564
  onError:
565
- run: step3
565
+ run: 'step3'
566
566
 
567
567
  # 실패를 기록만 하고 워크플로우는 계속 진행
568
- - run: pnpm typecheck
568
+ - run: 'pnpm typecheck'
569
569
  continue: true
570
570
  onError:
571
- run: echo "Type check failed, but continuing..."
571
+ run: 'echo "Type check failed, but continuing..."'
572
572
 
573
573
  # 커스텀 쉘 사용 (스텝별)
574
- - run: echo $SHELL
574
+ - run: 'echo $SHELL'
575
575
  shell:
576
576
  - zsh
577
577
  - -c
578
578
 
579
579
  # bash 로그인 쉘 사용
580
- - run: source ~/.bashrc && echo "프로필 로드됨"
580
+ - run: 'source ~/.bashrc && echo "프로필 로드됨"'
581
581
  shell:
582
582
  - bash
583
583
  - -lc
@@ -679,7 +679,7 @@ steps:
679
679
  - when:
680
680
  var: # 변수를 사용한다는 정의
681
681
  env: prod # 'env' 변수가 'prod'와 같은지 확인
682
- run: echo "프로덕션에 배포 중"
682
+ run: 'echo "프로덕션에 배포 중"'
683
683
  ```
684
684
 
685
685
  ---
@@ -733,13 +733,13 @@ steps:
733
733
  **사용:**
734
734
  ```yaml
735
735
  # 명령에서 사용
736
- - run: echo "Building version {{version}}"
736
+ - run: 'echo "Building version {{version}}"'
737
737
 
738
738
  # 조건에서 확인
739
739
  - when:
740
740
  var:
741
741
  version: "1.0.0"
742
- run: echo "안정 버전 배포 중"
742
+ run: 'echo "안정 버전 배포 중"'
743
743
  ```
744
744
 
745
745
  ---
@@ -768,19 +768,19 @@ steps:
768
768
  # 기본 병렬 실행
769
769
  # parallel 내부의 각 step은 `-`로 시작하며, `steps`와 동일한 형식
770
770
  - parallel:
771
- - run: npm run test:unit
772
- - run: npm run test:integration
773
- - run: npm run lint
771
+ - run: 'npm run test:unit'
772
+ - run: 'npm run test:integration'
773
+ - run: 'npm run lint'
774
774
 
775
775
  # 조건이 있는 병렬
776
776
  # 각 step은 자신만의 `when` 조건을 가질 수 있습니다
777
777
  - parallel:
778
778
  - when:
779
779
  file: ./src
780
- run: echo "프론트엔드 빌드 중..."
780
+ run: 'echo "프론트엔드 빌드 중..."'
781
781
  - when:
782
782
  file: ./api
783
- run: echo "백엔드 빌드 중..."
783
+ run: 'echo "백엔드 빌드 중..."'
784
784
 
785
785
  # 조건부 병렬 블록
786
786
  # 전체 parallel 블록에 `when` 조건을 적용할 수 있습니다
@@ -788,15 +788,15 @@ steps:
788
788
  var:
789
789
  env: staging
790
790
  parallel:
791
- - run: npm run test
792
- - run: npm run lint
791
+ - run: 'npm run test'
792
+ - run: 'npm run lint'
793
793
 
794
794
  # 중첩 parallel (허용); parallel 내부에는 run / parallel / fail만 사용
795
795
  - parallel:
796
- - run: npm run test
796
+ - run: 'npm run test'
797
797
  - parallel:
798
- - run: npm run lint
799
- - run: npm run typecheck
798
+ - run: 'npm run lint'
799
+ - run: 'npm run typecheck'
800
800
  ```
801
801
 
802
802
  **동작:**
@@ -870,16 +870,16 @@ when:
870
870
  ```yaml
871
871
  - when:
872
872
  file: ./dist
873
- run: echo "빌드가 존재합니다"
873
+ run: 'echo "빌드가 존재합니다"'
874
874
 
875
875
  - when:
876
876
  file: ./package.json
877
- run: npm install
877
+ run: 'npm install'
878
878
 
879
879
  - when:
880
880
  not:
881
881
  file: ./node_modules
882
- run: npm install
882
+ run: 'npm install'
883
883
  ```
884
884
 
885
885
  **동작:**
@@ -910,20 +910,20 @@ when:
910
910
  - when:
911
911
  var:
912
912
  env: prod
913
- run: echo "프로덕션에 배포 중"
913
+ run: 'echo "프로덕션에 배포 중"'
914
914
 
915
915
  # version이 특정 값과 같은지 확인
916
916
  - when:
917
917
  var:
918
918
  version: "1.0.0"
919
- run: echo "안정 버전 배포 중"
919
+ run: 'echo "안정 버전 배포 중"'
920
920
 
921
921
  # 여러 변수 확인 (모두 일치해야 함)
922
922
  - when:
923
923
  var:
924
924
  env: staging
925
925
  version: "2.0.0"
926
- run: echo "스테이징에 v2.0.0 배포 중"
926
+ run: 'echo "스테이징에 v2.0.0 배포 중"'
927
927
  ```
928
928
 
929
929
  **동작:**
@@ -955,12 +955,12 @@ when:
955
955
  # 변수가 존재하는지 확인
956
956
  - when:
957
957
  var: version
958
- run: echo "Version: {{version}}"
958
+ run: 'echo "Version: {{version}}"'
959
959
 
960
960
  # 'has' 별칭 사용
961
961
  - when:
962
962
  has: projectName
963
- run: echo "Project: {{projectName}}"
963
+ run: 'echo "Project: {{projectName}}"'
964
964
  ```
965
965
 
966
966
  **동작:**
@@ -994,7 +994,7 @@ when:
994
994
  - file: ./dist
995
995
  - var:
996
996
  env: production
997
- run: echo "프로덕션 빌드 준비 완료"
997
+ run: 'echo "프로덕션 빌드 준비 완료"'
998
998
 
999
999
  - when:
1000
1000
  all:
@@ -1003,7 +1003,7 @@ when:
1003
1003
  - var:
1004
1004
  version: "2.0.0"
1005
1005
  - file: ./dist
1006
- run: echo "스테이징에 v2.0.0 배포 중"
1006
+ run: 'echo "스테이징에 v2.0.0 배포 중"'
1007
1007
  ```
1008
1008
 
1009
1009
  **동작:**
@@ -1034,13 +1034,13 @@ when:
1034
1034
  env: staging
1035
1035
  - var:
1036
1036
  env: production
1037
- run: echo "서버에 배포 중"
1037
+ run: 'echo "서버에 배포 중"'
1038
1038
 
1039
1039
  - when:
1040
1040
  any:
1041
1041
  - file: ./dist
1042
1042
  - file: ./build
1043
- run: echo "빌드 출력을 찾았습니다"
1043
+ run: 'echo "빌드 출력을 찾았습니다"'
1044
1044
  ```
1045
1045
 
1046
1046
  **동작:**
@@ -1075,7 +1075,7 @@ when:
1075
1075
  not:
1076
1076
  var:
1077
1077
  env: prod
1078
- run: echo "프로덕션 환경이 아닙니다"
1078
+ run: 'echo "프로덕션 환경이 아닙니다"'
1079
1079
 
1080
1080
  # 복잡한 부정
1081
1081
  - when:
@@ -1084,7 +1084,7 @@ when:
1084
1084
  - file: ./dist
1085
1085
  - var:
1086
1086
  env: prod
1087
- run: echo "프로덕션 준비가 되지 않았습니다"
1087
+ run: 'echo "프로덕션 준비가 되지 않았습니다"'
1088
1088
  ```
1089
1089
 
1090
1090
  **동작:**
@@ -1112,7 +1112,7 @@ when:
1112
1112
  - not:
1113
1113
  var:
1114
1114
  version: "0.0.0"
1115
- run: echo "배포 준비 완료"
1115
+ run: 'echo "배포 준비 완료"'
1116
1116
 
1117
1117
  # 여러 수준의 중첩
1118
1118
  - when:
@@ -1126,7 +1126,7 @@ when:
1126
1126
  env: staging
1127
1127
  - not:
1128
1128
  file: ./test-results
1129
- run: echo "조건부 배포"
1129
+ run: 'echo "조건부 배포"'
1130
1130
  ```
1131
1131
 
1132
1132
  ---
@@ -1137,9 +1137,9 @@ when:
1137
1137
 
1138
1138
  **문법:**
1139
1139
  ```yaml
1140
- run: echo "{{variableName}}"
1140
+ run: 'echo "{{variableName}}"'
1141
1141
  # 또는 선택적으로 공백 사용
1142
- run: echo "{{ variableName }}"
1142
+ run: 'echo "{{ variableName }}"'
1143
1143
  ```
1144
1144
 
1145
1145
  **⚠️ 중요: YAML 문법 규칙**
@@ -1148,9 +1148,9 @@ run: echo "{{ variableName }}"
1148
1148
 
1149
1149
  ✅ **안전한 패턴:**
1150
1150
  ```yaml
1151
- # 단어로 시작 (따옴표 불필요)
1152
- - run: echo "Building {{version}}..."
1153
- - run: npm run build --version={{version}}
1151
+ # 작은따옴표로 감싸기 (권장)
1152
+ - run: 'echo "Building {{version}}..."'
1153
+ - run: 'npm run build --version={{version}}'
1154
1154
 
1155
1155
  # 전체 명령어를 작은따옴표로 감싸기
1156
1156
  - run: 'echo "Selected: {{mode}}"'
@@ -1171,7 +1171,7 @@ run: echo "{{ variableName }}"
1171
1171
  - prompt:
1172
1172
  message: "프로젝트 이름을 입력하세요:"
1173
1173
  as: projectName
1174
- - run: echo "Building {{projectName}}..."
1174
+ - run: 'echo "Building {{projectName}}..."'
1175
1175
 
1176
1176
  # 선택 변수 사용
1177
1177
  - choose:
@@ -1180,10 +1180,10 @@ run: echo "{{ variableName }}"
1180
1180
  - id: dev
1181
1181
  label: "개발"
1182
1182
  as: env
1183
- - run: echo "Deploying to {{env}}"
1183
+ - run: 'echo "Deploying to {{env}}"'
1184
1184
 
1185
1185
  # 여러 변수
1186
- - run: echo "Building {{projectName}} version {{version}} for {{env}}"
1186
+ - run: 'echo "Building {{projectName}} version {{version}} for {{env}}"'
1187
1187
  ```
1188
1188
 
1189
1189
  **동작:**
@@ -1203,7 +1203,7 @@ baseDir: ./
1203
1203
 
1204
1204
  steps:
1205
1205
  # 1. 간단한 명령
1206
- - run: echo "워크플로우 시작 중..."
1206
+ - run: 'echo "워크플로우 시작 중..."'
1207
1207
 
1208
1208
  # 2. 변수 저장이 있는 사용자 선택
1209
1209
  - choose:
@@ -1229,12 +1229,12 @@ steps:
1229
1229
  - when:
1230
1230
  var:
1231
1231
  env: dev
1232
- run: echo "개발 환경에 배포 중..."
1232
+ run: 'echo "개발 환경에 배포 중..."'
1233
1233
 
1234
1234
  - when:
1235
1235
  var:
1236
1236
  env: staging
1237
- run: echo "스테이징에 배포 중..."
1237
+ run: 'echo "스테이징에 배포 중..."'
1238
1238
 
1239
1239
  # 5. 복잡한 조건 (all)
1240
1240
  - when:
@@ -1243,22 +1243,22 @@ steps:
1243
1243
  env: prod
1244
1244
  - var: deployReason
1245
1245
  - file: ./dist
1246
- run: echo "프로덕션 배포 승인됨"
1246
+ run: 'echo "프로덕션 배포 승인됨"'
1247
1247
 
1248
1248
  # 6. 병렬 실행
1249
1249
  - parallel:
1250
- - run: npm run test:unit
1251
- - run: npm run test:integration
1252
- - run: npm run lint
1250
+ - run: 'npm run test:unit'
1251
+ - run: 'npm run test:integration'
1252
+ - run: 'npm run lint'
1253
1253
 
1254
1254
  # 6.5. 스텝별 쉘 오버라이드
1255
- - run: echo "zsh로 실행"
1255
+ - run: 'echo "zsh로 실행"'
1256
1256
  shell: [zsh, -c] # 이 스텝만 워크플로우 쉘 오버라이드
1257
1257
 
1258
1258
  # 7. 파일 존재 확인
1259
1259
  - when:
1260
1260
  file: ./test-results
1261
- run: echo "테스트 완료"
1261
+ run: 'echo "테스트 완료"'
1262
1262
 
1263
1263
  # 8. 결합된 조건 (any)
1264
1264
  - when:
@@ -1267,7 +1267,7 @@ steps:
1267
1267
  env: staging
1268
1268
  - var:
1269
1269
  env: prod
1270
- run: echo "서버에 배포 중..."
1270
+ run: 'echo "서버에 배포 중..."'
1271
1271
 
1272
1272
  # 9. 부정
1273
1273
  - when:
@@ -1277,7 +1277,7 @@ steps:
1277
1277
  message: "빌드 출력을 찾을 수 없습니다"
1278
1278
 
1279
1279
  # 10. 변수 치환
1280
- - run: echo "Deploying {{projectName}} version {{version}} to {{env}}"
1280
+ - run: 'echo "Deploying {{projectName}} version {{version}} to {{env}}"'
1281
1281
  ```
1282
1282
 
1283
1283
  ---
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > A powerful workflow orchestration tool with condition-based execution and beautiful CLI output
4
4
 
5
- **Version:** 0.3.4
5
+ **Version:** 0.3.5
6
6
 
7
7
  ![fox2](https://github.com/user-attachments/assets/fdf8d786-6a91-4d2d-9dc1-72be6f3ccd98)
8
8
 
@@ -224,7 +224,7 @@ Create a `workflow.yaml` or `workflow.json` file:
224
224
  name: My Workflow
225
225
 
226
226
  steps:
227
- - run: echo "Hello, World!"
227
+ - run: 'echo "Hello, World!"'
228
228
 
229
229
  - choose:
230
230
  message: "What would you like to do?"
@@ -238,12 +238,12 @@ steps:
238
238
  - when:
239
239
  var:
240
240
  action: build
241
- run: npm run build
241
+ run: 'npm run build'
242
242
 
243
243
  - when:
244
244
  var:
245
245
  action: test
246
- run: npm test
246
+ run: 'npm test'
247
247
  ```
248
248
 
249
249
  **JSON Format (`workflow.json`):**
@@ -509,12 +509,12 @@ Execute a shell command.
509
509
  ```yaml
510
510
  # Simple command
511
511
  steps:
512
- - run: npm install
512
+ - run: 'npm install'
513
513
 
514
514
  # Command with condition
515
515
  - when:
516
516
  file: ./package.json
517
- run: npm install
517
+ run: 'npm install'
518
518
 
519
519
  # Variable input
520
520
  - choose:
@@ -529,55 +529,55 @@ steps:
529
529
  as: version
530
530
 
531
531
  # Command with variable substitution
532
- - run: echo "Building {{version}}"
532
+ - run: 'echo "Building {{version}}"'
533
533
 
534
534
  # Command with timeout (30 seconds)
535
- - run: npm install
535
+ - run: 'npm install'
536
536
  timeout: 30
537
537
 
538
538
  # Command with retry (retry up to 3 times)
539
- - run: npm install
539
+ - run: 'npm install'
540
540
  retry: 3
541
541
 
542
542
  # Command with infinite retry (retry until success)
543
- - run: npm install
543
+ - run: 'npm install'
544
544
  retry: Infinity
545
545
 
546
546
  # PM2-like process manager: auto-restart crashed server
547
- - run: node server.js
547
+ - run: 'node server.js'
548
548
  retry: Infinity
549
549
 
550
550
  # Using both timeout and retry
551
- - run: npm install
551
+ - run: 'npm install'
552
552
  timeout: 60
553
553
  retry: 2
554
554
 
555
555
  # Command with fallback on error
556
- - run: pnpm lint
556
+ - run: 'pnpm lint'
557
557
  onError:
558
- run: pnpm lint:fix
558
+ run: 'pnpm lint:fix'
559
559
 
560
560
  # Command with multi-level fallback on error
561
- - run: step1
561
+ - run: 'step1'
562
562
  onError:
563
- run: step2
563
+ run: 'step2'
564
564
  onError:
565
- run: step3
565
+ run: 'step3'
566
566
 
567
567
  # Command that records failure but continues workflow
568
- - run: pnpm typecheck
568
+ - run: 'pnpm typecheck'
569
569
  continue: true
570
570
  onError:
571
- run: echo "Type check failed, but continuing..."
571
+ run: 'echo "Type check failed, but continuing..."'
572
572
 
573
573
  # Command with custom shell (step-level)
574
- - run: echo $SHELL
574
+ - run: 'echo $SHELL'
575
575
  shell:
576
576
  - zsh
577
577
  - -c
578
578
 
579
579
  # Command with bash login shell
580
- - run: source ~/.bashrc && echo "Loaded profile"
580
+ - run: 'source ~/.bashrc && echo "Loaded profile"'
581
581
  shell:
582
582
  - bash
583
583
  - -lc
@@ -679,7 +679,7 @@ steps:
679
679
  - when:
680
680
  var: # Definition that uses a variable
681
681
  env: prod # Check if 'env' variable equals 'prod'
682
- run: echo "Deploying to production"
682
+ run: 'echo "Deploying to production"'
683
683
  ```
684
684
 
685
685
  ---
@@ -733,13 +733,13 @@ Ask user for text input.
733
733
  **Usage:**
734
734
  ```yaml
735
735
  # Use in command
736
- - run: echo "Building version {{version}}"
736
+ - run: 'echo "Building version {{version}}"'
737
737
 
738
738
  # Check in condition
739
739
  - when:
740
740
  var:
741
741
  version: "1.0.0"
742
- run: echo "Deploying stable version"
742
+ run: 'echo "Deploying stable version"'
743
743
  ```
744
744
 
745
745
  ---
@@ -768,19 +768,19 @@ Execute multiple steps simultaneously. Like `steps`, `parallel` contains an arra
768
768
  # Basic parallel execution
769
769
  # Each step inside parallel starts with `-`, same format as `steps`
770
770
  - parallel:
771
- - run: npm run test:unit
772
- - run: npm run test:integration
773
- - run: npm run lint
771
+ - run: 'npm run test:unit'
772
+ - run: 'npm run test:integration'
773
+ - run: 'npm run lint'
774
774
 
775
775
  # Parallel with conditions
776
776
  # Each step can have its own `when` condition
777
777
  - parallel:
778
778
  - when:
779
779
  file: ./src
780
- run: echo "Building frontend..."
780
+ run: 'echo "Building frontend..."'
781
781
  - when:
782
782
  file: ./api
783
- run: echo "Building backend..."
783
+ run: 'echo "Building backend..."'
784
784
 
785
785
  # Conditional parallel block
786
786
  # The entire parallel block can have a `when` condition
@@ -788,15 +788,15 @@ Execute multiple steps simultaneously. Like `steps`, `parallel` contains an arra
788
788
  var:
789
789
  env: staging
790
790
  parallel:
791
- - run: npm run test
792
- - run: npm run lint
791
+ - run: 'npm run test'
792
+ - run: 'npm run lint'
793
793
 
794
794
  # Nested parallel (allowed); only run / parallel / fail inside parallel
795
795
  - parallel:
796
- - run: npm run test
796
+ - run: 'npm run test'
797
797
  - parallel:
798
- - run: npm run lint
799
- - run: npm run typecheck
798
+ - run: 'npm run lint'
799
+ - run: 'npm run typecheck'
800
800
  ```
801
801
 
802
802
  **Behavior:**
@@ -870,16 +870,16 @@ when:
870
870
  ```yaml
871
871
  - when:
872
872
  file: ./dist
873
- run: echo "Build exists"
873
+ run: 'echo "Build exists"'
874
874
 
875
875
  - when:
876
876
  file: ./package.json
877
- run: npm install
877
+ run: 'npm install'
878
878
 
879
879
  - when:
880
880
  not:
881
881
  file: ./node_modules
882
- run: npm install
882
+ run: 'npm install'
883
883
  ```
884
884
 
885
885
  **Behavior:**
@@ -910,20 +910,20 @@ when:
910
910
  - when:
911
911
  var:
912
912
  env: prod
913
- run: echo "Deploying to production"
913
+ run: 'echo "Deploying to production"'
914
914
 
915
915
  # Check if version equals specific value
916
916
  - when:
917
917
  var:
918
918
  version: "1.0.0"
919
- run: echo "Deploying stable version"
919
+ run: 'echo "Deploying stable version"'
920
920
 
921
921
  # Multiple variable checks (all must match)
922
922
  - when:
923
923
  var:
924
924
  env: staging
925
925
  version: "2.0.0"
926
- run: echo "Deploying v2.0.0 to staging"
926
+ run: 'echo "Deploying v2.0.0 to staging"'
927
927
  ```
928
928
 
929
929
  **Behavior:**
@@ -955,12 +955,12 @@ when:
955
955
  # Check if variable exists
956
956
  - when:
957
957
  var: version
958
- run: echo "Version: {{version}}"
958
+ run: 'echo "Version: {{version}}"'
959
959
 
960
960
  # Use 'has' alias
961
961
  - when:
962
962
  has: projectName
963
- run: echo "Project: {{projectName}}"
963
+ run: 'echo "Project: {{projectName}}"'
964
964
  ```
965
965
 
966
966
  **Behavior:**
@@ -994,7 +994,7 @@ when:
994
994
  - file: ./dist
995
995
  - var:
996
996
  env: production
997
- run: echo "Production build ready"
997
+ run: 'echo "Production build ready"'
998
998
 
999
999
  - when:
1000
1000
  all:
@@ -1003,7 +1003,7 @@ when:
1003
1003
  - var:
1004
1004
  version: "2.0.0"
1005
1005
  - file: ./dist
1006
- run: echo "Deploying v2.0.0 to staging"
1006
+ run: 'echo "Deploying v2.0.0 to staging"'
1007
1007
  ```
1008
1008
 
1009
1009
  **Behavior:**
@@ -1034,13 +1034,13 @@ when:
1034
1034
  env: staging
1035
1035
  - var:
1036
1036
  env: production
1037
- run: echo "Deploying to server"
1037
+ run: 'echo "Deploying to server"'
1038
1038
 
1039
1039
  - when:
1040
1040
  any:
1041
1041
  - file: ./dist
1042
1042
  - file: ./build
1043
- run: echo "Build output found"
1043
+ run: 'echo "Build output found"'
1044
1044
  ```
1045
1045
 
1046
1046
  **Behavior:**
@@ -1075,7 +1075,7 @@ when:
1075
1075
  not:
1076
1076
  var:
1077
1077
  env: prod
1078
- run: echo "Not production environment"
1078
+ run: 'echo "Not production environment"'
1079
1079
 
1080
1080
  # Complex negation
1081
1081
  - when:
@@ -1084,7 +1084,7 @@ when:
1084
1084
  - file: ./dist
1085
1085
  - var:
1086
1086
  env: prod
1087
- run: echo "Production not ready"
1087
+ run: 'echo "Production not ready"'
1088
1088
  ```
1089
1089
 
1090
1090
  **Behavior:**
@@ -1112,7 +1112,7 @@ Nest conditions to create complex logic.
1112
1112
  - not:
1113
1113
  var:
1114
1114
  version: "0.0.0"
1115
- run: echo "Ready to deploy"
1115
+ run: 'echo "Ready to deploy"'
1116
1116
 
1117
1117
  # Multiple levels of nesting
1118
1118
  - when:
@@ -1126,7 +1126,7 @@ Nest conditions to create complex logic.
1126
1126
  env: staging
1127
1127
  - not:
1128
1128
  file: ./test-results
1129
- run: echo "Conditional deployment"
1129
+ run: 'echo "Conditional deployment"'
1130
1130
  ```
1131
1131
 
1132
1132
  ---
@@ -1137,9 +1137,9 @@ Variables can be used in commands using the `{{variable}}` syntax. Optional whit
1137
1137
 
1138
1138
  **Syntax:**
1139
1139
  ```yaml
1140
- run: echo "{{variableName}}"
1140
+ run: 'echo "{{variableName}}"'
1141
1141
  # or with optional spaces
1142
- run: echo "{{ variableName }}"
1142
+ run: 'echo "{{ variableName }}"'
1143
1143
  ```
1144
1144
 
1145
1145
  **⚠️ Important YAML Syntax Rules:**
@@ -1148,9 +1148,9 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
1148
1148
 
1149
1149
  ✅ **Safe patterns:**
1150
1150
  ```yaml
1151
- # Start with a word (no quotes needed)
1152
- - run: echo "Building {{version}}..."
1153
- - run: npm run build --version={{version}}
1151
+ # Wrap in single quotes (recommended)
1152
+ - run: 'echo "Building {{version}}..."'
1153
+ - run: 'npm run build --version={{version}}'
1154
1154
 
1155
1155
  # Wrap entire command in single quotes
1156
1156
  - run: 'echo "Selected: {{mode}}"'
@@ -1158,7 +1158,7 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
1158
1158
 
1159
1159
  ❌ **Problematic patterns:**
1160
1160
  ```yaml
1161
- # DO NOT: quotes + colons before variables
1161
+ # DO NOT: unquoted value with colons before variables
1162
1162
  - run: echo "mode: {{mode}}" # ❌ YAML parsing error!
1163
1163
 
1164
1164
  # FIX: Wrap entire command in single quotes
@@ -1171,7 +1171,7 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
1171
1171
  - prompt:
1172
1172
  message: "Enter project name:"
1173
1173
  as: projectName
1174
- - run: echo "Building {{projectName}}..."
1174
+ - run: 'echo "Building {{projectName}}..."'
1175
1175
 
1176
1176
  # Use choice variable
1177
1177
  - choose:
@@ -1180,10 +1180,11 @@ When using `{{variable}}` in commands, follow these rules to avoid parsing error
1180
1180
  - id: dev
1181
1181
  label: "Development"
1182
1182
  as: env
1183
- - run: echo "Deploying to {{env}}"
1183
+ - run: 'echo "Deploying to {{env}}"'
1184
+
1184
1185
 
1185
1186
  # Multiple variables
1186
- - run: echo "Building {{projectName}} version {{version}} for {{env}}"
1187
+ - run: 'echo "Building {{projectName}} version {{version}} for {{env}}"'
1187
1188
  ```
1188
1189
 
1189
1190
  **Behavior:**
@@ -1204,7 +1205,7 @@ shell: [bash, -c] # Optional: Use bash for all steps (default: user's current s
1204
1205
 
1205
1206
  steps:
1206
1207
  # 1. Simple command
1207
- - run: echo "Starting workflow..."
1208
+ - run: 'echo "Starting workflow..."'
1208
1209
 
1209
1210
  # 2. User choice with variable storage
1210
1211
  - choose:
@@ -1230,12 +1231,12 @@ steps:
1230
1231
  - when:
1231
1232
  var:
1232
1233
  env: dev
1233
- run: echo "Deploying to development..."
1234
+ run: 'echo "Deploying to development..."'
1234
1235
 
1235
1236
  - when:
1236
1237
  var:
1237
1238
  env: staging
1238
- run: echo "Deploying to staging..."
1239
+ run: 'echo "Deploying to staging..."'
1239
1240
 
1240
1241
  # 5. Complex condition (all)
1241
1242
  - when:
@@ -1244,22 +1245,22 @@ steps:
1244
1245
  env: prod
1245
1246
  - var: deployReason
1246
1247
  - file: ./dist
1247
- run: echo "Production deployment approved"
1248
+ run: 'echo "Production deployment approved"'
1248
1249
 
1249
1250
  # 6. Parallel execution
1250
1251
  - parallel:
1251
- - run: npm run test:unit
1252
- - run: npm run test:integration
1253
- - run: npm run lint
1252
+ - run: 'npm run test:unit'
1253
+ - run: 'npm run test:integration'
1254
+ - run: 'npm run lint'
1254
1255
 
1255
1256
  # 6.5. Step-level shell override
1256
- - run: echo "Running with zsh"
1257
+ - run: 'echo "Running with zsh"'
1257
1258
  shell: [zsh, -c] # Override workflow shell for this step only
1258
1259
 
1259
1260
  # 7. File existence check
1260
1261
  - when:
1261
1262
  file: ./test-results
1262
- run: echo "Tests completed"
1263
+ run: 'echo "Tests completed"'
1263
1264
 
1264
1265
  # 8. Combined condition (any)
1265
1266
  - when:
@@ -1268,7 +1269,7 @@ steps:
1268
1269
  env: staging
1269
1270
  - var:
1270
1271
  env: prod
1271
- run: echo "Deploying to server..."
1272
+ run: 'echo "Deploying to server..."'
1272
1273
 
1273
1274
  # 9. Negation
1274
1275
  - when:
@@ -1278,7 +1279,7 @@ steps:
1278
1279
  message: "Build output not found"
1279
1280
 
1280
1281
  # 10. Variable substitution
1281
- - run: echo "Deploying {{projectName}} version {{version}} to {{env}}"
1282
+ - run: 'echo "Deploying {{projectName}} version {{version}} to {{env}}"'
1282
1283
  ```
1283
1284
 
1284
1285
  ---
package/dist/index.cjs CHANGED
@@ -12,7 +12,7 @@ ${r.stack??""}
12
12
  `).forEach(o=>{o.trim()&&console.log(`| ${o}`)}):console.log(e)}displayBufferedOutput(e,t,o=!1,n,s){let i=Le(t,n,s,{borderColor:"cyan",isNested:o});this.formatNestedOutput(i,o),e.stdout.forEach(l=>{let c=Oe(l,o);process.stdout.write(`${c}
13
13
  `)}),e.stderr.forEach(l=>{let c=Oe(l,o);process.stderr.write(`${c}
14
14
  `)});let a=K(e.success,o);console.log(a)}};function no(r,e,t){if(e.hasVariable(r))return e.getVariable(r)??t;if(e.hasFact(r)){let o=e.getFact(r);return typeof o=="string"?o:String(o)}return e.hasChoice(r)?e.getChoice(r)??t:t}function ye(r,e){let t=/\{\{\s*(\w+)\s*\}\}/g;return r.replace(t,(o,n)=>no(n,e,o))}var be=class r{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,o){this.state.stepResults.set(e,{success:t,exitCode:o}),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 r;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 re=class r{static PARALLEL_STEP_INDEX_MULTIPLIER=1e3;workspace;taskRunner;choicePrompt;textPrompt;baseDir;globalShell;constructor(){this.workspace=new be,this.taskRunner=new we,this.choicePrompt=new I,this.textPrompt=new me}resolveBaseDir(e){if(e.baseDir)if((0,q.isAbsolute)(e.baseDir))this.baseDir=e.baseDir;else if(e._filePath){let t=(0,q.dirname)(e._filePath);this.baseDir=(0,q.resolve)(t,e.baseDir)}else this.baseDir=(0,q.resolve)(process.cwd(),e.baseDir)}createStepContext(e,t){let o={workspace:this.workspace,stepIndex:e};return t._lineNumbers&&(o.lineNumber=t._lineNumbers.get(e)),t._fileName&&(o.fileName=t._fileName),o}evaluateStepCondition(e){return e.when?new ee(this.workspace).evaluate(e.when):!0}calculateBaseStepIndex(e){return e.branchIndex===void 0?e.stepIndex:Math.floor(e.stepIndex/r.PARALLEL_STEP_INDEX_MULTIPLIER)}isRunStep(e){return"run"in e}async execute(e,t){if(t?.profileVars&&Object.keys(t.profileVars).length>0)for(let[a,l]of Object.entries(t.profileVars))this.workspace.setVariable(a,l);this.resolveBaseDir(e),this.globalShell=e.shell;let o=new ge,n=Date.now();for(let a=0;a<e.steps.length;a++){let l=e.steps[a],c=this.createStepContext(a,e),f=!!l.when;if(this.evaluateStepCondition(l)){o.recordStart();try{let g=await this.executeStep(l,c,!1,f);this.handleStepResult(l,c,a,g,o)}catch(g){throw this.handleStepError(l,c,a,g,o),g}}}let s=Date.now()-n,i=Q(s);console.log(ut.default.cyan(`
15
- Total execution time: ${i}`)),await o.save(),o.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,o,n,s){let i=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(o);return c?c.success:!0})():this.isStepSuccessful(n,e),a=i?"success":"failure",l=s.recordEnd(e,t,n,a);if(!this.isRunStep(e)){let c=K(i,!1,l);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",f=i?`Step ${o}${c} completed, but workflow stopped due to continue: false`:`Step ${o}${c} failed`;throw new Error(f)}if(!i&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${o}${c} failed`)}}}handleStepError(e,t,o,n,s){this.workspace.setStepResult(o,!1);let i=n instanceof Error?n.message:String(n),a={success:!1,stdout:[],stderr:[i]};s.recordEnd(e,t,a,"failure")}fixMalformedStep(e){let o=e;return"choose"in e&&o.choose===null&&"message"in e&&"options"in e?{choose:{message:o.message,options:o.options,as:o.as},when:o.when}:"prompt"in e&&o.prompt===null&&"message"in e&&"as"in e?{prompt:{message:o.message,as:o.as,default:o.default},when:o.when}:e}async executeStep(e,t,o=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,o,n);return o&&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,o=!1,n=!1){let s=this.calculateBaseStepIndex(t),i=ye(e.run,this.workspace),a=e.shell??this.globalShell,l=e.retry??0,c=l==="Infinity"||l===1/0,f=typeof l=="number"?l:0,g=e.timeout,h=!1,d=0;for(;c||d<=f;){let w=await this.taskRunner.run(i,s,i,t.branchIndex,o,n,t.lineNumber,t.fileName,this.baseDir,g,a),b=typeof w=="boolean"?w:w.success;if(h=w,b||!c&&d>=f)break;if(d++,c||d<=f){let v=Math.min(1e3*Math.pow(2,d-1),1e4);await new Promise(E=>setTimeout(E,v))}}return h}async executeRunStep(e,t,o=!1,n=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,o,n),i=typeof s=="boolean"?s:s.success;if(this.workspace.setStepResult(t.stepIndex,i),i||!e.onError)return s;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,o,n)}async executeRunChain(e,t,o,n){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,o,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,o,n)}async executeChooseStep(e,t){let o=e.choose.as,n=e.choose.options.map(a=>a.id);if(o&&this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(t.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=o??s.id;this.workspace.setChoice(s.id,s.id),this.workspace.setVariable(i,s.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let o=e.prompt.as;if(this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";this.workspace.setFact(o,a),this.workspace.setStepResult(t.stepIndex,!0);return}let n=ye(e.prompt.message,this.workspace),s=e.prompt.default?ye(e.prompt.default,this.workspace):void 0,i=await this.textPrompt.prompt(n,s);this.workspace.setVariable(o,i),this.workspace.setFact(o,i),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((o,n)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*r.PARALLEL_STEP_INDEX_MULTIPLIER+n,branchIndex:n,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 o=[],n=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let c=0;c<e.length;c++){let f=e[c],g=t[c];if(f.when&&!new ee(g.workspace).evaluate(f.when))continue;let h=this.getBranchDisplayName(f,c);o.push({index:c,name:h,status:"pending"})}let i=setInterval(()=>{s=(s+1)%n.length,this.updateParallelBranchesDisplay(o,n[s])},100),a=o.map(async c=>{let{index:f}=c,g=e[f],h=t[f];c.status="running";try{let d=await this.executeStep(g,h,!0);return c.status="success",this.updateParallelBranchesDisplay(o,n[s]),{index:f,result:d,context:h}}catch(d){h.workspace.setStepResult(h.stepIndex,!1);let w=d instanceof Error?d.message:String(d);return c.status="failed",c.error=w,this.updateParallelBranchesDisplay(o,n[s]),{index:f,error:d,context:h}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(o,"",!0),Se.default.done(),l}updateParallelBranchesDisplay(e,t,o=!1){let n=e.map(s=>{let i=s.index+1,a="",l="";switch(s.status){case"pending":a="\u25CB",l=`Branch ${i}: ${s.name} - Pending`;break;case"running":a=t,l=`Branch ${i}: ${s.name} - Running...`;break;case"success":a="\u2713",l=`Branch ${i}: ${s.name} - Completed`;break;case"failed":a="\u2717",l=`Branch ${i}: ${s.name} - Failed${s.error?`: ${s.error}`:""}`;break}return`${a} ${l}`});o?(0,Se.default)(n.join(`
15
+ Total execution time: ${i}`)),await o.save(),o.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,o,n,s){let i=this.isRunStep(e)?(()=>{let c=this.workspace.getStepResult(o);return c?c.success:!0})():this.isStepSuccessful(n,e),a=i?"success":"failure",l=s.recordEnd(e,t,n,a);if(!this.isRunStep(e)){let c=K(i,!1,l);console.log(c)}if(this.isRunStep(e)){if(e.continue===!1){let c=t.lineNumber?` (line ${t.lineNumber})`:"",f=i?`Step ${o}${c} completed, but workflow stopped due to continue: false`:`Step ${o}${c} failed`;throw new Error(f)}if(!i&&e.continue!==!0){let c=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Step ${o}${c} failed`)}}}handleStepError(e,t,o,n,s){this.workspace.setStepResult(o,!1);let i=n instanceof Error?n.message:String(n),a={success:!1,stdout:[],stderr:[i]};s.recordEnd(e,t,a,"failure")}fixMalformedStep(e){let o=e;return"choose"in e&&o.choose===null&&"message"in e&&"options"in e?{choose:{message:o.message,options:o.options,as:o.as},when:o.when}:"prompt"in e&&o.prompt===null&&"message"in e&&"as"in e?{prompt:{message:o.message,as:o.as,default:o.default},when:o.when}:e}async executeStep(e,t,o=!1,n=!1){if(e=this.fixMalformedStep(e),"run"in e){let s=await this.executeRunStep(e,t,o,n);return o&&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,o=!1,n=!1){let s=this.calculateBaseStepIndex(t),i=ye(e.run.trim(),this.workspace),a=e.shell??this.globalShell,l=e.retry??0,c=l==="Infinity"||l===1/0,f=typeof l=="number"?l:0,g=e.timeout,h=!1,d=0;for(;c||d<=f;){let w=await this.taskRunner.run(i,s,i,t.branchIndex,o,n,t.lineNumber,t.fileName,this.baseDir,g,a),b=typeof w=="boolean"?w:w.success;if(h=w,b||!c&&d>=f)break;if(d++,c||d<=f){let v=Math.min(1e3*Math.pow(2,d-1),1e4);await new Promise(E=>setTimeout(E,v))}}return h}async executeRunStep(e,t,o=!1,n=!1){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:e.shell},t,o,n),i=typeof s=="boolean"?s:s.success;if(this.workspace.setStepResult(t.stepIndex,i),i||!e.onError)return s;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,o,n)}async executeRunChain(e,t,o,n){let s=await this.executeSingleRun({run:e.run,timeout:e.timeout,retry:e.retry,shell:void 0},t,o,n);return(typeof s=="boolean"?s:s.success)||!e.onError?s:this.executeRunChain(e.onError,t,o,n)}async executeChooseStep(e,t){let o=e.choose.as,n=e.choose.options.map(a=>a.id);if(o&&this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";if(n.includes(a)){this.workspace.setChoice(a,a),this.workspace.setStepResult(t.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=o??s.id;this.workspace.setChoice(s.id,s.id),this.workspace.setVariable(i,s.id),this.workspace.setStepResult(t.stepIndex,!0)}async executePromptStep(e,t){let o=e.prompt.as;if(this.workspace.hasVariable(o)){let a=this.workspace.getVariable(o)??"";this.workspace.setFact(o,a),this.workspace.setStepResult(t.stepIndex,!0);return}let n=ye(e.prompt.message,this.workspace),s=e.prompt.default?ye(e.prompt.default,this.workspace):void 0,i=await this.textPrompt.prompt(n,s);this.workspace.setVariable(o,i),this.workspace.setFact(o,i),this.workspace.setStepResult(t.stepIndex,!0)}createParallelContexts(e,t){return e.parallel.map((o,n)=>({workspace:this.workspace.clone(),stepIndex:t.stepIndex*r.PARALLEL_STEP_INDEX_MULTIPLIER+n,branchIndex:n,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 o=[],n=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],s=0;for(let c=0;c<e.length;c++){let f=e[c],g=t[c];if(f.when&&!new ee(g.workspace).evaluate(f.when))continue;let h=this.getBranchDisplayName(f,c);o.push({index:c,name:h,status:"pending"})}let i=setInterval(()=>{s=(s+1)%n.length,this.updateParallelBranchesDisplay(o,n[s])},100),a=o.map(async c=>{let{index:f}=c,g=e[f],h=t[f];c.status="running";try{let d=await this.executeStep(g,h,!0);return c.status="success",this.updateParallelBranchesDisplay(o,n[s]),{index:f,result:d,context:h}}catch(d){h.workspace.setStepResult(h.stepIndex,!1);let w=d instanceof Error?d.message:String(d);return c.status="failed",c.error=w,this.updateParallelBranchesDisplay(o,n[s]),{index:f,error:d,context:h}}}),l=await Promise.all(a);return clearInterval(i),this.updateParallelBranchesDisplay(o,"",!0),Se.default.done(),l}updateParallelBranchesDisplay(e,t,o=!1){let n=e.map(s=>{let i=s.index+1,a="",l="";switch(s.status){case"pending":a="\u25CB",l=`Branch ${i}: ${s.name} - Pending`;break;case"running":a=t,l=`Branch ${i}: ${s.name} - Running...`;break;case"success":a="\u2713",l=`Branch ${i}: ${s.name} - Completed`;break;case"failed":a="\u2717",l=`Branch ${i}: ${s.name} - Failed${s.error?`: ${s.error}`:""}`;break}return`${a} ${l}`});o?(0,Se.default)(n.join(`
16
16
  `)):(0,Se.default)(n.join(`
17
17
  `))}displayParallelResults(e,t,o){let n=!0,s=!1;console.log("");for(let a of e){if(!a)continue;s=!0;let{index:l,result:c,error:f,context:g}=a;if(f){n=!1;let h=`Branch ${l+1} failed: ${f instanceof Error?f.message:String(f)}`,d=ce(h);console.error(d)}else if(c&&typeof c=="object"&&"stdout"in c){let h=c;if(n=n&&h.success,h.stdout.length>0||h.stderr.length>0||!h.success){let d=t[l],w=this.getBranchDisplayName(d,l);this.taskRunner.displayBufferedOutput(h,w,!1,g.lineNumber,g.fileName)}}}s||console.log("\u26A0\uFE0F All parallel branches were skipped (conditions not met)");let i=st(n);return console.log(i),n}mergeParallelResults(e){for(let t of e){let o=t.workspace.getAllFacts(),n=t.workspace.getAllVariables();for(let[s,i]of o)this.workspace.setFact(s,i);for(let[s,i]of n)this.workspace.setVariable(s,i)}}countExecutableBranches(e,t){let o=0;for(let n=0;n<e.length;n++){let s=e[n],i=t[n];s.when&&!new ee(i.workspace).evaluate(s.when)||o++}return o}async executeParallelStep(e,t){let o=this.createParallelContexts(e,t),n=this.countExecutableBranches(e.parallel,o),s=nt(n);console.log(s);let i=await this.executeParallelBranches(e.parallel,o),a=this.displayParallelResults(i,e.parallel,t);if(this.workspace.setStepResult(t.stepIndex,a),!a){let l=t.lineNumber?` (line ${t.lineNumber})`:"";throw new Error(`Parallel step ${t.stepIndex}${l} failed: one or more branches failed`)}this.mergeParallelResults(o)}async executeFailStep(e,t){let o=new Error(e.fail.message);throw o.stack=void 0,o}};var ht=require("yaml"),He=require("zod");var u=require("zod"),so=u.z.object({file:u.z.string()}),io=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()}),ao=u.z.object({status:u.z.object({fact:u.z.string(),is:u.z.enum(["ready","failed","pending"])})}),lo=u.z.object({step:u.z.object({success:u.z.boolean()}).optional(),last_step:u.z.enum(["success","failure"]).optional()}),co=u.z.object({choice:u.z.string()}),uo=u.z.union([so,co,io,ao,lo]),A=u.z.lazy(()=>u.z.union([uo,u.z.object({all:u.z.array(A)}),u.z.object({any:u.z.array(A)}),u.z.object({not:A})])),pt=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:pt.optional()})),dt=u.z.object({run:u.z.string(),when:A.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:pt.optional()}),po=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:A.optional()}),fo=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:A.optional()});function ft(r){if(!r||typeof r!="object")return{found:!1};let e=r;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 t of e.parallel){let o=ft(t);if(o.found)return o}return{found:!1}}var mt=u.z.lazy(()=>u.z.union([dt,u.z.object({parallel:u.z.array(u.z.lazy(()=>mt)),when:A.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:A.optional()})]).superRefine((r,e)=>{let t=ft(r);t.found&&e.addIssue({code:u.z.ZodIssueCode.custom,message:`'${t.type}' step is not allowed inside 'parallel' block (user input cannot run in parallel)`})})),mo=u.z.lazy(()=>u.z.union([dt,po,fo,u.z.object({parallel:u.z.array(mt),when:A.optional()}),u.z.object({fail:u.z.object({message:u.z.string()}),when:A.optional()})])),ho=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))}),go=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(ho).optional(),steps:u.z.array(mo).min(1,"Workflow must have at least one step")});function Be(r){return go.parse(r)}function gt(r,e){let t=r.path;if(r.code==="custom"){let n=We(t);return` - ${r.message}${n}`}if(r.message==="Invalid input"){let n=We(t),s=wo(t,e);return s?` - ${s}${n}`:` - Invalid step type${n}`}let o=We(t);return` - ${r.message}${o}`}function We(r){if(r.length===0)return"";let e=[];for(let t=0;t<r.length;t++){let o=r[t],n=r[t+1];o==="steps"&&typeof n=="number"?(e.push(`step ${n+1}`),t++):o==="parallel"&&typeof n=="number"?(e.push(`parallel branch ${n+1}`),t++):typeof o=="string"&&o!=="steps"&&o!=="parallel"&&e.push(o)}return e.length>0?` (${e.join(" \u2192 ")})`:""}function k(r,e,t){let o=t?`
18
18
  Reason: ${t}`:"";throw new Error(`Invalid workflow structure:
@@ -48,7 +48,7 @@ ${n}`)}throw o}}extractStepLineNumbers(e){let t=new Map,o=e.split(`
48
48
  `))}}stop(){for(let e of this.tasks.values())e.stop();this.tasks.clear()}async stopDaemon(){let e=await $();if(!e.running||!e.pid)return!1;let t=e.pid;try{if(process.kill(t,"SIGTERM"),await new Promise(o=>setTimeout(o,1e3)),await H()){try{process.kill(t,"SIGKILL")}catch{}await new Promise(o=>setTimeout(o,500))}return await ae(),!0}catch{return await ae(),!1}}};var Ot=require("child_process"),Ee=require("fs"),Ft=require("fs/promises"),R=require("path"),Re=y(require("boxen"),1),m=y(require("chalk"),1),Bt=require("commander"),Pe=y(require("dayjs"),1),Ce=y(require("inquirer"),1),pe=y(require("log-update"),1),Wt=y(require("node-cron"),1);le();var Et=require("fs/promises"),Rt=require("path"),Pt=require("yaml"),Ct=require("zod");var C=require("zod"),vo=C.z.object({name:C.z.string().min(1,"Schedule name must be non-empty"),cron:C.z.string().min(1,"Cron expression is required"),workflow:C.z.string().min(1,"Workflow path is required"),baseDir:C.z.string().optional(),timezone:C.z.union([C.z.string(),C.z.number()]).transform(String).optional(),silent:C.z.boolean().optional(),profile:C.z.string().optional()}),ko=C.z.object({schedules:C.z.array(vo).min(1,"Schedule file must have at least one schedule")});function $t(r){return ko.parse(r)}async function Dt(r){let e=await(0,Et.readFile)(r,"utf-8"),t=(0,Rt.extname)(r).toLowerCase(),o;try{if(t===".yaml"||t===".yml")o=(0,Pt.parse)(e);else if(t===".json")o=JSON.parse(e);else throw new Error(`Unsupported file format: ${t}. Use .yaml, .yml, or .json`)}catch(n){if(n instanceof Error&&n.message.startsWith("Unsupported"))throw n;let s=t===".json"?"JSON":"YAML";throw new Error(`Invalid ${s} format: ${n instanceof Error?n.message:String(n)}`)}try{return $t(o)}catch(n){if(n instanceof Ct.ZodError){let s=n.issues.map(i=>` - ${i.message} (${i.path.join(".")})`).join(`
49
49
  `);throw new Error(`Invalid schedule file structure:
50
50
  ${s}`)}throw n}}var Tt=y(require("boxen"),1),S=y(require("chalk"),1),It=y(require("cronstrue"),1),Ye=y(require("dayjs"),1),Je=y(require("node-cron"),1);function qe(r){try{return It.default.toString(r)}catch{return null}}function xo(r){if(!Je.default.validate(r.cron))return null;try{let e={},t=ke(r.timezone);t&&(e.timezone=t);let o=Je.default.createTask(r.cron,()=>{},e),n=o.getNextRun();return o.destroy(),n}catch{return null}}function G(r,e){let t=r,{daemonRunning:o,emphasizeState:n}=e,s=t.enabled?n?S.default.bold.green("ENABLED"):S.default.green("enabled"):n?S.default.bold.gray("DISABLED"):S.default.gray("disabled"),i=o&&t.enabled,a=i?S.default.green("\u25CF active"):S.default.gray("\u25CB inactive"),l=n?t.enabled?S.default.bold.green(" [ENABLED]"):S.default.bold.gray(" [DISABLED]"):"",c=S.default.bold(t.name??t.workflowPath),f=xo(t),g=f?(0,Ye.default)(f).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("\u2014"),h=t.lastRun?(0,Ye.default)(t.lastRun).format("YYYY-MM-DD HH:mm:ss"):S.default.dim("never"),d=qe(t.cron),w=t.timezone?t.timezone.startsWith("+")||t.timezone.startsWith("-")?`UTC${t.timezone}`:`UTC+${t.timezone}`:null,b=d?`${t.cron} ${S.default.dim(`\u2192 ${d}`)}`:t.cron,v=[[S.default.gray("Enabled"),s],[S.default.gray("Cron"),b],...w?[[S.default.gray("Timezone"),w]]:[],[S.default.gray("Workflow"),t.workflowPath],...t.profile?[[S.default.gray("Profile"),S.default.cyan(t.profile)]]:[],...t.silent?[[S.default.gray("Silent"),S.default.yellow("yes")]]:[],[S.default.gray("Last run"),h],[S.default.gray("Next run"),g]],E=[`${c} ${a}${l}`,...v.map(([B,W])=>` ${B.padEnd(10)} ${W}`)].join(`
51
- `);return(0,Tt.default)(E,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:i?"green":"gray"})}var V=require("fs"),P=require("path"),Ge=require("url"),Mt={};function Nt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function jt(){return"0.3.4"}function $e(r){let e=r?(0,P.resolve)(r):process.cwd(),t=50,o=0;for(;o<t;){let n=(0,P.resolve)(e,"tp");try{if((0,V.existsSync)(n)&&(0,V.statSync)(n).isDirectory())return n}catch{}let s=(0,P.dirname)(e);if(s===e)break;e=s,o++}return null}function _t(){let r=new Bt.Command("schedule").description("Manage workflow schedules").action(async()=>{await At()});return r.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 $o(e)}),r.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await Eo()}),r.command("remove-all").description("Remove all workflow schedules").action(async()=>{await Mo()}),r.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await At()}),r.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await Ro(e.daemon??!1)}),r.command("stop").description("Stop the scheduler daemon").action(async()=>{await Po()}),r.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 To(t)}),r.command("toggle").description("Enable or disable a schedule").action(async()=>{await Io()}),r}function Ze(r,e){let t=e.workflow;if((0,R.isAbsolute)(t))return t;let o=e.baseDir?(0,R.resolve)(e.baseDir):(0,R.dirname)(r);return(0,R.resolve)(o,t)}async function $o(r){let e=new j;if(!r){let l=$e();l||(console.error(m.default.red(`
51
+ `);return(0,Tt.default)(E,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:i?"green":"gray"})}var V=require("fs"),P=require("path"),Ge=require("url"),Mt={};function Nt(){console.log=()=>{},console.error=()=>{},console.warn=()=>{},console.info=()=>{},process.stdout.write=()=>!0,process.stderr.write=()=>!0}function jt(){return"0.3.5"}function $e(r){let e=r?(0,P.resolve)(r):process.cwd(),t=50,o=0;for(;o<t;){let n=(0,P.resolve)(e,"tp");try{if((0,V.existsSync)(n)&&(0,V.statSync)(n).isDirectory())return n}catch{}let s=(0,P.dirname)(e);if(s===e)break;e=s,o++}return null}function _t(){let r=new Bt.Command("schedule").description("Manage workflow schedules").action(async()=>{await At()});return r.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 $o(e)}),r.command("remove").alias("rm").description("Remove a workflow schedule").action(async()=>{await Eo()}),r.command("remove-all").description("Remove all workflow schedules").action(async()=>{await Mo()}),r.command("list").alias("ls").description("List all workflow schedules").action(async()=>{await At()}),r.command("start").description("Start the scheduler daemon").option("-d, --daemon","Run in background daemon mode").action(async e=>{await Ro(e.daemon??!1)}),r.command("stop").description("Stop the scheduler daemon").action(async()=>{await Po()}),r.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 To(t)}),r.command("toggle").description("Enable or disable a schedule").action(async()=>{await Io()}),r}function Ze(r,e){let t=e.workflow;if((0,R.isAbsolute)(t))return t;let o=e.baseDir?(0,R.resolve)(e.baseDir):(0,R.dirname)(r);return(0,R.resolve)(o,t)}async function $o(r){let e=new j;if(!r){let l=$e();l||(console.error(m.default.red(`
52
52
  \u2717 No tp directory found`)),process.exit(1));let c=(0,R.join)(l,"schedules");(0,Ee.existsSync)(c)||(console.error(m.default.red(`
53
53
  \u2717 No schedules directory found at ${c}`)),process.exit(1));let g=(await(0,Ft.readdir)(c)).filter(b=>{let v=(0,R.extname)(b).toLowerCase();return[".yaml",".yml",".json"].includes(v)});g.length===0&&(console.error(m.default.red(`
54
54
  \u2717 No schedule files found in ${c}`)),process.exit(1));let h=g.map(b=>({id:(0,R.join)(c,b),label:b}));r=(await new I(!0).prompt("Select a schedule file to add",h)).id}let t=(0,R.resolve)(r);(0,Ee.existsSync)(t)||(console.error(`\u2717 File not found: ${t}`),process.exit(1));let o;try{o=await Dt(t)}catch(l){console.error(`\u2717 Failed to parse schedule file: ${l instanceof Error?l.message:String(l)}`),process.exit(1)}let n=o.schedules.filter(l=>!Wt.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}"`);process.exit(1)}let s=o.schedules.filter(l=>{let c=Ze(t,l);return!(0,Ee.existsSync)(c)});if(s.length>0){console.error("\u2717 Workflow file(s) not found:");for(let l of s){let c=Ze(t,l);console.error(` - ${l.name}: ${l.workflow} (resolved: ${c})`)}process.exit(1)}console.log(`
@@ -93,7 +93,7 @@ Quick Start:
93
93
 
94
94
  1. Create a workflow.yaml or workflow.json file:
95
95
  steps:
96
- - run: echo "Hello, World!"
96
+ - run: 'echo "Hello, World!"'
97
97
  - choose:
98
98
  message: "Select action:"
99
99
  options:
@@ -103,7 +103,7 @@ Quick Start:
103
103
  - when:
104
104
  var:
105
105
  action: build
106
- run: npm run build
106
+ run: 'npm run build'
107
107
 
108
108
  2. Run it:
109
109
  tp run workflow.yaml
@@ -195,7 +195,7 @@ Please visit manually: ${t}`)),process.exit(1)}});U.addCommand(_t());var jo=[{fi
195
195
 
196
196
  # Interactive choice: stored as variable and used in later steps
197
197
  steps:
198
- - run: echo "Hello from task-pipeliner"
198
+ - run: 'echo "Hello from task-pipeliner"'
199
199
  - choose:
200
200
  message: "Select action:"
201
201
  options:
@@ -204,15 +204,15 @@ steps:
204
204
  - id: info
205
205
  label: "Show info"
206
206
  as: action
207
- - run: echo "You chose: {{ action }}"
207
+ - run: 'echo "You chose: {{ action }}"'
208
208
  - when:
209
209
  var:
210
210
  action: greet
211
- run: echo "Hi there! Edit tp/workflows/*.yaml and run: tp run tp/workflows/example-hello.yaml"
211
+ run: 'echo "Hi there! Edit tp/workflows and run: tp run tp/workflows/example-hello.yaml"'
212
212
  - when:
213
213
  var:
214
214
  action: info
215
- run: echo "Tip: Use --profile to skip prompts. See example-build.yaml for profiles."
215
+ run: 'echo "Tip: Use --profile. See example-build.yaml for profiles."'
216
216
  `},{filename:"example-build.yaml",content:`name: Example Build (with profiles and choose)
217
217
 
218
218
  # Profiles: run without prompts via "tp run tp/workflows/example-build.yaml --profile Dev"
@@ -228,7 +228,7 @@ profiles:
228
228
  label: "prod-build"
229
229
 
230
230
  steps:
231
- - run: echo "Build workflow started..."
231
+ - run: 'echo "Build workflow started..."'
232
232
  - choose:
233
233
  message: "Select mode (or run with --profile Dev/Prod to skip):"
234
234
  options:
@@ -237,21 +237,21 @@ steps:
237
237
  - id: prod
238
238
  label: "Production"
239
239
  as: mode
240
- - run: echo "Mode: {{ mode }}"
240
+ - run: 'echo "Mode: {{ mode }}"'
241
241
  - prompt:
242
242
  message: "Enter build label"
243
243
  as: label
244
244
  default: "default"
245
- - run: echo "Label: {{ label }}"
245
+ - run: 'echo "Label: {{ label }}"'
246
246
  - when:
247
247
  var:
248
248
  mode: dev
249
- run: echo "Dev-only step (e.g. npm run build:dev)"
249
+ run: 'echo "Dev-only step (e.g. npm run build:dev)"'
250
250
  - when:
251
251
  var:
252
252
  mode: prod
253
- run: echo "Prod-only step (e.g. npm run build)"
254
- - run: echo "Done. Replace run steps with real commands."
253
+ run: 'echo "Prod-only step (e.g. npm run build)"'
254
+ - run: 'echo "Done. Replace run steps with real commands."'
255
255
  `}],Ao=[{filename:"example-daily.yaml",content:`schedules:
256
256
  # Runs at 09:00 daily; interactive choose is skipped in scheduled runs (no TTY)
257
257
  - name: Daily Hello
@@ -287,10 +287,9 @@ steps:
287
287
  \u2717 No tp directory found`)),null;let e=(0,D.join)(r,"workflows");if(!(0,O.existsSync)(e))return console.error(p.default.red(`
288
288
  \u2717 No workflows directory found at ${e}`)),null;try{let o=(await(0,F.readdir)(e)).filter(a=>{let l=(0,D.extname)(a).toLowerCase();return[".yaml",".yml",".json"].includes(l)});if(o.length===0)return console.error(p.default.red(`
289
289
  \u2717 No workflow files found in ${e}`)),null;let n=await Promise.all(o.map(async a=>{let l=(0,D.join)(e,a);try{let c=ue(l),f=(0,O.readFileSync)(l,"utf-8"),h=c.parse(f).name??"Untitled";return{id:l,label:`${a} - ${h}`}}catch{return{id:l,label:a}}}));return(await new I(!0).prompt("Select a workflow to run",n)).id}catch(t){let o=t instanceof Error?t.message:String(t);return console.error(p.default.red(`
290
- \u2717 Failed to read tp directory: ${o}`)),null}}function Fo(r){return r.split("/").pop()??r}function Bo(r,e){console.log(`
291
- `);let t=r.records.reduce((c,f)=>c+f.duration,0),o=r.records.filter(c=>c.status==="success").length,n=r.records.filter(c=>c.status==="failure").length,s=(0,Jt.default)(r.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=Q(t),l=[p.default.bold("Workflow Execution History"),"",`${p.default.cyan("File:")} ${e}`,`${p.default.cyan("Started:")} ${s}`,`${p.default.cyan("Total Duration:")} ${a}`,`${p.default.cyan("Total Steps:")} ${r.records.length}`,`${p.default.green("\u2713 Successful:")} ${o}`,n>0?`${p.default.red("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
292
- `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:"cyan"})),r.records.forEach((c,f)=>{Wo(c,f+1,r.records.length)}),console.log("")}function Wo(r,e,t){let o=_o(r.step),n=Ho(r.step),s=r.status==="success"?p.default.green("\u2713"):p.default.red("\u2717"),i=r.status==="success"?p.default.green("Success"):p.default.red("Failed"),a=Q(r.duration),l=[`${s} ${p.default.bold(`Step ${e}/${t}`)} - ${p.default.cyan(o)}`,`${p.default.gray("Duration:")} ${a} | ${p.default.gray("Status:")} ${i}`,"",p.default.white(n)].join(`
293
- `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),Vo(r.output)&&zo(r.output)}function _o(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function Ho(r){return"run"in r?`Command: ${p.default.yellow(r.run)}`:"choose"in r?`Message: ${p.default.yellow(r.choose.message)}`:"prompt"in r?`Message: ${p.default.yellow(r.prompt.message)} | Variable: ${p.default.cyan(r.prompt.as)}`:"parallel"in r?`Parallel execution with ${r.parallel.length} branches`:"fail"in r?`Error: ${p.default.red(r.fail.message)}`:"Unknown step type"}function Vo(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function zo(r){if(r.stdout.length>0){let e=r.stdout.map(t=>p.default.gray(` ${t}`)).join(`
290
+ \u2717 Failed to read tp directory: ${o}`)),null}}function Fo(r){return r.split("/").pop()??r}function Bo(r,e){console.log();let t=r.records.reduce((c,f)=>c+f.duration,0),o=r.records.filter(c=>c.status==="success").length,n=r.records.filter(c=>c.status==="failure").length,s=(0,Jt.default)(r.initialTimestamp).format("YYYY-MM-DD HH:mm:ss"),a=Q(t),l=[p.default.bold("Workflow Execution History"),"",`${p.default.cyan("File:")} ${e}`,`${p.default.cyan("Started:")} ${s}`,`${p.default.cyan("Total Duration:")} ${a}`,`${p.default.cyan("Total Steps:")} ${r.records.length}`,`${p.default.green("\u2713 Successful:")} ${o}`,n>0?`${p.default.red("\u2717 Failed:")} ${n}`:""].filter(Boolean).join(`
291
+ `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:"cyan"})),r.records.forEach((c,f)=>{Wo(c,f+1,r.records.length)}),console.log()}function Wo(r,e,t){let o=_o(r.step),n=Ho(r.step),s=r.status==="success"?p.default.green("\u2713"):p.default.red("\u2717"),i=r.status==="success"?p.default.green("Success"):p.default.red("Failed"),a=Q(r.duration),l=[`${s} ${p.default.bold(`Step ${e}/${t}`)} - ${p.default.cyan(o)}`,`${p.default.gray("Duration:")} ${a} | ${p.default.gray("Status:")} ${i}`,"",p.default.white(n)].join(`
292
+ `);console.log((0,Ke.default)(l,{borderStyle:"round",padding:{top:0,bottom:0,left:1,right:1},margin:{top:0,bottom:0,left:0,right:0},borderColor:r.status==="success"?"green":"red"})),Vo(r.output)&&zo(r.output)}function _o(r){return"run"in r?"Run":"choose"in r?"Choose":"prompt"in r?"Prompt":"parallel"in r?"Parallel":"fail"in r?"Fail":"Unknown"}function Ho(r){return"run"in r?`Command: ${p.default.yellow(r.run)}`:"choose"in r?`Message: ${p.default.yellow(r.choose.message)}`:"prompt"in r?`Message: ${p.default.yellow(r.prompt.message)} | Variable: ${p.default.cyan(r.prompt.as)}`:"parallel"in r?`Parallel execution with ${r.parallel.length} branches`:"fail"in r?`Error: ${p.default.red(r.fail.message)}`:"Unknown step type"}function Vo(r){return typeof r=="object"&&r!==null&&"success"in r&&"stdout"in r&&"stderr"in r}function zo(r){if(r.stdout.length>0){let e=r.stdout.map(t=>p.default.gray(` ${t}`)).join(`
294
293
  `);console.log(p.default.green(" Output:")),console.log(e)}if(r.stderr.length>0){let e=r.stderr.map(t=>p.default.gray(` ${t}`)).join(`
295
294
  `);console.log(p.default.red(" Errors:")),console.log(e)}}U.command("clean").description("Remove all data in ~/.pipeliner (schedules, daemon state, workflow history). Use after upgrades if data is incompatible.").action(async()=>{if((await new I().prompt(`This will remove all data in ${p.default.yellow(de)} (schedules, daemon PID, workflow history). Continue?`,[{id:"yes",label:"Yes, remove all"},{id:"no",label:"No, cancel"}]))?.id!=="yes"){console.log(p.default.yellow(`
296
295
  \u2717 Cancelled`));return}try{if(await H()){let t=await $();console.log(p.default.gray(`Stopping scheduler daemon (PID: ${t.pid})...`)),await new z().stopDaemon(),console.log(p.default.gray(" Daemon stopped"))}(0,O.existsSync)(de)?(await(0,F.rm)(de,{recursive:!0}),console.log(p.default.green(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "task-pipeliner",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "A task pipeline runner with condition-based workflow execution",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",