@owlmeans/server-api 0.1.18-rc.50 → 0.1.18-rc.52
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 +20 -19
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/server-api/SKILL.md +9 -9
- package/build/server.js +3 -3
- package/build/server.js.map +1 -1
- package/build/utils/context/types.d.ts +13 -0
- package/build/utils/context/types.d.ts.map +1 -0
- package/build/utils/context/types.js +2 -0
- package/build/utils/context/types.js.map +1 -0
- package/build/utils/context.d.ts +3 -3
- package/build/utils/context.d.ts.map +1 -1
- package/build/utils/context.js +5 -2
- package/build/utils/context.js.map +1 -1
- package/build/utils/error/types.d.ts +52 -0
- package/build/utils/error/types.d.ts.map +1 -0
- package/build/utils/error/types.js +2 -0
- package/build/utils/error/types.js.map +1 -0
- package/build/utils/error.d.ts +4 -47
- package/build/utils/error.d.ts.map +1 -1
- package/build/utils/error.js +154 -187
- package/build/utils/error.js.map +1 -1
- package/build/utils/guards.d.ts.map +1 -1
- package/build/utils/guards.js +6 -6
- package/build/utils/guards.js.map +1 -1
- package/build/utils/index.d.ts +4 -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/payload/types.d.ts +18 -0
- package/build/utils/payload/types.d.ts.map +1 -0
- package/build/utils/payload/types.js +2 -0
- package/build/utils/payload/types.js.map +1 -0
- package/build/utils/payload.d.ts +3 -15
- package/build/utils/payload.d.ts.map +1 -1
- package/build/utils/payload.js +40 -60
- package/build/utils/payload.js.map +1 -1
- package/build/utils/schema.d.ts +7 -0
- package/build/utils/schema.d.ts.map +1 -0
- package/build/utils/schema.js +20 -0
- package/build/utils/schema.js.map +1 -0
- package/build/utils/server.js +6 -6
- package/build/utils/server.js.map +1 -1
- package/package.json +12 -12
- package/src/server.ts +3 -3
- package/src/utils/context/types.ts +13 -0
- package/src/utils/context.ts +9 -4
- package/src/utils/error/types.ts +52 -0
- package/src/utils/error.ts +156 -186
- package/src/utils/guards.ts +6 -6
- package/src/utils/index.ts +4 -1
- package/src/utils/payload/types.ts +18 -0
- package/src/utils/payload.ts +41 -63
- package/src/utils/schema.ts +23 -0
- package/src/utils/server.ts +6 -6
- package/tests/error-status.spec.ts +11 -11
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ only when composing a context without that package. WebSocket routes belong to
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
bun add @owlmeans/server-api@^0.1.18-rc.
|
|
13
|
+
bun add @owlmeans/server-api@^0.1.18-rc.52
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Concepts
|
|
@@ -41,7 +41,7 @@ bun add @owlmeans/server-api@^0.1.18-rc.50
|
|
|
41
41
|
```ts
|
|
42
42
|
import { handlers } from '@owlmeans/server-api'
|
|
43
43
|
import { bind } from '@owlmeans/server-entrypoint'
|
|
44
|
-
import {
|
|
44
|
+
import { makeEntityScope } from '@owlmeans/auth-common'
|
|
45
45
|
import { projectProtocols } from 'my-app-common'
|
|
46
46
|
import type { Context } from './context.js'
|
|
47
47
|
|
|
@@ -49,15 +49,15 @@ const api = handlers<Context>()
|
|
|
49
49
|
|
|
50
50
|
// body: the validated body first, then context and the full request
|
|
51
51
|
const create = api.body(projectProtocols.create, async (payload, context, request) =>
|
|
52
|
-
context.project().create({ ...payload, entityId:
|
|
52
|
+
context.project().create({ ...payload, entityId: makeEntityScope(request).requireEntityKey() }))
|
|
53
53
|
|
|
54
54
|
// params: the validated URL params first
|
|
55
55
|
const get = api.params(projectProtocols.get, async ({ id }, context, request) =>
|
|
56
|
-
context.project().load({ id, entityId:
|
|
56
|
+
context.project().load({ id, entityId: makeEntityScope(request).requireEntityKey() }))
|
|
57
57
|
|
|
58
58
|
// request: every typed section plus request metadata (auth, entity, headers)
|
|
59
59
|
const search = api.request(projectProtocols.search, async (request, context) =>
|
|
60
|
-
context.project().list({ entityId:
|
|
60
|
+
context.project().list({ entityId: makeEntityScope(request).requireEntityKey(), ...request.query }))
|
|
61
61
|
|
|
62
62
|
export const serverBindings = [
|
|
63
63
|
bind(projectProtocols.base),
|
|
@@ -77,7 +77,7 @@ import { AuthForbidden } from '@owlmeans/auth'
|
|
|
77
77
|
|
|
78
78
|
// the protocol declares both `params` and `body`
|
|
79
79
|
export const rename = api.body(projectProtocols.rename, async ({ name }, context, request) => {
|
|
80
|
-
const entityId =
|
|
80
|
+
const entityId = makeEntityScope(request).requireEntityKey()
|
|
81
81
|
const project = await context.project().load({ id: request.params.id, entityId })
|
|
82
82
|
if (project == null) {
|
|
83
83
|
throw new AuthForbidden('project') // 403
|
|
@@ -120,7 +120,7 @@ export const upload = api.request(invoiceProtocols.attach, async (request, conte
|
|
|
120
120
|
const content = await file.toBuffer()
|
|
121
121
|
|
|
122
122
|
return context.attachment().create({
|
|
123
|
-
entityId:
|
|
123
|
+
entityId: makeEntityScope(request).requireEntityKey(),
|
|
124
124
|
name: file.filename,
|
|
125
125
|
mimetype: file.mimetype,
|
|
126
126
|
size: content.length,
|
|
@@ -187,17 +187,18 @@ code does not need it.
|
|
|
187
187
|
|
|
188
188
|
| Symbol | Kind | Purpose |
|
|
189
189
|
|---|---|---|
|
|
190
|
-
| `authorize(context, module, req, reply)` | function | Run guards, set `auth`, call `attachEntity` |
|
|
190
|
+
| `authorize(context, module, req, reply)` | function | Run guards, set `auth`, call `makeEntityScope(req).attachEntity(context)` |
|
|
191
191
|
| `createServerHandler(module, location)` | function | The Fastify handler: authorize, gates, handle, respond |
|
|
192
192
|
| `canServeModule(context, module)` | function | Whether an entrypoint belongs on this HTTP server |
|
|
193
|
-
| `provideRequest(alias, req, provision?)` |
|
|
194
|
-
| `executeResponse(response, reply, throwOnError?)` |
|
|
195
|
-
| `handleError(error, reply)` |
|
|
196
|
-
| `errorStatus(error)` |
|
|
197
|
-
| `declaredErrorStatus(error)` |
|
|
193
|
+
| `payloadHelper.provideRequest(alias, req, provision?)` | helper member | Build an `AbstractRequest` from a Fastify request |
|
|
194
|
+
| `payloadHelper.executeResponse(response, reply, throwOnError?)` | helper member | Send an `AbstractResponse` onto a reply |
|
|
195
|
+
| `httpErrorHelper.handleError(error, reply, exposure?)` | helper member | Answer an error with `httpErrorHelper.errorStatus` and the marshalled body |
|
|
196
|
+
| `httpErrorHelper.errorStatus(error)` | helper member | 403 / 401 for auth errors (by class or type name), else the class's declared 4xx, else 500 |
|
|
197
|
+
| `httpErrorHelper.declaredErrorStatus(error)` | helper member | The integer 4xx a class declares through `static httpStatus`, or `null` |
|
|
198
|
+
| `httpErrorHelper.errorExposure(config?)`, `.serializeError(error, exposure?)`, `.applyErrorHeaders(error, reply)` | helper member | The exposure policy, the wire shape and the response headers of an error |
|
|
198
199
|
| `HttpStatusDeclaration` | type | `{ httpStatus?: unknown }` — the structural shape a declaring class has |
|
|
199
200
|
| `fixFormatDates(schema)` | function | Rewrite `date-time` object schemas as strings |
|
|
200
|
-
| `populateContext(
|
|
201
|
+
| `makeRequestContextHelper(req).populateContext(context)`, `.extractContext(ctx?, location?)` | helper member | Carry the request-scoped context on the raw request |
|
|
201
202
|
|
|
202
203
|
## Common pitfalls
|
|
203
204
|
|
|
@@ -215,9 +216,9 @@ code does not need it.
|
|
|
215
216
|
is not a plain function fails that one route with `HandlerMisconfiguredError` instead of the
|
|
216
217
|
opaque `TypeError: handler is not a function`.
|
|
217
218
|
- A guard only authenticates. Gates authorize, and the handler keeps its organization check keyed on
|
|
218
|
-
`
|
|
219
|
-
- `request.entity` is absent when no entity resolver is registered; `requireEntityKey` falls back to
|
|
220
|
-
the slug there,
|
|
219
|
+
`makeEntityScope(request).requireEntityKey()` — never an id read from the token.
|
|
220
|
+
- `request.entity` is absent when no entity resolver is registered; `makeEntityScope(request).requireEntityKey()` falls back to
|
|
221
|
+
the slug there, `.requireEntity()` throws.
|
|
221
222
|
- A handler always answers 200 on success. The port comes from `cfg.services[cfg.service]`
|
|
222
223
|
(`internalPort ?? port ?? 80`).
|
|
223
224
|
- A `holdApiPort` bind failure must end the process with a non-zero exit.
|
|
@@ -229,7 +230,7 @@ code does not need it.
|
|
|
229
230
|
- [`@owlmeans/server-app`](../server-app) — application bootstrap and re-exports
|
|
230
231
|
- [`@owlmeans/server-socket`](../server-socket) — the WebSocket counterpart of `handlers`
|
|
231
232
|
- [`@owlmeans/entrypoint`](../entrypoint) — `contract`, `typed`, request/response types
|
|
232
|
-
- [`@owlmeans/auth-common`](../auth-common) — `requireEntityKey`, `attachEntity
|
|
233
|
+
- [`@owlmeans/auth-common`](../auth-common) — `makeEntityScope` (`requireEntityKey`, `attachEntity`), guard aliases
|
|
233
234
|
- [`@owlmeans/api`](../api) — the client that calls these endpoints from other services
|
|
234
235
|
|
|
235
236
|
<!-- owlmeans:agent-guidance:start -->
|
|
@@ -240,7 +241,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
240
241
|
your project's skill store (`.agents/skills/`):
|
|
241
242
|
|
|
242
243
|
```sh
|
|
243
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
244
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.51
|
|
244
245
|
```
|
|
245
246
|
|
|
246
247
|
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/server-api",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.52",
|
|
5
|
+
"generatedAt": "2026-10-06T11:45:57.650Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -7,7 +7,7 @@ user-invocable: false
|
|
|
7
7
|
|
|
8
8
|
# @owlmeans/server-api
|
|
9
9
|
|
|
10
|
-
**Install:** `bun add @owlmeans/server-api@^0.1.18-rc.
|
|
10
|
+
**Install:** `bun add @owlmeans/server-api@^0.1.18-rc.52`
|
|
11
11
|
|
|
12
12
|
Make handlers from the protocol declaration so input and output types stay coupled to the shared
|
|
13
13
|
contract:
|
|
@@ -65,7 +65,7 @@ that one route with `HandlerMisconfiguredError`, instead of the opaque
|
|
|
65
65
|
## The status a thrown error answers
|
|
66
66
|
|
|
67
67
|
A thrown error (or a rejected response) is answered with a body chosen by the exposure (§ Error
|
|
68
|
-
exposure) and a status from `errorStatus(error)` (`./utils`), resolved in this order:
|
|
68
|
+
exposure) and a status from `httpErrorHelper.errorStatus(error)` (`./utils`), resolved in this order:
|
|
69
69
|
|
|
70
70
|
| Error | Status |
|
|
71
71
|
|---|---|
|
|
@@ -90,14 +90,14 @@ exposure) and a status from `errorStatus(error)` (`./utils`), resolved in this o
|
|
|
90
90
|
- The auth branches win over a declaration, in that order (`AuthForbidden extends
|
|
91
91
|
AuthorizationError`, so 403 is tested first). An entitlement or permission refusal extends
|
|
92
92
|
`AuthForbidden` rather than declaring 403.
|
|
93
|
-
- `handleError` resolves the status on the error AS THROWN first, and asks the ENSURED
|
|
93
|
+
- `httpErrorHelper.handleError` resolves the status on the error AS THROWN first, and asks the ENSURED
|
|
94
94
|
(`ResilientError.ensure`) error only when that answers 500. The thrown object is the one whose
|
|
95
95
|
class is certainly what was raised; the rebuild is what gives a status to a marshalled error that
|
|
96
96
|
crossed a hop as a plain `Error`. `ensure` returns an error from any `@owlmeans/error` copy
|
|
97
97
|
untouched, so a development body keeps the thrown class's `type` (`AuthFailedError|||api:auth:…`) even in a
|
|
98
|
-
process holding duplicate module copies (`bun --preserve-symlinks`). `executeResponse` ensures
|
|
98
|
+
process holding duplicate module copies (`bun --preserve-symlinks`). `payloadHelper.executeResponse` ensures
|
|
99
99
|
nothing and answers the rejected error's status. `@owlmeans/server-socket` answers an upgrade
|
|
100
|
-
through the same `handleError`.
|
|
100
|
+
through the same `httpErrorHelper.handleError`.
|
|
101
101
|
- An auth family is recognised by `instanceof` OR by an exact registered type name — the instance's
|
|
102
102
|
`type` or any static `typeName` on its constructor chain — so a class from another module copy
|
|
103
103
|
answers the same status. Match whole names, never substrings: a subclass's `typeName` does not
|
|
@@ -117,7 +117,7 @@ than reaching through `request.original` in application code.
|
|
|
117
117
|
The server logs through `@owlmeans/log`, not a second pino: Fastify gets a pino-shaped adapter as its
|
|
118
118
|
`loggerInstance` (scope `http`) with its own request/response lines disabled. A request is one `debug`
|
|
119
119
|
record from `onResponse` (method, path without the query, status, ms). A failed request is logged once,
|
|
120
|
-
in `handleError`, by what it means: **5xx → `error`** (the error with its stack and the incident id),
|
|
120
|
+
in `httpErrorHelper.handleError`, by what it means: **5xx → `error`** (the error with its stack and the incident id),
|
|
121
121
|
**403 → `warn`, `event: 'access.forbidden'`**, 401 → `debug`, `event: 'auth.refused'`, any other 4xx →
|
|
122
122
|
`debug`. The level and format come from `cfg.log` (`/log`); access lines at info are
|
|
123
123
|
`cfg.log.debug: 'http'`.
|
|
@@ -129,7 +129,7 @@ An exact IAM `AuthForbidden` or `AccessError` refusal answers with
|
|
|
129
129
|
do not get this marker. The marker survives production exposure so browser clients can present a
|
|
130
130
|
permission message while keeping diagnostic bodies private.
|
|
131
131
|
|
|
132
|
-
`handleError` always assigns an incident UUID, attaches it to the logged error and returns it in the
|
|
132
|
+
`httpErrorHelper.handleError` always assigns an incident UUID, attaches it to the logged error and returns it in the
|
|
133
133
|
`X-Incident-ID` response header (`INCIDENT_ID_HEADER` in `./utils`, the same name and value
|
|
134
134
|
`@owlmeans/api` exports; exposed through CORS).
|
|
135
135
|
|
|
@@ -138,8 +138,8 @@ permission message while keeping diagnostic bodies private.
|
|
|
138
138
|
server log under the id.
|
|
139
139
|
- **Development** (an explicit `cfg.http.errors.exposure = 'development'`): the typed marshalled
|
|
140
140
|
form with message and stack, which the client rebuilds into its class.
|
|
141
|
-
- A client reads a production failure with `@owlmeans/api`'s `./status` subpath: `httpStatusOf(e)`
|
|
142
|
-
(the status a 428 or 409 is acted on by) and
|
|
141
|
+
- A client reads a production failure with `@owlmeans/api`'s `./status` subpath: `apiStatusHelper.httpStatusOf(e)`
|
|
142
|
+
(the status a 428 or 409 is acted on by) and `.incidentIdOf(e)` (the id a person reports). Keep
|
|
143
143
|
the default production-safe, and tell a client to report the incident id.
|
|
144
144
|
|
|
145
145
|
Do not use unbound compatibility handler wrappers. For a WebSocket route use
|
package/build/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assertContext, createService } from '@owlmeans/context';
|
|
2
|
-
import { canServeModule,
|
|
2
|
+
import { canServeModule, payloadHelper, createServerHandler, fixFormatDates } from './utils/index.js';
|
|
3
3
|
import { DEFAULT_ALIAS, CLOSED_HOST, PORT, OPENED_HOST } from './consts.js';
|
|
4
4
|
import { RouteMethod } from '@owlmeans/route';
|
|
5
5
|
import { provideResponse } from '@owlmeans/entrypoint';
|
|
@@ -119,13 +119,13 @@ export const createApiServer = (alias) => {
|
|
|
119
119
|
// An intermediate route can be created without a handler by the binding layer.
|
|
120
120
|
if (module.route.match(request, module.mount()) && module.handle != null) {
|
|
121
121
|
const response = provideResponse(reply);
|
|
122
|
-
const currentRequest = provideRequest(module.alias, request, true);
|
|
122
|
+
const currentRequest = payloadHelper.provideRequest(module.alias, request, true);
|
|
123
123
|
currentRequest.original._ctx = context;
|
|
124
124
|
const result = await module.handle(currentRequest, response);
|
|
125
125
|
if (result != null) {
|
|
126
126
|
context = result;
|
|
127
127
|
}
|
|
128
|
-
responded = executeResponse(response, reply, true) || responded;
|
|
128
|
+
responded = payloadHelper.executeResponse(response, reply, true) || responded;
|
|
129
129
|
}
|
|
130
130
|
return context;
|
|
131
131
|
}, Promise.resolve(context));
|
package/build/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Config, Context } from '../../types.js';
|
|
2
|
+
/** Carries the serving context on one raw request. */
|
|
3
|
+
export interface RequestContextHelper {
|
|
4
|
+
/** Stores the context on the request. */
|
|
5
|
+
populateContext: <C extends Config, T extends Context<C>>(context: T) => void;
|
|
6
|
+
/**
|
|
7
|
+
* The context stored on the request, else `ctx`.
|
|
8
|
+
*
|
|
9
|
+
* @throws {SyntaxError} when neither is there
|
|
10
|
+
*/
|
|
11
|
+
extractContext: <C extends Config, T extends Context<C>>(ctx?: T, location?: string) => T;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/context/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAErD,sDAAsD;AACtD,MAAM,WAAW,oBAAoB;IACnC,yCAAyC;IACzC,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,IAAI,CAAA;IAC7E;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,CAAC,CAAA;CAC1F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/context/types.ts"],"names":[],"mappings":""}
|
package/build/utils/context.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
1
|
+
import type { Request } from '../types.js';
|
|
2
|
+
import type { RequestContextHelper } from './context/types.js';
|
|
3
|
+
export declare const makeRequestContextHelper: (req: Request) => RequestContextHelper;
|
|
4
4
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,OAAO,EAAE,MAAM,aAAa,CAAA;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAE9D,eAAO,MAAM,wBAAwB,QAAS,OAAO,KAAG,oBAQvD,CAAA"}
|
package/build/utils/context.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { assertContext } from '@owlmeans/context';
|
|
2
2
|
import { DEFAULT_ALIAS } from '../consts.js';
|
|
3
|
-
export const
|
|
4
|
-
|
|
3
|
+
export const makeRequestContextHelper = (req) => {
|
|
4
|
+
const populateContext = (context) => void (req._ctx = context);
|
|
5
|
+
const extractContext = (ctx, location) => assertContext(req._ctx ?? ctx, location ?? DEFAULT_ALIAS);
|
|
6
|
+
return { populateContext, extractContext };
|
|
7
|
+
};
|
|
5
8
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAG5C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,GAAY,EAAwB,EAAE;IAC7E,MAAM,eAAe,GAAG,CAAyC,OAAU,EAAQ,EAAE,CACnF,KAAK,CAAE,GAAW,CAAC,IAAI,GAAG,OAAO,CAAC,CAAA;IAEpC,MAAM,cAAc,GAAG,CAAyC,GAAO,EAAE,QAAiB,EAAK,EAAE,CAC/F,aAAa,CAAQ,GAAW,CAAC,IAAI,IAAI,GAAG,EAAE,QAAQ,IAAI,aAAa,CAAC,CAAA;IAE1E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,CAAA;AAC5C,CAAC,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { FastifyReply } from 'fastify';
|
|
2
|
+
import type { Config, HttpErrorExposure } from '../../types.js';
|
|
3
|
+
import type { SerializedHttpError } from '../types.js';
|
|
4
|
+
/** How the HTTP boundary answers a thrown error: its status, its wire body, its headers and its log entry. */
|
|
5
|
+
export interface HttpErrorHelper {
|
|
6
|
+
/**
|
|
7
|
+
* The HTTP status an error's class declares, or `null` when it declares none that may be honoured.
|
|
8
|
+
*
|
|
9
|
+
* Read through the constructor chain — a static property is inherited, so a subclass answers what
|
|
10
|
+
* its nearest declaring ancestor says, and redeclares to change it. An integer 4xx is honoured
|
|
11
|
+
* directly. A 5xx is honoured only with `allowServerErrorStatus = true`, so a domain class must
|
|
12
|
+
* explicitly opt in to exposing a precise availability response. The read is structural, so a
|
|
13
|
+
* class from a duplicate module copy declares exactly what the imported one does.
|
|
14
|
+
*/
|
|
15
|
+
declaredErrorStatus: (error: unknown) => number | null;
|
|
16
|
+
/**
|
|
17
|
+
* The HTTP status an error is answered with, read off the error exactly as given.
|
|
18
|
+
*
|
|
19
|
+
* Two families reach here and both must be recognised. `AuthFailedError` / `AccessError` are this
|
|
20
|
+
* package's own, raised by the request pipeline itself. `AuthorizationError` / `AuthForbidden`
|
|
21
|
+
* come from `@owlmeans/auth` and are what the guards and gates actually throw — an unrecognised
|
|
22
|
+
* one answers 500, which reports a refused request as a crashed server: the client cannot tell
|
|
23
|
+
* "sign in again" from "the service is broken", and a consumer watching statuses concludes the
|
|
24
|
+
* application fell over. A family member is recognised by class OR by registered type name, so a
|
|
25
|
+
* class from a duplicate module copy answers the same status.
|
|
26
|
+
*
|
|
27
|
+
* **Order matters.** `AuthForbidden extends AuthorizationError`, so the 403 branch has to be
|
|
28
|
+
* tested first or every refusal of a permission is reported as a failure to authenticate. Both
|
|
29
|
+
* auth branches come before a class's own declaration, so an auth refusal can never be restated
|
|
30
|
+
* as something else. Everything that is neither an auth error nor a class declaring an allowed
|
|
31
|
+
* {@link HttpErrorHelper.declaredErrorStatus} answers 500.
|
|
32
|
+
*/
|
|
33
|
+
errorStatus: (error: unknown) => number;
|
|
34
|
+
/** Invalid or absent configuration always resolves to the production-safe policy. */
|
|
35
|
+
errorExposure: (config?: Pick<Config, 'http'>) => HttpErrorExposure;
|
|
36
|
+
/** One central wire shape for every server error. */
|
|
37
|
+
serializeError: (error: Error, exposure?: HttpErrorExposure) => SerializedHttpError;
|
|
38
|
+
/** Apply safe response metadata carried by an error without coupling its package to Fastify. */
|
|
39
|
+
applyErrorHeaders: (error: unknown, reply: FastifyReply) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Answer a thrown error: a status, and the marshalled `ResilientError` as the body.
|
|
42
|
+
*
|
|
43
|
+
* The status is resolved in two steps. The error AS THROWN comes first: it is the one object whose
|
|
44
|
+
* class is certainly the class that was raised, while `ResilientError.ensure` rebuilds through the
|
|
45
|
+
* registry of whichever `@owlmeans/error` copy this module loaded — under duplicate module copies
|
|
46
|
+
* that turns a perfectly recognisable auth refusal into a plain `ResilientError` answering 500.
|
|
47
|
+
* Only when the thrown error answers 500 is the ENSURED error asked, because the rebuild is what
|
|
48
|
+
* gives a status to a marshalled error that crossed a hop as a plain `Error`.
|
|
49
|
+
*/
|
|
50
|
+
handleError: (error: Error, reply: FastifyReply, exposure?: HttpErrorExposure) => void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/error/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEtD,8GAA8G;AAC9G,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,mBAAmB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAA;IACtD;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAA;IACvC,qFAAqF;IACrF,aAAa,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,iBAAiB,CAAA;IACnE,qDAAqD;IACrD,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,iBAAiB,KAAK,mBAAmB,CAAA;IACnF,gGAAgG;IAChG,iBAAiB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;IAChE;;;;;;;;;OASG;IACH,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAA;CACvF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/error/types.ts"],"names":[],"mappings":""}
|
package/build/utils/error.d.ts
CHANGED
|
@@ -1,49 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The HTTP status an error's class declares, or `null` when it declares none that may be honoured.
|
|
6
|
-
*
|
|
7
|
-
* Read through the constructor chain — a static property is inherited, so a subclass answers what
|
|
8
|
-
* its nearest declaring ancestor says, and redeclares to change it. An integer 4xx is honoured
|
|
9
|
-
* directly. A 5xx is honoured only with `allowServerErrorStatus = true`, so a domain class must
|
|
10
|
-
* explicitly opt in to exposing a precise availability response. The read is structural, so a
|
|
11
|
-
* class from a duplicate module copy declares exactly what the imported one does.
|
|
12
|
-
*/
|
|
13
|
-
export declare const declaredErrorStatus: (error: unknown) => number | null;
|
|
14
|
-
/**
|
|
15
|
-
* The HTTP status an error is answered with, read off the error exactly as given.
|
|
16
|
-
*
|
|
17
|
-
* Two families reach here and both must be recognised. `AuthFailedError` / `AccessError` are this
|
|
18
|
-
* package's own, raised by the request pipeline itself. `AuthorizationError` / `AuthForbidden`
|
|
19
|
-
* come from `@owlmeans/auth` and are what the guards and gates actually throw — an unrecognised
|
|
20
|
-
* one answers 500, which reports a refused request as a crashed server: the client cannot tell
|
|
21
|
-
* "sign in again" from "the service is broken", and a consumer watching statuses concludes the
|
|
22
|
-
* application fell over. A family member is recognised by class OR by registered type name
|
|
23
|
-
* ({@link typeNamesOf}), so a class from a duplicate module copy answers the same status.
|
|
24
|
-
*
|
|
25
|
-
* **Order matters.** `AuthForbidden extends AuthorizationError`, so the 403 branch has to be
|
|
26
|
-
* tested first or every refusal of a permission is reported as a failure to authenticate. Both
|
|
27
|
-
* auth branches come before a class's own declaration, so an auth refusal can never be restated
|
|
28
|
-
* as something else. Everything that is neither an auth error nor a class declaring an allowed
|
|
29
|
-
* {@link declaredErrorStatus} answers 500.
|
|
30
|
-
*/
|
|
1
|
+
import type { HttpErrorHelper } from './error/types.js';
|
|
2
|
+
export declare const createHttpErrorHelper: () => HttpErrorHelper;
|
|
3
|
+
export declare const httpErrorHelper: HttpErrorHelper;
|
|
4
|
+
/** @deprecated compat:factory-refactor — use `httpErrorHelper.errorStatus(…)` */
|
|
31
5
|
export declare const errorStatus: (error: unknown) => number;
|
|
32
|
-
/** Invalid or absent configuration always resolves to the production-safe policy. */
|
|
33
|
-
export declare const errorExposure: (config?: Pick<Config, 'http'>) => HttpErrorExposure;
|
|
34
|
-
/** One central wire shape for every server error. */
|
|
35
|
-
export declare const serializeError: (error: Error, exposure?: HttpErrorExposure) => SerializedHttpError;
|
|
36
|
-
/** Apply safe response metadata carried by an error without coupling its package to Fastify. */
|
|
37
|
-
export declare const applyErrorHeaders: (error: unknown, reply: FastifyReply) => void;
|
|
38
|
-
/**
|
|
39
|
-
* Answer a thrown error: a status, and the marshalled `ResilientError` as the body.
|
|
40
|
-
*
|
|
41
|
-
* The status is resolved in two steps. The error AS THROWN comes first: it is the one object whose
|
|
42
|
-
* class is certainly the class that was raised, while `ResilientError.ensure` rebuilds through the
|
|
43
|
-
* registry of whichever `@owlmeans/error` copy this module loaded — under duplicate module copies
|
|
44
|
-
* that turns a perfectly recognisable auth refusal into a plain `ResilientError` answering 500.
|
|
45
|
-
* Only when the thrown error answers 500 is the ENSURED error asked, because the rebuild is what
|
|
46
|
-
* gives a status to a marshalled error that crossed a hop as a plain `Error`.
|
|
47
|
-
*/
|
|
48
|
-
export declare const handleError: (error: Error, reply: FastifyReply, exposure?: HttpErrorExposure) => void;
|
|
49
6
|
//# sourceMappingURL=error.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAEvD,eAAO,MAAM,qBAAqB,QAAO,eAyKxC,CAAA;AAED,eAAO,MAAM,eAAe,iBAA0B,CAAA;AAEtD,iFAAiF;AACjF,eAAO,MAAM,WAAW,UAAW,OAAO,KAAG,MAA4C,CAAA"}
|