@owlmeans/api 0.1.18-rc.46 → 0.1.18-rc.47
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/README.md +2 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/api/SKILL.md +22 -20
- package/build/index.d.ts +2 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/service.js +6 -6
- package/build/service.js.map +1 -1
- package/build/status/helper.d.ts +4 -0
- package/build/status/helper.d.ts.map +1 -0
- package/build/status/helper.js +49 -0
- package/build/status/helper.js.map +1 -0
- package/build/status/index.d.ts +3 -22
- package/build/status/index.d.ts.map +1 -1
- package/build/status/index.js +4 -61
- package/build/status/index.js.map +1 -1
- package/build/status/types.d.ts +24 -0
- package/build/status/types.d.ts.map +1 -1
- package/build/utils/body/types.d.ts +36 -0
- package/build/utils/body/types.d.ts.map +1 -0
- package/build/utils/{types.js.map → body/types.js.map} +1 -1
- package/build/utils/body.d.ts +3 -38
- package/build/utils/body.d.ts.map +1 -1
- package/build/utils/body.js +49 -66
- package/build/utils/body.js.map +1 -1
- package/build/utils/index.d.ts +2 -1
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +1 -1
- package/build/utils/index.js.map +1 -1
- package/build/utils/response/types.d.ts +15 -0
- package/build/utils/response/types.d.ts.map +1 -0
- package/build/utils/response/types.js +2 -0
- package/build/utils/response/types.js.map +1 -0
- package/build/utils/response.d.ts +4 -0
- package/build/utils/response.d.ts.map +1 -0
- package/build/utils/response.js +99 -0
- package/build/utils/response.js.map +1 -0
- package/package.json +11 -11
- package/src/index.ts +2 -2
- package/src/service.ts +6 -6
- package/src/status/helper.ts +63 -0
- package/src/status/index.ts +5 -76
- package/src/status/types.ts +25 -0
- package/src/utils/body/types.ts +37 -0
- package/src/utils/body.ts +50 -67
- package/src/utils/index.ts +2 -1
- package/src/utils/response/types.ts +15 -0
- package/src/utils/response.ts +117 -0
- package/tests/body.spec.ts +29 -29
- package/tests/handler.spec.ts +45 -45
- package/build/utils/handler.d.ts +0 -11
- package/build/utils/handler.d.ts.map +0 -1
- package/build/utils/handler.js +0 -95
- package/build/utils/handler.js.map +0 -1
- package/build/utils/types.d.ts +0 -11
- package/build/utils/types.d.ts.map +0 -1
- package/src/utils/handler.ts +0 -110
- package/src/utils/types.ts +0 -12
- /package/build/utils/{types.js → body/types.js} +0 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ HTTP API client service for OwlMeans client contexts — carries entrypoint call
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
bun add @owlmeans/api@^0.1.18-rc.
|
|
15
|
+
bun add @owlmeans/api@^0.1.18-rc.47
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Usage
|
|
@@ -73,7 +73,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
73
73
|
your project's skill store (`.agents/skills/`):
|
|
74
74
|
|
|
75
75
|
```sh
|
|
76
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
76
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.49
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/api",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.47",
|
|
5
|
+
"generatedAt": "2026-10-05T21:03:06.419Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -8,7 +8,7 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/api
|
|
9
9
|
|
|
10
10
|
**Layer:** Core
|
|
11
|
-
**Install:** `"@owlmeans/api": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/api": "^0.1.18-rc.47"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
## Key Exports
|
|
14
14
|
|
|
@@ -18,16 +18,17 @@ user-invocable: false
|
|
|
18
18
|
| `appendApiClient(ctx, alias?)` | Register it and make it the context's default `webService` when none is set |
|
|
19
19
|
| `ApiClient` | Service interface — a single `handler(req, reply)` |
|
|
20
20
|
| `ApiError`, `ApiClientError`, `ServerCrashedError`, `ServerAuthError`, `ApiStatusError` | Typed transport errors; an `ApiClientError` carries the answered `status` and the server's `incidentId` |
|
|
21
|
-
| `httpStatusOf`, `incidentIdOf`, `isAccessDenied`, `isIncidentBody
|
|
21
|
+
| `apiStatusHelper` (`httpStatusOf`, `incidentIdOf`, `isAccessDenied`, `isIncidentBody`), `parseClientMarker`, `API_CLIENT_MARKER`, `API_STATUS_MARKER` | Read a failure's HTTP status, incident id and IAM denial marker (also the `./status` subpath) |
|
|
22
22
|
| Constants | Status codes (`OK`, `CREATED`, `ACCEPTED`, `FINISHED`, `UNAUTHORIZED_ERROR`, `FORBIDDEN_ERROR`, `SERVER_ERROR`), `INCIDENT_ID_HEADER` (`X-Incident-ID`), `DEFAULT_ALIAS` (`web-client`) |
|
|
23
23
|
|
|
24
|
-
Subpath `./status` — `httpStatusOf`, `incidentIdOf`, `
|
|
25
|
-
markers and `INCIDENT_ID_HEADER`, importing only
|
|
26
|
-
status without pulling axios in.
|
|
24
|
+
Subpath `./status` — `apiStatusHelper` (`httpStatusOf`, `incidentIdOf`, `isAccessDenied`,
|
|
25
|
+
`isIncidentBody`), `parseClientMarker`, the markers and `INCIDENT_ID_HEADER`, importing only
|
|
26
|
+
`@owlmeans/error`: a browser package reads a status without pulling axios in.
|
|
27
27
|
|
|
28
|
-
`isAccessDenied(error)` requires the server's `X-OwlMeans-Denial: access-denied`
|
|
29
|
-
Do not classify all 403 responses as IAM denials: entitlement and other refusals
|
|
30
|
-
too. The API client stamps the marker on its rejection even under production error
|
|
28
|
+
`apiStatusHelper.isAccessDenied(error)` requires the server's `X-OwlMeans-Denial: access-denied`
|
|
29
|
+
marker and a 403. Do not classify all 403 responses as IAM denials: entitlement and other refusals
|
|
30
|
+
use that status too. The API client stamps the marker on its rejection even under production error
|
|
31
|
+
exposure.
|
|
31
32
|
|
|
32
33
|
## How a call is carried
|
|
33
34
|
|
|
@@ -94,15 +95,15 @@ browser reads that header cross-origin only when the server exposes it, the body
|
|
|
94
95
|
| Production — a bare incident UUID; also proxy HTML, framework JSON, anything else | `ServerCrashedError` `api:client:crashed:<id>` (500) · `ServerAuthError` `api:client:auth:<id>` (401) · `ApiClientError` `api:client:forbidden[:<id>]` (403) · `ApiStatusError` `api:client:status:<n>[:<id>]` (every other status) |
|
|
95
96
|
|
|
96
97
|
An `@owlmeans/server-api` boundary in production exposure sends ONLY the incident id, so a typed
|
|
97
|
-
refusal's class never reaches the browser — its status does. Read it with
|
|
98
|
-
stamped `responseStatus`, else an `ApiClientError`'s parsed
|
|
99
|
-
`httpStatus` (a 4xx; a 5xx only with `allowServerErrorStatus`,
|
|
100
|
-
else an `api:client:*` marker in the message or type; `null` when
|
|
101
|
-
that acts on a refusal checks the class/marker AND the status
|
|
102
|
-
httpStatusOf(e) === 428`). Markers without an id stay as
|
|
103
|
-
`api:client:forbidden`). The status and id are rebuilt from
|
|
104
|
-
so they survive a marshal. No class of this family declares a
|
|
105
|
-
rethrows one still answers 500.
|
|
98
|
+
refusal's class never reaches the browser — its status does. Read it with
|
|
99
|
+
`apiStatusHelper.httpStatusOf(e)`: the stamped `responseStatus`, else an `ApiClientError`'s parsed
|
|
100
|
+
`status`, else a class's declared `httpStatus` (a 4xx; a 5xx only with `allowServerErrorStatus`,
|
|
101
|
+
exactly what the server answers), else an `api:client:*` marker in the message or type; `null` when
|
|
102
|
+
nothing states one. A consumer that acts on a refusal checks the class/marker AND the status
|
|
103
|
+
(`consentRefusalOf(e) || apiStatusHelper.httpStatusOf(e) === 428`). Markers without an id stay as
|
|
104
|
+
they were (`api:client:crashed:error`, `api:client:forbidden`). The status and id are rebuilt from
|
|
105
|
+
the marker in `finalizeUnmarshal()`, so they survive a marshal. No class of this family declares a
|
|
106
|
+
static `httpStatus`: a server that rethrows one still answers 500.
|
|
106
107
|
|
|
107
108
|
**A failure with no answer at all is a different family.** Suppressing status errors does not wrap
|
|
108
109
|
the call: an expired `timeout` (`ECONNABORTED`), an aborted `signal` (`CanceledError` /
|
|
@@ -114,8 +115,9 @@ An `auth-token-refresh` response header is consumed here: when the context has a
|
|
|
114
115
|
rotated token is handed to it, which is what keeps a long session alive without the caller doing
|
|
115
116
|
anything.
|
|
116
117
|
|
|
117
|
-
Building a URL without making the call is a different question — that is
|
|
118
|
-
`@owlmeans/client-entrypoint/utils`, or
|
|
118
|
+
Building a URL without making the call is a different question — that is
|
|
119
|
+
`apiCallOf(ref).entrypointUrl(req, opts)` from `@owlmeans/client-entrypoint/utils`, or
|
|
120
|
+
`ep.url(req, { absolute })`.
|
|
119
121
|
|
|
120
122
|
## Usage
|
|
121
123
|
|
|
@@ -132,7 +134,7 @@ transport keeps it.
|
|
|
132
134
|
## Depends On
|
|
133
135
|
|
|
134
136
|
- `@owlmeans/context` — service registration
|
|
135
|
-
- `@owlmeans/entrypoint` — the entrypoint being addressed, `@owlmeans/client-route` — `extractParams`
|
|
137
|
+
- `@owlmeans/entrypoint` — the entrypoint being addressed, `@owlmeans/client-route` — `clientRouteHelper.extractParams`
|
|
136
138
|
- `@owlmeans/config` — `makeSecurityHelper`, `@owlmeans/client-config` — the config shape
|
|
137
139
|
- `@owlmeans/auth-common` — the token-refresh header and the auth service it updates
|
|
138
140
|
- `@owlmeans/error`, `@owlmeans/route`
|
package/build/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from './errors.js';
|
|
|
2
2
|
export * from './consts.js';
|
|
3
3
|
export * from './service.js';
|
|
4
4
|
export type * from './types.js';
|
|
5
|
-
export { httpStatusOf,
|
|
6
|
-
export type { ClientMarker } from './status/index.js';
|
|
5
|
+
export { httpStatusOf, apiStatusHelper, createApiStatusHelper, parseClientMarker, API_CLIENT_MARKER, API_STATUS_MARKER, } from './status/index.js';
|
|
6
|
+
export type { ClientMarker, ApiStatusHelper } from './status/index.js';
|
|
7
7
|
export type { ResponseStatusCarrier } from './status/types.js';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EACL,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,mBAAmB,YAAY,CAAA;AAC/B,OAAO,EACL,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,GAC9G,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACtE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
|
package/build/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './errors.js';
|
|
2
2
|
export * from './consts.js';
|
|
3
3
|
export * from './service.js';
|
|
4
|
-
export { httpStatusOf,
|
|
4
|
+
export { httpStatusOf, apiStatusHelper, createApiStatusHelper, parseClientMarker, API_CLIENT_MARKER, API_STATUS_MARKER, } from './status/index.js';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAE5B,OAAO,EACL,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAE5B,OAAO,EACL,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,GAC9G,MAAM,mBAAmB,CAAA"}
|
package/build/service.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { assertContext, createService } from '@owlmeans/context';
|
|
2
|
-
import {
|
|
2
|
+
import { clientRouteHelper } from '@owlmeans/client-route';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { DEFAULT_ALIAS, UNAUTHORIZED_ERROR } from './consts.js';
|
|
5
|
-
import {
|
|
5
|
+
import { responseUtils } from './utils/response.js';
|
|
6
6
|
import { makeSecurityHelper } from '@owlmeans/config';
|
|
7
7
|
import { AUTH_HEADER, DEF_AUTH_SRV, TOKEN_UPDATE } from '@owlmeans/auth-common';
|
|
8
|
-
import {
|
|
8
|
+
import { bodyUtils } from './utils/body.js';
|
|
9
9
|
/** Whether a request carried an authentication header of its own. */
|
|
10
10
|
const presented = (headers) => headers != null && Object.entries(headers).some(([key, value]) => key.toLowerCase() === AUTH_HEADER && value != null && value !== '');
|
|
11
11
|
export const createApiService = (alias = DEFAULT_ALIAS) => {
|
|
@@ -19,7 +19,7 @@ export const createApiService = (alias = DEFAULT_ALIAS) => {
|
|
|
19
19
|
const module = context.entrypoint(request.alias);
|
|
20
20
|
const route = module.route.route;
|
|
21
21
|
let path = module.path();
|
|
22
|
-
const params = extractParams(path);
|
|
22
|
+
const params = clientRouteHelper.extractParams(path);
|
|
23
23
|
path = params.reduce((path, param) => {
|
|
24
24
|
if (request.params[param] == null) {
|
|
25
25
|
throw new SyntaxError(`No value for param ${param}`);
|
|
@@ -32,7 +32,7 @@ export const createApiService = (alias = DEFAULT_ALIAS) => {
|
|
|
32
32
|
const url = helper.makeUrl(module.address(), path, { host: request.host, base: request.base, forceUnsecure: request.unsecure });
|
|
33
33
|
// A scalar JSON body (a string, a number, a boolean) is serialized here, so the server parses
|
|
34
34
|
// back the value the caller sent; objects and arrays are left to axios.
|
|
35
|
-
const body =
|
|
35
|
+
const body = bodyUtils.requestBodyOf(request.body, request.headers, route.method, module.filter?.body);
|
|
36
36
|
const transformer = body.verbatim ? data => data : undefined;
|
|
37
37
|
const requestHeaders = body.contentType != null
|
|
38
38
|
? { ...request.headers, 'content-type': body.contentType }
|
|
@@ -74,7 +74,7 @@ export const createApiService = (alias = DEFAULT_ALIAS) => {
|
|
|
74
74
|
*/
|
|
75
75
|
await context.service(DEF_AUTH_SRV).update(undefined);
|
|
76
76
|
}
|
|
77
|
-
processResponse(response, reply);
|
|
77
|
+
responseUtils.processResponse(response, reply);
|
|
78
78
|
return [reply.error ?? reply.value, reply.outcome];
|
|
79
79
|
}
|
|
80
80
|
}, service => async () => {
|
package/build/service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../src/status/helper.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAuC,MAAM,YAAY,CAAA;AAEtF,eAAO,MAAM,qBAAqB,QAAO,eAqDxC,CAAA;AAED,eAAO,MAAM,eAAe,iBAA0B,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ResilientError } from '@owlmeans/error';
|
|
2
|
+
import { ApiClientError } from '../errors.js';
|
|
3
|
+
import { parseClientMarker } from './marker.js';
|
|
4
|
+
import { ACCESS_DENIED_KIND } from '../consts.js';
|
|
5
|
+
import { UUID } from './consts.local.js';
|
|
6
|
+
export const createApiStatusHelper = () => {
|
|
7
|
+
const isAccessDenied = (error) => httpStatusOf(error) === 403
|
|
8
|
+
&& typeof error === 'object' && error != null
|
|
9
|
+
&& error.denialKind === ACCESS_DENIED_KIND;
|
|
10
|
+
const httpStatus = (value) => typeof value === 'number' && Number.isInteger(value) && value >= 100 && value <= 599 ? value : null;
|
|
11
|
+
/** The first `api:client:*` marker in an error's `message`, else in its `type`. */
|
|
12
|
+
const markerOf = (error) => {
|
|
13
|
+
const { message, type } = error;
|
|
14
|
+
return (typeof message === 'string' ? parseClientMarker(message) : null)
|
|
15
|
+
?? (typeof type === 'string' ? parseClientMarker(type) : null);
|
|
16
|
+
};
|
|
17
|
+
const httpStatusOf = (error) => {
|
|
18
|
+
if (error == null || typeof error !== 'object') {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const stamped = httpStatus(error.responseStatus);
|
|
22
|
+
if (stamped != null) {
|
|
23
|
+
return stamped;
|
|
24
|
+
}
|
|
25
|
+
if (error instanceof ApiClientError && httpStatus(error.status) != null) {
|
|
26
|
+
return error.status;
|
|
27
|
+
}
|
|
28
|
+
const declaration = error.constructor;
|
|
29
|
+
const declared = httpStatus(declaration?.httpStatus);
|
|
30
|
+
if (declared != null && (declared < 500 || declaration?.allowServerErrorStatus === true)) {
|
|
31
|
+
return declared;
|
|
32
|
+
}
|
|
33
|
+
return markerOf(error)?.status ?? null;
|
|
34
|
+
};
|
|
35
|
+
const incidentIdOf = (error) => {
|
|
36
|
+
if (error == null || typeof error !== 'object') {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const own = error.incidentId;
|
|
40
|
+
if (typeof own === 'string' && own !== '') {
|
|
41
|
+
return own;
|
|
42
|
+
}
|
|
43
|
+
return markerOf(error)?.incidentId ?? null;
|
|
44
|
+
};
|
|
45
|
+
const isIncidentBody = (data) => typeof data === 'string' && !data.includes(ResilientError.separator) && UUID.test(data.trim());
|
|
46
|
+
return { isAccessDenied, httpStatusOf, incidentIdOf, isIncidentBody };
|
|
47
|
+
};
|
|
48
|
+
export const apiStatusHelper = createApiStatusHelper();
|
|
49
|
+
//# sourceMappingURL=helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../../src/status/helper.ts"],"names":[],"mappings":"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"}
|
package/build/status/index.d.ts
CHANGED
|
@@ -2,27 +2,8 @@ export { INCIDENT_ID_HEADER } from '../consts.js';
|
|
|
2
2
|
export { DENIAL_KIND_HEADER, ACCESS_DENIED_KIND } from '../consts.js';
|
|
3
3
|
export { parseClientMarker } from './marker.js';
|
|
4
4
|
export { API_CLIENT_MARKER, API_STATUS_MARKER } from './consts.js';
|
|
5
|
-
export type { ClientMarker } from './types.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The HTTP status an error answers to, or `null` when nothing states one.
|
|
10
|
-
*
|
|
11
|
-
* Read in order: the status the API client stamped on the error it rebuilt from a response
|
|
12
|
-
* (`responseStatus`); the status an `ApiClientError` parsed from its marker; the `httpStatus` its
|
|
13
|
-
* class declares — a 4xx always, a 5xx only with `allowServerErrorStatus`, exactly what an
|
|
14
|
-
* `@owlmeans/server-api` boundary answers with; finally an `api:client:*` marker in the message or
|
|
15
|
-
* the type of anything else. This is what lets a browser recognise a refusal from its status
|
|
16
|
-
* alone when a production body carries nothing but an incident id.
|
|
17
|
-
*/
|
|
5
|
+
export type { ClientMarker, ResponseStatusCarrier, ApiStatusHelper } from './types.js';
|
|
6
|
+
export { apiStatusHelper, createApiStatusHelper } from './helper.js';
|
|
7
|
+
/** @deprecated compat:factory-refactor — use `apiStatusHelper.httpStatusOf(…)` */
|
|
18
8
|
export declare const httpStatusOf: (error: unknown) => number | null;
|
|
19
|
-
/** The server's incident id carried by an error — its own field, else its marker — or `null`. */
|
|
20
|
-
export declare const incidentIdOf: (error: unknown) => string | null;
|
|
21
|
-
/**
|
|
22
|
-
* Whether a response body is a production incident body — the bare incident UUID an
|
|
23
|
-
* `@owlmeans/server-api` boundary sends instead of the marshaled error. A development body
|
|
24
|
-
* carries the `ResilientError` separator and is never one.
|
|
25
|
-
*/
|
|
26
|
-
export declare const isIncidentBody: (data: unknown) => data is string;
|
|
27
|
-
export type { ResponseStatusCarrier } from './types.js';
|
|
28
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/status/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/status/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClE,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACtF,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEpE,kFAAkF;AAClF,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,GAAG,IAA2C,CAAA"}
|
package/build/status/index.js
CHANGED
|
@@ -1,66 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ApiClientError } from '../errors.js';
|
|
3
|
-
import { parseClientMarker } from './marker.js';
|
|
1
|
+
import { apiStatusHelper } from './helper.js';
|
|
4
2
|
export { INCIDENT_ID_HEADER } from '../consts.js';
|
|
5
3
|
export { DENIAL_KIND_HEADER, ACCESS_DENIED_KIND } from '../consts.js';
|
|
6
|
-
import { ACCESS_DENIED_KIND } from '../consts.js';
|
|
7
|
-
import { UUID } from './consts.local.js';
|
|
8
4
|
export { parseClientMarker } from './marker.js';
|
|
9
5
|
export { API_CLIENT_MARKER, API_STATUS_MARKER } from './consts.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
&& error.denialKind === ACCESS_DENIED_KIND;
|
|
14
|
-
const httpStatus = (value) => typeof value === 'number' && Number.isInteger(value) && value >= 100 && value <= 599 ? value : null;
|
|
15
|
-
/** The first `api:client:*` marker in an error's `message`, else in its `type`. */
|
|
16
|
-
const markerOf = (error) => {
|
|
17
|
-
const { message, type } = error;
|
|
18
|
-
return (typeof message === 'string' ? parseClientMarker(message) : null)
|
|
19
|
-
?? (typeof type === 'string' ? parseClientMarker(type) : null);
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* The HTTP status an error answers to, or `null` when nothing states one.
|
|
23
|
-
*
|
|
24
|
-
* Read in order: the status the API client stamped on the error it rebuilt from a response
|
|
25
|
-
* (`responseStatus`); the status an `ApiClientError` parsed from its marker; the `httpStatus` its
|
|
26
|
-
* class declares — a 4xx always, a 5xx only with `allowServerErrorStatus`, exactly what an
|
|
27
|
-
* `@owlmeans/server-api` boundary answers with; finally an `api:client:*` marker in the message or
|
|
28
|
-
* the type of anything else. This is what lets a browser recognise a refusal from its status
|
|
29
|
-
* alone when a production body carries nothing but an incident id.
|
|
30
|
-
*/
|
|
31
|
-
export const httpStatusOf = (error) => {
|
|
32
|
-
if (error == null || typeof error !== 'object') {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
const stamped = httpStatus(error.responseStatus);
|
|
36
|
-
if (stamped != null) {
|
|
37
|
-
return stamped;
|
|
38
|
-
}
|
|
39
|
-
if (error instanceof ApiClientError && httpStatus(error.status) != null) {
|
|
40
|
-
return error.status;
|
|
41
|
-
}
|
|
42
|
-
const declaration = error.constructor;
|
|
43
|
-
const declared = httpStatus(declaration?.httpStatus);
|
|
44
|
-
if (declared != null && (declared < 500 || declaration?.allowServerErrorStatus === true)) {
|
|
45
|
-
return declared;
|
|
46
|
-
}
|
|
47
|
-
return markerOf(error)?.status ?? null;
|
|
48
|
-
};
|
|
49
|
-
/** The server's incident id carried by an error — its own field, else its marker — or `null`. */
|
|
50
|
-
export const incidentIdOf = (error) => {
|
|
51
|
-
if (error == null || typeof error !== 'object') {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
const own = error.incidentId;
|
|
55
|
-
if (typeof own === 'string' && own !== '') {
|
|
56
|
-
return own;
|
|
57
|
-
}
|
|
58
|
-
return markerOf(error)?.incidentId ?? null;
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* Whether a response body is a production incident body — the bare incident UUID an
|
|
62
|
-
* `@owlmeans/server-api` boundary sends instead of the marshaled error. A development body
|
|
63
|
-
* carries the `ResilientError` separator and is never one.
|
|
64
|
-
*/
|
|
65
|
-
export const isIncidentBody = (data) => typeof data === 'string' && !data.includes(ResilientError.separator) && UUID.test(data.trim());
|
|
6
|
+
export { apiStatusHelper, createApiStatusHelper } from './helper.js';
|
|
7
|
+
/** @deprecated compat:factory-refactor — use `apiStatusHelper.httpStatusOf(…)` */
|
|
8
|
+
export const httpStatusOf = (error) => apiStatusHelper.httpStatusOf(error);
|
|
66
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/status/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/status/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAElE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEpE,kFAAkF;AAClF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAc,EAAiB,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA"}
|
package/build/status/types.d.ts
CHANGED
|
@@ -8,4 +8,28 @@ export interface ClientMarker {
|
|
|
8
8
|
status?: number;
|
|
9
9
|
incidentId?: string;
|
|
10
10
|
}
|
|
11
|
+
/** Reads the HTTP status, the incident id and the denial kind a failed call carries. */
|
|
12
|
+
export interface ApiStatusHelper {
|
|
13
|
+
/** True only for a server-labelled auth/IAM refusal, never an unrelated 403. */
|
|
14
|
+
isAccessDenied: (error: unknown) => boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The HTTP status an error answers to, or `null` when nothing states one.
|
|
17
|
+
*
|
|
18
|
+
* Read in order: the status the API client stamped on the error it rebuilt from a response
|
|
19
|
+
* (`responseStatus`); the status an `ApiClientError` parsed from its marker; the `httpStatus` its
|
|
20
|
+
* class declares — a 4xx always, a 5xx only with `allowServerErrorStatus`, exactly what an
|
|
21
|
+
* `@owlmeans/server-api` boundary answers with; finally an `api:client:*` marker in the message or
|
|
22
|
+
* the type of anything else. This is what lets a browser recognise a refusal from its status
|
|
23
|
+
* alone when a production body carries nothing but an incident id.
|
|
24
|
+
*/
|
|
25
|
+
httpStatusOf: (error: unknown) => number | null;
|
|
26
|
+
/** The server's incident id carried by an error — its own field, else its marker — or `null`. */
|
|
27
|
+
incidentIdOf: (error: unknown) => string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a response body is a production incident body — the bare incident UUID an
|
|
30
|
+
* `@owlmeans/server-api` boundary sends instead of the marshaled error. A development body
|
|
31
|
+
* carries the `ResilientError` separator and is never one.
|
|
32
|
+
*/
|
|
33
|
+
isIncidentBody: (data: unknown) => data is string;
|
|
34
|
+
}
|
|
11
35
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/status/types.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/status/types.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;IAC3C;;;;;;;;;OASG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAA;IAC/C,iGAAiG;IACjG,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAA;IAC/C;;;;OAIG;IACH,cAAc,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,IAAI,MAAM,CAAA;CAClD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { RouteMethod } from '@owlmeans/route';
|
|
2
|
+
export interface RequestBody {
|
|
3
|
+
/** What axios is handed as `data`. */
|
|
4
|
+
data: unknown;
|
|
5
|
+
/** A `content-type` the request lacked and must carry. */
|
|
6
|
+
contentType?: string;
|
|
7
|
+
/** `data` is final text — axios must not transform it again. */
|
|
8
|
+
verbatim: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** How a request's body travels: its content type and the text a scalar body becomes. */
|
|
11
|
+
export interface BodyUtils {
|
|
12
|
+
/** The request's own `content-type`, whatever case its key is written in. */
|
|
13
|
+
contentTypeOf: (headers?: Record<string, unknown>) => string | undefined;
|
|
14
|
+
/** `application/json` or a `+json` suffix type, with or without parameters. */
|
|
15
|
+
isJsonContentType: (type?: string) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The JSON text a scalar body travels as, so the server parses it back to the same value.
|
|
18
|
+
*
|
|
19
|
+
* A number or a boolean is `JSON.stringify`'d. A string is a value unless it is already JSON text:
|
|
20
|
+
* one that does not parse is quoted; one that parses is sent as it is (the caller serialized it
|
|
21
|
+
* itself) — except under a body schema of `type: 'string'`, where only a JSON string literal
|
|
22
|
+
* counts as serialized and `123`, `true` or `{…}` are the text the caller means.
|
|
23
|
+
*/
|
|
24
|
+
jsonScalarBody: (body: string | number | boolean, schema?: object) => string;
|
|
25
|
+
/**
|
|
26
|
+
* What a request's body becomes on the wire.
|
|
27
|
+
*
|
|
28
|
+
* - A `x-www-form-urlencoded` request: the body through `qs`.
|
|
29
|
+
* - A string, number or boolean under a JSON `content-type` — the caller's, or `application/json`
|
|
30
|
+
* supplied for a `POST` that names none — becomes JSON text ({@link BodyUtils.jsonScalarBody}).
|
|
31
|
+
* - Anything else — objects, arrays, a scalar under another content type — goes to axios as it is,
|
|
32
|
+
* which serializes an object or an array as JSON.
|
|
33
|
+
*/
|
|
34
|
+
requestBodyOf: (body: unknown, headers: Record<string, unknown> | undefined, method?: RouteMethod, schema?: object) => RequestBody;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/body/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,IAAI,EAAE,OAAO,CAAA;IACb,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,yFAAyF;AACzF,MAAM,WAAW,SAAS;IACxB,6EAA6E;IAC7E,aAAa,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GAAG,SAAS,CAAA;IACxE,+EAA+E;IAC/E,iBAAiB,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAA;IAC7C;;;;;;;OAOG;IACH,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC5E;;;;;;;;OAQG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,WAAW,CAAA;CACnI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/body/types.ts"],"names":[],"mappings":""}
|
package/build/utils/body.d.ts
CHANGED
|
@@ -1,39 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
declare const contentTypeOf: (headers?: Record<string, unknown>) => string | undefined;
|
|
5
|
-
/** `application/json` or a `+json` suffix type, with or without parameters. */
|
|
6
|
-
declare const isJsonContentType: (type?: string) => boolean;
|
|
7
|
-
/**
|
|
8
|
-
* The JSON text a scalar body travels as, so the server parses it back to the same value.
|
|
9
|
-
*
|
|
10
|
-
* A number or a boolean is `JSON.stringify`'d. A string is a value unless it is already JSON text:
|
|
11
|
-
* one that does not parse is quoted; one that parses is sent as it is (the caller serialized it
|
|
12
|
-
* itself) — except under a body schema of `type: 'string'`, where only a JSON string literal
|
|
13
|
-
* counts as serialized and `123`, `true` or `{…}` are the text the caller means.
|
|
14
|
-
*/
|
|
15
|
-
declare const jsonScalarBody: (body: string | number | boolean, schema?: object) => string;
|
|
16
|
-
/**
|
|
17
|
-
* What a request's body becomes on the wire.
|
|
18
|
-
*
|
|
19
|
-
* - A `x-www-form-urlencoded` request: the body through `qs`.
|
|
20
|
-
* - A string, number or boolean under a JSON `content-type` — the caller's, or `application/json`
|
|
21
|
-
* supplied for a `POST` that names none — becomes JSON text ({@link jsonScalarBody}).
|
|
22
|
-
* - Anything else — objects, arrays, a scalar under another content type — goes to axios as it is,
|
|
23
|
-
* which serializes an object or an array as JSON.
|
|
24
|
-
*/
|
|
25
|
-
declare const requestBodyOf: (body: unknown, headers: Record<string, unknown> | undefined, method?: RouteMethod, schema?: object) => RequestBody;
|
|
26
|
-
export declare const createBodyHelper: () => {
|
|
27
|
-
contentTypeOf: typeof contentTypeOf;
|
|
28
|
-
isJsonContentType: typeof isJsonContentType;
|
|
29
|
-
jsonScalarBody: typeof jsonScalarBody;
|
|
30
|
-
requestBodyOf: typeof requestBodyOf;
|
|
31
|
-
};
|
|
32
|
-
export declare const bodyHelper: {
|
|
33
|
-
contentTypeOf: typeof contentTypeOf;
|
|
34
|
-
isJsonContentType: typeof isJsonContentType;
|
|
35
|
-
jsonScalarBody: typeof jsonScalarBody;
|
|
36
|
-
requestBodyOf: typeof requestBodyOf;
|
|
37
|
-
};
|
|
38
|
-
export {};
|
|
1
|
+
import type { BodyUtils } from './body/types.js';
|
|
2
|
+
export declare const createBodyUtils: () => BodyUtils;
|
|
3
|
+
export declare const bodyUtils: BodyUtils;
|
|
39
4
|
//# sourceMappingURL=body.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../../src/utils/body.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../../src/utils/body.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,iBAAiB,CAAA;AAE7D,eAAO,MAAM,eAAe,QAAO,SA6DlC,CAAA;AAED,eAAO,MAAM,SAAS,WAAoB,CAAA"}
|