rest-pipeline-js 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +103 -74
  3. package/.claude/settings.local.json +0 -11
  4. package/CHANGELOG.md +0 -150
  5. package/demo/App.vue +0 -122
  6. package/demo/index.html +0 -22
  7. package/demo/main.js +0 -5
  8. package/demo/style.css +0 -857
  9. package/demo/views/CacheDemo.vue +0 -599
  10. package/demo/views/FlightDemo.vue +0 -481
  11. package/demo/views/ParallelDemo.vue +0 -546
  12. package/demo/views/RetryDemo.vue +0 -506
  13. package/eslint.config.js +0 -40
  14. package/react-shim.d.ts +0 -1
  15. package/src/cache.ts +0 -93
  16. package/src/circuit-breaker.ts +0 -90
  17. package/src/error-handler.ts +0 -10
  18. package/src/index.ts +0 -11
  19. package/src/pipeline-builder.ts +0 -179
  20. package/src/pipeline-orchestrator.ts +0 -1397
  21. package/src/pipeline-validator.ts +0 -151
  22. package/src/progress-tracker.ts +0 -60
  23. package/src/rate-limiter.ts +0 -76
  24. package/src/react.ts +0 -12
  25. package/src/request-executor.ts +0 -168
  26. package/src/rest-client.ts +0 -570
  27. package/src/tsconfig.json +0 -10
  28. package/src/types.ts +0 -720
  29. package/src/usePipelineProgress-react.ts +0 -21
  30. package/src/usePipelineProgress-vue.ts +0 -17
  31. package/src/usePipelineRun-react.ts +0 -52
  32. package/src/usePipelineRun-vue.ts +0 -63
  33. package/src/usePipelineStageResult-react.ts +0 -32
  34. package/src/usePipelineStageResult-vue.ts +0 -34
  35. package/src/usePipelineStepEvents-react.ts +0 -49
  36. package/src/usePipelineStepEvents-vue.ts +0 -48
  37. package/src/useRestClient-react.ts +0 -12
  38. package/src/useRestClient-vue.ts +0 -12
  39. package/src/vue-demo/demo.css +0 -768
  40. package/src/vue-demo/demo.vue +0 -621
  41. package/src/vue-demo/index.html +0 -21
  42. package/src/vue-demo/main.js +0 -4
  43. package/src/vue.ts +0 -12
  44. package/tests/error-handler.test.ts +0 -10
  45. package/tests/pipeline-builder.test.ts +0 -112
  46. package/tests/pipeline-orchestrator.test.ts +0 -1461
  47. package/tests/progress-tracker.test.ts +0 -13
  48. package/tests/react-hooks.test.ts +0 -61
  49. package/tests/request-executor.test.ts +0 -39
  50. package/tests/rest-client.test.ts +0 -548
  51. package/tests/types.test.ts +0 -105
  52. package/tests/vue-hooks.test.ts +0 -57
  53. package/tsconfig.cjs.json +0 -17
  54. package/tsconfig.esm.json +0 -16
  55. package/tsconfig.json +0 -17
  56. package/vite.config.js +0 -25
  57. package/vitest.config.ts +0 -9
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Danil Lisin Vladimirovich (macrulez)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json CHANGED
@@ -1,74 +1,103 @@
1
- {
2
- "name": "rest-pipeline-js",
3
- "version": "1.4.0",
4
- "description": "Pipeline Orchestration Utilities for JavaScript REST API Clients",
5
- "main": "dist/cjs/index.js",
6
- "module": "dist/esm/index.js",
7
- "types": "dist/esm/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/esm/index.d.ts",
11
- "import": "./dist/esm/index.js",
12
- "require": "./dist/cjs/index.js"
13
- },
14
- "./vue": {
15
- "types": "./dist/esm/vue.d.ts",
16
- "import": "./dist/esm/vue.js",
17
- "require": "./dist/cjs/vue.js"
18
- },
19
- "./react": {
20
- "types": "./dist/esm/react.d.ts",
21
- "import": "./dist/esm/react.js",
22
- "require": "./dist/cjs/react.js"
23
- }
24
- },
25
- "sideEffects": false,
26
- "scripts": {
27
- "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json",
28
- "test": "vitest run",
29
- "demo:vue": "npm run start-demo-vite",
30
- "start-demo-vite": "vite --config vite.config.js"
31
- },
32
- "repository": {
33
- "type": "git",
34
- "url": ""
35
- },
36
- "keywords": [
37
- "rest",
38
- "api",
39
- "client",
40
- "pipeline"
41
- ],
42
- "author": "macrulez",
43
- "license": "MIT",
44
- "bugs": {
45
- "url": "https://github.com/macrulezru/pipeline-js"
46
- },
47
- "homepage": "https://macrulez.ru/#/en",
48
- "devDependencies": {
49
- "@testing-library/react": "^16.3.1",
50
- "@types/react": "^19.2.8",
51
- "@typescript-eslint/eslint-plugin": "^8.53.0",
52
- "@typescript-eslint/parser": "^8.53.0",
53
- "@vitejs/plugin-vue": "^6.0.3",
54
- "eslint": "^9.39.2",
55
- "eslint-plugin-vue": "^10.6.2",
56
- "jsdom": "^27.4.0",
57
- "react": "^19.2.3",
58
- "react-dom": "^19.2.3",
59
- "scheduler": "^0.27.0",
60
- "typescript": "^5.9.3",
61
- "vite": "^7.3.1",
62
- "vitest": "^4.0.17",
63
- "vue": "^3.5.26",
64
- "vue-eslint-parser": "^10.2.0"
65
- },
66
- "peerDependencies": {
67
- "react": "^19.2.3",
68
- "react-dom": "^19.2.3"
69
- },
70
- "dependencies": {
71
- "axios": "^1.13.2",
72
- "prismjs": "^1.30.0"
73
- }
74
- }
1
+ {
2
+ "name": "rest-pipeline-js",
3
+ "version": "1.4.1",
4
+ "description": "Orchestrate REST API calls in sequential and parallel pipelines with retry, caching, rate limiting and SSE streaming. Vanilla JS / Vue 3 / React.",
5
+ "author": "macrulez <macrulezru@gmail.com> (https://macrulez.ru/en)",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/macrulezru/pipeline-js#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/macrulezru/pipeline-js.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/macrulezru/pipeline-js/issues"
14
+ },
15
+ "main": "dist/cjs/index.js",
16
+ "module": "dist/esm/index.js",
17
+ "types": "dist/esm/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/esm/index.d.ts",
21
+ "import": "./dist/esm/index.js",
22
+ "require": "./dist/cjs/index.js"
23
+ },
24
+ "./vue": {
25
+ "types": "./dist/esm/vue.d.ts",
26
+ "import": "./dist/esm/vue.js",
27
+ "require": "./dist/cjs/vue.js"
28
+ },
29
+ "./react": {
30
+ "types": "./dist/esm/react.d.ts",
31
+ "import": "./dist/esm/react.js",
32
+ "require": "./dist/cjs/react.js"
33
+ }
34
+ },
35
+ "sideEffects": false,
36
+ "files": [
37
+ "dist",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "scripts": {
45
+ "prepublishOnly": "npm run build",
46
+ "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json",
47
+ "test": "vitest run",
48
+ "demo:vue": "npm run start-demo-vite",
49
+ "start-demo-vite": "vite --config vite.config.js"
50
+ },
51
+ "keywords": [
52
+ "rest",
53
+ "api",
54
+ "pipeline",
55
+ "orchestration",
56
+ "retry",
57
+ "cache",
58
+ "rate-limit",
59
+ "sse",
60
+ "axios",
61
+ "vue",
62
+ "react",
63
+ "typescript"
64
+ ],
65
+ "peerDependencies": {
66
+ "react": ">=18.0.0",
67
+ "react-dom": ">=18.0.0",
68
+ "vue": ">=3.3.0"
69
+ },
70
+ "peerDependenciesMeta": {
71
+ "react": {
72
+ "optional": true
73
+ },
74
+ "react-dom": {
75
+ "optional": true
76
+ },
77
+ "vue": {
78
+ "optional": true
79
+ }
80
+ },
81
+ "dependencies": {
82
+ "axios": "^1.13.2"
83
+ },
84
+ "devDependencies": {
85
+ "@testing-library/react": "^16.3.1",
86
+ "@types/react": "^19.2.8",
87
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
88
+ "@typescript-eslint/parser": "^8.53.0",
89
+ "@vitejs/plugin-vue": "^6.0.3",
90
+ "eslint": "^9.39.2",
91
+ "eslint-plugin-vue": "^10.6.2",
92
+ "jsdom": "^27.4.0",
93
+ "prismjs": "^1.30.0",
94
+ "react": "^19.2.3",
95
+ "react-dom": "^19.2.3",
96
+ "scheduler": "^0.27.0",
97
+ "typescript": "^5.9.3",
98
+ "vite": "^7.3.1",
99
+ "vitest": "^4.0.17",
100
+ "vue": "^3.5.26",
101
+ "vue-eslint-parser": "^10.2.0"
102
+ }
103
+ }
@@ -1,11 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(grep -n \"stepIndex,$\\\\|stepIndex: i,\\\\|emitStepStart\\(\\\\|emitStepFinish\\(\\\\|emitStepError\\(\\\\|emitStepSkipped\\(\\\\|stageResults: { \\\\.\\\\.\\\\.this\\\\.stageResults }\" src/pipeline-orchestrator.ts)",
5
- "Bash(cat > *)"
6
- ],
7
- "additionalDirectories": [
8
- "\\tmp"
9
- ]
10
- }
11
- }
package/CHANGELOG.md DELETED
@@ -1,150 +0,0 @@
1
- # Changelog
2
-
3
- ## [Unreleased]
4
-
5
- ### Fixed
6
-
7
- - **Flaky test in `tests/rest-client.test.ts`** ("при повторном 401 после onUnauthorized — не попадает в бесконечный цикл") — the mock error set `err.isAxiosError = true` *after* `Object.setPrototypeOf(err, axios.AxiosError.prototype)`. `AxiosError.prototype.isAxiosError` is defined as non-writable (`Object.defineProperty(..., { value: true })`), so that assignment threw a `TypeError` in strict mode, which masked the actual 401-retry logic being exercised. Fixed by assigning `isAxiosError` before swapping the prototype, matching the (correct) pattern already used by the other axios-error mocks in the same file. No production code changed.
8
-
9
- ### Added
10
-
11
- #### Pipeline Orchestrator
12
-
13
- - **`signal` in stage hooks** — `request`, `condition`, `before`, `after`, `errorHandler`, and `StreamStageConfig.stream` now receive the pipeline's `AbortSignal` in their params object. Pass it down to `fetch`/`axios`/etc. so `abort()` actually cancels custom async work inside stage functions, not just the orchestrator's own bookkeeping.
14
- - **`recoverStep(data)`** (from `types.ts`, re-exported from the root entry point) — `errorHandler` can return `recoverStep(data)` to recover a failed stage back into a successful one (`status: "success"`, `data`), running the same commit path as a normal success (metrics, `persistAdapter.save()`, `middleware.afterEach`, `step:success` event) instead of stopping/continuing-as-error. Returning anything else keeps the previous behavior (error, transformed via `toApiError`).
15
-
16
- #### RestClient
17
-
18
- - **No `axios.create()` when `adapter` is set** — `createRestClient()` no longer constructs the built-in axios instance if a custom `HttpAdapter` is provided, avoiding unnecessary work in edge/serverless environments that only use the adapter.
19
-
20
- ### Changed
21
-
22
- - Internal: `PipelineOrchestrator.executeStage()` success/error commit logic was extracted into `_commitStepSuccess()` / `_commitStepError()` so the new `errorHandler` recovery path and the normal success path share identical metrics/persist/middleware/event behavior.
23
-
24
- #### Pipeline Orchestrator
25
-
26
- - **`ParallelStageGroup.concurrency`** — caps how many stages of a parallel group run at once instead of always starting all of them via `Promise.all`. Useful for fan-out over many items (e.g. paginated fetches) without opening hundreds of requests at the same time. Results are still returned/stored in the same shape and order as an unlimited group. Supported by the `pipe()` builder via `.parallel(stages, { concurrency })`.
27
-
28
- #### RestClient
29
-
30
- - **`AuthProvider.tokenTtlMs`** — caches `getToken()`'s result for the given duration instead of calling it before every request. The cache is invalidated automatically on a `401` (before `onUnauthorized` runs), so the retried request always fetches a fresh token. Without `tokenTtlMs`, behavior is unchanged (`getToken()` called every request).
31
- - **`invalidateCache(matcher)`** — new method on the client returned by `createRestClient()`. Removes only the response-cache entries whose URL matches `matcher` (substring, `RegExp`, or `(info: { method, url }) => boolean`) instead of clearing the whole cache like `clearCache()`. Returns the number of entries removed.
32
- - `TtlCache` gained `keys()` and `deleteWhere(predicate)` to support the above.
33
-
34
- ### Added (continued)
35
-
36
- #### RestClient — Circuit breaker
37
-
38
- - **`HttpConfig.circuitBreaker`** (new `CircuitBreakerConfig`: `{ failureThreshold, openMs, successThreshold?, isFailure? }`) — after `failureThreshold` consecutive failures the client rejects requests immediately with `CircuitOpenError` (`code: "CIRCUIT_OPEN"`) for `openMs`, without making a network call. After `openMs` it probes with real requests in a `half-open` state: success (×`successThreshold`, default 1) closes the circuit, failure re-opens it. `isFailure(error)` can exclude certain errors (e.g. 4xx) from counting as failures. Cancelled/aborted requests never count as failures. New module `src/circuit-breaker.ts` exports `CircuitBreaker`, `CircuitOpenError`, and the `CircuitBreakerState` type.
39
- - **`client.getCircuitBreakerState()`** — returns `"closed" | "open" | "half-open"`, or `null` if `circuitBreaker` isn't configured.
40
- - Not set by default — without `circuitBreaker`, behavior is unchanged.
41
-
42
- #### Pipeline Orchestrator — run correlation
43
-
44
- - **`runId`** — every `run()` call generates a fresh ID (via `crypto.randomUUID()`, falling back to a timestamp-based string), shared by `PipelineMetrics.onPipelineStart/onPipelineEnd/onStepDuration`, every `PipelineStepEvent` (`.runId`), and every entry returned by `getLogs()`/`exportState()`. All attempts within one `run()` (including `pipelineRetry` retries) share the same `runId`. `rerunStep()` generates its own separate `runId`. New `orchestrator.getRunId()` reads the current/last one. `PipelineMetrics`' three callback `info` objects and `PipelineStepEvent` gained a `runId` field (required on the former, optional on the latter for backward compatibility).
45
-
46
- #### DX utilities — typed `pipe()` builder
47
-
48
- - **`PipelineBuilder<TPrev>`** — the fluent builder is now generic: `.step()` infers and threads the previous step's output type into the next step's `prev`, so TypeScript catches type mismatches across a chain and provides autocomplete. The first step's `prev` is typed `undefined`, matching actual runtime behavior. `.parallel()` / `.subPipeline()` / `.stream()` intentionally don't change the threaded type, since the orchestrator's `prev` for the next step always comes from the last regular `.step()`, never from a parallel group/sub-pipeline/stream. Purely a type-level addition — `PipelineBuilder` still mutates the same instance internally, so existing non-chained usage (calling `.step()` without reassigning the result) keeps working unchanged.
49
- - `ParallelStageGroup.concurrency` is also exposed through `pipe().parallel(stages, { concurrency })`.
50
-
51
- ---
52
-
53
- ## [1.3.7] - 2026-04-04
54
-
55
- ### Added
56
-
57
- #### Pipeline Orchestrator
58
-
59
- - **Pipeline metrics** — `PipelineConfig.metrics` with three callbacks:
60
- - `onPipelineStart({ timestamp })` — fires at the beginning of `run()`
61
- - `onPipelineEnd({ durationMs, success, stageResults })` — fires when `run()` completes
62
- - `onStepDuration({ stepKey, durationMs, status })` — fires after every executed step
63
- - **Plugin system** — `options.plugins` accepts an array of `PipelinePlugin` objects. Each plugin receives the orchestrator instance in `install(orchestrator)` and can subscribe to events, add middleware hooks, etc. Returning a function from `install()` registers it as a cleanup callback.
64
- - **`destroy()`** — new public method that invokes cleanup functions from all installed plugins.
65
- - **Persist adapter** — `options.persistAdapter` accepts a `PipelineStateAdapter` object with `save` / `load` methods. When set: state is automatically loaded at the start of `run()` (via `importState`) and saved after each successfully completed step.
66
- - **Stream stages** — new `StreamStageConfig` element type for `PipelineItem`. The `stream` function returns an `AsyncIterable<T>`; the orchestrator iterates it and collects chunks into an array (the stage result). The optional `onChunk(chunk, sharedData)` callback fires for each chunk in real time. Stream stages honour `abort()`, `continueOnError`, and emit standard step events.
67
- - **Generic step keys** — `PipelineOrchestrator<TKeys extends string = string>` now accepts a generic type parameter for typed auto-complete in `on()`, `rerunStep()`, and `subscribeStepProgress()`.
68
-
69
- #### DX utilities
70
-
71
- - **`createPipeline(stages, options?)`** — factory function that creates a `PipelineOrchestrator` without the nested `{ config: { stages } }` boilerplate.
72
- - **`pipe()`** — fluent builder API. Methods: `.step()`, `.parallel()`, `.subPipeline()`, `.stream()`, `.build(options?)`, `.toConfig(options?)`.
73
- - **`validatePipelineConfig(config, context?)`** — validates a `PipelineConfig` before runtime. Checks for duplicate keys, empty keys, empty `stages` array, invalid field types, and recursively validates nested sub-pipelines. Returns `{ valid: boolean; errors: string[] }`.
74
- - **`getStageResults()`** — synchronous snapshot of all stage results (no subscription needed).
75
-
76
- #### Vue / React hooks
77
-
78
- - **`usePipelineStageResultVue(orchestrator, stepKey)`** — reactive `Ref<PipelineStepResult | null>` for a single step.
79
- - **`usePipelineStageResultReact(orchestrator, stepKey)`** — state hook for a single step, updates on every `stageResults` change.
80
-
81
- #### RestClient
82
-
83
- - **`HttpAdapter`** — new `adapter` field in `HttpConfig`. When provided, replaces the built-in axios client with a custom implementation (e.g. native `fetch`). All other features (auth, interceptors, retry, sanitization, metrics) continue to work on top of the adapter.
84
-
85
- #### Types
86
-
87
- - `PipelineMetrics` interface
88
- - `PipelinePlugin` type
89
- - `PipelineStateAdapter` type
90
- - `StreamStageConfig<T>` type; updated `PipelineItem` union to include it
91
- - `HttpAdapter` type
92
- - `PipelineLogEventType` union — exhaustive list of all log event type strings
93
- - Extended `PipelineConfig` with `metrics?`
94
- - Extended `PipelineOptions` with `persistAdapter?` and `plugins?`
95
- - Extended `HttpConfig` with `adapter?`
96
-
97
- ---
98
-
99
- ## [1.3.6] - 2026-04-03
100
-
101
- ### Added
102
-
103
- #### Pipeline Orchestrator
104
-
105
- - **`continueOnError`** — per-stage and global flag to continue pipeline execution when a step fails. When enabled, failed steps are marked with `status: "error"` but do not stop the pipeline.
106
- - **`next()` function** — DAG (directed acyclic graph) transitions allowing non-linear pipeline flows. After successful step execution, you can dynamically jump to any stage by its key or continue sequentially by returning `null`. Includes protection against infinite loops (max steps = stages.length × 10).
107
- - **Sub-pipelines** — embed a complete `PipelineConfig` as a stage using the `subPipeline` field. Sub-pipelines run with their own context but share the parent's `sharedData` and abort signal. Results are stored under the stage key.
108
- - **`pipelineRetry`** — automatic retry of the entire pipeline on failure. Supports:
109
- - `attempts` — number of retry attempts
110
- - `delayMs` — delay between retries
111
- - `retryFrom` — resume from `"start"` (default, resets all results) or `"failed-step"` (preserves successful stage results)
112
- - **`pipelineTimeoutMs`** — global timeout for the entire pipeline execution. When exceeded, the pipeline is automatically aborted via `abort()`, cancelling any in-flight HTTP requests.
113
-
114
- #### RestClient
115
-
116
- - **Request interceptors** — modify request configuration before sending. Supports single interceptor or array of interceptors applied in sequence.
117
- - **Response interceptors** — transform response data after receiving. Applied before returning the response to the caller.
118
- - **Error interceptors** — handle or modify errors before they are thrown.
119
- - **Global `onError` handler** — simple callback for centralized error handling. Receives the `ApiError` and the original request configuration.
120
- - **Stale-While-Revalidate cache strategy** — serves stale cached data immediately while fetching fresh data in the background. Configured via:
121
- - `strategy: "stale-while-revalidate"`
122
- - `staleMs` — extra time to serve stale data after TTL expires
123
- - **Request deduplication** — prevents duplicate in-flight GET requests. When enabled (`deduplicateRequests: true`), multiple identical requests share the same pending Promise, reducing network traffic.
124
- - **`head()` method** — execute HEAD requests to retrieve headers without the response body.
125
- - **`options()` method** — execute OPTIONS requests to discover allowed HTTP methods and CORS policies.
126
-
127
- #### Types
128
-
129
- - Added `RequestInterceptor`, `ResponseInterceptor`, `ErrorInterceptor` types
130
- - Added `SubPipelineStage` type and updated `PipelineItem` union
131
- - Extended `CacheConfig` with `strategy` and `staleMs` fields
132
- - Extended `HttpConfig` with `interceptors`, `onError`, `deduplicateRequests`
133
- - Extended `PipelineConfig` with `options` object containing `continueOnError`, `pipelineRetry`, `pipelineTimeoutMs`
134
- - Extended `PipelineStageConfig` with `continueOnError` and `next` fields
135
-
136
- #### Cache
137
-
138
- - **`TtlCache.getStale()`** — new method that returns cached values even after TTL expiration, as long as they are within the `staleMs` window. Returns an object with `{ value, isStale }` where `isStale: true` indicates the value is beyond TTL but still usable.
139
-
140
- ### Changed
141
-
142
- - `PipelineOrchestrator.run()` now supports retry logic via `pipelineRetry` configuration
143
- - Main `run()` logic extracted to `_runOnce()` private method to enable retry functionality
144
- - `PipelineOrchestrator` constructor now properly handles `config.options` separately from constructor `options`
145
-
146
- ### Fixed
147
-
148
- - Backward compatibility with existing `PipelineConfig` objects that do not include the new `options` field
149
- - `PipelineOrchestrator` constructor no longer conflicts between `config.options` and constructor `params.options`
150
- - Parallel stage groups now correctly handle `continueOnError` behavior
package/demo/App.vue DELETED
@@ -1,122 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, shallowRef, defineAsyncComponent } from "vue";
3
-
4
- const FlightDemo = defineAsyncComponent(() => import("./views/FlightDemo.vue"));
5
- const ParallelDemo = defineAsyncComponent(
6
- () => import("./views/ParallelDemo.vue"),
7
- );
8
- const RetryDemo = defineAsyncComponent(() => import("./views/RetryDemo.vue"));
9
- const CacheDemo = defineAsyncComponent(() => import("./views/CacheDemo.vue"));
10
-
11
- const demos = [
12
- {
13
- id: "flight",
14
- icon: "✈️",
15
- title: "Flight Pipeline",
16
- subtitle: "Sequential stages · sharedData",
17
- component: FlightDemo,
18
- },
19
- {
20
- id: "parallel",
21
- icon: "🔀",
22
- title: "Parallel Loading",
23
- subtitle: "pipe() builder · concurrent",
24
- component: ParallelDemo,
25
- },
26
- {
27
- id: "retry",
28
- icon: "🛡️",
29
- title: "Retry & Recovery",
30
- subtitle: "Backoff · abort · pause/resume",
31
- component: RetryDemo,
32
- },
33
- {
34
- id: "cache",
35
- icon: "⚡",
36
- title: "Cache & Rate Limit",
37
- subtitle: "HTTP optimization · metrics",
38
- component: CacheDemo,
39
- },
40
- ];
41
-
42
- const activeId = ref("flight");
43
- const ActiveComponent = shallowRef(FlightDemo);
44
-
45
- function navigate(demo: (typeof demos)[number]) {
46
- activeId.value = demo.id;
47
- ActiveComponent.value = demo.component;
48
- }
49
- </script>
50
-
51
- <template>
52
- <div class="app-layout">
53
- <!-- ── Sidebar ──────────────────────────────────────────── -->
54
- <aside class="sidebar">
55
- <div class="sidebar-logo">
56
- <div class="sidebar-logo__icon">🚀</div>
57
- <div class="sidebar-logo__text">
58
- <div class="sidebar-logo__name">rest-pipeline-js</div>
59
- <div class="sidebar-logo__sub">Interactive Demo</div>
60
- </div>
61
- </div>
62
-
63
- <nav class="sidebar-nav">
64
- <button
65
- v-for="demo in demos"
66
- :key="demo.id"
67
- class="nav-item"
68
- :class="{ 'nav-item--active': activeId === demo.id }"
69
- @click="navigate(demo)"
70
- >
71
- <span class="nav-item__icon">{{ demo.icon }}</span>
72
- <div class="nav-item__text">
73
- <div class="nav-item__title">{{ demo.title }}</div>
74
- <div class="nav-item__sub">{{ demo.subtitle }}</div>
75
- </div>
76
- </button>
77
- </nav>
78
-
79
- <div class="sidebar-links">
80
- <a
81
- href="https://github.com/macrulezru/pipeline-js"
82
- target="_blank"
83
- class="sidebar-link"
84
- title="GitHub"
85
- >
86
- <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
87
- <path
88
- d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z"
89
- />
90
- </svg>
91
- GitHub
92
- </a>
93
- <a
94
- href="https://www.npmjs.com/package/rest-pipeline-js"
95
- target="_blank"
96
- class="sidebar-link"
97
- title="npm"
98
- >
99
- <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
100
- <path
101
- d="M0 0v24h24V0H0zm6.672 18.586H3.328V5.414h3.344v13.172zm7.656 0h-3.344v-9.83H7.656V5.414h10.004v13.172h-3.332v-9.83z"
102
- />
103
- </svg>
104
- npm
105
- </a>
106
- </div>
107
- </aside>
108
-
109
- <!-- ── Main content ───────────────────────────────────── -->
110
- <main class="content">
111
- <Suspense>
112
- <component :is="ActiveComponent" />
113
- <template #fallback>
114
- <div class="loading-placeholder">
115
- <div class="loading-spinner"></div>
116
- <span>Loading demo…</span>
117
- </div>
118
- </template>
119
- </Suspense>
120
- </main>
121
- </div>
122
- </template>
package/demo/index.html DELETED
@@ -1,22 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>rest-pipeline-js — Interactive Demo</title>
7
- <link
8
- rel="icon"
9
- href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🚀</text></svg>"
10
- />
11
- <link rel="preconnect" href="https://fonts.googleapis.com" />
12
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
13
- <link
14
- href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
15
- rel="stylesheet"
16
- />
17
- </head>
18
- <body>
19
- <div id="app"></div>
20
- <script type="module" src="./main.js"></script>
21
- </body>
22
- </html>
package/demo/main.js DELETED
@@ -1,5 +0,0 @@
1
- import { createApp } from "vue";
2
- import App from "./App.vue";
3
- import "./style.css";
4
-
5
- createApp(App).mount("#app");