Repository navigation
Commit 259ce36
authored
feat(js-api-client): modernize, harden, and test the API client (#259)
* fix(catalogue): fix 'chidlren' typo in GraphQL query builder
The onFolder helper in create-catalogue-fetcher.ts produced a field
named 'chidlren' instead of 'children' in generated GraphQL queries,
causing incorrect query results for folder children.
* fix(api-caller): remove dead try/catch block that only rethrows
The outer try/catch in the `post` function was a no-op that added
visual noise and misleadingly suggested error handling was happening.
* chore: delete dead commented-out subscription.ts file
The file contained 543 lines of entirely commented-out code,
replaced by the modules in src/core/pim/subscriptions/.
Git history preserves it if ever needed.
* fix(catalogue): simplify double spread to single spread in product hydrater
The query object construction used `{ ...{ ...productListQuery } }` which
is functionally identical to `{ ...productListQuery }`. Simplified to
remove the unnecessary nesting.
* fix(mass-call): use object literal instead of array for results initialization
The `results` variable was typed as `{ [key: string]: any }` but initialized
as `[]`. While JS allows property assignment on arrays, this is misleading.
Changed to `{}` to match the declared type and actual usage.
* fix(package): correct module field to match actual ESM build output
The module field pointed to ./dist/index.mjs which doesn't exist.
The build outputs ./dist/index.js for ESM. This mismatch could cause
import failures in bundlers (Webpack, Rollup) that use the module field.
* fix(error): set name property on JSApiClientCallError for better debugging
Stack traces and error.name now correctly show 'JSApiClientCallError'
instead of generic 'Error', making it easier to identify API client
errors in logs and error handlers.
* fix(types): replace 'any' with proper GrabOptions type in grabber and API caller
The `RequestInit | any | undefined` union types collapsed to `any`, defeating
TypeScript's type checking for all library consumers. Introduced a focused
GrabOptions type covering method, headers, and body, and updated all signatures.
* fix(security): replace tracked .env with .env.example template
Add .env to .gitignore and create .env.example with placeholder values
to prevent accidental credential commits.
* feat(auth): warn when no authentication credentials are configured
Adds a console.warn when the fallback auth path is reached with empty
accessTokenId and accessTokenSecret, helping developers catch missing
auth configuration early instead of getting cryptic 401/403 errors.
Uses a WeakSet to ensure the warning fires only once per config object.
* fix(profiling): use regex to parse Server-Timing header reliably
Replace fragile split-based parsing with a regex that extracts the
dur= value per the Server-Timing spec, avoiding garbage results from
non-standard header formats.
* refactor(types): rename cryptic generic parameters to descriptive names in fetchers/managers
Replace abbreviations like OO, OOI, OC, OSC, OP with readable names
(OrderExtra, OrderItemExtra, CustomerExtra, SubscriptionContractExtra,
PaymentExtra) across order, customer, and subscription modules for
better IDE tooltip readability.
* feat(client): add Symbol.dispose support for automatic cleanup
Enables `using client = createClient({...})` syntax (TypeScript 5.2+)
so HTTP/2 connections are automatically closed when the scope exits.
Added `esnext.disposable` to tsconfig lib and implemented Symbol.dispose
on both ClientInterface and MassClientInterface.
* feat(client): add request timeout support via AbortController
Add optional `timeout` field (in milliseconds) to CreateClientOptions.
When configured, requests that exceed the timeout are automatically
aborted using AbortSignal.timeout(). Works for both fetch and HTTP/2
code paths. Default is no timeout (backward compatible).
* refactor(types): replace any with proper types in mass call client
- Replace Promise<any> with Promise<MassCallResults> (Record<string, unknown>)
- Replace any in afterRequest callback with Record<string, unknown>
- Replace any for exception in onFailure with unknown
- Type buildStandardPromise return as { key: string; result: unknown } | undefined
- Fix typo: situaion → situation in changeIncrementFor parameter
* refactor(mass-call): replace repetitive enqueue methods with generated approach
The five identical enqueue methods (catalogueApi, discoveryApi, pimApi, nextPimApi, shopCartApi)
differed only in their key prefix and caller reference. Replaced with Object.fromEntries
to eliminate ~20 lines of boilerplate while preserving the public API and types.
* test: add unit tests with mocked HTTP for core modules
Add 38 unit tests covering create-api-caller, create-grabber, and
create-mass-call-client without requiring API credentials or network
access. Tests cover: authentication headers, successful responses,
HTTP errors, GraphQL errors, Core Next wrapped errors, 204 handling,
profiling, mass call batching, retry logic, and adaptive concurrency.
* test: add comprehensive error-path tests for API caller
Cover HTTP error codes (400-503), GraphQL errors in 200 responses,
Core Next wrapped errors, network failures, timeout scenarios,
malformed JSON responses, 204 No Content, and JSApiClientCallError
property validation.
* ci: add GitHub Actions workflow for PR and main branch checks
Runs build and unit tests across Node.js 20, 22, and 24 on every
pull request and push to main, so broken code is caught before merge.
* docs: add JSDoc comments to all main exported factory functions
Add comprehensive JSDoc with @PARAM, @returns, and @example tags to
12 exported factory functions for better IDE discoverability.
* feat: review
* fix: await onBatchDone callback in mass call client
The onBatchDone callback is typed as returning Promise<void> but was not
awaited, causing batch callbacks to overlap with subsequent batch execution.
* fix: remove Promise constructor antipattern in mass call client
Replace `new Promise(async (resolve) => { ... })` with plain async/await
flow. The old pattern swallowed errors from beforeRequest/afterRequest
hooks, causing the promise to silently hang instead of rejecting.
* fix: type HTTP/2 clients Map and add null guard in grabber
The clients Map was untyped (new Map()), hiding potential null-access
bugs. Added proper generic type parameters and a guard in
resetIdleTimeout for when clientObj is undefined.
* fix: stop sending empty auth headers when no credentials configured
When no accessTokenId/accessTokenSecret are set, return an empty object
instead of headers with empty string values. Crystallize APIs already
handle missing headers correctly.
* refactor: extract shared lifecycleAction helper in subscription contract manager
cancel, pause, resume, renew, create, and update all followed the same
pattern: build a mutation object, call nextPimApi, unwrap the response.
A private lifecycleAction helper now encapsulates this, eliminating ~80
lines of duplication while keeping the public API identical.
* refactor: extract shared helpers in cart manager to eliminate duplication
Cart manager methods (fetch, place, abandon, fulfill, addSkuItem, removeItem,
setMeta, setCustomer, hydrate) all followed the same pattern of building a
GraphQL query/mutation, calling shopCartApi, and unwrapping the response.
Extracted cartQuery and cartMutation helpers to remove ~80 lines of
structural duplication. Public API unchanged.
* deprecate: add deprecation notice to mass call client, recommend p-limit/p-queue
The mass call client duplicates functionality that mature ecosystem
packages provide better. Added @deprecated JSDoc tag, one-time
console.warn on first use, and updated README with deprecation notice
and p-limit usage example. The function remains fully functional.
* feat: add statusCode getter alias on JSApiClientCallError
Adds a `get statusCode()` getter that returns `this.code`, following
Node.js conventions where `code` is typically a string error code
(ECONNREFUSED, etc.) and `statusCode` is the numeric HTTP status.
Non-breaking — existing `.code` usage is unaffected.
* feat: make HTTP/2 idle timeout configurable via http2IdleTimeout option
Expose http2IdleTimeout on CreateClientOptions so users can tune the
idle timeout for serverless (short) and long-running server (long) use
cases. Defaults to 300000ms (5 minutes) when not set.
* docs: update README with http2IdleTimeout, timeout options and statusCode alias
Document the new timeout and http2IdleTimeout client options, and add
an error handling section showing the statusCode getter on
JSApiClientCallError.
* clean
* review 1
* review1 parent 0761847 commit 259ce36
30 files changed
Lines changed: 2559 additions & 1101 deletions
File tree
- components/js-api-client
- src/core
- catalogue
- client
- pim
- customers
- orders
- subscriptions
- shop
- tests/unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| 66 | + | |
| 67 | + | |
66 | 68 | | |
67 | 69 | | |
68 | 70 | | |
| |||
89 | 91 | | |
90 | 92 | | |
91 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
92 | 111 | | |
93 | 112 | | |
94 | 113 | | |
| |||
378 | 397 | | |
379 | 398 | | |
380 | 399 | | |
381 | | - | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
382 | 430 | | |
383 | 431 | | |
384 | 432 | | |
| |||
396 | 444 | | |
397 | 445 | | |
398 | 446 | | |
399 | | - | |
400 | | - | |
| 447 | + | |
401 | 448 | | |
402 | 449 | | |
403 | 450 | | |
| |||
416 | 463 | | |
417 | 464 | | |
418 | 465 | | |
419 | | - | |
420 | | - | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
1 | 27 | | |
2 | 28 | | |
3 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
30 | 30 | | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
| 42 | + | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
25 | 44 | | |
26 | 45 | | |
27 | 46 | | |
| |||
64 | 83 | | |
65 | 84 | | |
66 | 85 | | |
67 | | - | |
| 86 | + | |
68 | 87 | | |
69 | 88 | | |
70 | 89 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
112 | 112 | | |
113 | 113 | | |
114 | 114 | | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
115 | 129 | | |
116 | 130 | | |
117 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
90 | | - | |
| 90 | + | |
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| |||
140 | 140 | | |
141 | 141 | | |
142 | 142 | | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
143 | 158 | | |
144 | 159 | | |
145 | 160 | | |
| |||
0 commit comments