@sapporta/rest-core 3.52.1 → 3.52.2

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 (60) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +75 -10
  3. package/index.cjs.d.ts +1 -0
  4. package/index.cjs.default.js +1 -0
  5. package/index.cjs.js +807 -0
  6. package/index.cjs.mjs +2 -0
  7. package/index.esm.js +762 -0
  8. package/package.json +13 -3
  9. package/src/lib/client.d.ts +107 -0
  10. package/src/lib/dsl.d.ts +222 -0
  11. package/src/lib/infer-types.d.ts +78 -0
  12. package/src/lib/paths.d.ts +30 -0
  13. package/src/lib/query.d.ts +17 -0
  14. package/src/lib/response-error.d.ts +20 -0
  15. package/src/lib/response-validation-error.d.ts +14 -0
  16. package/src/lib/server.d.ts +18 -0
  17. package/src/lib/standard-schema-utils.d.ts +68 -0
  18. package/src/lib/standard-schema.d.ts +55 -0
  19. package/src/lib/status-codes.d.ts +6 -0
  20. package/src/lib/{test-helpers.ts → test-helpers.d.ts} +1 -6
  21. package/src/lib/type-guards.d.ts +12 -0
  22. package/src/lib/type-utils.d.ts +96 -0
  23. package/src/lib/unknown-status-error.d.ts +10 -0
  24. package/src/lib/validation-error.d.ts +11 -0
  25. package/.babelrc +0 -10
  26. package/.eslintrc.json +0 -21
  27. package/LICENCE +0 -21
  28. package/jest.config.ts +0 -16
  29. package/project.json +0 -51
  30. package/src/lib/client.spec.ts +0 -1330
  31. package/src/lib/client.ts +0 -481
  32. package/src/lib/dsl.spec.ts +0 -1308
  33. package/src/lib/dsl.ts +0 -472
  34. package/src/lib/fetch.spec.ts +0 -102
  35. package/src/lib/infer-types.spec.ts +0 -935
  36. package/src/lib/infer-types.ts +0 -282
  37. package/src/lib/paths.spec.ts +0 -138
  38. package/src/lib/paths.ts +0 -61
  39. package/src/lib/query.spec.ts +0 -329
  40. package/src/lib/query.ts +0 -114
  41. package/src/lib/response-error.spec.ts +0 -67
  42. package/src/lib/response-error.ts +0 -61
  43. package/src/lib/response-validation-error.ts +0 -24
  44. package/src/lib/server.spec.ts +0 -163
  45. package/src/lib/server.ts +0 -83
  46. package/src/lib/standard-schema-utils.spec.ts +0 -218
  47. package/src/lib/standard-schema-utils.ts +0 -280
  48. package/src/lib/standard-schema.ts +0 -71
  49. package/src/lib/status-codes.ts +0 -75
  50. package/src/lib/type-guards.spec.ts +0 -355
  51. package/src/lib/type-guards.ts +0 -99
  52. package/src/lib/type-utils.spec.ts +0 -59
  53. package/src/lib/type-utils.ts +0 -234
  54. package/src/lib/unknown-status-error.ts +0 -15
  55. package/src/lib/validation-error.ts +0 -36
  56. package/tsconfig.json +0 -22
  57. package/tsconfig.lib.json +0 -10
  58. package/tsconfig.spec.json +0 -9
  59. package/typedoc.json +0 -5
  60. /package/src/{index.ts → index.d.ts} +0 -0
