Releases: datocms/cda-client
Release list
v0.3.2
Patch Changes
-
f0d3603: Add jitter to the rate-limit retry
Many concurrent requests hitting a 429 at once (e.g. a static build rendering
pages in parallel) used to all retry on the exact same tick, immediately
re-triggering the same rate limit. Retries are now spread out with a random
extra wait on top of the required one.
v0.3.1
Patch Changes
-
70f126d: Keep the API token out of the errors the client throws
ApiErrorstored the options of the failed query verbatim, soerror.options.token
held the API token in clear text — and travelled with the error into
console.error()output shipped to log aggregators, into error trackers, and
into any HTTP handler that echoed the error back to its caller.The token is now replaced by
[REDACTED, ending in abcd], which still tells two
tokens apart while debugging; the real one only ever reaches theAuthorization
header. For the same reasonquery,optionsandresponseare now
non-enumerable: readingerror.optionsexplicitly works exactly as before, but
the details of the failed query no longer travel throughJSON.stringify(),
object spread orserialize-errorby accident.
v0.3.0 — `instanceof ApiError` now works
instanceof ApiError now works
Until this release, error instanceof ApiError was always false — even with a single copy of the module loaded and no bundler involved:
e.name : ApiError
e.constructor.name : Error
Object.getPrototypeOf(e) : Error.prototype ← not ApiError.prototype
e instanceof ApiError : false
e.response.status : 422 (payload was intact)
This failed silently: the guard compiled, type-narrowed, and simply never matched — so error handlers fell through to a generic 500 while looking perfectly correct.
Nothing to change on your side. Plain instanceof now works, including across duplicated copies of the package. If you worked around this with a name-based check, you can delete it:
- if (e instanceof Error && e.name === 'ApiError') {
+ if (e instanceof ApiError) {What was wrong
1. ES5 downlevel. Both tsconfigs set "target": "es5", so class ApiError extends Error was emitted as _this = _super.call(this, message) || this; … return _this. Error.call(this) ignores this and returns a fresh Error — and that object, being truthy, became the instance. Its prototype was therefore Error.prototype, never ApiError.prototype.
The build target is now es2017. The package is built on the browser Fetch API, so no real ES5 runtime could ever have executed it — the ES5 target was only costing correctness.
2. Duplicate module copies. The package ships parallel CJS and ESM builds, so a bundler can load two distinct copies and therefore two distinct ApiError classes. A prototype check then fails for an error thrown by the other copy — and no packaging metadata fully prevents this, since a bundler may inline one copy while another stays external.
ApiError instances are now branded with Symbol.for('@datocms/cda-client:ApiError'), and the class implements static [Symbol.hasInstance], making instanceof structural rather than identity-based. The global symbol registry is shared across copies and realms, so the check holds wherever the error came from. Subclasses still fall back to a real prototype-chain check, so they stay exact.
Packaging
The package now declares an exports map, and relative imports carry .js extensions so the ESM build is actually loadable. Previously dist/esm used extensionless specifiers and had no "type": "module" marker, so importing it from Node failed with ERR_MODULE_NOT_FOUND — it was bundler-only.
Upgrade notes
Released as a minor rather than a patch, for two reasons:
- Emitted syntax is now ES2017 instead of ES5. If you were feeding this package through a build that assumed ES5 output, it will now see modern syntax. (The package already required
fetch,Responseand promises, so this changes the syntax floor, not the practical runtime requirement.) - Resolution now goes through
exports. The map deliberately keeps./dist/*,./src/*and./package.jsonreachable, so existing deep imports keep working — butexportstargets don't get Node's extension guessing, so a deep import must now spell out the extension:@datocms/cda-client/dist/cjs/ApiError.js, not…/ApiError.
Full Changelog: v0.2.11...v0.3.0