@nxgt/datasource-rest 1.0.2 → 1.0.3
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 +72 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,9 +4,6 @@ An Apollo-style REST datasource over `openapi-fetch`: auth forwarding, caching
|
|
|
4
4
|
and error translation, so a GraphQL resolver can call a REST service with the
|
|
5
5
|
same typed client the REST apps use.
|
|
6
6
|
|
|
7
|
-
Errors come back as `CustomException` from `@nxgt/shared-exceptions`, so a
|
|
8
|
-
downstream 404 surfaces as a `NotFound` rather than a transport failure.
|
|
9
|
-
|
|
10
7
|
## Install
|
|
11
8
|
|
|
12
9
|
```bash
|
|
@@ -16,3 +13,75 @@ bun add @nxgt/datasource-rest
|
|
|
16
13
|
Public on npmjs; no token needed to install. TypeScript is a peer, pinned to
|
|
17
14
|
`^6.0.3` across every `@nxgt/*` package — the set is unsatisfiable if one of
|
|
18
15
|
them widens it.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { RESTDataSource, errorToException } from '@nxgt/datasource-rest';
|
|
21
|
+
import createClient from '@nxgt/shared-hono/openapi-fetch';
|
|
22
|
+
|
|
23
|
+
const client = createClient<paths>({ baseUrl: env.BOOKMARKS_API_URL });
|
|
24
|
+
|
|
25
|
+
const bookmarks = new RESTDataSource({
|
|
26
|
+
client,
|
|
27
|
+
authOptions: { token: () => getAccessToken() },
|
|
28
|
+
cacheOptions: { ttl: 5_000 },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const { data } = await bookmarks.get('/bookmarks/{id}', {
|
|
32
|
+
params: { path: { id } },
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`get` / `post` / `put` / `patch` / `delete` / `head` / `options` / `trace` are
|
|
37
|
+
the client's methods, rebound. Auth and cache are `openapi-fetch` middleware
|
|
38
|
+
installed in the constructor, cache first, then auth.
|
|
39
|
+
|
|
40
|
+
## Auth middleware
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
authOptions: {
|
|
44
|
+
token: string | (() => Promise<string>),
|
|
45
|
+
shouldUseToken?: (request: Request) => boolean,
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The thunk is called per request. `shouldUseToken` skips the header on the
|
|
50
|
+
requests you name. No `token` means the middleware is a no-op.
|
|
51
|
+
|
|
52
|
+
## Cache middleware
|
|
53
|
+
|
|
54
|
+
In-process `Map`, keyed by `method:url`. Default TTL is five minutes. GET
|
|
55
|
+
(and any other non-POST) responses that are `ok` are stored. POST is cached
|
|
56
|
+
only when `shouldCachePostRequest` says so — the default is "the URL contains
|
|
57
|
+
`/search`".
|
|
58
|
+
|
|
59
|
+
This is a process cache, not Redis. Two instances of the datasource do not
|
|
60
|
+
share it.
|
|
61
|
+
|
|
62
|
+
## Errors
|
|
63
|
+
|
|
64
|
+
`errorToException(error, response)` maps HTTP status to `CustomException`:
|
|
65
|
+
|
|
66
|
+
| Status | `ErrorCode` |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| 401 | `Unauthenticated` |
|
|
69
|
+
| 403 | `Forbidden` |
|
|
70
|
+
| 404 | `NotFound` |
|
|
71
|
+
| 500 | `InternalServerError` |
|
|
72
|
+
| other | `BadRequest` |
|
|
73
|
+
|
|
74
|
+
A downstream 404 is `NotFound`, not a transport failure. Catch
|
|
75
|
+
`CustomException`, not an error named after the HTTP library.
|
|
76
|
+
|
|
77
|
+
`relayPaginate(data)` turns a REST `{ data, metadata }` page into a Relay
|
|
78
|
+
`{ edges, pageInfo }` connection, using `item.id` as the cursor.
|
|
79
|
+
|
|
80
|
+
## Things that bite
|
|
81
|
+
|
|
82
|
+
- **The cache is per process and unbounded except by TTL.** Do not point it at
|
|
83
|
+
an endpoint that varies by caller unless `shouldUseToken` / the URL already
|
|
84
|
+
distinguish them.
|
|
85
|
+
- **`authOptions.token` as a thunk is not awaited by the middleware today.**
|
|
86
|
+
Pass a string, or a thunk that returns a string synchronously, until that
|
|
87
|
+
is a real `async` `onRequest`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/datasource-rest",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"lodash": "^4.18.1",
|
|
41
|
-
"@nxgt/shared": "^1.0.
|
|
42
|
-
"@nxgt/shared-exceptions": "^1.0.
|
|
41
|
+
"@nxgt/shared": "^1.0.2",
|
|
42
|
+
"@nxgt/shared-exceptions": "^1.0.2",
|
|
43
43
|
"openapi-fetch": "^0.17.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|