@nxgt/datasource-rest 2.0.0 → 3.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Steve Tsala
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -29,9 +29,8 @@ request:
29
29
  ```ts
30
30
  import { RESTDataSource } from '@nxgt/datasource-rest';
31
31
  import { operations } from './generated/bookmarks/operations.js';
32
- import type { ClientOperations } from './generated/bookmarks/types.js';
33
32
 
34
- export class Bookmarks extends RESTDataSource<ClientOperations> {
33
+ export class Bookmarks extends RESTDataSource.for(operations) {
35
34
  bookmark(id: string) {
36
35
  return this.data(this.get('/bookmarks/{id}', { param: { id } }));
37
36
  }
@@ -43,18 +42,24 @@ export class Bookmarks extends RESTDataSource<ClientOperations> {
43
42
  // Per request, in the GraphQL context:
44
43
  const bookmarks = new Bookmarks({
45
44
  baseUrl: 'https://bookmarks.example.com',
46
- operations,
47
45
  token: () => context.token,
48
46
  });
49
47
  ```
50
48
 
49
+ - **`RESTDataSource.for(operations)`** is the class bound to the generated
50
+ table, whose types it takes from it. The same without it:
51
+ `extends RESTDataSource<ClientOperations>`, with `operations` passed to the
52
+ constructor.
53
+ - **It validates and decodes by default**, as its client does: the request
54
+ before it is sent, and each reply as its schema outputs it.
55
+ `validate: false` and `decode: false` turn that off.
51
56
  - **`this.get`, `this.post`, `this.query`…** call the operation at a path,
52
57
  typed by the spec. There is one for each method the spec has an operation
53
58
  for, and it offers only the paths that method has. Each call resolves to
54
59
  one of the declared replies, narrowed on its status.
55
60
  - **`this.api`** is the bound client they come from, for `op(operationId)`,
56
- `stream()` and `group()`. The shorthands are getters on the class, so a
57
- subclass's own method of the same name wins.
61
+ `stream()` and `group()`. The shorthands are set on each datasource, for
62
+ the spec's methods only, so a subclass's own method of the same name wins.
58
63
  - **`this.data(call)`** returns the data of a 2xx reply. Any other reply, or
59
64
  none, throws a `DataSourceError`.
60
65
 
@@ -95,8 +100,8 @@ its `extensions`, `{ code, status }`, with the error a resolver throws.
95
100
  | any 5xx | `INTERNAL_SERVER_ERROR` |
96
101
  | any other status | `BAD_REQUEST` |
97
102
  | no reply: network, timeout | `SERVICE_UNAVAILABLE` |
98
- | a request `validate` refuses | `BAD_REQUEST` |
99
- | a reply `validate` refuses | `INTERNAL_SERVER_ERROR` |
103
+ | a request `validate` refuses, with its `issues` | `BAD_REQUEST` |
104
+ | a reply `validate` or `decode` refuses, with its `issues` | `INTERNAL_SERVER_ERROR` |
100
105
  | anything else thrown | `INTERNAL_SERVER_ERROR` |
101
106
 
102
107
  Its message is the reply body's `message`, when it has a non-empty one. For
