@data-client/rest 0.1.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.
Files changed (158) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +110 -0
  3. package/dist/index.js +561 -0
  4. package/dist/index.umd.min.js +1 -0
  5. package/dist/next.js +520 -0
  6. package/dist/package.json +1 -0
  7. package/legacy/NetworkError.js +13 -0
  8. package/legacy/OptionsToFunction.js +2 -0
  9. package/legacy/RestEndpoint.js +225 -0
  10. package/legacy/RestEndpointTypeHelp.js +2 -0
  11. package/legacy/RestHelpers.js +33 -0
  12. package/legacy/createResource.js +88 -0
  13. package/legacy/extractCollection.js +14 -0
  14. package/legacy/getArrayPath.js +19 -0
  15. package/legacy/hookifyResource.js +24 -0
  16. package/legacy/index.js +10 -0
  17. package/legacy/mapCollection.js +14 -0
  18. package/legacy/next/OptionsToFunction.js +2 -0
  19. package/legacy/next/RestEndpoint.js +225 -0
  20. package/legacy/next/createResource.js +86 -0
  21. package/legacy/next/index.js +4 -0
  22. package/legacy/next/resourceTypes.js +2 -0
  23. package/legacy/paginatedCollections.js +29 -0
  24. package/legacy/paginationUpdate.js +36 -0
  25. package/legacy/paramsToString.js +6 -0
  26. package/legacy/paramsToString.native.js +9 -0
  27. package/legacy/pathTypes.js +2 -0
  28. package/legacy/test-fixtures.js +111 -0
  29. package/legacy/utiltypes.js +2 -0
  30. package/lib/NetworkError.d.ts +11 -0
  31. package/lib/NetworkError.d.ts.map +1 -0
  32. package/lib/NetworkError.js +13 -0
  33. package/lib/OptionsToFunction.d.ts +7 -0
  34. package/lib/OptionsToFunction.d.ts.map +1 -0
  35. package/lib/OptionsToFunction.js +2 -0
  36. package/lib/RestEndpoint.d.ts +548 -0
  37. package/lib/RestEndpoint.js +229 -0
  38. package/lib/RestEndpointTypeHelp.d.ts +10 -0
  39. package/lib/RestEndpointTypeHelp.d.ts.map +1 -0
  40. package/lib/RestEndpointTypeHelp.js +2 -0
  41. package/lib/RestHelpers.d.ts +7 -0
  42. package/lib/RestHelpers.d.ts.map +1 -0
  43. package/lib/RestHelpers.js +33 -0
  44. package/lib/createResource.d.ts +66 -0
  45. package/lib/createResource.d.ts.map +1 -0
  46. package/lib/createResource.js +104 -0
  47. package/lib/extractCollection.d.ts +11 -0
  48. package/lib/extractCollection.d.ts.map +1 -0
  49. package/lib/extractCollection.js +16 -0
  50. package/lib/getArrayPath.d.ts +3 -0
  51. package/lib/getArrayPath.d.ts.map +1 -0
  52. package/lib/getArrayPath.js +19 -0
  53. package/lib/hookifyResource.d.ts +14 -0
  54. package/lib/hookifyResource.d.ts.map +1 -0
  55. package/lib/hookifyResource.js +24 -0
  56. package/lib/index.d.ts +12 -0
  57. package/lib/index.d.ts.map +1 -0
  58. package/lib/index.js +10 -0
  59. package/lib/mapCollection.d.ts +16 -0
  60. package/lib/mapCollection.d.ts.map +1 -0
  61. package/lib/mapCollection.js +16 -0
  62. package/lib/next/OptionsToFunction.d.ts +7 -0
  63. package/lib/next/OptionsToFunction.d.ts.map +1 -0
  64. package/lib/next/OptionsToFunction.js +2 -0
  65. package/lib/next/RestEndpoint.d.ts +542 -0
  66. package/lib/next/RestEndpoint.js +229 -0
  67. package/lib/next/createResource.d.ts +86 -0
  68. package/lib/next/createResource.d.ts.map +1 -0
  69. package/lib/next/createResource.js +100 -0
  70. package/lib/next/index.d.ts +6 -0
  71. package/lib/next/index.d.ts.map +1 -0
  72. package/lib/next/index.js +4 -0
  73. package/lib/next/resourceTypes.d.ts +31 -0
  74. package/lib/next/resourceTypes.d.ts.map +1 -0
  75. package/lib/next/resourceTypes.js +2 -0
  76. package/lib/paginatedCollections.d.ts +3 -0
  77. package/lib/paginatedCollections.d.ts.map +1 -0
  78. package/lib/paginatedCollections.js +29 -0
  79. package/lib/paginationUpdate.d.ts +8 -0
  80. package/lib/paginationUpdate.d.ts.map +1 -0
  81. package/lib/paginationUpdate.js +40 -0
  82. package/lib/paramsToString.d.ts +2 -0
  83. package/lib/paramsToString.d.ts.map +1 -0
  84. package/lib/paramsToString.js +6 -0
  85. package/lib/paramsToString.native.d.ts +2 -0
  86. package/lib/paramsToString.native.d.ts.map +1 -0
  87. package/lib/paramsToString.native.js +9 -0
  88. package/lib/pathTypes.d.ts +20 -0
  89. package/lib/pathTypes.d.ts.map +1 -0
  90. package/lib/pathTypes.js +2 -0
  91. package/lib/test-fixtures.d.ts +141 -0
  92. package/lib/test-fixtures.d.ts.map +1 -0
  93. package/lib/test-fixtures.js +111 -0
  94. package/lib/utiltypes.d.ts +21 -0
  95. package/lib/utiltypes.d.ts.map +1 -0
  96. package/lib/utiltypes.js +2 -0
  97. package/node.mjs +1 -0
  98. package/package.json +121 -0
  99. package/src/NetworkError.ts +17 -0
  100. package/src/OptionsToFunction.ts +42 -0
  101. package/src/RestEndpoint.d.ts +548 -0
  102. package/src/RestEndpoint.js +262 -0
  103. package/src/RestEndpointTypeHelp.ts +20 -0
  104. package/src/RestHelpers.ts +48 -0
  105. package/src/__tests__/Resource.test.ts +317 -0
  106. package/src/__tests__/RestEndpoint.ts +1304 -0
  107. package/src/__tests__/__snapshots__/RestEndpoint.ts.snap +18 -0
  108. package/src/__tests__/__snapshots__/createResource.test.ts.snap +5 -0
  109. package/src/__tests__/createResource.test.ts +583 -0
  110. package/src/__tests__/getArrayPath.test.ts +30 -0
  111. package/src/__tests__/hookifyResource.ts +197 -0
  112. package/src/__tests__/types.test.ts +309 -0
  113. package/src/createResource.ts +172 -0
  114. package/src/extractCollection.ts +34 -0
  115. package/src/getArrayPath.ts +20 -0
  116. package/src/hookifyResource.ts +36 -0
  117. package/src/index.ts +42 -0
  118. package/src/mapCollection.ts +54 -0
  119. package/src/next/OptionsToFunction.ts +41 -0
  120. package/src/next/RestEndpoint.d.ts +542 -0
  121. package/src/next/RestEndpoint.js +262 -0
  122. package/src/next/__tests__/RestEndpoint.ts +1333 -0
  123. package/src/next/__tests__/__snapshots__/RestEndpoint.ts.snap +18 -0
  124. package/src/next/__tests__/types.test.ts +429 -0
  125. package/src/next/createResource.ts +194 -0
  126. package/src/next/index.ts +5 -0
  127. package/src/next/resourceTypes.ts +32 -0
  128. package/src/package.json +1 -0
  129. package/src/paginatedCollections.ts +32 -0
  130. package/src/paginationUpdate.ts +49 -0
  131. package/src/paramsToString.native.ts +10 -0
  132. package/src/paramsToString.ts +7 -0
  133. package/src/pathTypes.ts +58 -0
  134. package/src/test-fixtures.ts +128 -0
  135. package/src/utiltypes.ts +25 -0
  136. package/ts4.0/NetworkError.d.ts +11 -0
  137. package/ts4.0/OptionsToFunction.d.ts +16 -0
  138. package/ts4.0/RestEndpoint.d.ts +240 -0
  139. package/ts4.0/RestEndpointTypeHelp.d.ts +10 -0
  140. package/ts4.0/RestHelpers.d.ts +7 -0
  141. package/ts4.0/createResource.d.ts +66 -0
  142. package/ts4.0/extractCollection.d.ts +11 -0
  143. package/ts4.0/getArrayPath.d.ts +3 -0
  144. package/ts4.0/hookifyResource.d.ts +19 -0
  145. package/ts4.0/index.d.ts +12 -0
  146. package/ts4.0/mapCollection.d.ts +16 -0
  147. package/ts4.0/next/OptionsToFunction.d.ts +16 -0
  148. package/ts4.0/next/RestEndpoint.d.ts +226 -0
  149. package/ts4.0/next/createResource.d.ts +94 -0
  150. package/ts4.0/next/index.d.ts +6 -0
  151. package/ts4.0/next/resourceTypes.d.ts +31 -0
  152. package/ts4.0/paginatedCollections.d.ts +3 -0
  153. package/ts4.0/paginationUpdate.d.ts +10 -0
  154. package/ts4.0/paramsToString.d.ts +2 -0
  155. package/ts4.0/paramsToString.native.d.ts +2 -0
  156. package/ts4.0/pathTypes.d.ts +20 -0
  157. package/ts4.0/test-fixtures.d.ts +141 -0
  158. package/ts4.0/utiltypes.d.ts +5 -0
