@kibinrpc/client 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,17 +1,15 @@
1
- //#region src/errors.d.ts
2
- declare class KibinError extends Error {
3
- readonly code: string;
4
- constructor(code: string, message: string);
5
- }
6
- declare function isKibinError(error: unknown): error is KibinError;
7
- //#endregion
1
+ import { KibinError, isKibinError } from "@kibinrpc/shared";
2
+
8
3
  //#region src/types.d.ts
9
4
  type AsyncifyMethod<T> = T extends ((...args: infer Args) => infer Return) ? (...args: Args) => Promise<Awaited<Return>> : never;
10
5
  type ServiceClient<T> = { [K in keyof T as T[K] extends ((...args: never[]) => unknown) ? K : never]: AsyncifyMethod<T[K]> };
11
6
  type ExtractServices<T> = T extends {
12
7
  services: infer S;
13
8
  } ? S : never;
14
- type KibinClient<Router> = { [K in keyof ExtractServices<Router>]: ServiceClient<ExtractServices<Router>[K]> };
9
+ type RouterServices<Router> = { [K in keyof ExtractServices<Router>]: ServiceClient<ExtractServices<Router>[K]> };
10
+ type KibinClient<Router> = RouterServices<Router> & {
11
+ $unbatched: RouterServices<Router>;
12
+ };
15
13
  interface RequestCtx {
16
14
  namespace: string;
17
15
  method: string;
@@ -36,7 +34,12 @@ interface RetryConfig {
36
34
  }
37
35
  interface KibinClientConfig {
38
36
  baseUrl: string;
39
- headers?: Record<string, string>;
37
+ /** Static headers or a function returning headers (sync or async). Called once per fetch attempt. */
38
+ headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
39
+ /** Per-attempt timeout in ms. Uses `AbortSignal.timeout()` internally. */
40
+ timeout?: number;
41
+ /** AbortSignal to cancel all requests from this client. */
42
+ signal?: AbortSignal;
40
43
  retry?: RetryConfig;
41
44
  interceptors?: ClientInterceptors;
42
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/errors.ts","../src/types.ts","../src/client.ts"],"mappings":";cAAa,UAAA,SAAmB,KAAK;EAAA,SAC3B,IAAA;cAEG,IAAA,UAAc,OAAA;AAAA;AAAA,iBAOX,YAAA,CAAa,KAAA,YAAiB,KAAA,IAAS,UAAU;;;KCR5D,cAAA,MAAoB,CAAA,cAAc,IAAA,qCAChC,IAAA,EAAM,IAAA,KAAS,OAAA,CAAQ,OAAA,CAAQ,MAAA;AAAA,KAGjC,aAAA,oBACQ,CAAA,IAAK,CAAA,CAAE,CAAA,eAAe,IAAA,yBAA4B,CAAA,WAAY,cAAA,CAAe,CAAA,CAAE,CAAA;AAAA,KAGvF,eAAA,MAAqB,CAAC;EAAW,QAAA;AAAA,IAAsB,CAAA;AAAA,KAEhD,WAAA,yBACC,eAAA,CAAgB,MAAA,IAAU,aAAA,CAAc,eAAA,CAAgB,MAAA,EAAQ,CAAA;AAAA,UAG5D,UAAA;EAChB,SAAA;EACA,MAAA;EACA,IAAA;AAAA;AAAA,UAGgB,WAAA,SAAoB,UAAU;EAC9C,IAAI;AAAA;AAAA,UAGY,QAAA,SAAiB,UAAU;EAC3C,KAAA,EAAO,UAAA;AAAA;AAAA,UAGS,kBAAA;EAChB,OAAA,IAAW,GAAA,EAAK,UAAA,KAAe,UAAA,GAAa,OAAA,CAAQ,UAAA;EACpD,QAAA,IAAY,GAAA,EAAK,WAAA,eAA0B,OAAA;EAC3C,KAAA,IAAS,GAAA,EAAK,QAAA,eAAuB,OAAA;AAAA;AAAA,UAGrB,WAAA;EAjCJ;EAmCZ,QAAA;EAnC6B;EAqC7B,KAAK;AAAA;AAAA,UAGW,iBAAA;EAChB,OAAA;EACA,OAAA,GAAU,MAAA;EACV,KAAA,GAAQ,WAAA;EACR,YAAA,GAAe,kBAAA;AAAA;;;iBC9BA,iBAAA,QAAA,CAA0B,MAAA,EAAQ,iBAAA,GAAoB,WAAA,CAAY,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/client.ts"],"mappings":";;;KAEK,cAAA,MAAoB,CAAA,cAAc,IAAA,qCAChC,IAAA,EAAM,IAAA,KAAS,OAAA,CAAQ,OAAA,CAAQ,MAAA;AAAA,KAGjC,aAAA,oBACQ,CAAA,IAAK,CAAA,CAAE,CAAA,eAAe,IAAA,yBAA4B,CAAA,WAAY,cAAA,CAAe,CAAA,CAAE,CAAA;AAAA,KAGvF,eAAA,MAAqB,CAAC;EAAW,QAAA;AAAA,IAAsB,CAAA;AAAA,KAEvD,cAAA,yBACQ,eAAA,CAAgB,MAAA,IAAU,aAAA,CAAc,eAAA,CAAgB,MAAA,EAAQ,CAAA;AAAA,KAGjE,WAAA,WAAsB,cAAA,CAAe,MAAA;EAChD,UAAA,EAAY,cAAA,CAAe,MAAA;AAAA;AAAA,UAGX,UAAA;EAChB,SAAA;EACA,MAAA;EACA,IAAA;AAAA;AAAA,UAGgB,WAAA,SAAoB,UAAU;EAC9C,IAAI;AAAA;AAAA,UAGY,QAAA,SAAiB,UAAU;EAC3C,KAAA,EAAO,UAAA;AAAA;AAAA,UAGS,kBAAA;EAChB,OAAA,IAAW,GAAA,EAAK,UAAA,KAAe,UAAA,GAAa,OAAA,CAAQ,UAAA;EACpD,QAAA,IAAY,GAAA,EAAK,WAAA,eAA0B,OAAA;EAC3C,KAAA,IAAS,GAAA,EAAK,QAAA,eAAuB,OAAA;AAAA;AAAA,UAGrB,WAAA;EAjC8C;EAmC9D,QAAA;EAnC2F;EAqC3F,KAAK;AAAA;AAAA,UAGW,iBAAA;EAChB,OAAA;EAzCC;EA2CD,OAAA,GACG,MAAA,0BACO,MAAA,mBAAyB,OAAA,CAAQ,MAAA;EA7C1B;EA+CjB,OAAA;EA/CkC;EAiDlC,MAAA,GAAS,WAAA;EACT,KAAA,GAAQ,WAAA;EACR,YAAA,GAAe,kBAAA;AAAA;;;iBCzCA,iBAAA,QAAA,CAA0B,MAAA,EAAQ,iBAAA,GAAoB,WAAA,CAAY,MAAA"}
package/dist/index.js CHANGED
@@ -1,16 +1,4 @@
1
- //#region src/errors.ts
2
- var KibinError = class extends Error {
3
- code;
4
- constructor(code, message) {
5
- super(message);
6
- this.name = "KibinError";
7
- this.code = code;
8
- }
9
- };
10
- function isKibinError(error) {
11
- return error instanceof KibinError;
12
- }
13
- //#endregion
1
+ import { KibinError, isKibinError } from "@kibinrpc/shared";
14
2
  //#region src/client.ts
15
3
  const RETRY_DEFAULTS = {
16
4
  attempts: 3,
@@ -26,6 +14,16 @@ function createKibinClient(config) {
26
14
  const maxAttempts = config.retry?.attempts ?? RETRY_DEFAULTS.attempts;
27
15
  const baseDelay = config.retry?.delay ?? RETRY_DEFAULTS.delay;
28
16
  const { interceptors } = config;
17
+ async function getHeaders() {
18
+ if (!config.headers) return {};
19
+ if (typeof config.headers === "function") return await config.headers();
20
+ return config.headers;
21
+ }
22
+ function makeSignal() {
23
+ if (config.signal && config.timeout !== void 0) return AbortSignal.any([config.signal, AbortSignal.timeout(config.timeout)]);
24
+ if (config.signal) return config.signal;
25
+ if (config.timeout !== void 0) return AbortSignal.timeout(config.timeout);
26
+ }
29
27
  let pendingBatch = [];
30
28
  let flushScheduled = false;
31
29
  async function settleError(item, err) {
@@ -50,7 +48,7 @@ function createKibinClient(config) {
50
48
  }
51
49
  else item.resolve(data);
52
50
  }
53
- async function rpcCall(namespace, method, args) {
51
+ async function rpcCall(namespace, method, args, skipBatch = false) {
54
52
  let ctx = {
55
53
  namespace,
56
54
  method,
@@ -58,6 +56,14 @@ function createKibinClient(config) {
58
56
  };
59
57
  if (interceptors?.request) ctx = await interceptors.request(ctx);
60
58
  return new Promise((resolve, reject) => {
59
+ if (skipBatch) {
60
+ flushSingle({
61
+ ctx,
62
+ resolve,
63
+ reject
64
+ });
65
+ return;
66
+ }
61
67
  pendingBatch.push({
62
68
  ctx,
63
69
  resolve,
@@ -82,12 +88,14 @@ function createKibinClient(config) {
82
88
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
83
89
  if (attempt > 0) await sleep(attempt, baseDelay);
84
90
  try {
91
+ const resolvedHeaders = await getHeaders();
85
92
  const response = await fetch(config.baseUrl, {
86
93
  method: "POST",
87
94
  headers: {
88
95
  "Content-Type": "application/json",
89
- ...config.headers
96
+ ...resolvedHeaders
90
97
  },
98
+ signal: makeSignal(),
91
99
  body: JSON.stringify(item.ctx)
92
100
  });
93
101
  const result = await response.json();
@@ -103,6 +111,14 @@ function createKibinClient(config) {
103
111
  await settleSuccess(item, result.data);
104
112
  return;
105
113
  } catch (err) {
114
+ if (err instanceof Error && err.name === "TimeoutError") {
115
+ await settleError(item, new KibinError("TIMEOUT", "Request timed out", { cause: err }));
116
+ return;
117
+ }
118
+ if (err instanceof Error && err.name === "AbortError") {
119
+ await settleError(item, new KibinError("ABORTED", "Request was aborted", { cause: err }));
120
+ return;
121
+ }
106
122
  lastError = err;
107
123
  }
108
124
  }
@@ -116,45 +132,68 @@ function createKibinClient(config) {
116
132
  if (attempt > 0) await sleep(attempt, baseDelay);
117
133
  let results;
118
134
  try {
135
+ const resolvedHeaders = await getHeaders();
119
136
  results = await (await fetch(config.baseUrl, {
120
137
  method: "POST",
121
138
  headers: {
122
139
  "Content-Type": "application/json",
123
- ...config.headers
140
+ ...resolvedHeaders
124
141
  },
142
+ signal: makeSignal(),
125
143
  body: JSON.stringify(pending.map((item) => item.ctx))
126
144
  })).json();
127
145
  } catch (err) {
146
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
147
+ const code = err.name === "TimeoutError" ? "TIMEOUT" : "ABORTED";
148
+ const msg = err.name === "TimeoutError" ? "Request timed out" : "Request was aborted";
149
+ await Promise.all(pending.map((item) => settleError(item, new KibinError(code, msg, { cause: err }))));
150
+ return;
151
+ }
128
152
  for (const item of pending) lastErrors.set(item, err);
129
153
  continue;
130
154
  }
131
155
  const retryItems = [];
156
+ const settlements = [];
132
157
  for (let i = 0; i < pending.length; i++) {
133
158
  const result = results[i];
134
159
  const item = pending[i];
135
- if (result?.error) {
160
+ if (!result) {
161
+ item.reject(new KibinError("BATCH_MISMATCH", "Server returned fewer results than expected"));
162
+ continue;
163
+ }
164
+ if (result.error) {
136
165
  const err = rpcError(result.error);
137
166
  if (result.status >= 500) {
138
167
  retryItems.push(item);
139
168
  lastErrors.set(item, err);
140
- } else await settleError(item, err);
141
- } else await settleSuccess(item, result?.data);
169
+ } else settlements.push(settleError(item, err));
170
+ } else settlements.push(settleSuccess(item, result.data));
142
171
  }
172
+ await Promise.all(settlements);
143
173
  pending = retryItems;
144
174
  if (pending.length === 0) break;
145
175
  }
146
- for (const item of pending) {
176
+ await Promise.all(pending.map((item) => {
147
177
  const err = lastErrors.get(item);
148
- if (err instanceof KibinError) await settleError(item, err);
149
- else item.reject(err);
150
- }
178
+ if (err instanceof KibinError) return settleError(item, err);
179
+ item.reject(err);
180
+ return Promise.resolve();
181
+ }));
151
182
  }
152
- return new Proxy({}, { get(_, key) {
153
- if (typeof key !== "string") return void 0;
183
+ function makeNamespaceProxy(namespace, skipBatch) {
154
184
  return new Proxy({}, { get(_, method) {
155
185
  if (typeof method !== "string") return void 0;
156
- return (...args) => rpcCall(key, method, args);
186
+ return (...args) => rpcCall(namespace, method, args, skipBatch);
157
187
  } });
188
+ }
189
+ const unbatchedProxy = new Proxy({}, { get(_, key) {
190
+ if (typeof key !== "string") return void 0;
191
+ return makeNamespaceProxy(key, true);
192
+ } });
193
+ return new Proxy({}, { get(_, key) {
194
+ if (key === "$unbatched") return unbatchedProxy;
195
+ if (typeof key !== "string") return void 0;
196
+ return makeNamespaceProxy(key, false);
158
197
  } });
159
198
  }
160
199
  //#endregion
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["export class KibinError extends Error {\n\treadonly code: string;\n\n\tconstructor(code: string, message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'KibinError';\n\t\tthis.code = code;\n\t}\n}\n\nexport function isKibinError(error: unknown): error is KibinError {\n\treturn error instanceof KibinError;\n}\n","import { KibinError } from './errors.js';\nimport type { KibinClient, KibinClientConfig, RequestCtx } from './types.js';\n\nconst RETRY_DEFAULTS = { attempts: 3, delay: 300 };\n\ntype RpcResult = { data?: unknown; error?: { code?: string; message?: string } };\ntype BatchRpcResult = RpcResult & { status: number };\ntype QueueItem = { ctx: RequestCtx; resolve: (v: unknown) => void; reject: (e: unknown) => void };\n\nfunction rpcError(error: { code?: string; message?: string }): KibinError {\n\treturn new KibinError(error.code ?? 'RPC_ERROR', error.message ?? 'RPC Error');\n}\n\nfunction sleep(attempt: number, baseDelay: number): Promise<void> {\n\treturn new Promise<void>((r) => setTimeout(r, baseDelay * 2 ** (attempt - 1)));\n}\n\nexport function createKibinClient<Router>(config: KibinClientConfig): KibinClient<Router> {\n\tconst maxAttempts = config.retry?.attempts ?? RETRY_DEFAULTS.attempts;\n\tconst baseDelay = config.retry?.delay ?? RETRY_DEFAULTS.delay;\n\tconst { interceptors } = config;\n\n\tlet pendingBatch: QueueItem[] = [];\n\tlet flushScheduled = false;\n\n\tasync function settleError(item: QueueItem, err: KibinError): Promise<void> {\n\t\tif (interceptors?.error) {\n\t\t\ttry {\n\t\t\t\titem.resolve(await interceptors.error({ ...item.ctx, error: err }));\n\t\t\t} catch (interceptorError) {\n\t\t\t\titem.reject(interceptorError);\n\t\t\t}\n\t\t} else {\n\t\t\titem.reject(err);\n\t\t}\n\t}\n\n\tasync function settleSuccess(item: QueueItem, data: unknown): Promise<void> {\n\t\tif (interceptors?.response) {\n\t\t\ttry {\n\t\t\t\titem.resolve(await interceptors.response({ ...item.ctx, data }));\n\t\t\t} catch (interceptorError) {\n\t\t\t\titem.reject(interceptorError);\n\t\t\t}\n\t\t} else {\n\t\t\titem.resolve(data);\n\t\t}\n\t}\n\n\tasync function rpcCall(namespace: string, method: string, args: unknown[]): Promise<unknown> {\n\t\tlet ctx: RequestCtx = { namespace, method, args };\n\n\t\tif (interceptors?.request) {\n\t\t\tctx = await interceptors.request(ctx);\n\t\t}\n\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\tpendingBatch.push({ ctx, resolve, reject });\n\t\t\tif (!flushScheduled) {\n\t\t\t\tflushScheduled = true;\n\t\t\t\tqueueMicrotask(flush);\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction flush() {\n\t\tconst batch = pendingBatch;\n\t\tpendingBatch = [];\n\t\tflushScheduled = false;\n\n\t\tif (batch.length === 0) return;\n\t\tif (batch.length === 1) {\n\t\t\tflushSingle(batch[0]);\n\t\t} else {\n\t\t\tflushBatch(batch);\n\t\t}\n\t}\n\n\tasync function flushSingle(item: QueueItem) {\n\t\tlet lastError: unknown;\n\n\t\tfor (let attempt = 0; attempt < maxAttempts; attempt++) {\n\t\t\tif (attempt > 0) await sleep(attempt, baseDelay);\n\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(config.baseUrl, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'Content-Type': 'application/json', ...config.headers },\n\t\t\t\t\tbody: JSON.stringify(item.ctx),\n\t\t\t\t});\n\n\t\t\t\tconst result = (await response.json()) as RpcResult;\n\n\t\t\t\tif (result.error) {\n\t\t\t\t\tconst err = rpcError(result.error);\n\t\t\t\t\tif (response.status >= 500) {\n\t\t\t\t\t\tlastError = err;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tawait settleError(item, err);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait settleSuccess(item, result.data);\n\t\t\t\treturn;\n\t\t\t} catch (err) {\n\t\t\t\tlastError = err;\n\t\t\t}\n\t\t}\n\n\t\tif (lastError instanceof KibinError) {\n\t\t\tawait settleError(item, lastError);\n\t\t} else {\n\t\t\titem.reject(lastError);\n\t\t}\n\t}\n\n\tasync function flushBatch(batch: QueueItem[]) {\n\t\tlet pending = [...batch];\n\t\tconst lastErrors = new Map<QueueItem, unknown>();\n\n\t\tfor (let attempt = 0; attempt < maxAttempts; attempt++) {\n\t\t\tif (attempt > 0) await sleep(attempt, baseDelay);\n\n\t\t\tlet results: BatchRpcResult[];\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(config.baseUrl, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'Content-Type': 'application/json', ...config.headers },\n\t\t\t\t\tbody: JSON.stringify(pending.map((item) => item.ctx)),\n\t\t\t\t});\n\t\t\t\tresults = (await response.json()) as BatchRpcResult[];\n\t\t\t} catch (err) {\n\t\t\t\tfor (const item of pending) lastErrors.set(item, err);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst retryItems: QueueItem[] = [];\n\n\t\t\tfor (let i = 0; i < pending.length; i++) {\n\t\t\t\tconst result = results[i];\n\t\t\t\tconst item = pending[i];\n\n\t\t\t\tif (result?.error) {\n\t\t\t\t\tconst err = rpcError(result.error);\n\t\t\t\t\tif (result.status >= 500) {\n\t\t\t\t\t\tretryItems.push(item);\n\t\t\t\t\t\tlastErrors.set(item, err);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait settleError(item, err);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tawait settleSuccess(item, result?.data);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpending = retryItems;\n\t\t\tif (pending.length === 0) break;\n\t\t}\n\n\t\tfor (const item of pending) {\n\t\t\tconst err = lastErrors.get(item);\n\t\t\tif (err instanceof KibinError) {\n\t\t\t\tawait settleError(item, err);\n\t\t\t} else {\n\t\t\t\titem.reject(err);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget(_, key) {\n\t\t\t\tif (typeof key !== 'string') return undefined;\n\t\t\t\treturn new Proxy(\n\t\t\t\t\t{},\n\t\t\t\t\t{\n\t\t\t\t\t\tget(_, method) {\n\t\t\t\t\t\t\tif (typeof method !== 'string') return undefined;\n\t\t\t\t\t\t\treturn (...args: unknown[]) => rpcCall(key, method, args);\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t) as unknown as KibinClient<Router>;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["import { KibinError } from './errors.js';\nimport type { KibinClient, KibinClientConfig, RequestCtx } from './types.js';\n\nconst RETRY_DEFAULTS = { attempts: 3, delay: 300 };\n\ntype RpcResult = { data?: unknown; error?: { code?: string; message?: string } };\ntype BatchRpcResult = RpcResult & { status: number };\ntype QueueItem = { ctx: RequestCtx; resolve: (v: unknown) => void; reject: (e: unknown) => void };\n\nfunction rpcError(error: { code?: string; message?: string }): KibinError {\n\treturn new KibinError(error.code ?? 'RPC_ERROR', error.message ?? 'RPC Error');\n}\n\nfunction sleep(attempt: number, baseDelay: number): Promise<void> {\n\treturn new Promise<void>((r) => setTimeout(r, baseDelay * 2 ** (attempt - 1)));\n}\n\nexport function createKibinClient<Router>(config: KibinClientConfig): KibinClient<Router> {\n\tconst maxAttempts = config.retry?.attempts ?? RETRY_DEFAULTS.attempts;\n\tconst baseDelay = config.retry?.delay ?? RETRY_DEFAULTS.delay;\n\tconst { interceptors } = config;\n\n\tasync function getHeaders(): Promise<Record<string, string>> {\n\t\tif (!config.headers) return {};\n\t\tif (typeof config.headers === 'function') return await config.headers();\n\t\treturn config.headers;\n\t}\n\n\tfunction makeSignal(): AbortSignal | undefined {\n\t\tif (config.signal && config.timeout !== undefined) {\n\t\t\treturn AbortSignal.any([config.signal, AbortSignal.timeout(config.timeout)]);\n\t\t}\n\t\tif (config.signal) return config.signal;\n\t\tif (config.timeout !== undefined) return AbortSignal.timeout(config.timeout);\n\t\treturn undefined;\n\t}\n\n\tlet pendingBatch: QueueItem[] = [];\n\tlet flushScheduled = false;\n\n\tasync function settleError(item: QueueItem, err: KibinError): Promise<void> {\n\t\tif (interceptors?.error) {\n\t\t\ttry {\n\t\t\t\titem.resolve(await interceptors.error({ ...item.ctx, error: err }));\n\t\t\t} catch (interceptorError) {\n\t\t\t\titem.reject(interceptorError);\n\t\t\t}\n\t\t} else {\n\t\t\titem.reject(err);\n\t\t}\n\t}\n\n\tasync function settleSuccess(item: QueueItem, data: unknown): Promise<void> {\n\t\tif (interceptors?.response) {\n\t\t\ttry {\n\t\t\t\titem.resolve(await interceptors.response({ ...item.ctx, data }));\n\t\t\t} catch (interceptorError) {\n\t\t\t\titem.reject(interceptorError);\n\t\t\t}\n\t\t} else {\n\t\t\titem.resolve(data);\n\t\t}\n\t}\n\n\tasync function rpcCall(\n\t\tnamespace: string,\n\t\tmethod: string,\n\t\targs: unknown[],\n\t\tskipBatch = false,\n\t): Promise<unknown> {\n\t\tlet ctx: RequestCtx = { namespace, method, args };\n\n\t\tif (interceptors?.request) {\n\t\t\tctx = await interceptors.request(ctx);\n\t\t}\n\n\t\treturn new Promise<unknown>((resolve, reject) => {\n\t\t\tif (skipBatch) {\n\t\t\t\tflushSingle({ ctx, resolve, reject });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpendingBatch.push({ ctx, resolve, reject });\n\t\t\tif (!flushScheduled) {\n\t\t\t\tflushScheduled = true;\n\t\t\t\tqueueMicrotask(flush);\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction flush() {\n\t\tconst batch = pendingBatch;\n\t\tpendingBatch = [];\n\t\tflushScheduled = false;\n\n\t\tif (batch.length === 0) return;\n\t\tif (batch.length === 1) {\n\t\t\tflushSingle(batch[0]);\n\t\t} else {\n\t\t\tflushBatch(batch);\n\t\t}\n\t}\n\n\tasync function flushSingle(item: QueueItem) {\n\t\tlet lastError: unknown;\n\n\t\tfor (let attempt = 0; attempt < maxAttempts; attempt++) {\n\t\t\tif (attempt > 0) await sleep(attempt, baseDelay);\n\n\t\t\ttry {\n\t\t\t\tconst resolvedHeaders = await getHeaders();\n\t\t\t\tconst response = await fetch(config.baseUrl, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'Content-Type': 'application/json', ...resolvedHeaders },\n\t\t\t\t\tsignal: makeSignal(),\n\t\t\t\t\tbody: JSON.stringify(item.ctx),\n\t\t\t\t});\n\n\t\t\t\tconst result = (await response.json()) as RpcResult;\n\n\t\t\t\tif (result.error) {\n\t\t\t\t\tconst err = rpcError(result.error);\n\t\t\t\t\tif (response.status >= 500) {\n\t\t\t\t\t\tlastError = err;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tawait settleError(item, err);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait settleSuccess(item, result.data);\n\t\t\t\treturn;\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error && err.name === 'TimeoutError') {\n\t\t\t\t\tawait settleError(item, new KibinError('TIMEOUT', 'Request timed out', { cause: err }));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (err instanceof Error && err.name === 'AbortError') {\n\t\t\t\t\tawait settleError(item, new KibinError('ABORTED', 'Request was aborted', { cause: err }));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlastError = err;\n\t\t\t}\n\t\t}\n\n\t\tif (lastError instanceof KibinError) {\n\t\t\tawait settleError(item, lastError);\n\t\t} else {\n\t\t\titem.reject(lastError);\n\t\t}\n\t}\n\n\tasync function flushBatch(batch: QueueItem[]) {\n\t\tlet pending = [...batch];\n\t\tconst lastErrors = new Map<QueueItem, unknown>();\n\n\t\tfor (let attempt = 0; attempt < maxAttempts; attempt++) {\n\t\t\tif (attempt > 0) await sleep(attempt, baseDelay);\n\n\t\t\tlet results: BatchRpcResult[];\n\t\t\ttry {\n\t\t\t\tconst resolvedHeaders = await getHeaders();\n\t\t\t\tconst response = await fetch(config.baseUrl, {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { 'Content-Type': 'application/json', ...resolvedHeaders },\n\t\t\t\t\tsignal: makeSignal(),\n\t\t\t\t\tbody: JSON.stringify(pending.map((item) => item.ctx)),\n\t\t\t\t});\n\t\t\t\tresults = (await response.json()) as BatchRpcResult[];\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')) {\n\t\t\t\t\tconst code = err.name === 'TimeoutError' ? 'TIMEOUT' : 'ABORTED';\n\t\t\t\t\tconst msg = err.name === 'TimeoutError' ? 'Request timed out' : 'Request was aborted';\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tpending.map((item) => settleError(item, new KibinError(code, msg, { cause: err }))),\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const item of pending) lastErrors.set(item, err);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst retryItems: QueueItem[] = [];\n\t\t\tconst settlements: Promise<void>[] = [];\n\n\t\t\tfor (let i = 0; i < pending.length; i++) {\n\t\t\t\tconst result = results[i];\n\t\t\t\tconst item = pending[i];\n\n\t\t\t\tif (!result) {\n\t\t\t\t\titem.reject(\n\t\t\t\t\t\tnew KibinError('BATCH_MISMATCH', 'Server returned fewer results than expected'),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (result.error) {\n\t\t\t\t\tconst err = rpcError(result.error);\n\t\t\t\t\tif (result.status >= 500) {\n\t\t\t\t\t\tretryItems.push(item);\n\t\t\t\t\t\tlastErrors.set(item, err);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsettlements.push(settleError(item, err));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsettlements.push(settleSuccess(item, result.data));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait Promise.all(settlements);\n\t\t\tpending = retryItems;\n\t\t\tif (pending.length === 0) break;\n\t\t}\n\n\t\tawait Promise.all(\n\t\t\tpending.map((item) => {\n\t\t\t\tconst err = lastErrors.get(item);\n\t\t\t\tif (err instanceof KibinError) return settleError(item, err);\n\t\t\t\titem.reject(err);\n\t\t\t\treturn Promise.resolve();\n\t\t\t}),\n\t\t);\n\t}\n\n\tfunction makeNamespaceProxy(namespace: string, skipBatch: boolean) {\n\t\treturn new Proxy(\n\t\t\t{},\n\t\t\t{\n\t\t\t\tget(_, method) {\n\t\t\t\t\tif (typeof method !== 'string') return undefined;\n\t\t\t\t\treturn (...args: unknown[]) => rpcCall(namespace, method, args, skipBatch);\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\tconst unbatchedProxy = new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget(_, key) {\n\t\t\t\tif (typeof key !== 'string') return undefined;\n\t\t\t\treturn makeNamespaceProxy(key, true);\n\t\t\t},\n\t\t},\n\t);\n\n\treturn new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget(_, key) {\n\t\t\t\tif (key === '$unbatched') return unbatchedProxy;\n\t\t\t\tif (typeof key !== 'string') return undefined;\n\t\t\t\treturn makeNamespaceProxy(key, false);\n\t\t\t},\n\t\t},\n\t) as unknown as KibinClient<Router>;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kibinrpc/client",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Type-safe and developer-friendly RPC client with end-to-end type inference",
5
5
  "license": "MIT",
6
6
  "author": "ixexel661",
@@ -28,6 +28,9 @@
28
28
  "files": [
29
29
  "dist"
30
30
  ],
31
+ "dependencies": {
32
+ "@kibinrpc/shared": "0.2.0"
33
+ },
31
34
  "publishConfig": {
32
35
  "access": "public"
33
36
  },