rest-pipeline-js 1.3.12 → 1.3.14

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 (2) hide show
  1. package/README.md +211 -156
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  rest-pipeline-js
4
4
  </h1>
5
5
  <img
6
- src="https://s3.twcstorage.ru/c9a2cc89-780f97fd-311d-4a1a-b86f-c25665c9dc46/images/npm/rest-pipeline-js.webp"
6
+ src="https://s3.twcstorage.ru/c9a2cc89-780f97fd-311d-4a1a-b86f-c25665c9dc46/images/npm/rest-pipeline-js_v2.webp"
7
7
  alt="rest-pipeline-js"
8
8
  style="max-width:100%;width:auto;height:300px;border-radius:12px"
9
9
  />
@@ -95,12 +95,12 @@ npm run demo:vue
95
95
 
96
96
  Opens at `http://localhost:3000`. The demo app lives in the `demo/` directory.
97
97
 
98
- | Demo | What it shows |
99
- |---|---|
100
- | ✈️ **Flight Pipeline** | 4-stage sequential pipeline with `sharedData`, `pauseBefore`/`pauseAfter`, middleware, boarding pass result |
101
- | 🔀 **Parallel Loading** | `pipe()` fluent builder with `.parallel([])` — 3 sources queried simultaneously, timing breakdown |
102
- | 🛡️ **Retry & Recovery** | Configurable flaky stage with exponential backoff, event log, `abort()`, pause/resume between stages |
103
- | ⚡ **Cache & Rate Limit** | `createRestClient()` with cache TTL — see server vs cache timing; rate limiter burst visualization |
98
+ | Demo | What it shows |
99
+ | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
100
+ | ✈️ **Flight Pipeline** | 4-stage sequential pipeline with `sharedData`, `pauseBefore`/`pauseAfter`, middleware, boarding pass result |
101
+ | 🔀 **Parallel Loading** | `pipe()` fluent builder with `.parallel([])` — 3 sources queried simultaneously, timing breakdown |
102
+ | 🛡️ **Retry & Recovery** | Configurable flaky stage with exponential backoff, event log, `abort()`, pause/resume between stages |
103
+ | ⚡ **Cache & Rate Limit** | `createRestClient()` with cache TTL — see server vs cache timing; rate limiter burst visualization |
104
104
 
105
105
  ---
106
106
 
@@ -116,7 +116,9 @@ const client = createRestClient({
116
116
  cache: { enabled: true, ttlMs: 60000 },
117
117
  auth: {
118
118
  getToken: async () => localStorage.getItem("token") ?? "",
119
- onUnauthorized: async () => { /* refresh token */ },
119
+ onUnauthorized: async () => {
120
+ /* refresh token */
121
+ },
120
122
  },
121
123
  });
122
124
 
