@owlmeans/api 0.1.18-rc.46 → 0.1.18-rc.48

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.
Files changed (59) hide show
  1. package/README.md +2 -2
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/api/SKILL.md +22 -20
  4. package/build/index.d.ts +2 -2
  5. package/build/index.d.ts.map +1 -1
  6. package/build/index.js +1 -1
  7. package/build/index.js.map +1 -1
  8. package/build/service.js +6 -6
  9. package/build/service.js.map +1 -1
  10. package/build/status/helper.d.ts +4 -0
  11. package/build/status/helper.d.ts.map +1 -0
  12. package/build/status/helper.js +49 -0
  13. package/build/status/helper.js.map +1 -0
  14. package/build/status/index.d.ts +3 -22
  15. package/build/status/index.d.ts.map +1 -1
  16. package/build/status/index.js +4 -61
  17. package/build/status/index.js.map +1 -1
  18. package/build/status/types.d.ts +24 -0
  19. package/build/status/types.d.ts.map +1 -1
  20. package/build/utils/body/types.d.ts +36 -0
  21. package/build/utils/body/types.d.ts.map +1 -0
  22. package/build/utils/{types.js.map → body/types.js.map} +1 -1
  23. package/build/utils/body.d.ts +3 -38
  24. package/build/utils/body.d.ts.map +1 -1
  25. package/build/utils/body.js +49 -66
  26. package/build/utils/body.js.map +1 -1
  27. package/build/utils/handler.d.ts +1 -1
  28. package/build/utils/handler.d.ts.map +1 -1
  29. package/build/utils/handler.js.map +1 -1
  30. package/build/utils/index.d.ts +2 -1
  31. package/build/utils/index.d.ts.map +1 -1
  32. package/build/utils/index.js +1 -1
  33. package/build/utils/index.js.map +1 -1
  34. package/build/utils/response/types.d.ts +15 -0
  35. package/build/utils/response/types.d.ts.map +1 -0
  36. package/build/utils/response/types.js +2 -0
  37. package/build/utils/response/types.js.map +1 -0
  38. package/build/utils/response.d.ts +4 -0
  39. package/build/utils/response.d.ts.map +1 -0
  40. package/build/utils/response.js +99 -0
  41. package/build/utils/response.js.map +1 -0
  42. package/package.json +11 -11
  43. package/src/index.ts +2 -2
  44. package/src/service.ts +6 -6
  45. package/src/status/helper.ts +63 -0
  46. package/src/status/index.ts +5 -76
  47. package/src/status/types.ts +25 -0
  48. package/src/utils/body/types.ts +37 -0
  49. package/src/utils/body.ts +50 -67
  50. package/src/utils/index.ts +2 -1
  51. package/src/utils/response/types.ts +15 -0
  52. package/src/utils/response.ts +117 -0
  53. package/tests/body.spec.ts +29 -29
  54. package/tests/handler.spec.ts +45 -45
  55. package/build/utils/types.d.ts +0 -11
  56. package/build/utils/types.d.ts.map +0 -1
  57. package/src/utils/handler.ts +0 -110
  58. package/src/utils/types.ts +0 -12
  59. /package/build/utils/{types.js → body/types.js} +0 -0
