@owlmeans/api 0.1.18-rc.40 → 0.1.18-rc.41
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 +1 -1
- package/package.json +6 -5
- package/tests/handler.spec.ts +36 -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.41
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Usage
|
|
@@ -65,7 +65,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
65
65
|
your project's skill store (`.agents/skills/`):
|
|
66
66
|
|
|
67
67
|
```sh
|
|
68
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
68
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.42
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
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-09-
|
|
4
|
+
"version": "0.1.18-rc.41",
|
|
5
|
+
"generatedAt": "2026-09-29T08:01:58.146Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/api",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.41",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@owlmeans/auth-common": "^0.1.18-rc.
|
|
33
|
-
"@owlmeans/client-config": "^0.1.18-rc.
|
|
34
|
-
"@owlmeans/client-route": "^0.1.18-rc.
|
|
35
|
-
"@owlmeans/config": "^0.1.18-rc.
|
|
32
|
+
"@owlmeans/auth-common": "^0.1.18-rc.41",
|
|
33
|
+
"@owlmeans/client-config": "^0.1.18-rc.39",
|
|
34
|
+
"@owlmeans/client-route": "^0.1.18-rc.42",
|
|
35
|
+
"@owlmeans/config": "^0.1.18-rc.39",
|
|
36
36
|
"@owlmeans/context": "^0.1.18-rc.32",
|
|
37
37
|
"@owlmeans/error": "^0.1.18-rc.36",
|
|
38
38
|
"@owlmeans/entrypoint": "^0.1.18-rc.37",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@owlmeans/dep-config": "workspace:*",
|
|
45
|
+
"@owlmeans/resource": "^0.1.18-rc.37",
|
|
45
46
|
"@types/qs": "^6.9.16",
|
|
46
47
|
"nodemon": "^3.1.14",
|
|
47
48
|
"typescript": "^7.0.2"
|
package/tests/handler.spec.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { AxiosResponse } from 'axios'
|
|
|
4
4
|
import type { AbstractResponse } from '@owlmeans/entrypoint'
|
|
5
5
|
import { EntrypointOutcome } from '@owlmeans/entrypoint'
|
|
6
6
|
import { ResilientError } from '@owlmeans/error'
|
|
7
|
+
import { RecordExists, UnknownRecordError } from '@owlmeans/resource'
|
|
7
8
|
import {
|
|
8
9
|
ApiClientError, ApiStatusError, ServerAuthError, ServerCrashedError, httpStatusOf, incidentIdOf,
|
|
9
10
|
INCIDENT_ID_HEADER,
|
|
@@ -143,6 +144,41 @@ describe('a development body stays its typed class', () => {
|
|
|
143
144
|
expect(error.status).toBe(409)
|
|
144
145
|
expect(error.incidentId).toBe(INCIDENT)
|
|
145
146
|
})
|
|
147
|
+
|
|
148
|
+
test('a storage refusal (404 absent record, 409 taken key) rebuilds into its own class', () => {
|
|
149
|
+
for (const [refusal, code] of [
|
|
150
|
+
[new UnknownRecordError('shelf/3'), 404], [new RecordExists('isbn'), 409],
|
|
151
|
+
] as const) {
|
|
152
|
+
const body = ResilientError.marshal(refusal, { includeStack: true, incidentId: INCIDENT }).message
|
|
153
|
+
const { error } = respond(code, body, { [INCIDENT_ID_HEADER]: INCIDENT })
|
|
154
|
+
expect(error!.constructor).toBe(refusal.constructor)
|
|
155
|
+
expect(error!.message).toBe(refusal.message)
|
|
156
|
+
expect(httpStatusOf(error)).toBe(code)
|
|
157
|
+
expect(incidentIdOf(error)).toBe(INCIDENT)
|
|
158
|
+
}
|
|
159
|
+
const body = ResilientError.marshal(new UnknownRecordError('shelf/3')).message
|
|
160
|
+
expect((respond(404, body).error as UnknownRecordError).id).toBe('shelf/3')
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test('a class this process never registered still answers the status the server sent', () => {
|
|
164
|
+
const body = `ApiSpecUnregisteredRefusal${ResilientError.separator}spec:unregistered:x`
|
|
165
|
+
const { error } = respond(404, body, { [INCIDENT_ID_HEADER]: INCIDENT })
|
|
166
|
+
expect(error).not.toBeInstanceOf(ServerCrashedError)
|
|
167
|
+
expect(httpStatusOf(error)).toBe(404)
|
|
168
|
+
expect(incidentIdOf(error)).toBe(INCIDENT)
|
|
169
|
+
})
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
describe('a production body of a storage refusal keeps the declared status', () => {
|
|
173
|
+
test('404 and 409 become status errors, not a crash', () => {
|
|
174
|
+
for (const code of [404, 409]) {
|
|
175
|
+
const { error } = respond(code, INCIDENT)
|
|
176
|
+
expect(error).toBeInstanceOf(ApiStatusError)
|
|
177
|
+
expect(error).not.toBeInstanceOf(ServerCrashedError)
|
|
178
|
+
expect(error!.message).toBe(`api:client:status:${code}:${INCIDENT}`)
|
|
179
|
+
expect(httpStatusOf(error)).toBe(code)
|
|
180
|
+
}
|
|
181
|
+
})
|
|
146
182
|
})
|
|
147
183
|
|
|
148
184
|
describe('marshal round trips', () => {
|