@@ -126,8 +128,15 @@ const res = await client.get("/users/1");
126
128
  const orchestrator = new PipelineOrchestrator({
127
129
  config: {
128
130
  stages: [
129
- { key: "fetchUser", request: async ({ sharedData }) => client.get(`/users/${sharedData.userId}`) },
130
- { key: "processData", request: async ({ prev }) => ({ ...prev.data, processed: true }) },
131
+ {
132
+ key: "fetchUser",
133
+ request: async ({ sharedData }) =>
134
+ client.get(`/users/${sharedData.userId}`),
135
+ },
136
+ {
137
+ key: "processData",
138
+ request: async ({ prev }) => ({ ...prev.data, processed: true }),
139
+ },
131
140
  ],
132
141
  },
133
142
  sharedData: { userId: 42 },
@@ -149,43 +158,43 @@ Creates a REST client with advanced HTTP features.
149
158
 
150
159
  ### Methods
151
160
 
152
- | Method | Description |
153
- |---|---|
154
- | `get(url, config?)` | GET request |
155
- | `post(url, data?, config?)` | POST request |
156
- | `put(url, data?, config?)` | PUT request |
157
- | `patch(url, data?, config?)` | PATCH request |
158
- | `delete(url, config?)` | DELETE request |
159
- | `request(url, config?)` | Generic request |
160
- | `cancellableRequest(key, url, config?)` | Request cancellable by key |
161
- | `cancelRequest(key)` | Cancel request by key |
162
- | `clearCache()` | Clear this client's response cache |
161
+ | Method | Description |
162
+ | --------------------------------------- | ---------------------------------- |
163
+ | `get(url, config?)` | GET request |
164
+ | `post(url, data?, config?)` | POST request |
165
+ | `put(url, data?, config?)` | PUT request |
166
+ | `patch(url, data?, config?)` | PATCH request |
167
+ | `delete(url, config?)` | DELETE request |
168
+ | `request(url, config?)` | Generic request |
169
+ | `cancellableRequest(key, url, config?)` | Request cancellable by key |
170
+ | `cancelRequest(key)` | Cancel request by key |
171
+ | `clearCache()` | Clear this client's response cache |
163
172
 
164
173
  ### HttpConfig options
165
174
 
166
- | Option | Description |
167
- |---|---|
168
- | `baseURL` | Base URL for all requests |
169
- | `timeout` | Request timeout in ms |
170
- | `headers` | Default headers |
171
- | `withCredentials` | Include cookies |
172
- | `retry.attempts` | Number of retry attempts |
173
- | `retry.delayMs` | Base delay between retries in ms |
174
- | `retry.backoffMultiplier` | Exponential backoff multiplier |
175
- | `retry.retriableStatus` | HTTP status codes eligible for retry (e.g. `[429, 500, 503]`) |
176
- | `retry.maxRetryAfterMs` | Max wait from `Retry-After` header in ms (default: `60000`) |
177
- | `cache.enabled` | Enable response caching for GET requests |
178
- | `cache.ttlMs` | Cache TTL in ms |
179
- | `rateLimit.maxConcurrent` | Max simultaneous requests |
180
- | `rateLimit.maxRequestsPerInterval` | Max requests per time window |
181
- | `rateLimit.intervalMs` | Time window size in ms |
182
- | `metrics.onRequestStart` | Callback on request start |
183
- | `metrics.onRequestEnd` | Callback on request end (includes duration and bytes) |
184
- | `auth.getToken` | Async function returning a Bearer token (called before every request) |
185
- | `auth.onUnauthorized` | Optional async callback on 401 — refresh the token here; request is retried once |
186
- | `sanitizeHeaders` | Mask sensitive headers in metrics callbacks (default: `false`) |
187
- | `sensitiveHeaders` | Additional headers to mask (extends `DEFAULT_SENSITIVE_HEADERS`) |
188
- | `adapter` | Custom HTTP adapter (e.g. native `fetch`) — replaces built-in axios |
175
+ | Option | Description |
176
+ | ---------------------------------- | -------------------------------------------------------------------------------- |
177
+ | `baseURL` | Base URL for all requests |
178
+ | `timeout` | Request timeout in ms |
179
+ | `headers` | Default headers |
180
+ | `withCredentials` | Include cookies |
181
+ | `retry.attempts` | Number of retry attempts |
182
+ | `retry.delayMs` | Base delay between retries in ms |
183
+ | `retry.backoffMultiplier` | Exponential backoff multiplier |
184
+ | `retry.retriableStatus` | HTTP status codes eligible for retry (e.g. `[429, 500, 503]`) |
185
+ | `retry.maxRetryAfterMs` | Max wait from `Retry-After` header in ms (default: `60000`) |
186
+ | `cache.enabled` | Enable response caching for GET requests |
187
+ | `cache.ttlMs` | Cache TTL in ms |
188
+ | `rateLimit.maxConcurrent` | Max simultaneous requests |
189
+ | `rateLimit.maxRequestsPerInterval` | Max requests per time window |
190
+ | `rateLimit.intervalMs` | Time window size in ms |
191
+ | `metrics.onRequestStart` | Callback on request start |
192
+ | `metrics.onRequestEnd` | Callback on request end (includes duration and bytes) |
193
+ | `auth.getToken` | Async function returning a Bearer token (called before every request) |
194
+ | `auth.onUnauthorized` | Optional async callback on 401 — refresh the token here; request is retried once |
195
+ | `sanitizeHeaders` | Mask sensitive headers in metrics callbacks (default: `false`) |
196
+ | `sensitiveHeaders` | Additional headers to mask (extends `DEFAULT_SENSITIVE_HEADERS`) |
197
+ | `adapter` | Custom HTTP adapter (e.g. native `fetch`) — replaces built-in axios |
189
198
 
190
199
  ### Per-request cache override
191
200
 
@@ -215,7 +224,9 @@ const client = createRestClient({
215
224
  rateLimit: { maxConcurrent: 3, maxRequestsPerInterval: 10, intervalMs: 1000 },
216
225
  auth: {
217
226
  getToken: async () => localStorage.getItem("token") ?? "",
218
- onUnauthorized: async () => { /* refresh token here */ },
227
+ onUnauthorized: async () => {
228
+ /* refresh token here */
229
+ },
219
230
  },
220
231
  sanitizeHeaders: true,
221
232
  });
@@ -227,7 +238,9 @@ console.log(res.data);
227
238
  await client.patch("/users/1", { name: "Alice" });
228
239
 
229
240
  // Cancellable request
230
- const req = client.cancellableRequest("my-key", "/search", { params: { q: "foo" } });
241
+ const req = client.cancellableRequest("my-key", "/search", {
242
+ params: { q: "foo" },
243
+ });
231
244
  // Cancel it any time:
232
245
  client.cancelRequest("my-key");
233
246
  ```
@@ -270,8 +283,8 @@ import { createRestClient, DEFAULT_SENSITIVE_HEADERS } from "rest-pipeline-js";
270
283
 
271
284
  const client = createRestClient({
272
285
  baseURL: "https://api.example.com",
273
- sanitizeHeaders: true, // opt-in — disabled by default
274
- sensitiveHeaders: ["x-internal-secret"], // extend the default list
286
+ sanitizeHeaders: true, // opt-in — disabled by default
287
+ sensitiveHeaders: ["x-internal-secret"], // extend the default list
275
288
  metrics: {
276
289
  onRequestStart: (info) => {
277
290
  // info.requestHeaders — sensitive values replaced with "REDACTED"
@@ -309,7 +322,7 @@ const executor = new RequestExecutor({
309
322
  delayMs: 500,
310
323
  backoffMultiplier: 2,
311
324
  retriableStatus: [429, 500, 502, 503],
312
- maxRetryAfterMs: 30000, // cap Retry-After at 30 s
325
+ maxRetryAfterMs: 30000, // cap Retry-After at 30 s
313
326
  },
314
327
  });
315
328
 
@@ -338,42 +351,42 @@ new PipelineOrchestrator({
338
351
 
339
352
  ### Methods
340
353
 
341
- | Method | Description |
342
- |---|---|
343
- | `run(onStepPause?, externalSignal?)` | Execute all stages. Returns `{ stageResults, success }` |
344
- | `rerunStep(stepKey, options?)` | Re-execute a single stage (respects condition, before, after, middleware) |
345
- | `abort()` | Abort pipeline execution (cancels the current HTTP request via AbortSignal) |
346
- | `isAborted()` | Check if pipeline was aborted |
347
- | `pause()` | Pause after the current stage completes |
348
- | `resume()` | Resume a paused pipeline |
349
- | `isPaused()` | Check if pipeline is paused |
350
- | `exportState()` | Serialize stageResults and logs to a plain object |
351
- | `importState(state)` | Restore stageResults and logs from a snapshot |
352
- | `getStageResults()` | Synchronous snapshot of all stage results |
353
- | `destroy()` | Run cleanup callbacks from all installed plugins |
354
- | `subscribeProgress(listener)` | Subscribe to progress updates |
355
- | `subscribeStageResults(listener)` | Subscribe to stageResults changes |
356
- | `subscribeStepProgress(stepKey, listener)` | Subscribe to a specific stage's progress |
357
- | `on(eventName, handler)` | Subscribe to any event (`step:<key>:start\|success\|error\|skipped\|progress`, `log`) |
358
- | `onStepStart/Finish/Error(handler)` | Subscribe to stage lifecycle events |
359
- | `getProgress()` | Get current progress snapshot |
360
- | `getLogs()` | Get all pipeline logs |
361
- | `clearStageResults()` | Reset results and progress |
354
+ | Method | Description |
355
+ | ------------------------------------------ | ------------------------------------------------------------------------------------- |
356
+ | `run(onStepPause?, externalSignal?)` | Execute all stages. Returns `{ stageResults, success }` |
357
+ | `rerunStep(stepKey, options?)` | Re-execute a single stage (respects condition, before, after, middleware) |
358
+ | `abort()` | Abort pipeline execution (cancels the current HTTP request via AbortSignal) |
359
+ | `isAborted()` | Check if pipeline was aborted |
360
+ | `pause()` | Pause after the current stage completes |
361
+ | `resume()` | Resume a paused pipeline |
362
+ | `isPaused()` | Check if pipeline is paused |
363
+ | `exportState()` | Serialize stageResults and logs to a plain object |
364
+ | `importState(state)` | Restore stageResults and logs from a snapshot |
365
+ | `getStageResults()` | Synchronous snapshot of all stage results |
366
+ | `destroy()` | Run cleanup callbacks from all installed plugins |
367
+ | `subscribeProgress(listener)` | Subscribe to progress updates |
368
+ | `subscribeStageResults(listener)` | Subscribe to stageResults changes |
369
+ | `subscribeStepProgress(stepKey, listener)` | Subscribe to a specific stage's progress |
370
+ | `on(eventName, handler)` | Subscribe to any event (`step:<key>:start\|success\|error\|skipped\|progress`, `log`) |
371
+ | `onStepStart/Finish/Error(handler)` | Subscribe to stage lifecycle events |
372
+ | `getProgress()` | Get current progress snapshot |
373
+ | `getLogs()` | Get all pipeline logs |
374
+ | `clearStageResults()` | Reset results and progress |
362
375
 
363
376
  ### Stage parameters (PipelineStageConfig)
364
377
 
365
- | Parameter | Description |
366
- |---|---|
367
- | `key` | Unique stage identifier |
368
- | `request({ prev, allResults, sharedData })` | Main stage function — return value becomes the stage result |
369
- | `condition({ prev, allResults, sharedData })` | If returns `false`, stage is skipped with status `"skipped"` |
370
- | `before({ prev, allResults, sharedData })` | Pre-processing hook — returned value replaces `prev` passed to `request` |
371
- | `after({ result, allResults, sharedData })` | Post-processing hook — returned value replaces the stage result |
372
- | `errorHandler({ error, key, sharedData })` | Per-stage error handler |
373
- | `retryCount` | Override retry count for this stage |
374
- | `timeoutMs` | Override timeout for this stage |
375
- | `pauseBefore` | Delay in ms before executing `request` |
376
- | `pauseAfter` | Delay in ms after executing `request` |
378
+ | Parameter | Description |
379
+ | --------------------------------------------- | ------------------------------------------------------------------------ |
380
+ | `key` | Unique stage identifier |
381
+ | `request({ prev, allResults, sharedData })` | Main stage function — return value becomes the stage result |
382
+ | `condition({ prev, allResults, sharedData })` | If returns `false`, stage is skipped with status `"skipped"` |
383
+ | `before({ prev, allResults, sharedData })` | Pre-processing hook — returned value replaces `prev` passed to `request` |
384
+ | `after({ result, allResults, sharedData })` | Post-processing hook — returned value replaces the stage result |
385
+ | `errorHandler({ error, key, sharedData })` | Per-stage error handler |
386
+ | `retryCount` | Override retry count for this stage |
387
+ | `timeoutMs` | Override timeout for this stage |
388
+ | `pauseBefore` | Delay in ms before executing `request` |
389
+ | `pauseAfter` | Delay in ms after executing `request` |
377
390
 
378
391
  ### Stage execution flow
379
392
 
@@ -425,8 +438,10 @@ const orchestrator = new PipelineOrchestrator({
425
438
  ],
426
439
  middleware: {
427
440
  beforeEach: ({ stage }) => console.log("Starting:", stage.key),
428
- afterEach: ({ stage, result }) => console.log("Done:", stage.key, result.data),
429
- onError: ({ stage, error }) => console.error("Error in", stage.key, error),
441
+ afterEach: ({ stage, result }) =>
442
+ console.log("Done:", stage.key, result.data),
443
+ onError: ({ stage, error }) =>
444
+ console.error("Error in", stage.key, error),
430
445
  },
431
446
  },
432
447
  httpConfig: {
@@ -439,7 +454,12 @@ const orchestrator = new PipelineOrchestrator({
439
454
  });
440
455
 
441
456
  orchestrator.subscribeProgress((progress) => {
442
- console.log("Stage:", progress.currentStage, "Statuses:", progress.stageStatuses);
457
+ console.log(
458
+ "Stage:",
459
+ progress.currentStage,
460
+ "Statuses:",
461
+ progress.stageStatuses,
462
+ );
443
463
  });
444
464
 
445
465
  orchestrator.on("step:fetchUser:success", (payload) => {
@@ -468,7 +488,7 @@ const orchestrator = new PipelineOrchestrator({
468
488
  {
469
489
  key: "load-data",
470
490
  parallel: [
471
- { key: "loadUsers", request: async () => fetchUsers() },
491
+ { key: "loadUsers", request: async () => fetchUsers() },
472
492
  { key: "loadProducts", request: async () => fetchProducts() },
473
493
  { key: "loadSettings", request: async () => fetchSettings() },
474
494
  ],
@@ -495,7 +515,9 @@ Apply hooks to every stage without modifying individual stage configs:
495
515
  ```js
496
516
  const orchestrator = new PipelineOrchestrator({
497
517
  config: {
498
- stages: [ /* ... */ ],
518
+ stages: [
519
+ /* ... */
520
+ ],
499
521
  middleware: {
500
522
  beforeEach: async ({ stage, index, sharedData }) => {
501
523
  console.log(`[${index}] Starting: ${stage.key}`);
@@ -560,7 +582,7 @@ const orchestrator2 = new PipelineOrchestrator({ config });
560
582
  orchestrator2.importState(saved);
561
583
 
562
584
  console.log(orchestrator2.getProgress()); // restored progress
563
- console.log(orchestrator2.getLogs()); // restored logs (timestamps as Date objects)
585
+ console.log(orchestrator2.getLogs()); // restored logs (timestamps as Date objects)
564
586
  ```
565
587
 
566
588
  `exportState()` returns `{ stageResults, logs }` — a plain JSON-serializable object. Timestamps in logs are stored as ISO strings and restored as `Date` objects on `importState`.
@@ -574,7 +596,9 @@ Observe pipeline execution without modifying stage logic:
574
596
  ```js
575
597
  const orchestrator = new PipelineOrchestrator({
576
598
  config: {
577
- stages: [ /* ... */ ],
599
+ stages: [
600
+ /* ... */
601
+ ],
578
602
  metrics: {
579
603
  onPipelineStart: ({ timestamp }) => {
580
604
  console.log("Pipeline started at", new Date(timestamp).toISOString());
@@ -590,11 +614,11 @@ const orchestrator = new PipelineOrchestrator({
590
614
  });
591
615
  ```
592
616
 
593
- | Callback | Receives | Description |
594
- |---|---|---|
595
- | `onPipelineStart` | `{ timestamp }` | Fires at the beginning of `run()` |
596
- | `onPipelineEnd` | `{ durationMs, success, stageResults }` | Fires when `run()` completes |
597
- | `onStepDuration` | `{ stepKey, durationMs, status }` | Fires after every executed step |
617
+ | Callback | Receives | Description |
618
+ | ----------------- | --------------------------------------- | --------------------------------- |
619
+ | `onPipelineStart` | `{ timestamp }` | Fires at the beginning of `run()` |
620
+ | `onPipelineEnd` | `{ durationMs, success, stageResults }` | Fires when `run()` completes |
621
+ | `onStepDuration` | `{ stepKey, durationMs, status }` | Fires after every executed step |
598
622
 
599
623
  ---
600
624
 
@@ -608,14 +632,15 @@ import { createPipeline } from "rest-pipeline-js";
608
632
  const orchestrator = createPipeline(
609
633
  [
610
634
  { key: "fetchUser", request: async () => fetchUser() },
611
- { key: "process", request: async ({ prev }) => process(prev) },
635
+ { key: "process", request: async ({ prev }) => process(prev) },
612
636
  ],
613
637
  {
614
- httpConfig: { baseURL: "https://api.example.com" },
615
- sharedData: { userId: 42 },
638
+ httpConfig: { baseURL: "https://api.example.com" },
639
+ sharedData: { userId: 42 },
616
640
  pipelineOptions: { continueOnError: false },
617
641
  metrics: {
618
- onStepDuration: ({ stepKey, durationMs }) => console.log(stepKey, durationMs),
642
+ onStepDuration: ({ stepKey, durationMs }) =>
643
+ console.log(stepKey, durationMs),
619
644
  },
620
645
  },
621
646
  );
@@ -627,28 +652,30 @@ const orchestrator = createPipeline(
627
652
  import { pipe } from "rest-pipeline-js";
628
653
 
629
654
  const orchestrator = pipe()
630
- .step({ key: "auth", request: async () => getToken() })
655
+ .step({ key: "auth", request: async () => getToken() })
631
656
  .step({ key: "fetchUser", request: async ({ prev }) => fetchUser(prev) })
632
657
  .parallel([
633
- { key: "loadPosts", request: async () => fetchPosts() },
658
+ { key: "loadPosts", request: async () => fetchPosts() },
634
659
  { key: "loadNotifs", request: async () => fetchNotifications() },
635
660
  ])
636
661
  .stream({
637
662
  key: "liveUpdates",
638
- stream: async function* () { yield* subscribe("/events"); },
663
+ stream: async function* () {
664
+ yield* subscribe("/events");
665
+ },
639
666
  onChunk: (chunk) => updateUI(chunk),
640
667
  })
641
668
  .build({ httpConfig: { baseURL: "https://api.example.com" } });
642
669
  ```
643
670
 
644
- | Builder method | Description |
645
- |---|---|
646
- | `.step(stage)` | Add a sequential stage |
647
- | `.parallel(stages, options?)` | Add a parallel group (`key` auto-generated if omitted) |
648
- | `.subPipeline(item)` | Embed a sub-pipeline as a stage |
649
- | `.stream(stage)` | Add a stream stage (AsyncIterable) |
650
- | `.build(options?)` | Create and return a `PipelineOrchestrator` |
651
- | `.toConfig(options?)` | Return `PipelineConfig` without creating an orchestrator |
671
+ | Builder method | Description |
672
+ | ----------------------------- | -------------------------------------------------------- |
673
+ | `.step(stage)` | Add a sequential stage |
674
+ | `.parallel(stages, options?)` | Add a parallel group (`key` auto-generated if omitted) |
675
+ | `.subPipeline(item)` | Embed a sub-pipeline as a stage |
676
+ | `.stream(stage)` | Add a stream stage (AsyncIterable) |
677
+ | `.build(options?)` | Create and return a `PipelineOrchestrator` |
678
+ | `.toConfig(options?)` | Return `PipelineConfig` without creating an orchestrator |
652
679
 
653
680
  ---
654
681
 
@@ -662,8 +689,8 @@ import { validatePipelineConfig } from "rest-pipeline-js";
662
689
  const { valid, errors } = validatePipelineConfig({
663
690
  stages: [
664
691
  { key: "step1", request: async () => data },
665
- { key: "step1", request: async () => other }, // duplicate!
666
- { key: "", request: async () => other }, // empty key!
692
+ { key: "step1", request: async () => other }, // duplicate!
693
+ { key: "", request: async () => other }, // empty key!
667
694
  ],
668
695
  });
669
696
 
@@ -685,15 +712,18 @@ const loggingPlugin = {
685
712
  install(orchestrator) {
686
713
  const off = orchestrator.on("log", (event) => {
687
714
  if (event.type === "step:success") console.log("✓", event.stepKey);
688
- if (event.type === "step:error") console.error("✗", event.stepKey, event.error);
715
+ if (event.type === "step:error")
716
+ console.error("✗", event.stepKey, event.error);
689
717
  });
690
- return () => off(); // cleanup on orchestrator.destroy()
718
+ return () => off(); // cleanup on orchestrator.destroy()
691
719
  },
692
720
  };
693
721
 
694
722
  const orchestrator = new PipelineOrchestrator({
695
723
  config: {
696
- stages: [ /* ... */ ],
724
+ stages: [
725
+ /* ... */
726
+ ],
697
727
  options: { plugins: [loggingPlugin, analyticsPlugin] },
698
728
  },
699
729
  });
@@ -722,7 +752,9 @@ const localStorageAdapter = {
722
752
 
723
753
  const orchestrator = new PipelineOrchestrator({
724
754
  config: {
725
- stages: [ /* ... */ ],
755
+ stages: [
756
+ /* ... */
757
+ ],
726
758
  options: { persistAdapter: localStorageAdapter },
727
759
  },
728
760
  });
@@ -783,16 +815,20 @@ Replace the built-in axios client with any HTTP implementation:
783
815
  ```js
784
816
  const fetchAdapter = {
785
817
  async request(config) {
786
- const url = `${config.baseURL ?? ""}${config.url ?? ""}`;
787
- const res = await fetch(url, {
788
- method: config.method ?? "GET",
789
- body: config.data ? JSON.stringify(config.data) : undefined,
818
+ const url = `${config.baseURL ?? ""}${config.url ?? ""}`;
819
+ const res = await fetch(url, {
820
+ method: config.method ?? "GET",
821
+ body: config.data ? JSON.stringify(config.data) : undefined,
790
822
  headers: { "Content-Type": "application/json", ...config.headers },
791
- signal: config.signal,
823
+ signal: config.signal,
792
824
  });
793
825
  const data = await res.json();
794
- return { data, status: res.status, statusText: res.statusText,
795
- headers: Object.fromEntries(res.headers.entries()) };
826
+ return {
827
+ data,
828
+ status: res.status,
829
+ statusText: res.statusText,
830
+ headers: Object.fromEntries(res.headers.entries()),
831
+ };
796
832
  },
797
833
  };
798
834
 
@@ -824,7 +860,13 @@ import {
824
860
  usePipelineRunVue,
825
861
  } from "rest-pipeline-js/vue";
826
862
 
827
- const orchestrator = new PipelineOrchestrator({ config: { stages: [ /* ... */ ] } });
863
+ const orchestrator = new PipelineOrchestrator({
864
+ config: {
865
+ stages: [
866
+ /* ... */
867
+ ],
868
+ },
869
+ });
828
870
  const progress = usePipelineProgressVue(orchestrator);
829
871
  const { run, running, result, error, abort, pause, resume, rerunStep } =
830
872
  usePipelineRunVue(orchestrator);
@@ -845,15 +887,15 @@ const { run, running, result, error, abort, pause, resume, rerunStep } =
845
887
 
846
888
  Composables (import from `rest-pipeline-js/vue`):
847
889
 
848
- | Composable | Returns | Description |
849
- |---|---|---|
850
- | `usePipelineProgressVue(orchestrator)` | `Ref<PipelineProgress>` | Reactive progress |
851
- | `usePipelineRunVue(orchestrator)` | `{ run, running, result, error, stageResults, abort, pause, resume, rerunStep, clearStageResults }` | Run pipeline and get reactive state |
852
- | `usePipelineStepEventVue(orchestrator, stepKey, eventType)` | `Ref<any>` | Last payload for a specific step event |
853
- | `usePipelineLogsVue(orchestrator)` | `Ref<log[]>` | Reactive logs |
854
- | `useRerunPipelineStepVue(orchestrator)` | `function` | Bound `rerunStep` |
855
- | `useRestClientVue(config)` | `ComputedRef<RestClient>` | Reactive REST client |
856
- | `usePipelineStageResultVue(orchestrator, stepKey)` | `Ref<PipelineStepResult \| null>` | Reactive result of a single stage |
890
+ | Composable | Returns | Description |
891
+ | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------- |
892
+ | `usePipelineProgressVue(orchestrator)` | `Ref<PipelineProgress>` | Reactive progress |
893
+ | `usePipelineRunVue(orchestrator)` | `{ run, running, result, error, stageResults, abort, pause, resume, rerunStep, clearStageResults }` | Run pipeline and get reactive state |
894
+ | `usePipelineStepEventVue(orchestrator, stepKey, eventType)` | `Ref<any>` | Last payload for a specific step event |
895
+ | `usePipelineLogsVue(orchestrator)` | `Ref<log[]>` | Reactive logs |
896
+ | `useRerunPipelineStepVue(orchestrator)` | `function` | Bound `rerunStep` |
897
+ | `useRestClientVue(config)` | `ComputedRef<RestClient>` | Reactive REST client |
898
+ | `usePipelineStageResultVue(orchestrator, stepKey)` | `Ref<PipelineStepResult \| null>` | Reactive result of a single stage |
857
899
 
858
900
  ---
859
901
 
@@ -867,7 +909,13 @@ import {
867
909
  usePipelineRunReact,
868
910
  } from "rest-pipeline-js/react";
869
911
 
870
- const orchestrator = new PipelineOrchestrator({ config: { stages: [ /* ... */ ] } });
912
+ const orchestrator = new PipelineOrchestrator({
913
+ config: {
914
+ stages: [
915
+ /* ... */
916
+ ],
917
+ },
918
+ });
871
919
 
872
920
  export function PipelineComponent() {
873
921
  const progress = usePipelineProgressReact(orchestrator);
@@ -877,12 +925,16 @@ export function PipelineComponent() {
877
925
  return (
878
926
  <div>
879
927
  <div>Current stage: {progress.currentStage}</div>
880
- <button onClick={() => run()} disabled={running}>Start</button>
881
- <button onClick={() => abort()} disabled={!running}>Abort</button>
928
+ <button onClick={() => run()} disabled={running}>
929
+ Start
930
+ </button>
931
+ <button onClick={() => abort()} disabled={!running}>
932
+ Abort
933
+ </button>
882
934
  <button onClick={() => pause()}>Pause</button>
883
935
  <button onClick={() => resume()}>Resume</button>
884
936
  {result && <div>Done: {JSON.stringify(result)}</div>}
885
- {error && <div>Error: {error.message}</div>}
937
+ {error && <div>Error: {error.message}</div>}
886
938
  </div>
887
939
  );
888
940
  }
@@ -890,25 +942,25 @@ export function PipelineComponent() {
890
942
 
891
943
  Hooks (import from `rest-pipeline-js/react`):
892
944
 
893
- | Hook | Returns | Description |
894
- |---|---|---|
895
- | `usePipelineProgressReact(orchestrator)` | `PipelineProgress` | Reactive progress |
896
- | `usePipelineRunReact(orchestrator)` | `[run, { running, result, error, stageResults, abort, pause, resume, rerunStep }]` | Run pipeline and get state |
897
- | `usePipelineStepEventReact(orchestrator, stepKey, eventType)` | `any` | Last payload for a specific step event |
898
- | `usePipelineLogsReact(orchestrator)` | `log[]` | Reactive logs |
899
- | `useRerunPipelineStepReact(orchestrator)` | `function` | Bound `rerunStep` |
900
- | `useRestClientReact(config)` | `RestClient` | Memoized REST client |
901
- | `usePipelineStageResultReact(orchestrator, stepKey)` | `PipelineStepResult \| null` | Result of a single stage |
945
+ | Hook | Returns | Description |
946
+ | ------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------- |
947
+ | `usePipelineProgressReact(orchestrator)` | `PipelineProgress` | Reactive progress |
948
+ | `usePipelineRunReact(orchestrator)` | `[run, { running, result, error, stageResults, abort, pause, resume, rerunStep }]` | Run pipeline and get state |
949
+ | `usePipelineStepEventReact(orchestrator, stepKey, eventType)` | `any` | Last payload for a specific step event |
950
+ | `usePipelineLogsReact(orchestrator)` | `log[]` | Reactive logs |
951
+ | `useRerunPipelineStepReact(orchestrator)` | `function` | Bound `rerunStep` |
952
+ | `useRestClientReact(config)` | `RestClient` | Memoized REST client |
953
+ | `usePipelineStageResultReact(orchestrator, stepKey)` | `PipelineStepResult \| null` | Result of a single stage |
902
954
 
903
955
  ---
904
956
 
905
957
  ## Entry points
906
958
 
907
- | Entry point | Use for | Contents |
908
- |---|---|---|
909
- | `rest-pipeline-js` | Core only | `PipelineOrchestrator`, `createRestClient`, types, utilities. No Vue/React. |
910
- | `rest-pipeline-js/vue` | Vue projects | Core + Vue composables |
911
- | `rest-pipeline-js/react` | React projects | Core + React hooks |
959
+ | Entry point | Use for | Contents |
960
+ | ------------------------ | -------------- | --------------------------------------------------------------------------- |
961
+ | `rest-pipeline-js` | Core only | `PipelineOrchestrator`, `createRestClient`, types, utilities. No Vue/React. |
962
+ | `rest-pipeline-js/vue` | Vue projects | Core + Vue composables |
963
+ | `rest-pipeline-js/react` | React projects | Core + React hooks |
912
964
 
913
965
  ```js
914
966
  // Core only
@@ -918,7 +970,10 @@ import { createRestClient, PipelineOrchestrator } from "rest-pipeline-js";
918
970
  import { PipelineOrchestrator, usePipelineRunVue } from "rest-pipeline-js/vue";
919
971
 
920
972
  // React
921
- import { PipelineOrchestrator, usePipelineRunReact } from "rest-pipeline-js/react";
973
+ import {
974
+ PipelineOrchestrator,
975
+ usePipelineRunReact,
976
+ } from "rest-pipeline-js/react";
922
977
  ```
923
978
 
924
979
  `sideEffects: false` — unused entry points are tree-shaken. `react` / `react-dom` are `peerDependencies`.
@@ -972,11 +1027,11 @@ rest-pipeline-js
972
1027
 
973
1028
  ## Bundle size & peer dependencies
974
1029
 
975
- | Entry point | Peer deps | Notes |
976
- |---|---|---|
977
- | `rest-pipeline-js` | — | Core — orchestrator, HTTP client, utilities. Depends on `axios`. |
978
- | `rest-pipeline-js/vue` | `vue ^3.3` | Core + Vue composables |
979
- | `rest-pipeline-js/react` | `react ^19`, `react-dom ^19` | Core + React hooks |
1030
+ | Entry point | Peer deps | Notes |
1031
+ | ------------------------ | ---------------------------- | ---------------------------------------------------------------- |
1032
+ | `rest-pipeline-js` | — | Core — orchestrator, HTTP client, utilities. Depends on `axios`. |
1033
+ | `rest-pipeline-js/vue` | `vue ^3.3` | Core + Vue composables |
1034
+ | `rest-pipeline-js/react` | `react ^19`, `react-dom ^19` | Core + React hooks |
980
1035
 
981
1036
  The package ships as tree-shakeable ESM (`dist/esm/`) and CommonJS (`dist/cjs/`). The `/vue` and `/react` entry points are code-split — importing one does not bundle the other.
982
1037
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rest-pipeline-js",
3
- "version": "1.3.12",
3
+ "version": "1.3.14",
4
4
  "description": "Pipeline Orchestration Utilities for JavaScript REST API Clients",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",