@@ -1,110 +0,0 @@
1
- import { type AbstractResponse, EntrypointOutcome } from '@owlmeans/entrypoint'
2
- import type { AxiosResponse } from 'axios'
3
- import {
4
- ACCEPTED, CREATED, FINISHED, FORBIDDEN_ERROR, INCIDENT_ID_HEADER, DENIAL_KIND_HEADER,
5
- ACCESS_DENIED_KIND, OK, SERVER_ERROR, UNAUTHORIZED_ERROR,
6
- } from '../consts.js'
7
- import { ResilientError } from '@owlmeans/error'
8
- import { ApiClientError, ApiStatusError, ServerAuthError, ServerCrashedError } from '../errors.js'
9
- import { isIncidentBody } from '../status/index.js'
10
- import type { ResponseStatusCarrier } from '../status/types.js'
11
- import { logger } from '@owlmeans/log'
12
-
13
- const log = logger('api')
14
-
15
- export const processResponse = (response: AxiosResponse, reply: AbstractResponse<any>) => {
16
- switch (response.status) {
17
- case OK:
18
- reply.resolve(response.data, EntrypointOutcome.Ok)
19
- return
20
- case ACCEPTED:
21
- reply.resolve(response.data, EntrypointOutcome.Accepted)
22
- return
23
- case CREATED:
24
- return processEmptyResponse(response, reply, EntrypointOutcome.Created)
25
- case FINISHED:
26
- return processEmptyResponse(response, reply, EntrypointOutcome.Finished)
27
- default:
28
- // A refusal is ordinary traffic (401, 403, 409, 428): debug, and never the headers.
29
- log.debug('Request answered with a failure', {
30
- status: response.status, statusText: response.statusText, url: response.config?.url,
31
- incidentId: headerOf(response.headers, INCIDENT_ID_HEADER),
32
- })
33
-
34
- reply.reject(failureOf(response))
35
- }
36
- }
37
-
38
- /**
39
- * The error a non-2xx answer rejects with — always carrying the HTTP status and, when the server
40
- * sent one, its incident id.
41
- *
42
- * A development body is the marshaled `ResilientError`: it is rebuilt into its own class and
43
- * stamped with `responseStatus`. Anything else — the bare incident id of a production body, a
44
- * proxy's HTML, a framework's JSON — becomes the status error of {@link statusError}.
45
- */
46
- const failureOf = (response: AxiosResponse): Error => {
47
- const incidentId = headerOf(response.headers, INCIDENT_ID_HEADER)
48
- ?? (isIncidentBody(response.data) ? response.data.trim() : undefined)
49
- const denialKind = response.status === FORBIDDEN_ERROR
50
- && headerOf(response.headers, DENIAL_KIND_HEADER) === ACCESS_DENIED_KIND
51
- ? ACCESS_DENIED_KIND : undefined
52
-
53
- if (typeof response.data === 'string' && response.data.includes(ResilientError.separator)) {
54
- try {
55
- const error = ResilientError.ensure(response.data, true)
56
- error.incidentId ??= incidentId
57
- Object.assign(error, {
58
- responseStatus: response.status, denialKind,
59
- } satisfies ResponseStatusCarrier)
60
-
61
- return error
62
- } catch {
63
- log.warn('Server returned an unrecognizable text error', { status: response.status, body: response.data })
64
- }
65
- }
66
-
67
- return Object.assign(statusError(response.status, incidentId), { denialKind })
68
- }
69
-
70
- /**
71
- * The typed error of a bare status: `ServerCrashedError` (500), `ServerAuthError` (401),
72
- * `ApiClientError('forbidden[:<id>]')` (403), `ApiStatusError` (`api:client:status:<n>[:<id>]`)
73
- * for every other one.
74
- */
75
- export const statusError = (status: number, incidentId?: string): ApiClientError => {
76
- const error = status === SERVER_ERROR ? new ServerCrashedError(incidentId)
77
- : status === UNAUTHORIZED_ERROR ? new ServerAuthError(incidentId)
78
- : status === FORBIDDEN_ERROR ? new ApiClientError(incidentId != null ? `forbidden:${incidentId}` : 'forbidden')
79
- : new ApiStatusError(status, incidentId)
80
- if (incidentId != null) {
81
- error.incidentId = incidentId
82
- }
83
-
84
- return Object.assign(error, { responseStatus: status } satisfies ResponseStatusCarrier)
85
- }
86
-
87
- /** One response header, from an `AxiosHeaders` instance or a plain header object alike. */
88
- const headerOf = (headers: unknown, name: string): string | undefined => {
89
- if (headers == null || typeof headers !== 'object') {
90
- return undefined
91
- }
92
- const get = (headers as { get?: unknown }).get
93
- const viaGet = typeof get === 'function' ? get.call(headers, name) : undefined
94
- const value = viaGet ?? Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase())?.[1]
95
- const first = Array.isArray(value) ? value[0] : value
96
-
97
- return typeof first === 'string' && first.trim() !== '' ? first.trim() : undefined
98
- }
99
-
100
- const processEmptyResponse = (response: AxiosResponse, reply: AbstractResponse<any>, outcome: EntrypointOutcome) => {
101
- if (response.data != null && response.data != '') {
102
- reply.resolve(response.data, outcome)
103
- return
104
- }
105
- if (response.headers.toJSON != null && typeof response.headers.toJSON === 'function') {
106
- reply.resolve(response.headers.toJSON(), outcome)
107
- return
108
- }
109
- reply.resolve(response.headers, outcome)
110
- }
@@ -1,12 +0,0 @@
1
- import type { createBodyHelper } from './body.js'
2
-
3
- export interface RequestBody {
4
- /** What axios is handed as `data`. */
5
- data: unknown
6
- /** A `content-type` the request lacked and must carry. */
7
- contentType?: string
8
- /** `data` is final text — axios must not transform it again. */
9
- verbatim: boolean
10
- }
11
-
12
- export type BodyHelper = ReturnType<typeof createBodyHelper>
File without changes