@bikefinder/api-client 0.2.0 → 0.4.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/README.md +38 -2
- package/dist/admin/generated/client/client.gen.d.ts +3 -0
- package/dist/admin/generated/client/client.gen.d.ts.map +1 -0
- package/dist/admin/generated/client/client.gen.js +218 -0
- package/dist/admin/generated/client/client.gen.js.map +1 -0
- package/dist/admin/generated/client/index.d.ts +11 -0
- package/dist/admin/generated/client/index.d.ts.map +1 -0
- package/dist/admin/generated/client/index.js +7 -0
- package/dist/admin/generated/client/index.js.map +1 -0
- package/dist/admin/generated/client/types.gen.d.ts +121 -0
- package/dist/admin/generated/client/types.gen.d.ts.map +1 -0
- package/dist/admin/generated/client/types.gen.js +3 -0
- package/dist/admin/generated/client/types.gen.js.map +1 -0
- package/dist/admin/generated/client/utils.gen.d.ts +38 -0
- package/dist/admin/generated/client/utils.gen.d.ts.map +1 -0
- package/dist/admin/generated/client/utils.gen.js +232 -0
- package/dist/admin/generated/client/utils.gen.js.map +1 -0
- package/dist/admin/generated/client.gen.d.ts +13 -0
- package/dist/admin/generated/client.gen.d.ts.map +1 -0
- package/dist/admin/generated/client.gen.js +4 -0
- package/dist/admin/generated/client.gen.js.map +1 -0
- package/dist/admin/generated/core/auth.gen.d.ts +26 -0
- package/dist/admin/generated/core/auth.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/auth.gen.js +15 -0
- package/dist/admin/generated/core/auth.gen.js.map +1 -0
- package/dist/admin/generated/core/bodySerializer.gen.d.ts +26 -0
- package/dist/admin/generated/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/bodySerializer.gen.js +58 -0
- package/dist/admin/generated/core/bodySerializer.gen.js.map +1 -0
- package/dist/admin/generated/core/params.gen.d.ts +44 -0
- package/dist/admin/generated/core/params.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/params.gen.js +113 -0
- package/dist/admin/generated/core/params.gen.js.map +1 -0
- package/dist/admin/generated/core/pathSerializer.gen.d.ts +34 -0
- package/dist/admin/generated/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/pathSerializer.gen.js +115 -0
- package/dist/admin/generated/core/pathSerializer.gen.js.map +1 -0
- package/dist/admin/generated/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/admin/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/queryKeySerializer.gen.js +100 -0
- package/dist/admin/generated/core/queryKeySerializer.gen.js.map +1 -0
- package/dist/admin/generated/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/admin/generated/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/serverSentEvents.gen.js +137 -0
- package/dist/admin/generated/core/serverSentEvents.gen.js.map +1 -0
- package/dist/admin/generated/core/types.gen.d.ts +84 -0
- package/dist/admin/generated/core/types.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/types.gen.js +3 -0
- package/dist/admin/generated/core/types.gen.js.map +1 -0
- package/dist/admin/generated/core/utils.gen.d.ts +20 -0
- package/dist/admin/generated/core/utils.gen.d.ts.map +1 -0
- package/dist/admin/generated/core/utils.gen.js +88 -0
- package/dist/admin/generated/core/utils.gen.js.map +1 -0
- package/dist/admin/generated/index.d.ts +3 -0
- package/dist/admin/generated/index.d.ts.map +1 -0
- package/dist/admin/generated/index.js +3 -0
- package/dist/admin/generated/index.js.map +1 -0
- package/dist/admin/generated/sdk.gen.d.ts +188 -0
- package/dist/admin/generated/sdk.gen.d.ts.map +1 -0
- package/dist/admin/generated/sdk.gen.js +531 -0
- package/dist/admin/generated/sdk.gen.js.map +1 -0
- package/dist/admin/generated/types.gen.d.ts +2493 -0
- package/dist/admin/generated/types.gen.d.ts.map +1 -0
- package/dist/admin/generated/types.gen.js +3 -0
- package/dist/admin/generated/types.gen.js.map +1 -0
- package/dist/admin/generated/zod.gen.d.ts +2755 -0
- package/dist/admin/generated/zod.gen.d.ts.map +1 -0
- package/dist/admin/generated/zod.gen.js +606 -0
- package/dist/admin/generated/zod.gen.js.map +1 -0
- package/dist/admin/index.d.ts +15 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +19 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/generated/sdk.gen.d.ts +80 -45
- package/dist/generated/sdk.gen.d.ts.map +1 -1
- package/dist/generated/sdk.gen.js +192 -157
- package/dist/generated/sdk.gen.js.map +1 -1
- package/dist/generated/types.gen.d.ts +887 -453
- package/dist/generated/types.gen.d.ts.map +1 -1
- package/dist/generated/zod.gen.d.ts +468 -286
- package/dist/generated/zod.gen.d.ts.map +1 -1
- package/dist/generated/zod.gen.js +188 -201
- package/dist/generated/zod.gen.js.map +1 -1
- package/dist/http-client.d.ts +1 -1
- package/dist/http-client.d.ts.map +1 -1
- package/dist/http-client.js +3 -3
- package/dist/http-client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/realtime/api-stream-error.d.ts +2 -1
- package/dist/realtime/api-stream-error.d.ts.map +1 -1
- package/dist/realtime/api-stream-error.js +8 -1
- package/dist/realtime/api-stream-error.js.map +1 -1
- package/dist/realtime/watch.d.ts +8 -8
- package/dist/realtime/watch.d.ts.map +1 -1
- package/dist/realtime/watch.js +2 -2
- package/dist/realtime/watch.js.map +1 -1
- package/dist/transport.js +10 -1
- package/dist/transport.js.map +1 -1
- package/package.json +7 -2
- package/src/admin/generated/client/client.gen.ts +300 -0
- package/src/admin/generated/client/index.ts +27 -0
- package/src/admin/generated/client/types.gen.ts +238 -0
- package/src/admin/generated/client/utils.gen.ts +337 -0
- package/src/admin/generated/client.gen.ts +24 -0
- package/src/admin/generated/core/auth.gen.ts +49 -0
- package/src/admin/generated/core/bodySerializer.gen.ts +96 -0
- package/src/admin/generated/core/params.gen.ts +188 -0
- package/src/admin/generated/core/pathSerializer.gen.ts +186 -0
- package/src/admin/generated/core/queryKeySerializer.gen.ts +134 -0
- package/src/admin/generated/core/serverSentEvents.gen.ts +265 -0
- package/src/admin/generated/core/types.gen.ts +126 -0
- package/src/admin/generated/core/utils.gen.ts +146 -0
- package/src/admin/generated/index.ts +231 -0
- package/src/admin/generated/sdk.gen.ts +1180 -0
- package/src/admin/generated/types.gen.ts +2814 -0
- package/src/admin/generated/zod.gen.ts +746 -0
- package/src/admin/index.ts +34 -0
- package/src/generated/index.ts +6 -2
- package/src/generated/sdk.gen.ts +408 -373
- package/src/generated/types.gen.ts +956 -516
- package/src/generated/zod.gen.ts +217 -231
- package/src/http-client.ts +6 -3
- package/src/realtime/api-stream-error.ts +12 -1
- package/src/realtime/watch.ts +34 -22
- package/src/transport.ts +10 -1
package/src/http-client.ts
CHANGED
|
@@ -2,9 +2,12 @@ import { createClient } from "./generated/client/index.js";
|
|
|
2
2
|
import type { ResolvedClientOptions } from "./options.js";
|
|
3
3
|
import { createAuthenticatedFetch } from "./transport.js";
|
|
4
4
|
|
|
5
|
-
export function createHttpClient(
|
|
5
|
+
export function createHttpClient(
|
|
6
|
+
options: ResolvedClientOptions,
|
|
7
|
+
clientFactory = createClient,
|
|
8
|
+
) {
|
|
6
9
|
const authenticatedFetch = createAuthenticatedFetch(options);
|
|
7
|
-
const client =
|
|
10
|
+
const client = clientFactory({
|
|
8
11
|
baseUrl: options.baseUrl,
|
|
9
12
|
redirect: "error",
|
|
10
13
|
credentials: "omit",
|
|
@@ -15,7 +18,7 @@ export function createHttpClient(options: ResolvedClientOptions) {
|
|
|
15
18
|
// A per-call fetch would bypass authentication and transport policy.
|
|
16
19
|
if (requestOptions.fetch !== authenticatedFetch) {
|
|
17
20
|
throw new TypeError(
|
|
18
|
-
"Configure fetch on
|
|
21
|
+
"Configure fetch on the client factory, not individual requests.",
|
|
19
22
|
);
|
|
20
23
|
}
|
|
21
24
|
return request;
|
|
@@ -4,8 +4,13 @@ export type ApiStreamErrorCode = "http" | "protocol" | "network";
|
|
|
4
4
|
export class ApiStreamError extends Error {
|
|
5
5
|
readonly code: ApiStreamErrorCode;
|
|
6
6
|
readonly status: number | undefined;
|
|
7
|
+
readonly retryAfterMs: number | undefined;
|
|
7
8
|
|
|
8
|
-
constructor(
|
|
9
|
+
constructor(
|
|
10
|
+
code: ApiStreamErrorCode,
|
|
11
|
+
status?: number,
|
|
12
|
+
retryAfterMs?: number,
|
|
13
|
+
) {
|
|
9
14
|
super(
|
|
10
15
|
code === "http"
|
|
11
16
|
? `The tracker stream returned HTTP ${status}.`
|
|
@@ -16,5 +21,11 @@ export class ApiStreamError extends Error {
|
|
|
16
21
|
this.name = "ApiStreamError";
|
|
17
22
|
this.code = code;
|
|
18
23
|
this.status = status;
|
|
24
|
+
this.retryAfterMs =
|
|
25
|
+
retryAfterMs !== undefined &&
|
|
26
|
+
Number.isFinite(retryAfterMs) &&
|
|
27
|
+
retryAfterMs >= 0
|
|
28
|
+
? Math.min(retryAfterMs, 300_000)
|
|
29
|
+
: undefined;
|
|
19
30
|
}
|
|
20
31
|
}
|
package/src/realtime/watch.ts
CHANGED
|
@@ -17,43 +17,48 @@ import type { Options } from "../generated/sdk.gen.js";
|
|
|
17
17
|
import { ApiStreamError } from "./api-stream-error.js";
|
|
18
18
|
|
|
19
19
|
type Method = (...args: never[]) => unknown;
|
|
20
|
-
type Result<TKey extends keyof
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
: never;
|
|
20
|
+
type Result<TSdk, TKey extends keyof TSdk> = TSdk[TKey] extends Method
|
|
21
|
+
? Awaited<ReturnType<TSdk[TKey]>>
|
|
22
|
+
: never;
|
|
24
23
|
|
|
25
|
-
export type StreamOperation = {
|
|
26
|
-
[TKey in keyof
|
|
24
|
+
export type StreamOperation<TSdk = BikeFinderSdk> = {
|
|
25
|
+
[TKey in keyof TSdk]: Result<TSdk, TKey> extends {
|
|
27
26
|
stream: AsyncIterable<unknown>;
|
|
28
27
|
}
|
|
29
28
|
? TKey
|
|
30
29
|
: never;
|
|
31
|
-
}[keyof
|
|
30
|
+
}[keyof TSdk];
|
|
32
31
|
|
|
33
|
-
export type StreamPayload<
|
|
34
|
-
|
|
32
|
+
export type StreamPayload<
|
|
33
|
+
TKey extends StreamOperation<TSdk>,
|
|
34
|
+
TSdk = BikeFinderSdk,
|
|
35
|
+
> =
|
|
36
|
+
Result<TSdk, TKey> extends {
|
|
35
37
|
stream: AsyncIterable<infer TPayload>;
|
|
36
38
|
}
|
|
37
39
|
? Exclude<TPayload, null>
|
|
38
40
|
: never;
|
|
39
41
|
|
|
40
|
-
export type StreamOptions<
|
|
41
|
-
|
|
42
|
+
export type StreamOptions<
|
|
43
|
+
TKey extends StreamOperation<TSdk>,
|
|
44
|
+
TSdk = BikeFinderSdk,
|
|
45
|
+
> = Pick<
|
|
46
|
+
NonNullable<Parameters<Extract<TSdk[TKey], Method>>[0]>,
|
|
42
47
|
Extract<
|
|
43
|
-
keyof NonNullable<Parameters<
|
|
48
|
+
keyof NonNullable<Parameters<Extract<TSdk[TKey], Method>>[0]>,
|
|
44
49
|
"path" | "query"
|
|
45
50
|
>
|
|
46
51
|
>;
|
|
47
52
|
/**
|
|
48
|
-
* Observe complete snapshots of
|
|
53
|
+
* Observe complete snapshots of a generated view, shared by this observable's consumers.
|
|
49
54
|
* Unsubscribe when leaving the view or changing accounts. Re-subscribe after an error
|
|
50
55
|
* to start a fresh retry budget. Reconnects never request historical event replay.
|
|
51
56
|
*/
|
|
52
|
-
export function watch<TOperation extends StreamOperation
|
|
53
|
-
requests:
|
|
57
|
+
export function watch<TSdk, TOperation extends StreamOperation<TSdk>>(
|
|
58
|
+
requests: TSdk,
|
|
54
59
|
operation: TOperation,
|
|
55
|
-
options: StreamOptions<TOperation>,
|
|
56
|
-
): Observable<StreamPayload<TOperation>> {
|
|
60
|
+
options: StreamOptions<TOperation, TSdk>,
|
|
61
|
+
): Observable<StreamPayload<TOperation, TSdk>> {
|
|
57
62
|
// The generated SDK supplies paths, arguments and validators for every stream.
|
|
58
63
|
// This boundary only adds the shared connection lifecycle.
|
|
59
64
|
const invoke = requests[operation] as (
|
|
@@ -61,7 +66,7 @@ export function watch<TOperation extends StreamOperation>(
|
|
|
61
66
|
) => Promise<{ stream: AsyncIterable<unknown> }>;
|
|
62
67
|
return defer(() => {
|
|
63
68
|
const disconnected = new Subject<undefined>();
|
|
64
|
-
const snapshots = new Observable<StreamPayload<TOperation>>(
|
|
69
|
+
const snapshots = new Observable<StreamPayload<TOperation, TSdk>>(
|
|
65
70
|
(subscriber) => {
|
|
66
71
|
disconnected.next(undefined);
|
|
67
72
|
const controller = new AbortController();
|
|
@@ -88,7 +93,7 @@ export function watch<TOperation extends StreamOperation>(
|
|
|
88
93
|
if (data === null || typeof data !== "object") {
|
|
89
94
|
throw new ApiStreamError("protocol");
|
|
90
95
|
}
|
|
91
|
-
subscriber.next(data as StreamPayload<TOperation>);
|
|
96
|
+
subscriber.next(data as StreamPayload<TOperation, TSdk>);
|
|
92
97
|
},
|
|
93
98
|
});
|
|
94
99
|
// Event callbacks retain SSE event names; consuming drives the generated
|
|
@@ -131,7 +136,12 @@ export function watch<TOperation extends StreamOperation>(
|
|
|
131
136
|
(error.status ?? 0) >= 500)));
|
|
132
137
|
if (!retryable) throw error;
|
|
133
138
|
const maximum = Math.min(30_000, 1_000 * 2 ** (attempt - 1));
|
|
134
|
-
return timer(
|
|
139
|
+
return timer(
|
|
140
|
+
Math.max(
|
|
141
|
+
maximum * (0.5 + Math.random() * 0.5),
|
|
142
|
+
error.retryAfterMs ?? 0,
|
|
143
|
+
),
|
|
144
|
+
);
|
|
135
145
|
},
|
|
136
146
|
}),
|
|
137
147
|
),
|
|
@@ -139,13 +149,15 @@ export function watch<TOperation extends StreamOperation>(
|
|
|
139
149
|
}).pipe(
|
|
140
150
|
share({
|
|
141
151
|
connector: () =>
|
|
142
|
-
new ReplaySubject<StreamPayload<TOperation> | undefined>(1),
|
|
152
|
+
new ReplaySubject<StreamPayload<TOperation, TSdk> | undefined>(1),
|
|
143
153
|
resetOnError: true,
|
|
144
154
|
resetOnComplete: true,
|
|
145
155
|
resetOnRefCountZero: true,
|
|
146
156
|
}),
|
|
147
157
|
// An internal disconnect marker replaces the cached page during backoff, so a
|
|
148
158
|
// new subscriber never receives an old snapshot as though it were current.
|
|
149
|
-
filter(
|
|
159
|
+
filter(
|
|
160
|
+
(page): page is StreamPayload<TOperation, TSdk> => page !== undefined,
|
|
161
|
+
),
|
|
150
162
|
);
|
|
151
163
|
}
|
package/src/transport.ts
CHANGED
|
@@ -60,7 +60,7 @@ export function createAuthenticatedFetch(
|
|
|
60
60
|
if (response.status !== 200) {
|
|
61
61
|
await response.body?.cancel().catch(() => {});
|
|
62
62
|
if (response.status === 401) throw new AuthenticationError();
|
|
63
|
-
throw new ApiStreamError("http", response.status);
|
|
63
|
+
throw new ApiStreamError("http", response.status, retryAfter(response));
|
|
64
64
|
}
|
|
65
65
|
const contentType = response.headers
|
|
66
66
|
.get("Content-Type")
|
|
@@ -86,6 +86,15 @@ export function createAuthenticatedFetch(
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
function retryAfter(response: Response): number | undefined {
|
|
90
|
+
const value = response.headers.get("Retry-After")?.trim();
|
|
91
|
+
if (!value) return undefined;
|
|
92
|
+
const delay = /^\d+$/.test(value)
|
|
93
|
+
? Number(value) * 1_000
|
|
94
|
+
: Date.parse(value) - Date.now();
|
|
95
|
+
return Number.isFinite(delay) ? Math.max(0, delay) : undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
89
98
|
function throwIfAborted(signal?: AbortSignal): void {
|
|
90
99
|
// Expo's React Native AbortSignal supports aborted, but not throwIfAborted().
|
|
91
100
|
if (signal?.aborted) {
|