@@ -144,9 +149,10 @@ export class Bookmarks extends RESTDataSource<ClientOperations> {
144
149
  class RESTDataSource<
145
150
  Ops extends OperationsShape<Ops>, // ClientOperations, generated
146
151
  Routes = RoutesOf<Ops>,
147
- Decoded extends boolean = false,
152
+ Decoded extends boolean = true,
148
153
  > {
149
154
  constructor(options: RESTDataSourceOptions<Ops> & { decode?: Decoded });
155
+ static for(operations: OperationTable<Ops>, options?: { decode?: boolean }): BoundDataSource<Ops, Decoded>;
150
156
  readonly api: OpenApiClient<Ops, Routes, Decoded>;
151
157
  data<R extends { readonly status: number; readonly data: unknown }>(
152
158
  call: Promise<R>,
@@ -157,8 +163,8 @@ class RESTDataSource<
157
163
 
158
164
  The class to extend, one per service; see [Usage](#usage). `RESTDataSource`
159
165
  is both a constructor and a type, the datasource's own members and the
160
- spec's path methods. With `Decoded` set to `true`, the options require
161
- `decode: true`.
166
+ spec's path methods. With `Decoded` set to `false`, the options require
167
+ `decode: false`.
162
168
 
163
169
  | Option | Type | Default | Description |
164
170
  | --- | --- | --- | --- |
@@ -167,14 +173,30 @@ spec's path methods. With `Decoded` set to `true`, the options require
167
173
  | `token` | `string \| null \| undefined \| (() => … \| Promise<…>)` | none | Sent as `Authorization: Bearer <token>`. A function is read, and awaited, before each request. None, or a nullish result, sends no header. |
168
174
  | `cache` | `Cache \| false` | `defaultCache` | The replies cache: your own `cache()` from `@nxgt/httpyz`, or `false` for none. See [Cache](#cache). |
169
175
  | `http` | `Omit<HttpClientOptions, 'baseUrl' \| 'auth'>` | `{}` | What else the core client takes: `headers`, `timeout`, `retry`, `use`, `fetch`… Its `use` runs inside the cache. |
170
- | `validate` | `boolean \| { request?: boolean; response?: boolean }` | neither | Checks the request and the reply with the spec's schemas, as `createOpenApiClient` does. |
171
- | `decode` | `Decoded` | `false` | `true` returns each reply as its schema outputs it. |
176
+ | `validate` | `boolean \| { request?: boolean; response?: boolean }` | both | Checks the request and the reply with the spec's schemas, as `createOpenApiClient` does. `false`: neither. |
177
+ | `decode` | `Decoded` | `true` | Returns each reply as its schema outputs it. `false` returns it as JSON carries it. |
172
178
 
173
179
  | Member | Type | Description |
174
180
  | --- | --- | --- |
175
181
  | `api` | `OpenApiClient<Ops, Routes, Decoded>` | The client bound to the spec, for `op()`, `stream()`, `group()` and `operations`. |
176
182
  | `data(call)` | `Promise<Success<R>['data']>` | The data of `call`'s 2xx reply. Any other reply, or none, throws a `DataSourceError`; an abort is rethrown as it is. The body of a status the spec does not declare is read for its message. |
177
- | `get`, `put`, `post`, `delete`, `options`, `head`, `patch`, `trace`, `query` | `PathMethods<Ops, Routes, Decoded>[M]` | `this.api[method]`, for the methods the spec has an operation for only: `(path, ...args) => Promise<reply>`. Getters on the prototype, so a subclass's method of the same name wins. |
183
+ | `get`, `put`, `post`, `delete`, `options`, `head`, `patch`, `trace`, `query` | `PathMethods<Ops, Routes, Decoded>[M]` | `this.api[method]`, for the methods the spec has an operation for only, in the types and at runtime: `(path, ...args) => Promise<reply>`. Set on each datasource, so a subclass's method of the same name wins. |
184
+
185
+ #### `RESTDataSource.for`
186
+
187
+ ```ts
188
+ RESTDataSource.for<Ops extends OperationsShape<Ops>>(operations: OperationTable<Ops>): BoundDataSource<Ops, true>;
189
+ RESTDataSource.for<Ops extends OperationsShape<Ops>>(
190
+ operations: OperationTable<Ops>,
191
+ options: { readonly decode: false },
192
+ ): BoundDataSource<Ops, false>;
193
+ ```
194
+
195
+ A datasource class bound to the generated `operations` table, which takes
196
+ its types from it: `class Bookmarks extends RESTDataSource.for(operations)`,
197
+ with no `ClientOperations` to import. Its constructor takes every option but
198
+ `operations`. With `{ decode: false }`, its replies are returned as JSON
199
+ carries them. See [Usage](#usage).
178
200
 
179
201
  #### `DataSourceError`
180
202
 
@@ -185,6 +207,7 @@ class DataSourceError extends Error {
185
207
  readonly code: DataSourceErrorCode;
186
208
  readonly status: number | undefined;
187
209
  readonly data: unknown;
210
+ readonly issues: readonly ValidationIssue[] | undefined;
188
211
  readonly extensions: {
189
212
  readonly code: DataSourceErrorCode;
190
213
  readonly status: number | undefined;
@@ -201,7 +224,8 @@ passes `cause`, and any other `ErrorOptions`, on to `Error`.
201
224
  | `message` | `string` | The reply body's `message`, or the client error's; `'An error occurred'` when what was thrown is not an `Error`. |
202
225
  | `code` | `DataSourceErrorCode` | What failed, from the reply's status or the lack of one. |
203
226
  | `status` | `number \| undefined` | The status of the service's reply; none when no reply came back. |
204
- | `data` | `unknown` | The reply's body, as the service sent it, or the issues of a `validate` check that failed. |
227
+ | `data` | `unknown` | The reply's body, as the service sent it; none when no reply was read. |
228
+ | `issues` | `readonly ValidationIssue[] \| undefined` | What a `validate` or `decode` check refused, in the request or the reply, as `@nxgt/httpyz` has them; none otherwise. |
205
229
  | `extensions` | `{ code, status }` | What a GraphQL server reports with the error: graphql-js reads `extensions` off the error a resolver throws. |
206
230
  | `cause` | `unknown` | What was thrown, when `toDataSourceError` made the error: the client's own error, or anything else. |
207
231
 
@@ -271,6 +295,17 @@ interface RESTDataSourceOptions<Ops> extends OpenApiOptions {
271
295
  What the `RESTDataSource` constructor takes, with `decode`; each option is in
272
296
  [its table](#restdatasource).
273
297
 
298
+ #### `BoundDataSource`
299
+
300
+ ```ts
301
+ type BoundDataSource<Ops extends OperationsShape<Ops>, Decoded extends boolean = true> = new (
302
+ options: Omit<RESTDataSourceOptions<Ops>, 'operations'>,
303
+ ) => RESTDataSource<Ops, RoutesOf<Ops>, Decoded>;
304
+ ```
305
+
306
+ What [`RESTDataSource.for`](#restdatasourcefor) returns: a datasource class
307
+ bound to its table, to extend.
308
+
274
309
  #### `DataSourceErrorCode`
275
310
 
276
311
  ```ts
@@ -292,6 +327,7 @@ interface DataSourceErrorOptions extends ErrorOptions {
292
327
  readonly code: DataSourceErrorCode;
293
328
  readonly status?: number | undefined;
294
329
  readonly data?: unknown;
330
+ readonly issues?: readonly ValidationIssue[] | undefined;
295
331
  }
296
332
  ```
297
333
 
@@ -30,16 +30,26 @@ export interface RESTDataSourceOptions<Ops> extends OpenApiOptions {
30
30
  /** What else the core client takes: `headers`, `timeout`, `retry`, `use`, `fetch`… */
31
31
  http?: Omit<HttpClientOptions, 'baseUrl' | 'auth'>;
32
32
  }
33
- /** `decode`, as the binding takes it: a datasource typed as decoding must decode. */
33
+ /** `decode`, as the binding takes it: a datasource typed as not decoding must say `decode: false`. */
34
34
  type Decoding<Decoded extends boolean> = {
35
35
  readonly decode?: Decoded;
36
- } & (Decoded extends true ? {
37
- readonly decode: true;
36
+ } & (Decoded extends false ? {
37
+ readonly decode: false;
38
38
  } : unknown);
39
39
  /** The datasource's own members; `RESTDataSource` adds the client's path methods. */
40
40
  declare class DataSource<Ops extends OperationsShape<Ops>, Routes, Decoded extends boolean> {
41
41
  /** The client bound to the spec, for `op()`, `stream()` and `group()`. */
42
42
  readonly api: OpenApiClient<Ops, Routes, Decoded>;
43
+ /**
44
+ * A datasource class bound to `operations`, whose types it takes from the
45
+ * generated table: no `ClientOperations` to import. Its constructor takes
46
+ * the other options.
47
+ */
48
+ static for(operations: object, fixed?: {
49
+ readonly decode?: boolean;
50
+ }): {
51
+ new (options: object): {};
52
+ };
43
53
  constructor(options: RESTDataSourceOptions<Ops> & Decoding<Decoded>);
44
54
  /**
45
55
  * The data of a call's 2xx reply. Any other reply, or none, throws a
@@ -56,15 +66,30 @@ declare class DataSource<Ops extends OperationsShape<Ops>, Routes, Decoded exten
56
66
  * an operation for. Extend it with the calls a resolver makes:
57
67
  *
58
68
  * ```ts
59
- * class Bookmarks extends RESTDataSource<ClientOperations> {
69
+ * class Bookmarks extends RESTDataSource.for(operations) {
60
70
  * bookmark(id: string) {
61
71
  * return this.data(this.get('/bookmarks/{id}', { param: { id } }));
62
72
  * }
63
73
  * }
64
- * new Bookmarks({ baseUrl, operations, token: () => context.token });
74
+ * new Bookmarks({ baseUrl, token: () => context.token });
65
75
  * ```
66
76
  */
67
- export type RESTDataSource<Ops extends OperationsShape<Ops>, Routes = RoutesOf<Ops>, Decoded extends boolean = false> = DataSource<Ops, Routes, Decoded> & PathMethods<Ops, Routes, Decoded>;
68
- export declare const RESTDataSource: new <Ops extends OperationsShape<Ops>, Routes = RoutesOf<Ops>, Decoded extends boolean = false>(options: RESTDataSourceOptions<Ops> & Decoding<Decoded>) => RESTDataSource<Ops, Routes, Decoded>;
77
+ export type RESTDataSource<Ops extends OperationsShape<Ops>, Routes = RoutesOf<Ops>, Decoded extends boolean = true> = DataSource<Ops, Routes, Decoded> & PathMethods<Ops, Routes, Decoded>;
78
+ /** What `RESTDataSource.for(operations)` returns: a datasource class bound to the table. */
79
+ export type BoundDataSource<Ops extends OperationsShape<Ops>, Decoded extends boolean = true> = new (options: Omit<RESTDataSourceOptions<Ops>, 'operations'>) => RESTDataSource<Ops, RoutesOf<Ops>, Decoded>;
80
+ export declare const RESTDataSource: {
81
+ new <Ops extends OperationsShape<Ops>, Routes = RoutesOf<Ops>, Decoded extends boolean = true>(options: RESTDataSourceOptions<Ops> & Decoding<Decoded>): RESTDataSource<Ops, Routes, Decoded>;
82
+ /**
83
+ * A datasource class bound to `operations`, whose types it takes from the
84
+ * generated table: `class Bookmarks extends RESTDataSource.for(operations)`.
85
+ * `{ decode: false }` returns the replies as JSON carries them.
86
+ */
87
+ for<Ops extends OperationsShape<Ops>>(operations: OperationTable<Ops>, options: {
88
+ readonly decode: false;
89
+ }): BoundDataSource<Ops, false>;
90
+ for<Ops extends OperationsShape<Ops>>(operations: OperationTable<Ops>, options?: {
91
+ readonly decode?: true;
92
+ }): BoundDataSource<Ops, true>;
93
+ };
69
94
  export {};
70
95
  //# sourceMappingURL=rest-datasource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rest-datasource.d.ts","sourceRoot":"","sources":["../../src/datasource/rest-datasource.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACN,KAAK,KAAK,EAEV,KAAK,iBAAiB,EAItB,KAAK,OAAO,EAEZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EAGN,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,MAAM,sBAAsB,CAAC;AAG9B,KAAK,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,KAAiB,CAAC;AAE7C,MAAM,WAAW,qBAAqB,CAAC,GAAG,CAAE,SAAQ,cAAc;IACjE,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,UAAU,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;IAChC;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,GAAG,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/C,0EAA0E;IAC1E,KAAK,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACtB,sFAAsF;IACtF,IAAI,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC;CACnD;AAED,qFAAqF;AACrF,KAAK,QAAQ,CAAC,OAAO,SAAS,OAAO,IAAI;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,CAAC,OAAO,SAAS,IAAI,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC;AAEjE,qFAAqF;AACrF,cAAM,UAAU,CACf,GAAG,SAAS,eAAe,CAAC,GAAG,CAAC,EAChC,MAAM,EACN,OAAO,SAAS,OAAO;IAEvB,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEtC,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC;IA4BnE;;;OAGG;IACG,IAAI,CAAC,CAAC,SAAS;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,EACvE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACd,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CAa9B;AAaD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,CACzB,GAAG,SAAS,eAAe,CAAC,GAAG,CAAC,EAChC,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,EACtB,OAAO,SAAS,OAAO,GAAG,KAAK,IAC5B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAEzE,eAAO,MAAM,cAAc,EAA4B,KACtD,GAAG,SAAS,eAAe,CAAC,GAAG,CAAC,EAChC,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,EACtB,OAAO,SAAS,OAAO,GAAG,KAAK,EAE/B,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,KACnD,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"rest-datasource.d.ts","sourceRoot":"","sources":["../../src/datasource/rest-datasource.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,25 @@
1
+ /**
2
+ * `DataSourceError`: every way a call to a service can fail, as one error
3
+ * with a code a GraphQL server reports. It is the package's own, and depends
4
+ * on no exception package of the app's: map it to yours where you catch it.
5
+ */
6
+ import { type ValidationIssue } from '@nxgt/httpyz';
1
7
  export type DataSourceErrorCode = 'BAD_REQUEST' | 'UNAUTHENTICATED' | 'FORBIDDEN' | 'NOT_FOUND' | 'INTERNAL_SERVER_ERROR' | 'SERVICE_UNAVAILABLE';
2
8
  export interface DataSourceErrorOptions extends ErrorOptions {
3
9
  readonly code: DataSourceErrorCode;
4
10
  readonly status?: number | undefined;
5
11
  readonly data?: unknown;
12
+ readonly issues?: readonly ValidationIssue[] | undefined;
6
13
  }
7
14
  export declare class DataSourceError extends Error {
8
15
  readonly name = "DataSourceError";
9
16
  readonly code: DataSourceErrorCode;
10
17
  /** The status of the service's reply; none when no reply came back. */
11
18
  readonly status: number | undefined;
12
- /** The body of the service's reply, as it sent it, or the issues of a check that failed. */
19
+ /** The body of the service's reply, as it sent it; none when no reply was read. */
13
20
  readonly data: unknown;
21
+ /** What a `validate` check refused, in the request or the reply; none otherwise. */
22
+ readonly issues: readonly ValidationIssue[] | undefined;
14
23
  /**
15
24
  * What a GraphQL server reports with the error: graphql-js reads
16
25
  * `extensions` off the error a resolver throws.
@@ -19,7 +28,7 @@ export declare class DataSourceError extends Error {
19
28
  readonly code: DataSourceErrorCode;
20
29
  readonly status: number | undefined;
21
30
  };
22
- constructor(message: string, { code, status, data, ...options }: DataSourceErrorOptions);
31
+ constructor(message: string, { code, status, data, issues, ...options }: DataSourceErrorOptions);
23
32
  }
24
33
  /** The code of a reply's status: any 5xx is the service's failure, any other 4xx a bad request. */
25
34
  export declare function codeOf(status: number): DataSourceErrorCode;
@@ -1 +1 @@
1
- {"version":3,"file":"data-source-error.d.ts","sourceRoot":"","sources":["../../src/errors/data-source-error.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,mBAAmB,GAC5B,aAAa,GACb,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,qBAAqB,CAAC;AAEzB,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC3D,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACzC,SAAkB,IAAI,qBAAqB;IAC3C,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,4FAA4F;IAC5F,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE;QACpB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;KACpC,CAAC;gBAGD,OAAO,EAAE,MAAM,EACf,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,EAAE,sBAAsB;CAQ3D;AAED,mGAAmG;AACnG,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAM1D;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,OAAO,EACd,IAAI,CAAC,EAAE,OAAO,GACZ,eAAe,CAuCjB"}
1
+ {"version":3,"file":"data-source-error.d.ts","sourceRoot":"","sources":["../../src/errors/data-source-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAMN,KAAK,eAAe,EACpB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,mBAAmB,GAC5B,aAAa,GACb,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,qBAAqB,CAAC;AAEzB,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC3D,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,CAAC;CACzD;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACzC,SAAkB,IAAI,qBAAqB;IAC3C,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,CAAC;IACxD;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE;QACpB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;QACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;KACpC,CAAC;gBAGD,OAAO,EAAE,MAAM,EACf,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,EAAE,sBAAsB;CASnE;AAED,mGAAmG;AACnG,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAM1D;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,OAAO,EACd,IAAI,CAAC,EAAE,OAAO,GACZ,eAAe,CAwCjB"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { defaultCache, RESTDataSource, type RESTDataSourceOptions, } from './datasource/rest-datasource';
1
+ export { type BoundDataSource, defaultCache, RESTDataSource, type RESTDataSourceOptions, } from './datasource/rest-datasource';
2
2
  export { codeOf, DataSourceError, type DataSourceErrorCode, type DataSourceErrorOptions, toDataSourceError, } from './errors/data-source-error';
3
3
  export { relayPaginate } from './pagination/relay';
4
4
  export type { Connection, Edge, PageInfo, Paginated } from './pagination/types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,cAAc,EACd,KAAK,qBAAqB,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACN,MAAM,EACN,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,iBAAiB,GACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,eAAe,EACpB,YAAY,EACZ,cAAc,EACd,KAAK,qBAAqB,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACN,MAAM,EACN,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,iBAAiB,GACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -21,12 +21,13 @@ import {
21
21
  } from "@nxgt/httpyz";
22
22
 
23
23
  class DataSourceError extends Error {
24
- constructor(message, { code, status, data, ...options }) {
24
+ constructor(message, { code, status, data, issues, ...options }) {
25
25
  super(message, options);
26
26
  this.name = "DataSourceError";
27
27
  this.code = code;
28
28
  this.status = status;
29
29
  this.data = data;
30
+ this.issues = issues;
30
31
  this.extensions = { code, status };
31
32
  }
32
33
  }
@@ -70,7 +71,8 @@ function toDataSourceError(error, data) {
70
71
  if (error instanceof ValidationError) {
71
72
  return new DataSourceError(error.message, {
72
73
  code: error.failure.kind === "request" ? "BAD_REQUEST" : "INTERNAL_SERVER_ERROR",
73
- data: error.failure.issues,
74
+ status: error.failure.status,
75
+ issues: error.failure.issues,
74
76
  cause: error
75
77
  });
76
78
  }
@@ -81,6 +83,14 @@ function toDataSourceError(error, data) {
81
83
  var defaultCache = replies();
82
84
 
83
85
  class DataSource {
86
+ static for(operations, fixed = {}) {
87
+ const Base = DataSource;
88
+ return class extends Base {
89
+ constructor(options) {
90
+ super({ ...options, ...fixed, operations });
91
+ }
92
+ };
93
+ }
84
94
  constructor(options) {
85
95
  const {
86
96
  baseUrl,
@@ -99,6 +109,16 @@ class DataSource {
99
109
  use: [...cache ? [cache] : [], ...http.use ?? []]
100
110
  });
101
111
  this.api = createOpenApiClient(client, operations, ...[binding]);
112
+ const api = this.api;
113
+ for (const method of METHODS) {
114
+ if (method in api && !(method in this)) {
115
+ Object.defineProperty(this, method, {
116
+ configurable: true,
117
+ writable: true,
118
+ value: api[method]
119
+ });
120
+ }
121
+ }
102
122
  }
103
123
  async data(call) {
104
124
  try {
@@ -110,14 +130,6 @@ class DataSource {
110
130
  }
111
131
  }
112
132
  }
113
- for (const method of METHODS) {
114
- Object.defineProperty(DataSource.prototype, method, {
115
- configurable: true,
116
- get() {
117
- return this.api[method];
118
- }
119
- });
120
- }
121
133
  var RESTDataSource = DataSource;
122
134
  async function bodyOf(response) {
123
135
  const text = await response.clone().text().catch(() => {
@@ -153,5 +165,5 @@ export {
153
165
  toDataSourceError
154
166
  };
155
167
 
156
- //# debugId=6D7A6C634E40DB2764756E2164756E21
168
+ //# debugId=F26F117CA5680FFB64756E2164756E21
157
169
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -2,11 +2,11 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/datasource/rest-datasource.ts", "../src/errors/data-source-error.ts", "../src/pagination/relay.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * `RESTDataSource`: a REST service, called from a GraphQL resolver or any\n * server code, through the client `@nxgt/openapi-httpyz` binds to its spec.\n * The caller's token is forwarded, reads are cached, and a call that fails\n * becomes one `DataSourceError`.\n */\nimport {\n\ttype Cache,\n\tcreateHttpClient,\n\ttype HttpClientOptions,\n\tisAbortError,\n\tok,\n\tcache as replies,\n\ttype Success,\n\tUndeclaredStatusError,\n} from '@nxgt/httpyz';\nimport { METHODS } from '@nxgt/httpyz/integration';\nimport {\n\tcreateOpenApiClient,\n\ttype OpenApiArgs,\n\ttype OpenApiClient,\n\ttype OpenApiOptions,\n\ttype OperationsShape,\n\ttype OperationTable,\n\ttype PathMethods,\n\ttype RoutesOf,\n} from '@nxgt/openapi-httpyz';\nimport { toDataSourceError } from '../errors/data-source-error';\n\ntype Token = string | null | undefined;\n\n/**\n * The cache every datasource shares unless it is given its own: a server\n * makes its datasources per request, and each would otherwise start empty.\n * It keeps the reads, `GET`, `HEAD` and `QUERY`, a search by what it searches\n * for. It is keyed by the caller's token, so no caller is answered with\n * another's reply. `defaultCache.clear()` empties it.\n */\nexport const defaultCache: Cache = replies();\n\nexport interface RESTDataSourceOptions<Ops> extends OpenApiOptions {\n\t/** The service's base URL. */\n\tbaseUrl: string;\n\t/** The `operations` table generated from the service's spec. */\n\toperations: OperationTable<Ops>;\n\t/**\n\t * Sent as `Authorization: Bearer <token>`: the caller's, forwarded. A\n\t * function is read, and awaited, before each request. None sends no header.\n\t */\n\ttoken?: Token | (() => Token | Promise<Token>);\n\t/** Default: `defaultCache`, shared by every datasource. `false`: none. */\n\tcache?: Cache | false;\n\t/** What else the core client takes: `headers`, `timeout`, `retry`, `use`, `fetch`… */\n\thttp?: Omit<HttpClientOptions, 'baseUrl' | 'auth'>;\n}\n\n/** `decode`, as the binding takes it: a datasource typed as decoding must decode. */\ntype Decoding<Decoded extends boolean> = {\n\treadonly decode?: Decoded;\n} & (Decoded extends true ? { readonly decode: true } : unknown);\n\n/** The datasource's own members; `RESTDataSource` adds the client's path methods. */\nclass DataSource<\n\tOps extends OperationsShape<Ops>,\n\tRoutes,\n\tDecoded extends boolean,\n> {\n\t/** The client bound to the spec, for `op()`, `stream()` and `group()`. */\n\treadonly api: OpenApiClient<Ops, Routes, Decoded>;\n\n\tconstructor(options: RESTDataSourceOptions<Ops> & Decoding<Decoded>) {\n\t\tconst {\n\t\t\tbaseUrl,\n\t\t\toperations,\n\t\t\ttoken,\n\t\t\tcache = defaultCache,\n\t\t\thttp = {},\n\t\t\t...binding\n\t\t} = options;\n\t\tconst client = createHttpClient({\n\t\t\t...http,\n\t\t\tbaseUrl,\n\t\t\t...(token === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tauth: { token: typeof token === 'function' ? token : () => token },\n\t\t\t\t\t}),\n\t\t\t// Inside `auth`, so the cache is keyed by the token it sent.\n\t\t\tuse: [...(cache ? [cache] : []), ...(http.use ?? [])],\n\t\t});\n\t\tthis.api = createOpenApiClient<Ops, Routes, Decoded>(\n\t\t\tclient,\n\t\t\toperations,\n\t\t\t// `Decoding` already holds `decode` to `Decoded`.\n\t\t\t...([binding] as unknown as OpenApiArgs<Decoded>),\n\t\t);\n\t}\n\n\t/**\n\t * The data of a call's 2xx reply. Any other reply, or none, throws a\n\t * `DataSourceError`; an aborted call throws its abort, as it is.\n\t */\n\tasync data<R extends { readonly status: number; readonly data: unknown }>(\n\t\tcall: Promise<R>,\n\t): Promise<Success<R>['data']> {\n\t\ttry {\n\t\t\treturn ok(await call);\n\t\t} catch (error) {\n\t\t\tif (isAbortError(error)) throw error;\n\t\t\tthrow toDataSourceError(\n\t\t\t\terror,\n\t\t\t\terror instanceof UndeclaredStatusError\n\t\t\t\t\t? await bodyOf(error.response)\n\t\t\t\t\t: undefined,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// `this.get(...)` for `this.api.get(...)`: getters on the prototype, so that a\n// subclass's own `get()` or `delete()` still wins.\nfor (const method of METHODS) {\n\tObject.defineProperty(DataSource.prototype, method, {\n\t\tconfigurable: true,\n\t\tget(this: { readonly api: Record<string, unknown> }) {\n\t\t\treturn this.api[method];\n\t\t},\n\t});\n}\n\n/**\n * A datasource for a service, typed by the `ClientOperations` generated from\n * its spec. It has the client's `get`, `post`… for each method the spec has\n * an operation for. Extend it with the calls a resolver makes:\n *\n * ```ts\n * class Bookmarks extends RESTDataSource<ClientOperations> {\n * \tbookmark(id: string) {\n * \t\treturn this.data(this.get('/bookmarks/{id}', { param: { id } }));\n * \t}\n * }\n * new Bookmarks({ baseUrl, operations, token: () => context.token });\n * ```\n */\nexport type RESTDataSource<\n\tOps extends OperationsShape<Ops>,\n\tRoutes = RoutesOf<Ops>,\n\tDecoded extends boolean = false,\n> = DataSource<Ops, Routes, Decoded> & PathMethods<Ops, Routes, Decoded>;\n\nexport const RESTDataSource = DataSource as unknown as new <\n\tOps extends OperationsShape<Ops>,\n\tRoutes = RoutesOf<Ops>,\n\tDecoded extends boolean = false,\n>(\n\toptions: RESTDataSourceOptions<Ops> & Decoding<Decoded>,\n) => RESTDataSource<Ops, Routes, Decoded>;\n\n/** A reply's body: JSON when it parses, its text otherwise, nothing when it cannot be read. */\nasync function bodyOf(response: Response): Promise<unknown> {\n\tconst text = await response\n\t\t.clone()\n\t\t.text()\n\t\t.catch(() => undefined);\n\tif (!text) return undefined;\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn text;\n\t}\n}\n",
6
- "/**\n * `DataSourceError`: every way a call to a service can fail, as one error\n * with a code a GraphQL server reports. It is the package's own, and depends\n * on no exception package of the app's: map it to yours where you catch it.\n */\nimport {\n\tNetworkError,\n\tReplyStatusError,\n\tTimeoutError,\n\tUndeclaredStatusError,\n\tValidationError,\n} from '@nxgt/httpyz';\n\nexport type DataSourceErrorCode =\n\t| 'BAD_REQUEST'\n\t| 'UNAUTHENTICATED'\n\t| 'FORBIDDEN'\n\t| 'NOT_FOUND'\n\t| 'INTERNAL_SERVER_ERROR'\n\t| 'SERVICE_UNAVAILABLE';\n\nexport interface DataSourceErrorOptions extends ErrorOptions {\n\treadonly code: DataSourceErrorCode;\n\treadonly status?: number | undefined;\n\treadonly data?: unknown;\n}\n\nexport class DataSourceError extends Error {\n\toverride readonly name = 'DataSourceError';\n\treadonly code: DataSourceErrorCode;\n\t/** The status of the service's reply; none when no reply came back. */\n\treadonly status: number | undefined;\n\t/** The body of the service's reply, as it sent it, or the issues of a check that failed. */\n\treadonly data: unknown;\n\t/**\n\t * What a GraphQL server reports with the error: graphql-js reads\n\t * `extensions` off the error a resolver throws.\n\t */\n\treadonly extensions: {\n\t\treadonly code: DataSourceErrorCode;\n\t\treadonly status: number | undefined;\n\t};\n\n\tconstructor(\n\t\tmessage: string,\n\t\t{ code, status, data, ...options }: DataSourceErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t\tthis.status = status;\n\t\tthis.data = data;\n\t\tthis.extensions = { code, status };\n\t}\n}\n\n/** The code of a reply's status: any 5xx is the service's failure, any other 4xx a bad request. */\nexport function codeOf(status: number): DataSourceErrorCode {\n\tif (status === 401) return 'UNAUTHENTICATED';\n\tif (status === 403) return 'FORBIDDEN';\n\tif (status === 404) return 'NOT_FOUND';\n\tif (status >= 500) return 'INTERNAL_SERVER_ERROR';\n\treturn 'BAD_REQUEST';\n}\n\n/** The `message` of an error body, as the services write it, or `fallback`. */\nconst messageOf = (data: unknown, fallback: string): string =>\n\ttypeof data === 'object' &&\n\tdata !== null &&\n\t'message' in data &&\n\ttypeof data.message === 'string' &&\n\tdata.message !== ''\n\t\t? data.message\n\t\t: fallback;\n\n/**\n * `error` as a `DataSourceError`, whatever the client threw. `data` is the\n * body of a reply the error does not carry: an `UndeclaredStatusError`'s,\n * which only a read of its response gives.\n */\nexport function toDataSourceError(\n\terror: unknown,\n\tdata?: unknown,\n): DataSourceError {\n\tif (error instanceof DataSourceError) return error;\n\tif (error instanceof ReplyStatusError) {\n\t\treturn new DataSourceError(messageOf(error.data, error.message), {\n\t\t\tcode: codeOf(error.status),\n\t\t\tstatus: error.status,\n\t\t\tdata: error.data,\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (error instanceof UndeclaredStatusError) {\n\t\treturn new DataSourceError(messageOf(data, error.message), {\n\t\t\tcode: codeOf(error.status),\n\t\t\tstatus: error.status,\n\t\t\tdata,\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (error instanceof NetworkError || error instanceof TimeoutError) {\n\t\treturn new DataSourceError(error.message, {\n\t\t\tcode: 'SERVICE_UNAVAILABLE',\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (error instanceof ValidationError) {\n\t\t// A request the spec refuses is the caller's fault; a reply it refuses, the service's.\n\t\treturn new DataSourceError(error.message, {\n\t\t\tcode:\n\t\t\t\terror.failure.kind === 'request'\n\t\t\t\t\t? 'BAD_REQUEST'\n\t\t\t\t\t: 'INTERNAL_SERVER_ERROR',\n\t\t\tdata: error.failure.issues,\n\t\t\tcause: error,\n\t\t});\n\t}\n\treturn new DataSourceError(\n\t\terror instanceof Error ? error.message : 'An error occurred',\n\t\t{ code: 'INTERNAL_SERVER_ERROR', cause: error },\n\t);\n}\n",
5
+ "/**\n * `RESTDataSource`: a REST service, called from a GraphQL resolver or any\n * server code, through the client `@nxgt/openapi-httpyz` binds to its spec.\n * The caller's token is forwarded, reads are cached, and a call that fails\n * becomes one `DataSourceError`.\n */\nimport {\n\ttype Cache,\n\tcreateHttpClient,\n\ttype HttpClientOptions,\n\tisAbortError,\n\tok,\n\tcache as replies,\n\ttype Success,\n\tUndeclaredStatusError,\n} from '@nxgt/httpyz';\nimport { METHODS } from '@nxgt/httpyz/integration';\nimport {\n\tcreateOpenApiClient,\n\ttype OpenApiArgs,\n\ttype OpenApiClient,\n\ttype OpenApiOptions,\n\ttype OperationsShape,\n\ttype OperationTable,\n\ttype PathMethods,\n\ttype RoutesOf,\n} from '@nxgt/openapi-httpyz';\nimport { toDataSourceError } from '../errors/data-source-error';\n\ntype Token = string | null | undefined;\n\n/**\n * The cache every datasource shares unless it is given its own: a server\n * makes its datasources per request, and each would otherwise start empty.\n * It keeps the reads, `GET`, `HEAD` and `QUERY`, a search by what it searches\n * for. It is keyed by the caller's token, so no caller is answered with\n * another's reply. `defaultCache.clear()` empties it.\n */\nexport const defaultCache: Cache = replies();\n\nexport interface RESTDataSourceOptions<Ops> extends OpenApiOptions {\n\t/** The service's base URL. */\n\tbaseUrl: string;\n\t/** The `operations` table generated from the service's spec. */\n\toperations: OperationTable<Ops>;\n\t/**\n\t * Sent as `Authorization: Bearer <token>`: the caller's, forwarded. A\n\t * function is read, and awaited, before each request. None sends no header.\n\t */\n\ttoken?: Token | (() => Token | Promise<Token>);\n\t/** Default: `defaultCache`, shared by every datasource. `false`: none. */\n\tcache?: Cache | false;\n\t/** What else the core client takes: `headers`, `timeout`, `retry`, `use`, `fetch`… */\n\thttp?: Omit<HttpClientOptions, 'baseUrl' | 'auth'>;\n}\n\n/** `decode`, as the binding takes it: a datasource typed as not decoding must say `decode: false`. */\ntype Decoding<Decoded extends boolean> = {\n\treadonly decode?: Decoded;\n} & (Decoded extends false ? { readonly decode: false } : unknown);\n\n/** The datasource's own members; `RESTDataSource` adds the client's path methods. */\nclass DataSource<\n\tOps extends OperationsShape<Ops>,\n\tRoutes,\n\tDecoded extends boolean,\n> {\n\t/** The client bound to the spec, for `op()`, `stream()` and `group()`. */\n\treadonly api: OpenApiClient<Ops, Routes, Decoded>;\n\n\t/**\n\t * A datasource class bound to `operations`, whose types it takes from the\n\t * generated table: no `ClientOperations` to import. Its constructor takes\n\t * the other options.\n\t */\n\tstatic for(operations: object, fixed: { readonly decode?: boolean } = {}) {\n\t\tconst Base = DataSource as unknown as new (options: object) => object;\n\t\treturn class extends Base {\n\t\t\tconstructor(options: object) {\n\t\t\t\tsuper({ ...options, ...fixed, operations });\n\t\t\t}\n\t\t};\n\t}\n\n\tconstructor(options: RESTDataSourceOptions<Ops> & Decoding<Decoded>) {\n\t\tconst {\n\t\t\tbaseUrl,\n\t\t\toperations,\n\t\t\ttoken,\n\t\t\tcache = defaultCache,\n\t\t\thttp = {},\n\t\t\t...binding\n\t\t} = options;\n\t\tconst client = createHttpClient({\n\t\t\t...http,\n\t\t\tbaseUrl,\n\t\t\t...(token === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tauth: { token: typeof token === 'function' ? token : () => token },\n\t\t\t\t\t}),\n\t\t\t// Inside `auth`, so the cache is keyed by the token it sent.\n\t\t\tuse: [...(cache ? [cache] : []), ...(http.use ?? [])],\n\t\t});\n\t\tthis.api = createOpenApiClient<Ops, Routes, Decoded>(\n\t\t\tclient,\n\t\t\toperations,\n\t\t\t// `Decoding` already holds `decode` to `Decoded`.\n\t\t\t...([binding] as unknown as OpenApiArgs<Decoded>),\n\t\t);\n\t\t// `this.get(...)` for `this.api.get(...)`, for the spec's methods only.\n\t\t// A subclass's own `get()` or `delete()` is already there, and wins.\n\t\tconst api = this.api as unknown as Record<string, unknown>;\n\t\tfor (const method of METHODS) {\n\t\t\tif (method in api && !(method in this)) {\n\t\t\t\tObject.defineProperty(this, method, {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: api[method],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * The data of a call's 2xx reply. Any other reply, or none, throws a\n\t * `DataSourceError`; an aborted call throws its abort, as it is.\n\t */\n\tasync data<R extends { readonly status: number; readonly data: unknown }>(\n\t\tcall: Promise<R>,\n\t): Promise<Success<R>['data']> {\n\t\ttry {\n\t\t\treturn ok(await call);\n\t\t} catch (error) {\n\t\t\tif (isAbortError(error)) throw error;\n\t\t\tthrow toDataSourceError(\n\t\t\t\terror,\n\t\t\t\terror instanceof UndeclaredStatusError\n\t\t\t\t\t? await bodyOf(error.response)\n\t\t\t\t\t: undefined,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * A datasource for a service, typed by the `ClientOperations` generated from\n * its spec. It has the client's `get`, `post`… for each method the spec has\n * an operation for. Extend it with the calls a resolver makes:\n *\n * ```ts\n * class Bookmarks extends RESTDataSource.for(operations) {\n * \tbookmark(id: string) {\n * \t\treturn this.data(this.get('/bookmarks/{id}', { param: { id } }));\n * \t}\n * }\n * new Bookmarks({ baseUrl, token: () => context.token });\n * ```\n */\nexport type RESTDataSource<\n\tOps extends OperationsShape<Ops>,\n\tRoutes = RoutesOf<Ops>,\n\tDecoded extends boolean = true,\n> = DataSource<Ops, Routes, Decoded> & PathMethods<Ops, Routes, Decoded>;\n\n/** What `RESTDataSource.for(operations)` returns: a datasource class bound to the table. */\nexport type BoundDataSource<\n\tOps extends OperationsShape<Ops>,\n\tDecoded extends boolean = true,\n> = new (\n\toptions: Omit<RESTDataSourceOptions<Ops>, 'operations'>,\n) => RESTDataSource<Ops, RoutesOf<Ops>, Decoded>;\n\nexport const RESTDataSource = DataSource as unknown as {\n\tnew <\n\t\tOps extends OperationsShape<Ops>,\n\t\tRoutes = RoutesOf<Ops>,\n\t\tDecoded extends boolean = true,\n\t>(\n\t\toptions: RESTDataSourceOptions<Ops> & Decoding<Decoded>,\n\t): RESTDataSource<Ops, Routes, Decoded>;\n\t/**\n\t * A datasource class bound to `operations`, whose types it takes from the\n\t * generated table: `class Bookmarks extends RESTDataSource.for(operations)`.\n\t * `{ decode: false }` returns the replies as JSON carries them.\n\t */\n\tfor<Ops extends OperationsShape<Ops>>(\n\t\toperations: OperationTable<Ops>,\n\t\toptions: { readonly decode: false },\n\t): BoundDataSource<Ops, false>;\n\tfor<Ops extends OperationsShape<Ops>>(\n\t\toperations: OperationTable<Ops>,\n\t\toptions?: { readonly decode?: true },\n\t): BoundDataSource<Ops, true>;\n};\n\n/** A reply's body: JSON when it parses, its text otherwise, nothing when it cannot be read. */\nasync function bodyOf(response: Response): Promise<unknown> {\n\tconst text = await response\n\t\t.clone()\n\t\t.text()\n\t\t.catch(() => undefined);\n\tif (!text) return undefined;\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn text;\n\t}\n}\n",
6
+ "/**\n * `DataSourceError`: every way a call to a service can fail, as one error\n * with a code a GraphQL server reports. It is the package's own, and depends\n * on no exception package of the app's: map it to yours where you catch it.\n */\nimport {\n\tNetworkError,\n\tReplyStatusError,\n\tTimeoutError,\n\tUndeclaredStatusError,\n\tValidationError,\n\ttype ValidationIssue,\n} from '@nxgt/httpyz';\n\nexport type DataSourceErrorCode =\n\t| 'BAD_REQUEST'\n\t| 'UNAUTHENTICATED'\n\t| 'FORBIDDEN'\n\t| 'NOT_FOUND'\n\t| 'INTERNAL_SERVER_ERROR'\n\t| 'SERVICE_UNAVAILABLE';\n\nexport interface DataSourceErrorOptions extends ErrorOptions {\n\treadonly code: DataSourceErrorCode;\n\treadonly status?: number | undefined;\n\treadonly data?: unknown;\n\treadonly issues?: readonly ValidationIssue[] | undefined;\n}\n\nexport class DataSourceError extends Error {\n\toverride readonly name = 'DataSourceError';\n\treadonly code: DataSourceErrorCode;\n\t/** The status of the service's reply; none when no reply came back. */\n\treadonly status: number | undefined;\n\t/** The body of the service's reply, as it sent it; none when no reply was read. */\n\treadonly data: unknown;\n\t/** What a `validate` check refused, in the request or the reply; none otherwise. */\n\treadonly issues: readonly ValidationIssue[] | undefined;\n\t/**\n\t * What a GraphQL server reports with the error: graphql-js reads\n\t * `extensions` off the error a resolver throws.\n\t */\n\treadonly extensions: {\n\t\treadonly code: DataSourceErrorCode;\n\t\treadonly status: number | undefined;\n\t};\n\n\tconstructor(\n\t\tmessage: string,\n\t\t{ code, status, data, issues, ...options }: DataSourceErrorOptions,\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t\tthis.status = status;\n\t\tthis.data = data;\n\t\tthis.issues = issues;\n\t\tthis.extensions = { code, status };\n\t}\n}\n\n/** The code of a reply's status: any 5xx is the service's failure, any other 4xx a bad request. */\nexport function codeOf(status: number): DataSourceErrorCode {\n\tif (status === 401) return 'UNAUTHENTICATED';\n\tif (status === 403) return 'FORBIDDEN';\n\tif (status === 404) return 'NOT_FOUND';\n\tif (status >= 500) return 'INTERNAL_SERVER_ERROR';\n\treturn 'BAD_REQUEST';\n}\n\n/** The `message` of an error body, as the services write it, or `fallback`. */\nconst messageOf = (data: unknown, fallback: string): string =>\n\ttypeof data === 'object' &&\n\tdata !== null &&\n\t'message' in data &&\n\ttypeof data.message === 'string' &&\n\tdata.message !== ''\n\t\t? data.message\n\t\t: fallback;\n\n/**\n * `error` as a `DataSourceError`, whatever the client threw. `data` is the\n * body of a reply the error does not carry: an `UndeclaredStatusError`'s,\n * which only a read of its response gives.\n */\nexport function toDataSourceError(\n\terror: unknown,\n\tdata?: unknown,\n): DataSourceError {\n\tif (error instanceof DataSourceError) return error;\n\tif (error instanceof ReplyStatusError) {\n\t\treturn new DataSourceError(messageOf(error.data, error.message), {\n\t\t\tcode: codeOf(error.status),\n\t\t\tstatus: error.status,\n\t\t\tdata: error.data,\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (error instanceof UndeclaredStatusError) {\n\t\treturn new DataSourceError(messageOf(data, error.message), {\n\t\t\tcode: codeOf(error.status),\n\t\t\tstatus: error.status,\n\t\t\tdata,\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (error instanceof NetworkError || error instanceof TimeoutError) {\n\t\treturn new DataSourceError(error.message, {\n\t\t\tcode: 'SERVICE_UNAVAILABLE',\n\t\t\tcause: error,\n\t\t});\n\t}\n\tif (error instanceof ValidationError) {\n\t\t// A request the spec refuses is the caller's fault; a reply it refuses, the service's.\n\t\treturn new DataSourceError(error.message, {\n\t\t\tcode:\n\t\t\t\terror.failure.kind === 'request'\n\t\t\t\t\t? 'BAD_REQUEST'\n\t\t\t\t\t: 'INTERNAL_SERVER_ERROR',\n\t\t\tstatus: error.failure.status,\n\t\t\tissues: error.failure.issues,\n\t\t\tcause: error,\n\t\t});\n\t}\n\treturn new DataSourceError(\n\t\terror instanceof Error ? error.message : 'An error occurred',\n\t\t{ code: 'INTERNAL_SERVER_ERROR', cause: error },\n\t);\n}\n",
7
7
  "import type { Connection, Paginated } from './types';\n\n/**\n * A service's `{ data, metadata }` page as a Relay connection: each item an\n * edge, its `id` the cursor. Without `metadata`, its page info is an empty\n * last page's, even when it has items.\n */\nexport function relayPaginate<T extends { id: string }>(\n\tpage: Paginated<T>,\n): Connection<T> {\n\tconst { data: items, metadata } = page;\n\treturn {\n\t\tedges: (items ?? []).map((item) => ({ node: item, cursor: item.id })),\n\t\tpageInfo: metadata ?? {\n\t\t\tstartCursor: undefined,\n\t\t\tendCursor: undefined,\n\t\t\thasNextPage: false,\n\t\t\ttotalElements: 0,\n\t\t},\n\t};\n}\n"
8
8
  ],
9
- "mappings": "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",
10
- "debugId": "6D7A6C634E40DB2764756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "F26F117CA5680FFB64756E2164756E21",
11
11
  "names": []
12
12
  }
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@nxgt/datasource-rest",
3
- "version": "2.0.0",
4
- "license": "UNLICENSED",
3
+ "version": "3.0.0",
4
+ "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "files": [
9
9
  "dist",
10
10
  "README.md",
11
- "package.json"
11
+ "package.json",
12
+ "LICENSE"
12
13
  ],
13
14
  "exports": {
14
15
  ".": {
@@ -39,15 +40,15 @@
39
40
  ]
40
41
  },
41
42
  "devDependencies": {
42
- "@nxgt/httpyz": "^0.0.0",
43
- "@nxgt/openapi-codegen": "^0.1.0",
44
- "@nxgt/openapi-httpyz": "^0.0.0",
43
+ "@nxgt/httpyz": "^0.1.0",
44
+ "@nxgt/openapi-codegen": "^0.2.0",
45
+ "@nxgt/openapi-httpyz": "^0.1.0",
45
46
  "@types/bun": "^1.4.0",
46
47
  "zod": "^4.5.4"
47
48
  },
48
49
  "peerDependencies": {
49
- "@nxgt/httpyz": "^0.0.0",
50
- "@nxgt/openapi-httpyz": "^0.0.0",
50
+ "@nxgt/httpyz": "^0.1.0",
51
+ "@nxgt/openapi-httpyz": "^0.1.0",
51
52
  "typescript": "^6.0.3"
52
53
  }
53
54
  }