@@ -1,355 +0,0 @@
1
- import {
2
- isResponse,
3
- isSuccessResponse,
4
- isErrorResponse,
5
- isUnknownResponse,
6
- isUnknownSuccessResponse,
7
- isUnknownErrorResponse,
8
- } from './type-guards';
9
- import { initContract } from './dsl';
10
- import { Equal, Expect } from './test-helpers';
11
- import {
12
- ErrorHttpStatusCode,
13
- HTTPStatusCode,
14
- SuccessfulHttpStatusCode,
15
- } from './status-codes';
16
-
17
- const c = initContract();
18
-
19
- describe('Type Guards', () => {
20
- const contract = c.router({
21
- getPost: {
22
- method: 'GET',
23
- path: '/posts/:id',
24
- responses: {
25
- 200: c.type<{ id: string }>(),
26
- 404: c.type<{ message: string }>(),
27
- },
28
- },
29
- getPostStrict: {
30
- method: 'GET',
31
- path: '/posts/:id',
32
- responses: {
33
- 200: c.type<{ id: string }>(),
34
- 404: c.type<{ message: string }>(),
35
- },
36
- strictStatusCodes: true,
37
- },
38
- });
39
-
40
- type ResponseType = {
41
- status: number;
42
- body: unknown;
43
- headers: Headers;
44
- };
45
-
46
- const errorObject = new Error('Error');
47
-
48
- const successResponse: ResponseType = {
49
- status: 200,
50
- body: {
51
- id: '1',
52
- },
53
- headers: new Headers(),
54
- };
55
-
56
- const errorResponse: ResponseType = {
57
- status: 404,
58
- body: {
59
- message: 'Not Found',
60
- },
61
- headers: new Headers(),
62
- };
63
-
64
- const unknownSuccessResponse: ResponseType = {
65
- status: 207,
66
- body: 'Success',
67
- headers: new Headers(),
68
- };
69
-
70
- const unknownErrorResponse: ResponseType = {
71
- status: 500,
72
- body: 'Server Error',
73
- headers: new Headers(),
74
- };
75
-
76
- describe('isResponse', () => {
77
- it.each([
78
- successResponse,
79
- errorResponse,
80
- unknownSuccessResponse,
81
- unknownErrorResponse,
82
- ])('should return true for a valid response object', (response) => {
83
- const result = isResponse(response, contract.getPost);
84
- expect(result).toStrictEqual(true);
85
-
86
- if (result) {
87
- type TypeTest = Expect<
88
- Equal<
89
- typeof response,
90
- | { status: 200; body: { id: string }; headers: Headers }
91
- | { status: 404; body: { message: string }; headers: Headers }
92
- | {
93
- status: Exclude<HTTPStatusCode, 200 | 404>;
94
- body: unknown;
95
- headers: Headers;
96
- }
97
- >
98
- >;
99
- }
100
- });
101
-
102
- it.each([successResponse, errorResponse])(
103
- '[strictStatusCode] should return true for a valid defined response object',
104
- (response) => {
105
- const result = isResponse(response, contract.getPostStrict);
106
- expect(result).toStrictEqual(true);
107
-
108
- if (result) {
109
- type TypeTest = Expect<
110
- Equal<
111
- typeof response,
112
- | { status: 200; body: { id: string }; headers: Headers }
113
- | { status: 404; body: { message: string }; headers: Headers }
114
- >
115
- >;
116
- }
117
- },
118
- );
119
-
120
- it.each([
121
- errorObject,
122
- null,
123
- {},
124
- { status: 200, noBody: '' },
125
- { status: 200 },
126
- ])('should return false for an invalid response object', (response) => {
127
- expect(isResponse(response)).toBe(false);
128
- });
129
-
130
- it.each([
131
- unknownSuccessResponse,
132
- unknownErrorResponse,
133
- errorObject,
134
- null,
135
- {},
136
- { status: 200, noBody: '' },
137
- { status: 200 },
138
- ])(
139
- '[strictStatusCode] should return false for an invalid response object or undefined response',
140
- (response) => {
141
- expect(isResponse(response, contract.getPostStrict)).toBe(false);
142
- },
143
- );
144
- });
145
-
146
- describe('isSuccessResponse', () => {
147
- it.each([successResponse, unknownSuccessResponse])(
148
- 'should return true for a successful response',
149
- (response) => {
150
- const result = isSuccessResponse(response, contract.getPost);
151
- expect(result).toStrictEqual(true);
152
-
153
- if (result) {
154
- type TypeTest = Expect<
155
- Equal<
156
- typeof response,
157
- | { status: 200; body: { id: string }; headers: Headers }
158
- | {
159
- status: Exclude<SuccessfulHttpStatusCode, 200>;
160
- body: unknown;
161
- headers: Headers;
162
- }
163
- >
164
- >;
165
- }
166
- },
167
- );
168
-
169
- it.each([successResponse])(
170
- '[strictStatusCode] should return true for a successful response',
171
- (response) => {
172
- const result = isSuccessResponse(response, contract.getPostStrict);
173
- expect(result).toStrictEqual(true);
174
-
175
- if (result) {
176
- type TypeTest = Expect<
177
- Equal<
178
- typeof response,
179
- { status: 200; body: { id: string }; headers: Headers }
180
- >
181
- >;
182
- }
183
- },
184
- );
185
-
186
- it.each([errorResponse, unknownErrorResponse])(
187
- 'should return false for a non-successful response',
188
- (response) => {
189
- expect(isSuccessResponse(response)).toStrictEqual(false);
190
- },
191
- );
192
-
193
- it.each([unknownSuccessResponse, errorResponse, unknownErrorResponse])(
194
- 'should return false for a non-successful response',
195
- (response) => {
196
- expect(
197
- isSuccessResponse(response, contract.getPostStrict),
198
- ).toStrictEqual(false);
199
- },
200
- );
201
- });
202
-
203
- describe('isErrorResponse', () => {
204
- it.each([errorResponse, unknownErrorResponse])(
205
- 'should return true for an error response',
206
- (response) => {
207
- const result = isErrorResponse(response, contract.getPost);
208
- expect(result).toStrictEqual(true);
209
-
210
- if (result) {
211
- type TypeTest = Expect<
212
- Equal<
213
- typeof response,
214
- | { status: 404; body: { message: string }; headers: Headers }
215
- | {
216
- status: Exclude<ErrorHttpStatusCode, 404>;
217
- body: unknown;
218
- headers: Headers;
219
- }
220
- >
221
- >;
222
- }
223
- },
224
- );
225
-
226
- it.each([errorResponse])(
227
- '[strictStatusCode] should return true for an error response',
228
- (response) => {
229
- const result = isErrorResponse(response, contract.getPostStrict);
230
- expect(result).toStrictEqual(true);
231
-
232
- if (result) {
233
- type TypeTest = Expect<
234
- Equal<
235
- typeof response,
236
- { status: 404; body: { message: string }; headers: Headers }
237
- >
238
- >;
239
- }
240
- },
241
- );
242
-
243
- it.each([successResponse, unknownSuccessResponse])(
244
- 'should return false for a non-error response',
245
- (response) => {
246
- expect(isErrorResponse(response)).toStrictEqual(false);
247
- },
248
- );
249
-
250
- it.each([unknownErrorResponse, successResponse, unknownSuccessResponse])(
251
- 'should return false for a non-error response',
252
- (response) => {
253
- expect(isErrorResponse(response, contract.getPostStrict)).toStrictEqual(
254
- false,
255
- );
256
- },
257
- );
258
- });
259
-
260
- describe('isUnknownResponse', () => {
261
- it.each([unknownSuccessResponse, unknownErrorResponse])(
262
- 'should return true for responses not defined in the contract',
263
- (response) => {
264
- const result = isUnknownResponse(response, contract.getPost);
265
- expect(result).toStrictEqual(true);
266
-
267
- if (result) {
268
- type TypeTest = Expect<
269
- Equal<
270
- typeof response,
271
- {
272
- status: Exclude<HTTPStatusCode, 200 | 404>;
273
- body: unknown;
274
- headers: Headers;
275
- }
276
- >
277
- >;
278
- }
279
- },
280
- );
281
-
282
- it.each([successResponse, errorResponse])(
283
- 'should return false for a response defined in the contract',
284
- (response) => {
285
- expect(isUnknownResponse(response, contract.getPost)).toStrictEqual(
286
- false,
287
- );
288
- },
289
- );
290
- });
291
-
292
- describe('isUnknownSuccessResponse', () => {
293
- it.each([unknownSuccessResponse])(
294
- 'should return true for successful responses not defined in the contract or error responses',
295
- (response) => {
296
- const result = isUnknownSuccessResponse(response, contract.getPost);
297
- expect(result).toStrictEqual(true);
298
-
299
- if (result) {
300
- type TypeTest = Expect<
301
- Equal<
302
- typeof response,
303
- {
304
- status: Exclude<SuccessfulHttpStatusCode, 200>;
305
- body: unknown;
306
- headers: Headers;
307
- }
308
- >
309
- >;
310
- }
311
- },
312
- );
313
-
314
- it.each([successResponse, errorResponse, unknownErrorResponse])(
315
- 'should return false for a success response defined in the contract or non-success responses',
316
- (response) => {
317
- expect(
318
- isUnknownSuccessResponse(response, contract.getPost),
319
- ).toStrictEqual(false);
320
- },
321
- );
322
- });
323
-
324
- describe('isUnknownErrorResponse', () => {
325
- it.each([unknownErrorResponse])(
326
- 'should return true for error responses not defined in the contract or successful responses',
327
- (response) => {
328
- const result = isUnknownErrorResponse(response, contract.getPost);
329
- expect(result).toStrictEqual(true);
330
-
331
- if (result) {
332
- type TypeTest = Expect<
333
- Equal<
334
- typeof response,
335
- {
336
- status: Exclude<ErrorHttpStatusCode, 404>;
337
- body: unknown;
338
- headers: Headers;
339
- }
340
- >
341
- >;
342
- }
343
- },
344
- );
345
-
346
- it.each([errorResponse, successResponse, unknownSuccessResponse])(
347
- 'should return false for an error response defined in the contract or non-error responses',
348
- (response) => {
349
- expect(
350
- isUnknownErrorResponse(response, contract.getPost),
351
- ).toStrictEqual(false);
352
- },
353
- );
354
- });
355
- });
@@ -1,99 +0,0 @@
1
- import { AppRoute } from './dsl';
2
- import {
3
- ClientInferResponses,
4
- InferResponseUndefinedStatusCodes,
5
- } from './infer-types';
6
- import {
7
- ErrorHttpStatusCode,
8
- HTTPStatusCode,
9
- SuccessfulHttpStatusCode,
10
- } from './status-codes';
11
-
12
- export const isResponse = <T extends AppRoute>(
13
- response: unknown,
14
- contractEndpoint?: T,
15
- ): response is ClientInferResponses<T, HTTPStatusCode> => {
16
- return (
17
- typeof response === 'object' &&
18
- response !== null &&
19
- 'status' in response &&
20
- 'body' in response &&
21
- typeof response.status === 'number' &&
22
- response.status >= 200 &&
23
- response.status < 600 &&
24
- (contractEndpoint?.strictStatusCodes
25
- ? Object.keys(contractEndpoint.responses).includes(
26
- response.status.toString(),
27
- )
28
- : true)
29
- );
30
- };
31
-
32
- export const isSuccessResponse = <T extends AppRoute>(
33
- response: unknown,
34
- contractEndpoint?: T,
35
- ): response is ClientInferResponses<T, SuccessfulHttpStatusCode> => {
36
- return (
37
- isResponse(response, contractEndpoint) &&
38
- response.status >= 200 &&
39
- response.status < 300
40
- );
41
- };
42
-
43
- export const isErrorResponse = <T extends AppRoute>(
44
- response: unknown,
45
- contractEndpoint?: T,
46
- ): response is ClientInferResponses<T, ErrorHttpStatusCode> => {
47
- return (
48
- isResponse(response, contractEndpoint) &&
49
- !isSuccessResponse(response, contractEndpoint)
50
- );
51
- };
52
-
53
- export const isUnknownResponse = <T extends AppRoute>(
54
- response: unknown,
55
- contractEndpoint: T,
56
- ): response is ClientInferResponses<
57
- T,
58
- InferResponseUndefinedStatusCodes<T>,
59
- 'ignore'
60
- > => {
61
- return (
62
- isResponse(response) &&
63
- !Object.keys(contractEndpoint.responses).includes(
64
- response.status.toString(),
65
- )
66
- );
67
- };
68
-
69
- export const isUnknownSuccessResponse = <T extends AppRoute>(
70
- response: unknown,
71
- contractEndpoint: T,
72
- ): response is ClientInferResponses<
73
- T,
74
- InferResponseUndefinedStatusCodes<T, SuccessfulHttpStatusCode>,
75
- 'ignore'
76
- > => {
77
- return (
78
- isSuccessResponse(response) && isUnknownResponse(response, contractEndpoint)
79
- );
80
- };
81
-
82
- export const isUnknownErrorResponse = <T extends AppRoute>(
83
- response: unknown,
84
- contractEndpoint: T,
85
- ): response is ClientInferResponses<
86
- T,
87
- InferResponseUndefinedStatusCodes<T, ErrorHttpStatusCode>,
88
- 'ignore'
89
- > => {
90
- return (
91
- isErrorResponse(response) && isUnknownResponse(response, contractEndpoint)
92
- );
93
- };
94
-
95
- export const exhaustiveGuard = <T extends { status: never }>(
96
- response: T,
97
- ): never => {
98
- throw new Error(`Unreachable code: Response status is ${response.status}`);
99
- };
@@ -1,59 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import { z } from 'zod';
3
- import { Equal, Expect } from './test-helpers';
4
- import {
5
- AreAllPropertiesOptional,
6
- Without,
7
- SchemaOutputOrType,
8
- } from './type-utils';
9
-
10
- const zodObject = z.object({ title: z.string() });
11
- type Test1 = SchemaOutputOrType<typeof zodObject>;
12
-
13
- const zodObjectNullable = zodObject.nullable();
14
- type Test2 = SchemaOutputOrType<typeof zodObject>;
15
-
16
- type Test3 = SchemaOutputOrType<{ title: string }>;
17
-
18
- it.todo('should infer type');
19
-
20
- type AreAllPropertiesOptional1 = Expect<
21
- Equal<AreAllPropertiesOptional<{ a: string; b?: string }>, false>
22
- >;
23
-
24
- type AreAllPropertiesOptional2 = Expect<
25
- Equal<AreAllPropertiesOptional<{ a?: string; b?: string }>, true>
26
- >;
27
-
28
- type AreAllPropertiesOptional3 = Expect<
29
- Equal<
30
- AreAllPropertiesOptional<{
31
- params: {
32
- id: string;
33
- };
34
- headers?: Record<string, string>;
35
- }>,
36
- false
37
- >
38
- >;
39
-
40
- type WithoutTest = Expect<
41
- Equal<
42
- Without<
43
- {
44
- body: never;
45
- params: {
46
- id: string;
47
- };
48
- headers?: Record<string, string>;
49
- },
50
- never
51
- >,
52
- {
53
- params: {
54
- id: string;
55
- };
56
- headers?: Record<string, string>;
57
- }
58
- >
59
- >;