@@ -0,0 +1,32 @@
1
+ export function paginatedMerge(existing: any[], incoming: any[]) {
2
+ const existingSet: Set<string> = new Set(existing);
3
+ const mergedList = [...existing];
4
+ for (const pk of incoming) {
5
+ if (!existingSet.has(pk)) mergedList.push(pk);
6
+ }
7
+ return mergedList;
8
+ }
9
+ export const paginatedFilter =
10
+ <C extends (...args: readonly any[]) => readonly any[]>(removeCursor: C) =>
11
+ (...args: Parameters<C>) => {
12
+ const noCursorArgs = removeCursor(...args);
13
+ return (collectionKey: Record<string, string>) =>
14
+ shallowEqual(collectionKey, noCursorArgs[0] ?? {});
15
+ };
16
+
17
+ function shallowEqual(
18
+ object1: Record<string, any>,
19
+ object2: Record<string, any>,
20
+ ) {
21
+ const keys1 = Object.keys(object1);
22
+ const keys2 = Object.keys(object2);
23
+ if (keys1.length !== keys2.length) {
24
+ return false;
25
+ }
26
+ for (const key of keys1) {
27
+ if (object1[key] != object2[key]) {
28
+ return false;
29
+ }
30
+ }
31
+ return true;
32
+ }
@@ -0,0 +1,49 @@
1
+ import { Schema } from '@data-client/endpoint';
2
+
3
+ import getArrayPath from './getArrayPath.js';
4
+
5
+ export default function paginationUpdate<
6
+ E extends { schema: Schema; key: any } & ((...args: any) => Promise<any>),
7
+ A extends any[],
8
+ >(
9
+ endpoint: E,
10
+ removeCursor: (...args: A) => readonly [...Parameters<typeof endpoint>],
11
+ ) {
12
+ // infer path from schema. if schema is undefined assume array is top level
13
+ const path = getArrayPath(endpoint.schema);
14
+ if (path === false) throw new Error('schema has no array');
15
+
16
+ return (newPage: any, ...args: A) => ({
17
+ [endpoint.key(...(removeCursor(...args) as any))]: (existing: any) => {
18
+ const existingList = getIn(existing, path);
19
+ // using set so our lookups are O(1) in case this is large
20
+ const existingSet: Set<string> = new Set(existingList);
21
+ const addedList = getIn(newPage, path).filter(
22
+ (pk: string) => !existingSet.has(pk),
23
+ );
24
+ const mergedResults: string[] = [...existingList, ...addedList];
25
+ return setIn(newPage, path, mergedResults);
26
+ },
27
+ });
28
+ }
29
+
30
+ const getIn = (results: any, path: string[]): any[] => {
31
+ let cur = results;
32
+ for (const p of path) {
33
+ if (!cur) return [];
34
+ cur = cur[p];
35
+ }
36
+ return cur || [];
37
+ };
38
+
39
+ const setIn = <T>(results: T, path: string[], values: any[]): T => {
40
+ if (path.length === 0) return values as any;
41
+ const newResults = { ...results };
42
+ let cur: any = newResults;
43
+ for (let i = 0; i < path.length - 1; i++) {
44
+ const p = path[i];
45
+ cur = cur[p] = { ...cur[p] };
46
+ }
47
+ cur[path[path.length - 1]] = values;
48
+ return newResults;
49
+ };
@@ -0,0 +1,10 @@
1
+ export default function paramsToString(
2
+ searchParams: Readonly<Record<string, string | number>>,
3
+ ) {
4
+ const params = new URLSearchParams(searchParams as any);
5
+ try {
6
+ params.sort();
7
+ // eslint-disable-next-line no-empty
8
+ } catch {}
9
+ return params.toString();
10
+ }
@@ -0,0 +1,7 @@
1
+ export default function paramsToString(
2
+ searchParams: Readonly<Record<string, string | number | boolean>>,
3
+ ) {
4
+ const params = new URLSearchParams(searchParams as any);
5
+ params.sort();
6
+ return params.toString();
7
+ }
@@ -0,0 +1,58 @@
1
+ type OnlyOptional<S extends string> = S extends `${infer K}?` ? K : never;
2
+ type OnlyRequired<S extends string> = S extends `${string}?` ? never : S;
3
+
4
+ /** Computes the union of keys for a path string */
5
+ export type PathKeys<S extends string> = string extends S
6
+ ? string
7
+ : S extends `${infer A}\\:${infer B}`
8
+ ? PathKeys<A> | PathKeys<B>
9
+ : S extends `${infer A}\\?${infer B}`
10
+ ? PathKeys<A> | PathKeys<B>
11
+ : PathSplits<S>;
12
+
13
+ type PathSplits<S extends string> = S extends `${string}:${infer K}${
14
+ | '/'
15
+ | ','
16
+ | '%'
17
+ | '&'}${infer R}`
18
+ ? PathSplits<`:${K}`> | PathSplits<R>
19
+ : S extends `${string}:${infer K}:${infer R}`
20
+ ? PathSplits<`:${K}`> | PathSplits<`:${R}`>
21
+ : S extends `${string}:${infer K}`
22
+ ? K
23
+ : never;
24
+
25
+ /** Parameters for a given path */
26
+ export type PathArgs<S extends string> = PathKeys<S> extends never
27
+ ? // unknown is identity for intersection ('&')
28
+ unknown
29
+ : KeysToArgs<PathKeys<S>>;
30
+
31
+ export type KeysToArgs<Key extends string> = {
32
+ [K in Key as OnlyOptional<K>]?: string | number;
33
+ } & (OnlyRequired<Key> extends never
34
+ ? unknown
35
+ : {
36
+ [K in Key as OnlyRequired<K>]: string | number;
37
+ });
38
+
39
+ export type PathArgsAndSearch<S extends string> = OnlyRequired<
40
+ PathKeys<S>
41
+ > extends never
42
+ ? Record<string, number | string | boolean> | undefined
43
+ : {
44
+ [K in PathKeys<S> as OnlyRequired<K>]: string | number;
45
+ } & Record<string, number | string>;
46
+
47
+ /** Removes the last :token */
48
+ export type ShortenPath<S extends string> = string extends S
49
+ ? string
50
+ : S extends `${infer B}:${infer R}`
51
+ ? TrimColon<`${B}:${ShortenPath<R>}`>
52
+ : '';
53
+
54
+ type TrimColon<S extends string> = string extends S
55
+ ? string
56
+ : S extends `${infer R}:`
57
+ ? R
58
+ : S;
@@ -0,0 +1,128 @@
1
+ export const payload = {
2
+ id: 5,
3
+ title: 'hi ho',
4
+ content: 'whatever',
5
+ tags: ['a', 'best', 'react'],
6
+ };
7
+
8
+ export const createPayload = {
9
+ id: 1,
10
+ title: 'hi ho',
11
+ content: 'whatever',
12
+ tags: ['a', 'best', 'react'],
13
+ };
14
+
15
+ export const articlesPages = {
16
+ prevPage: '23asdl',
17
+ nextPage: 's3f3',
18
+ results: [
19
+ {
20
+ id: 23,
21
+ title: 'the first draft',
22
+ content: 'the best things in life com efree',
23
+ tags: ['one', 'two'],
24
+ },
25
+ {
26
+ id: 44,
27
+ title: 'the second book',
28
+ content: 'the best things in life com efree',
29
+ tags: ['hbh', 'wew'],
30
+ },
31
+ {
32
+ id: 2,
33
+ title: 'the third novel',
34
+ content: 'the best things in life com efree',
35
+ tags: ['free', 'honey'],
36
+ },
37
+ {
38
+ id: 643,
39
+ title: 'a long time ago',
40
+ content: 'the best things in life com efree',
41
+ },
42
+ ],
43
+ };
44
+
45
+ export const users = [
46
+ {
47
+ id: 23,
48
+ username: 'bob',
49
+ email: 'bob@bob.com',
50
+ isAdmin: false,
51
+ },
52
+ {
53
+ id: 7342,
54
+ username: 'lindsey',
55
+ email: 'lindsey@bob.com',
56
+ isAdmin: true,
57
+ },
58
+ ];
59
+
60
+ export const nested = [
61
+ {
62
+ id: 5,
63
+ title: 'hi ho',
64
+ content: 'whatever',
65
+ tags: ['a', 'best', 'react'],
66
+ author: {
67
+ id: 23,
68
+ username: 'bob',
69
+ },
70
+ },
71
+ {
72
+ id: 3,
73
+ title: 'the next time',
74
+ content: 'whatever',
75
+ author: {
76
+ id: 23,
77
+ username: 'charles',
78
+ email: 'bob@bob.com',
79
+ },
80
+ },
81
+ ];
82
+
83
+ export const moreNested = [
84
+ {
85
+ id: 7,
86
+ title: 'article 7',
87
+ content: 'whatever',
88
+ tags: ['blah'],
89
+ author: {
90
+ id: 23,
91
+ username: 'bob',
92
+ },
93
+ },
94
+ {
95
+ id: 8,
96
+ title: 'article 8',
97
+ content: 'whatever',
98
+ author: {
99
+ id: 27,
100
+ username: 'zac',
101
+ email: 'zac@bob.com',
102
+ },
103
+ },
104
+ ];
105
+
106
+ export const valuesFixture = {
107
+ first: {
108
+ id: 1,
109
+ title: 'first thing',
110
+ content: 'blah',
111
+ tags: [],
112
+ },
113
+ second: {
114
+ id: 2,
115
+ name: 'second thing',
116
+ content: 'blah',
117
+ tags: [],
118
+ },
119
+ };
120
+
121
+ export const paginatedFirstPage = {
122
+ nextPage: '2',
123
+ data: { results: nested },
124
+ };
125
+
126
+ export const paginatedSecondPage = {
127
+ data: { results: moreNested },
128
+ };
@@ -0,0 +1,25 @@
1
+ /** Extracts only the keys that will be required
2
+ *
3
+ * Removes optional, as well as unbounded (aka 'string')
4
+ *
5
+ * @example
6
+ ```
7
+ RequiredKeys<{
8
+ opt?: string;
9
+ bob: string;
10
+ alice: number;
11
+ [k: string]: string | number | undefined;
12
+ }> // = 'bob' | 'alice'
13
+ ```
14
+ */
15
+ export type RequiredKeys<T> = Values<OnlyRequired<T>>;
16
+
17
+ type OnlyRequired<T> = {
18
+ [K in keyof T as string extends K ? never : K]-?: {} extends Pick<T, K>
19
+ ? never
20
+ : K;
21
+ };
22
+
23
+ // exclude number only required for typescript 4.4 and below
24
+ // https://www.typescriptlang.org/play?ts=4.4.4#code/C4TwDgpgBAglC8UDeUBGB7VAuKBnYATgJYB2A5gNxQDaA1jvseQLo4CsAPo6WVAL4UAsACgRIiAA8w6AsCihIUAEoQAjgFciBCABMA0hBC4APABUAfAigA1AIYAbdRBMB5EvZAqNW3WfPmhUWFJaVl5cGg3Dy9NbR0-KyQRKBo9KFIoWkN0ADMoUyhbXDxCHihJYAgSHWK0gH4oEggANwgCKBw9ZgBaOpwkPnKJSurigAUiAGNaMwAaKD1zZJSoBqbWgmWUzsCBMWEFaDtHZwTEUzpsvNNmQJFDqABhKyjPNVjfGCWDiKgAIT+ViyIFyT3uv0ez0QxycJke5iAA
25
+ type Values<T> = T[Exclude<keyof T, number>];
@@ -0,0 +1,11 @@
1
+ /** An error with a Rest Endpoint fetch
2
+ *
3
+ * @see https://resthooks.io/rest/api/NetworkError
4
+ */
5
+ export default class NetworkError extends Error {
6
+ status: number;
7
+ response: Response;
8
+ name: string;
9
+ constructor(response: Response);
10
+ }
11
+ //# sourceMappingURL=NetworkError.d.ts.map
@@ -0,0 +1,16 @@
1
+ import type { FetchFunction, ResolveType } from '@data-client/endpoint';
2
+
3
+ import { PartialRestGenerics, RestInstance } from './RestEndpoint.js';
4
+
5
+ export type OptionsToFunction<
6
+ O extends PartialRestGenerics,
7
+ E extends RestInstance & {
8
+ body?: any;
9
+ },
10
+ F extends FetchFunction,
11
+ > = (
12
+ this: ThisParameterType<F>,
13
+ ...args: any
14
+ ) => Promise<
15
+ O['process'] extends {} ? ReturnType<O['process']> : ResolveType<F>
16
+ >;
@@ -0,0 +1,240 @@
1
+ /* eslint-disable @typescript-eslint/ban-types */
2
+ import type { EndpointExtraOptions, EndpointInstanceInterface, Schema, FetchFunction, ResolveType, } from '@data-client/endpoint';
3
+ import type { ExtractCollection } from './extractCollection.js';
4
+ import { OptionsToFunction } from './OptionsToFunction.js';
5
+ import { PathArgs } from './pathTypes.js';
6
+ import { EndpointUpdateFunction } from './RestEndpointTypeHelp.js';
7
+ export interface RestInstanceBase<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, M extends true | undefined = true | undefined, O extends {
8
+ path: string;
9
+ body?: any;
10
+ searchParams?: any;
11
+ } = {
12
+ path: string;
13
+ }> extends EndpointInstanceInterface<F, S, M> {
14
+ readonly body?: 'body' extends keyof O ? O['body'] : any;
15
+ readonly searchParams?: 'searchParams' extends keyof O ? O['searchParams'] : unknown;
16
+ /** Pattern to construct url based on Url Parameters
17
+ * @see https://resthooks.io/rest/api/RestEndpoint#path
18
+ */
19
+ readonly path: O['path'];
20
+ /** Prepended to all urls
21
+ * @see https://resthooks.io/rest/api/RestEndpoint#urlPrefix
22
+ */
23
+ readonly urlPrefix: string;
24
+ readonly requestInit: RequestInit;
25
+ readonly method: string;
26
+ readonly signal: AbortSignal | undefined;
27
+ /* fetch lifecycles */
28
+ /* before-fetch */
29
+ url(...args: Parameters<F>): string;
30
+ /** @see https://resthooks.io/rest/api/RestEndpoint#getRequestInit */
31
+ getRequestInit(this: any, body?: RequestInit['body'] | Record<string, unknown>): RequestInit;
32
+ /** @see https://resthooks.io/rest/api/RestEndpoint#getHeaders */
33
+ getHeaders(headers: HeadersInit): HeadersInit;
34
+ /* after-fetch */
35
+ /** @see https://resthooks.io/rest/api/RestEndpoint#fetchResponse */
36
+ fetchResponse(input: RequestInfo, init: RequestInit): Promise<Response>;
37
+ /** @see https://resthooks.io/rest/api/RestEndpoint#parseResponse */
38
+ parseResponse(response: Response): Promise<any>;
39
+ /** @see https://resthooks.io/rest/api/RestEndpoint#process */
40
+ process(value: any, ...args: Parameters<F>): ResolveType<F>;
41
+ /* utilities */
42
+ /** @see https://resthooks.io/rest/api/RestEndpoint#testKey */
43
+ testKey(key: string): boolean;
44
+ /* extenders */
45
+ // TODO: figure out better way than wrapping whole options in Readonly<> + making O extend from {}
46
+ // this is just a hack to handle when no members of PartialRestGenerics are present
47
+ // Note: Using overloading (like paginated did) struggles because typescript does not have a clear way of distinguishing one
48
+ // should be used from the other (due to same problem with every member being partial)
49
+ extend<E extends RestInstanceBase, O extends PartialRestGenerics | {}>(this: E, options: Readonly<RestEndpointExtendOptions<O, E, F> & O>): RestExtendedEndpoint<O, E>;
50
+ paginated<E extends RestInstanceBase<FetchFunction, any, undefined>, A extends any[]>(this: E, removeCursor: (...args: A) => readonly [
51
+ ...Parameters<E>
52
+ ]): PaginationEndpoint<E, A>;
53
+ paginated<E extends RestInstanceBase<FetchFunction, any, undefined>, C extends string>(this: E, cursorField: C): PaginationFieldEndpoint<E, C>;
54
+ }
55
+ export interface RestInstance<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, M extends true | undefined = true | undefined, O extends {
56
+ path: string;
57
+ body?: any;
58
+ searchParams?: any;
59
+ } = {
60
+ path: string;
61
+ }> extends RestInstanceBase<F, S, M, O> {
62
+ push: AddEndpoint<F, S, O>;
63
+ unshift: AddEndpoint<F, S, O>;
64
+ assign: AddEndpoint<F, S, O>;
65
+ }
66
+ export type ContainsCollectionArray = {
67
+ push: any;
68
+ unshift: any;
69
+ } | {
70
+ [K: string]: ContainsCollectionArray;
71
+ } | {
72
+ schema: {
73
+ [K: string]: ContainsCollectionArray;
74
+ };
75
+ };
76
+ export type ContainsCollectionValues = {
77
+ assign: any;
78
+ } | {
79
+ [K: string]: ContainsCollectionValues;
80
+ } | {
81
+ schema: {
82
+ [K: string]: ContainsCollectionValues;
83
+ };
84
+ };
85
+ export type RestEndpointExtendOptions<O extends PartialRestGenerics, E extends RestInstanceBase, F extends FetchFunction> = RestEndpointOptions<OptionsToFunction<O, E, F>, 'schema' extends keyof O ? Extract<O['schema'], Schema | undefined> : E['schema']> & Partial<Omit<E, KeyofRestEndpoint | keyof PartialRestGenerics>>;
86
+ type OptionsToRestEndpoint<O extends PartialRestGenerics, E extends RestInstanceBase & {
87
+ body?: any;
88
+ }, F extends FetchFunction> = 'path' extends keyof O ? RestType<'searchParams' extends keyof O ? O['searchParams'] extends undefined ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<O['path'], undefined>> : PathArgs<Exclude<O['path'], undefined>>, 'body' extends keyof O ? O['body'] : E['body'], 'schema' extends keyof O ? O['schema'] : E['schema'], 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], O['process'] extends {} ? ReturnType<O['process']> : ResolveType<F>, {
89
+ path: Exclude<O['path'], undefined>;
90
+ body: 'body' extends keyof O ? O['body'] : E['body'];
91
+ searchParams: 'searchParams' extends keyof O ? O['searchParams'] : E['searchParams'];
92
+ }> : 'body' extends keyof O ? RestType<'searchParams' extends keyof O ? O['searchParams'] extends undefined ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<E['path'], undefined>> : PathArgs<Exclude<E['path'], undefined>>, O['body'], 'schema' extends keyof O ? O['schema'] : E['schema'], 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], O['process'] extends {} ? ReturnType<O['process']> : ResolveType<F>, {
93
+ path: E['path'];
94
+ body: O['body'];
95
+ searchParams: 'searchParams' extends keyof O ? O['searchParams'] : E['searchParams'];
96
+ }> : 'searchParams' extends keyof O ? RestType<O['searchParams'] extends undefined ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<E['path'], undefined>>, E['body'], 'schema' extends keyof O ? O['schema'] : E['schema'], 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], O['process'] extends {} ? ReturnType<O['process']> : ResolveType<F>, {
97
+ path: E['path'];
98
+ body: E['body'];
99
+ searchParams: O['searchParams'];
100
+ }> : RestInstance<F, 'schema' extends keyof O ? O['schema'] : E['schema'], 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect'], {
101
+ path: 'path' extends keyof O ? Exclude<O['path'], undefined> : E['path'];
102
+ body: 'body' extends keyof O ? O['body'] : E['body'];
103
+ searchParams: 'searchParams' extends keyof O ? O['searchParams'] : E['searchParams'];
104
+ }>;
105
+ export type RestExtendedEndpoint<O extends PartialRestGenerics, E extends RestInstanceBase> = OptionsToRestEndpoint<O, E, RestInstance<(...args: Parameters<E>) => O['process'] extends {} ? Promise<ReturnType<O['process']>> : ReturnType<E>, 'schema' extends keyof O ? O['schema'] : E['schema'], 'method' extends keyof O ? MethodToSide<O['method']> : E['sideEffect']>> & Omit<O, KeyofRestEndpoint> & Omit<E, KeyofRestEndpoint | keyof O>;
106
+ export interface PartialRestGenerics {
107
+ readonly path?: string;
108
+ readonly schema?: Schema | undefined;
109
+ readonly method?: string;
110
+ /** Only used for types */
111
+ readonly body?: any;
112
+ /** Only used for types */
113
+ readonly searchParams?: any;
114
+ /** @see https://resthooks.io/rest/api/RestEndpoint#process */
115
+ process?(value: any, ...args: any): any;
116
+ }
117
+ export interface RestGenerics extends PartialRestGenerics {
118
+ readonly path: string;
119
+ }
120
+ export type PaginationEndpoint<E extends RestInstanceBase, A extends any[]> = RestInstance<ParamFetchNoBody<A[0], ResolveType<E>>, E['schema'], E['sideEffect'], Pick<E, 'path' | 'searchParams' | 'body'> & {
121
+ searchParams: Omit<A[0], keyof PathArgs<E['path']>>;
122
+ }>;
123
+ export type PaginationFieldEndpoint<E extends RestInstanceBase, C extends string> = RestInstance<ParamFetchNoBody<{
124
+ [K in C]: string | number | boolean;
125
+ } & E['searchParams'] & PathArgs<Exclude<E['path'], undefined>>, ResolveType<E>>, E['schema'], E['sideEffect'], Pick<E, 'path' | 'searchParams' | 'body'> & {
126
+ searchParams: {
127
+ [K in C]: string | number | boolean;
128
+ } & E['searchParams'];
129
+ }>;
130
+ export type AddEndpoint<F extends FetchFunction = FetchFunction, S extends Schema | undefined = any, O extends {
131
+ path: string;
132
+ body?: any;
133
+ searchParams?: any;
134
+ } = {
135
+ path: string;
136
+ }> = RestInstanceBase<RestFetch<'searchParams' extends keyof O ? O['searchParams'] extends undefined ? PathArgs<Exclude<O['path'], undefined>> : O['searchParams'] & PathArgs<Exclude<O['path'], undefined>> : PathArgs<Exclude<O['path'], undefined>>, any, ReturnType<F>>, ExtractCollection<S>, true, Omit<O, 'body'>> & {
137
+ method: 'POST';
138
+ };
139
+ export type BodyDefault<O extends RestGenerics> = 'body' extends keyof O ? O['body'] : O['method'] extends 'POST' | 'PUT' | 'PATCH' ? Record<string, unknown> | FormData : undefined;
140
+ type OptionsBodyDefault<O extends RestGenerics> = 'body' extends keyof O ? O : O['method'] extends 'POST' | 'PUT' | 'PATCH' ? O & {
141
+ body: any;
142
+ } : O & {
143
+ body: undefined;
144
+ };
145
+ export interface RestEndpointOptions<F extends FetchFunction = FetchFunction, S extends Schema | undefined = undefined> extends EndpointExtraOptions<F> {
146
+ urlPrefix?: string;
147
+ requestInit?: RequestInit;
148
+ getHeaders?(headers: HeadersInit): Promise<HeadersInit> | HeadersInit;
149
+ getRequestInit?(body: any): Promise<RequestInit> | RequestInit;
150
+ fetchResponse?(input: RequestInfo, init: RequestInit): Promise<any>;
151
+ parseResponse?(response: Response): Promise<any>;
152
+ sideEffect?: true | undefined;
153
+ name?: string;
154
+ signal?: AbortSignal;
155
+ fetch?: F;
156
+ key?(...args: Parameters<F>): string;
157
+ url?(...args: Parameters<F>): string;
158
+ update?: EndpointUpdateFunction<F, S>;
159
+ }
160
+ export type RestEndpointConstructorOptions<O extends RestGenerics = any> = RestEndpointOptions<RestFetch<'searchParams' extends keyof O ? O['searchParams'] extends undefined ? PathArgs<O['path']> : O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, BodyDefault<O>, O['process'] extends {} ? ReturnType<O['process']> : any /*Denormalize<O['schema']>*/>, O['schema']>;
161
+ export interface RestEndpointConstructor {
162
+ new <O extends RestGenerics = any>({ method, sideEffect, name, ...options }: RestEndpointConstructorOptions<O> & Readonly<O>): RestInstance<RestFetch<'searchParams' extends keyof O ? O['searchParams'] extends undefined ? PathArgs<O['path']> : O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, BodyDefault<O>, O['process'] extends {} ? ReturnType<O['process']> : any /*Denormalize<O['schema']>*/>, 'schema' extends keyof O ? O['schema'] : undefined, MethodToSide<O['method']>, OptionsBodyDefault<O>>;
163
+ readonly prototype: RestInstanceBase;
164
+ }
165
+ /** Simplifies endpoint definitions that follow REST patterns
166
+ *
167
+ * @see https://resthooks.io/rest/api/RestEndpoint
168
+ */
169
+ export declare let RestEndpoint: RestEndpointConstructor;
170
+ export default RestEndpoint;
171
+ export type MethodToSide<M> = M extends string ? M extends 'GET' ? undefined : true : undefined;
172
+ /** RestEndpoint types simplified */
173
+ export type RestType<UrlParams = any, Body = any, S extends Schema | undefined = Schema | undefined, M extends true | undefined = true | undefined, R = any, O extends {
174
+ path: string;
175
+ body?: any;
176
+ searchParams?: any;
177
+ } = {
178
+ path: string;
179
+ }> = IfTypeScriptLooseNull<RestInstance<keyof UrlParams extends never ? (this: EndpointInstanceInterface, body?: Body) => Promise<R> : {} extends UrlParams ? ((this: EndpointInstanceInterface, body?: Body) => Promise<R>) | ((this: EndpointInstanceInterface, params: UrlParams, body?: Body) => Promise<R>) : (this: EndpointInstanceInterface, params: UrlParams, body?: Body) => Promise<R>, S, M, O>, Body extends {} ? RestTypeWithBody<UrlParams, S, M, Body, R, O> : RestTypeNoBody<UrlParams, S, M, R, O>>;
180
+ export type RestTypeWithBody<UrlParams = any, S extends Schema | undefined = Schema | undefined, M extends true | undefined = true | undefined, Body = any, R = any /*Denormalize<S>*/, O extends {
181
+ path: string;
182
+ body?: any;
183
+ searchParams?: any;
184
+ } = {
185
+ path: string;
186
+ body: any;
187
+ }> = RestInstance<ParamFetchWithBody<UrlParams, Body, R>, S, M, O>;
188
+ export type RestTypeNoBody<UrlParams = any, S extends Schema | undefined = Schema | undefined, M extends true | undefined = true | undefined, R = any /*Denormalize<S>*/, O extends {
189
+ path: string;
190
+ body?: undefined;
191
+ searchParams?: any;
192
+ } = {
193
+ path: string;
194
+ body: undefined;
195
+ }> = RestInstance<ParamFetchNoBody<UrlParams, R>, S, M, O>;
196
+ /** Simple parameters, and body fetch functions */
197
+ export type RestFetch<UrlParams,
198
+ // eslint-disable-next-line @typescript-eslint/ban-types
199
+ Body = {}, Resolve = any> = IfTypeScriptLooseNull<ParamFetchNoBody<UrlParams, Resolve> | ParamFetchWithBody<UrlParams, Body, Resolve>, Body extends {} ? ParamFetchWithBody<UrlParams, Body, Resolve> : ParamFetchNoBody<UrlParams, Resolve>>;
200
+ export type ParamFetchWithBody<P, B = {}, R = any> =
201
+ // we must always allow undefined in a union and give it a type without params
202
+ P extends undefined ? (this: EndpointInstanceInterface, body: B) => Promise<R> : {} extends P ? keyof P extends never ? (this: EndpointInstanceInterface, body: B) => Promise<R> : ((this: EndpointInstanceInterface, params: P, body: B) => Promise<R>) | ((this: EndpointInstanceInterface, body: B) => Promise<R>) : (this: EndpointInstanceInterface, params: P, body: B) => Promise<R>;
203
+ export type ParamFetchNoBody<P, R = any> =
204
+ // we must always allow undefined in a union and give it a type without params
205
+ P extends undefined ? (this: EndpointInstanceInterface) => Promise<R> : {} extends P ? keyof P extends never ? (this: EndpointInstanceInterface) => Promise<R> : ((this: EndpointInstanceInterface, params: P) => Promise<R>) | ((this: EndpointInstanceInterface) => Promise<R>) : (this: EndpointInstanceInterface, params: P) => Promise<R>;
206
+ type IfTypeScriptLooseNull<Y, N> = 1 | undefined extends 1 ? Y : N;
207
+ export type KeyofRestEndpoint = keyof RestInstance;
208
+ export type FromFallBack<K extends keyof E, O, E> = K extends keyof O ? O[K] : E[K];
209
+ export type FetchMutate<A extends readonly any[] = [
210
+ any,
211
+ {}
212
+ ]
213
+ // eslint-disable-next-line @typescript-eslint/ban-types
214
+ | [
215
+ {}
216
+ ], R = any> = (this: RestInstance, ...args: A) => Promise<R>;
217
+ export type FetchGet<A extends readonly any[] = [
218
+ any
219
+ ], R = any> = (this: RestInstance, ...args: A) => Promise<R>;
220
+ export type GetEndpoint<UrlParams = any, S extends Schema | undefined = Schema | undefined> = RestTypeNoBody<UrlParams, S, undefined>;
221
+ export type MutateEndpoint<UrlParams = any, Body extends BodyInit | Record<string, any> = any, S extends Schema | undefined = Schema | undefined> = RestTypeWithBody<UrlParams, S, true, Body>;
222
+ export type Defaults<O, D> = {
223
+ [K in keyof O | keyof D]: K extends keyof O ? Exclude<O[K], undefined> : D[Extract<K, keyof D>];
224
+ };
225
+ export type NewGetEndpoint<O extends {
226
+ path: string;
227
+ searchParams?: any;
228
+ } = {
229
+ path: string;
230
+ }, S extends Schema | undefined = Schema | undefined> = RestTypeNoBody<'searchParams' extends keyof O ? O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, S, undefined, any, O & {
231
+ body: undefined;
232
+ }>;
233
+ export type NewMutateEndpoint<O extends {
234
+ path: string;
235
+ body?: any;
236
+ searchParams?: any;
237
+ } = {
238
+ path: string;
239
+ body: any;
240
+ }, S extends Schema | undefined = Schema | undefined> = RestTypeWithBody<'searchParams' extends keyof O ? O['searchParams'] & PathArgs<O['path']> : PathArgs<O['path']>, S, true, O['body'], any, O>;
@@ -0,0 +1,10 @@
1
+ import type { FetchFunction, ResolveType, Normalize } from '@data-client/endpoint';
2
+ export type EndpointUpdateFunction<Source extends FetchFunction, Schema, Updaters extends Record<string, any> = Record<string, any>> = (source: ResultEntry<Source & {
3
+ schema: Schema;
4
+ }>, ...args: Parameters<Source>) => {
5
+ [K in keyof Updaters]: (result: Updaters[K]) => Updaters[K];
6
+ };
7
+ export type ResultEntry<E extends FetchFunction & {
8
+ schema: any;
9
+ }> = E['schema'] extends undefined | null ? ResolveType<E> : Normalize<E['schema']>;
10
+ //# sourceMappingURL=RestEndpointTypeHelp.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { PathFunction } from 'path-to-regexp';
2
+ import { ShortenPath } from './pathTypes.js';
3
+ export declare function getUrlBase(path: string): PathFunction;
4
+ export declare function getUrlTokens(path: string): Set<string>;
5
+ export declare function isPojo(obj: unknown): obj is Record<string, any>;
6
+ export declare function shortenPath<S extends string>(path: S): ShortenPath<S>;
7
+ //# sourceMappingURL=RestHelpers.d.ts.map