@xemahq/biome-host-api-client 0.3.27 → 0.3.29
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/dist/custom-fetch.js
CHANGED
|
@@ -223,14 +223,66 @@ const customFetch = async (url, options) => {
|
|
|
223
223
|
}
|
|
224
224
|
};
|
|
225
225
|
exports.customFetch = customFetch;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Does this media type carry JSON?
|
|
228
|
+
*
|
|
229
|
+
* ── THE OUTAGE THIS FIXES ────────────────────────────────────────────────
|
|
230
|
+
*
|
|
231
|
+
* This used to be `contentType?.includes('application/json')`, and EVERY error
|
|
232
|
+
* this fleet returns failed that test. The platform's `GlobalExceptionFilter`
|
|
233
|
+
* emits RFC 9457 problem documents and sets the media type explicitly —
|
|
234
|
+
* `.type(PROBLEM_DETAILS_CONTENT_TYPE)` before `.json()`, so it cannot be
|
|
235
|
+
* overridden — and that constant is `application/problem+json`, which does NOT
|
|
236
|
+
* contain the substring `application/json`: after `application/` comes
|
|
237
|
+
* `problem+json`.
|
|
238
|
+
*
|
|
239
|
+
* So every non-2xx body fell through to `response.text()` and reached the
|
|
240
|
+
* caller as an UNPARSED STRING. `ClientError.body` is typed `unknown`, so
|
|
241
|
+
* nothing complained; every consumer that reads a machine-readable code off an
|
|
242
|
+
* error — `error.body.code`, `error.body.details.code` — silently read
|
|
243
|
+
* `undefined` instead, for every error, in every service.
|
|
244
|
+
*
|
|
245
|
+
* Measured in production on 2026-09-15: skill-registry-api's
|
|
246
|
+
* `resolveOrNull()` absorbs `RELEASE_CHANNEL_NOT_FOUND` into `null` by exactly
|
|
247
|
+
* that read. With the code unreadable the absorb never fired, a routine "no
|
|
248
|
+
* pointer on this channel" 404 became a 500 on `GET /skills` and
|
|
249
|
+
* `GET /describe-objects`, and agent-session-api's `apply_control_bundle` step
|
|
250
|
+
* aborted EVERY session launch in the organisation — 7,871 failed resolutions
|
|
251
|
+
* an hour. A fix written for that exact page months earlier was present in the
|
|
252
|
+
* running image and could not help, because the classifier it repaired was
|
|
253
|
+
* being handed a string.
|
|
254
|
+
*
|
|
255
|
+
* ── WHY THE STRUCTURED SUFFIX, NOT A SECOND SUBSTRING ────────────────────
|
|
256
|
+
*
|
|
257
|
+
* Adding `|| includes('application/problem+json')` would fix this one media
|
|
258
|
+
* type and leave the next one — `application/vnd.api+json`, and anything else
|
|
259
|
+
* a service legitimately emits. RFC 6839 defines `+json` as the structured
|
|
260
|
+
* syntax suffix meaning "this is JSON"; that is the actual rule, so it is the
|
|
261
|
+
* rule implemented. Parameters are stripped first, because
|
|
262
|
+
* `application/problem+json; charset=utf-8` is the same media type.
|
|
263
|
+
*/
|
|
264
|
+
function isJsonMediaType(contentType) {
|
|
265
|
+
if (contentType === null) {
|
|
266
|
+
return false;
|
|
230
267
|
}
|
|
268
|
+
const essence = contentType.split(';')[0]?.trim().toLowerCase() ?? '';
|
|
269
|
+
return essence === 'application/json' || essence.endsWith('+json');
|
|
270
|
+
}
|
|
271
|
+
async function parseBody(response) {
|
|
272
|
+
// 204 FIRST, and deliberately — this ORDER is carried from `develop`, which
|
|
273
|
+
// fixed the same defect independently and got this half right where `main`
|
|
274
|
+
// did not. A 204 carries no body, so `response.json()` on one throws
|
|
275
|
+
// SyntaxError; and a 204 whose headers STILL declare a JSON content type is
|
|
276
|
+
// ordinary, because the framework sets the header before the handler returns
|
|
277
|
+
// nothing. With the JSON branch first, a documented `undefined` becomes a
|
|
278
|
+
// thrown parse error. Pinned by a case in `transport-problem-json.test.cjs`.
|
|
231
279
|
if (response.status === 204) {
|
|
232
280
|
return undefined;
|
|
233
281
|
}
|
|
282
|
+
const contentType = response.headers.get('content-type');
|
|
283
|
+
if (isJsonMediaType(contentType)) {
|
|
284
|
+
return response.json();
|
|
285
|
+
}
|
|
234
286
|
return response.text();
|
|
235
287
|
}
|
|
236
288
|
function parseRetryAfter(value) {
|
|
@@ -37,6 +37,7 @@ export declare const ContributionKind: {
|
|
|
37
37
|
readonly 'opencode-plugin': "opencode-plugin";
|
|
38
38
|
readonly capability: "capability";
|
|
39
39
|
readonly 'resource-ownership': "resource-ownership";
|
|
40
|
+
readonly 'resource-kind': "resource-kind";
|
|
40
41
|
readonly 'resource-definition': "resource-definition";
|
|
41
42
|
readonly 'stage-machine': "stage-machine";
|
|
42
43
|
readonly 'search-type': "search-type";
|
|
@@ -44,5 +45,6 @@ export declare const ContributionKind: {
|
|
|
44
45
|
readonly 'canonical-object-type': "canonical-object-type";
|
|
45
46
|
readonly 'resource-role': "resource-role";
|
|
46
47
|
readonly 'ingestion-source': "ingestion-source";
|
|
48
|
+
readonly 'notification-descriptor': "notification-descriptor";
|
|
47
49
|
readonly 'contribution-kind': "contribution-kind";
|
|
48
50
|
};
|
|
@@ -36,6 +36,7 @@ exports.ContributionKind = {
|
|
|
36
36
|
'opencode-plugin': 'opencode-plugin',
|
|
37
37
|
capability: 'capability',
|
|
38
38
|
'resource-ownership': 'resource-ownership',
|
|
39
|
+
'resource-kind': 'resource-kind',
|
|
39
40
|
'resource-definition': 'resource-definition',
|
|
40
41
|
'stage-machine': 'stage-machine',
|
|
41
42
|
'search-type': 'search-type',
|
|
@@ -43,5 +44,6 @@ exports.ContributionKind = {
|
|
|
43
44
|
'canonical-object-type': 'canonical-object-type',
|
|
44
45
|
'resource-role': 'resource-role',
|
|
45
46
|
'ingestion-source': 'ingestion-source',
|
|
47
|
+
'notification-descriptor': 'notification-descriptor',
|
|
46
48
|
'contribution-kind': 'contribution-kind',
|
|
47
49
|
};
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* OpenAPI spec version: 0.1.1
|
|
5
5
|
*/
|
|
6
6
|
import type { ProblemFieldIssueDto } from './problemFieldIssueDto.js';
|
|
7
|
+
/**
|
|
8
|
+
* RFC 9457 problem document. The declared members are the reserved core; extension members are TOP-LEVEL and OPEN, owned by the refusing plane.
|
|
9
|
+
*/
|
|
7
10
|
export interface ProblemDetailsDto {
|
|
8
11
|
/** Absolute URI identifying the refusal TYPE. Derived one-to-one from `code`, so a caller may branch on either and can never be told two different things. Never `about:blank`. */
|
|
9
12
|
type: string;
|
|
@@ -21,4 +24,5 @@ export interface ProblemDetailsDto {
|
|
|
21
24
|
traceId?: string;
|
|
22
25
|
/** Field-level issues, when the refusal is about the request body. */
|
|
23
26
|
errors?: ProblemFieldIssueDto[];
|
|
27
|
+
[key: string]: unknown;
|
|
24
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xemahq/biome-host-api-client",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.29",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"service": "biome-host-api",
|
|
20
20
|
"biome": "biome-host",
|
|
21
21
|
"target": "server",
|
|
22
|
-
"generator": "@xemahq/api-client-generator@0.
|
|
22
|
+
"generator": "@xemahq/api-client-generator@0.21.0",
|
|
23
23
|
"source": "openapi.public.json"
|
|
24
24
|
},
|
|
25
25
|
"license": "LicenseRef-Xema-BSL-1.1",
|