@richie-rpc/client 1.2.7 → 1.2.8
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/cjs/index.cjs +59 -22
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/index.mjs +59 -22
- package/dist/mjs/index.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -105,14 +105,16 @@ function validateRequest(endpoint, options) {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
function
|
|
108
|
+
function parseResponse(endpoint, status, data) {
|
|
109
109
|
const responseSchema = endpoint.responses[status];
|
|
110
110
|
if (responseSchema) {
|
|
111
111
|
const result = responseSchema.safeParse(data);
|
|
112
112
|
if (!result.success) {
|
|
113
113
|
throw new ClientValidationError(`response[${status}]`, result.error.issues);
|
|
114
114
|
}
|
|
115
|
+
return result.data;
|
|
115
116
|
}
|
|
117
|
+
return data;
|
|
116
118
|
}
|
|
117
119
|
function extractFilename(contentDisposition) {
|
|
118
120
|
if (!contentDisposition)
|
|
@@ -147,7 +149,7 @@ function validateDownloadRequest(endpoint, options) {
|
|
|
147
149
|
}
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
|
-
function
|
|
152
|
+
function parseDownloadErrorResponse(endpoint, status, data) {
|
|
151
153
|
if (endpoint.errorResponses) {
|
|
152
154
|
const responseSchema = endpoint.errorResponses[status];
|
|
153
155
|
if (responseSchema) {
|
|
@@ -155,8 +157,10 @@ function validateDownloadErrorResponse(endpoint, status, data) {
|
|
|
155
157
|
if (!result.success) {
|
|
156
158
|
throw new ClientValidationError(`response[${status}]`, result.error.issues);
|
|
157
159
|
}
|
|
160
|
+
return result.data;
|
|
158
161
|
}
|
|
159
162
|
}
|
|
163
|
+
return data;
|
|
160
164
|
}
|
|
161
165
|
async function makeDownloadRequest(config, endpoint, options = {}) {
|
|
162
166
|
if (config.validateRequest !== false) {
|
|
@@ -224,12 +228,10 @@ async function makeDownloadRequest(config, endpoint, options = {}) {
|
|
|
224
228
|
if (endpoint.errorResponses && !(response.status in endpoint.errorResponses)) {
|
|
225
229
|
throw new HTTPError(response.status, response.statusText, data);
|
|
226
230
|
}
|
|
227
|
-
|
|
228
|
-
validateDownloadErrorResponse(endpoint, response.status, data);
|
|
229
|
-
}
|
|
231
|
+
const parsedData = config.parseResponse !== false ? parseDownloadErrorResponse(endpoint, response.status, data) : data;
|
|
230
232
|
return {
|
|
231
233
|
status: response.status,
|
|
232
|
-
data
|
|
234
|
+
data: parsedData
|
|
233
235
|
};
|
|
234
236
|
}
|
|
235
237
|
function makeRequestWithXHR(config, endpoint, options, url) {
|
|
@@ -287,9 +289,10 @@ function makeRequestWithXHR(config, endpoint, options, url) {
|
|
|
287
289
|
reject(new HTTPError(xhr.status, xhr.statusText, data));
|
|
288
290
|
return;
|
|
289
291
|
}
|
|
290
|
-
|
|
292
|
+
let parsedData = data;
|
|
293
|
+
if (config.parseResponse !== false) {
|
|
291
294
|
try {
|
|
292
|
-
|
|
295
|
+
parsedData = parseResponse(endpoint, xhr.status, data);
|
|
293
296
|
} catch (err) {
|
|
294
297
|
reject(err);
|
|
295
298
|
return;
|
|
@@ -297,7 +300,7 @@ function makeRequestWithXHR(config, endpoint, options, url) {
|
|
|
297
300
|
}
|
|
298
301
|
resolve({
|
|
299
302
|
status: xhr.status,
|
|
300
|
-
data
|
|
303
|
+
data: parsedData
|
|
301
304
|
});
|
|
302
305
|
};
|
|
303
306
|
xhr.onerror = () => reject(new Error("Network error"));
|
|
@@ -371,20 +374,38 @@ async function makeRequest(config, endpoint, options) {
|
|
|
371
374
|
if (!response.ok && !(response.status in endpoint.responses)) {
|
|
372
375
|
throw new HTTPError(response.status, response.statusText, data);
|
|
373
376
|
}
|
|
374
|
-
|
|
375
|
-
validateResponse(endpoint, response.status, data);
|
|
376
|
-
}
|
|
377
|
+
const parsedData = config.parseResponse !== false ? parseResponse(endpoint, response.status, data) : data;
|
|
377
378
|
return {
|
|
378
379
|
status: response.status,
|
|
379
|
-
data
|
|
380
|
+
data: parsedData
|
|
380
381
|
};
|
|
381
382
|
}
|
|
382
|
-
function createStreamingResult(response, controller) {
|
|
383
|
+
function createStreamingResult(response, controller, endpoint, config) {
|
|
383
384
|
const listeners = {
|
|
384
385
|
chunk: new Set,
|
|
385
386
|
close: new Set,
|
|
386
387
|
error: new Set
|
|
387
388
|
};
|
|
389
|
+
const parseChunk = (data) => {
|
|
390
|
+
if (config.parseResponse !== false && endpoint.chunk) {
|
|
391
|
+
const result = endpoint.chunk.safeParse(data);
|
|
392
|
+
if (!result.success) {
|
|
393
|
+
throw new ClientValidationError("chunk", result.error.issues);
|
|
394
|
+
}
|
|
395
|
+
return result.data;
|
|
396
|
+
}
|
|
397
|
+
return data;
|
|
398
|
+
};
|
|
399
|
+
const parseFinalResponse = (data) => {
|
|
400
|
+
if (config.parseResponse !== false && endpoint.finalResponse) {
|
|
401
|
+
const result = endpoint.finalResponse.safeParse(data);
|
|
402
|
+
if (!result.success) {
|
|
403
|
+
throw new ClientValidationError("finalResponse", result.error.issues);
|
|
404
|
+
}
|
|
405
|
+
return result.data;
|
|
406
|
+
}
|
|
407
|
+
return data;
|
|
408
|
+
};
|
|
388
409
|
(async () => {
|
|
389
410
|
const reader = response.body.getReader();
|
|
390
411
|
const decoder = new TextDecoder;
|
|
@@ -404,9 +425,11 @@ function createStreamingResult(response, controller) {
|
|
|
404
425
|
try {
|
|
405
426
|
const parsed = JSON.parse(line);
|
|
406
427
|
if (parsed.__final__) {
|
|
407
|
-
|
|
428
|
+
const finalData = parseFinalResponse(parsed.data);
|
|
429
|
+
listeners.close.forEach((h) => h(finalData));
|
|
408
430
|
} else {
|
|
409
|
-
|
|
431
|
+
const chunkData = parseChunk(parsed);
|
|
432
|
+
listeners.chunk.forEach((h) => h(chunkData));
|
|
410
433
|
}
|
|
411
434
|
} catch (parseErr) {
|
|
412
435
|
listeners.error.forEach((h) => h(parseErr));
|
|
@@ -417,9 +440,11 @@ function createStreamingResult(response, controller) {
|
|
|
417
440
|
try {
|
|
418
441
|
const parsed = JSON.parse(buffer);
|
|
419
442
|
if (parsed.__final__) {
|
|
420
|
-
|
|
443
|
+
const finalData = parseFinalResponse(parsed.data);
|
|
444
|
+
listeners.close.forEach((h) => h(finalData));
|
|
421
445
|
} else {
|
|
422
|
-
|
|
446
|
+
const chunkData = parseChunk(parsed);
|
|
447
|
+
listeners.chunk.forEach((h) => h(chunkData));
|
|
423
448
|
}
|
|
424
449
|
} catch {}
|
|
425
450
|
}
|
|
@@ -517,7 +542,7 @@ async function makeStreamingRequest(config, endpoint, options) {
|
|
|
517
542
|
}
|
|
518
543
|
throw new HTTPError(response.status, response.statusText, data);
|
|
519
544
|
}
|
|
520
|
-
return createStreamingResult(response, controller);
|
|
545
|
+
return createStreamingResult(response, controller, endpoint, config);
|
|
521
546
|
}
|
|
522
547
|
function createSSEConnection(config, endpoint, options = {}) {
|
|
523
548
|
let path = endpoint.path;
|
|
@@ -535,8 +560,20 @@ function createSSEConnection(config, endpoint, options = {}) {
|
|
|
535
560
|
eventSource.addEventListener(eventName, (e) => {
|
|
536
561
|
const messageEvent = e;
|
|
537
562
|
try {
|
|
538
|
-
const
|
|
539
|
-
|
|
563
|
+
const rawData = JSON.parse(messageEvent.data);
|
|
564
|
+
let parsedData = rawData;
|
|
565
|
+
if (config.parseResponse !== false) {
|
|
566
|
+
const eventSchema = endpoint.events[eventName];
|
|
567
|
+
if (eventSchema) {
|
|
568
|
+
const result = eventSchema.safeParse(rawData);
|
|
569
|
+
if (!result.success) {
|
|
570
|
+
listeners.error.forEach((h) => h(new ClientValidationError(`event[${eventName}]`, result.error.issues)));
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
parsedData = result.data;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
listeners[eventName].forEach((h) => h(parsedData, messageEvent.lastEventId || undefined));
|
|
540
577
|
} catch (err) {
|
|
541
578
|
listeners.error.forEach((h) => h(new Error(`Failed to parse SSE data: ${err.message}`)));
|
|
542
579
|
}
|
|
@@ -613,4 +650,4 @@ function createTypedClient(_config) {
|
|
|
613
650
|
}
|
|
614
651
|
})
|
|
615
652
|
|
|
616
|
-
//# debugId=
|
|
653
|
+
//# debugId=FF579F2ABF9D24DD64756E2164756E21
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n Contract,\n DownloadEndpointDefinition,\n DownloadProgressEvent,\n EndpointDefinition,\n ExtractBody,\n ExtractChunk,\n ExtractFinalResponse,\n ExtractHeaders,\n ExtractParams,\n ExtractQuery,\n ExtractSSEEventData,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n UploadProgressEvent,\n} from '@richie-rpc/core';\nimport { buildUrl, interpolatePath, objectToFormData } from '@richie-rpc/core';\n\n// Re-export for convenience\nexport type { UploadProgressEvent, DownloadProgressEvent };\nimport type { z } from 'zod';\n\n// Client configuration\nexport interface ClientConfig {\n baseUrl: string;\n headers?: Record<string, string>;\n validateRequest?: boolean;\n validateResponse?: boolean;\n}\n\n// Request options for an endpoint\nexport type EndpointRequestOptions<T extends EndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n body?: ExtractBody<T> extends never ? never : ExtractBody<T>;\n abortSignal?: AbortSignal;\n /** Upload progress callback (uses XHR for progress tracking) */\n onUploadProgress?: (event: UploadProgressEvent) => void;\n};\n\n// Response type for a standard endpoint (union of all possible responses)\nexport type EndpointResponse<T extends StandardEndpointDefinition> = {\n [Status in keyof T['responses']]: {\n status: Status;\n data: T['responses'][Status] extends z.ZodTypeAny ? z.infer<T['responses'][Status]> : never;\n };\n}[keyof T['responses']];\n\n// Client method type for a standard endpoint\nexport type ClientMethod<T extends StandardEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<EndpointResponse<T>>;\n\n// ============================================\n// Streaming Endpoint Client Types\n// ============================================\n\n/**\n * Result object for streaming endpoints - event-based API\n */\nexport interface StreamingResult<T extends StreamingEndpointDefinition> {\n /** Subscribe to chunks */\n on(event: 'chunk', handler: (chunk: ExtractChunk<T>) => void): () => void;\n /** Subscribe to stream close (with optional final response) */\n on(event: 'close', handler: (final?: ExtractFinalResponse<T>) => void): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Abort the stream */\n abort(): void;\n /** Check if aborted */\n readonly aborted: boolean;\n}\n\n/**\n * Client method type for streaming endpoints\n */\nexport type StreamingClientMethod<T extends StreamingEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<StreamingResult<T>>;\n\n// ============================================\n// SSE Endpoint Client Types\n// ============================================\n\n/**\n * Connection object for SSE endpoints - event-based API\n */\nexport interface SSEConnection<T extends SSEEndpointDefinition> {\n /** Subscribe to a specific event type */\n on<K extends keyof T['events']>(\n event: K,\n handler: (data: ExtractSSEEventData<T, K>, id?: string) => void,\n ): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Close the connection */\n close(): void;\n /** Current connection state */\n readonly state: 'connecting' | 'open' | 'closed';\n}\n\n/**\n * Client method type for SSE endpoints\n */\nexport type SSEClientMethod<T extends SSEEndpointDefinition> = (\n options?: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'>,\n) => SSEConnection<T>;\n\n// ============================================\n// Download Endpoint Client Types\n// ============================================\n\n/**\n * Request options for download endpoints\n */\nexport type DownloadRequestOptions<T extends DownloadEndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n abortSignal?: AbortSignal;\n /** Download progress callback */\n onDownloadProgress?: (event: DownloadProgressEvent) => void;\n};\n\n/**\n * Response type for download endpoints\n * Success (200) returns File, errors return typed error response\n */\nexport type DownloadResponse<T extends DownloadEndpointDefinition> =\n | { status: 200; data: File }\n | (T['errorResponses'] extends Record<number, z.ZodTypeAny>\n ? {\n [S in keyof T['errorResponses']]: {\n status: S;\n data: T['errorResponses'][S] extends z.ZodTypeAny\n ? z.infer<T['errorResponses'][S]>\n : never;\n };\n }[keyof T['errorResponses']]\n : never);\n\n/**\n * Client method type for download endpoints\n */\nexport type DownloadClientMethod<T extends DownloadEndpointDefinition> = (\n options?: DownloadRequestOptions<T>,\n) => Promise<DownloadResponse<T>>;\n\n// Client type for a contract (supports all endpoint types)\nexport type Client<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? ClientMethod<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingClientMethod<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEClientMethod<T[K]>\n : T[K] extends DownloadEndpointDefinition\n ? DownloadClientMethod<T[K]>\n : never;\n};\n\n// Validation error\nexport class ClientValidationError extends Error {\n constructor(\n public field: string,\n public issues: z.ZodIssue[],\n ) {\n super(`Validation failed for ${field}`);\n this.name = 'ClientValidationError';\n }\n}\n\n// HTTP error\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public statusText: string,\n public body: unknown,\n ) {\n super(`HTTP Error ${status}: ${statusText}`);\n this.name = 'HTTPError';\n }\n}\n\n/**\n * Validate request data before sending\n */\nfunction validateRequest<T extends StandardEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Validate response data after receiving\n */\nfunction validateResponse<T extends StandardEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): void {\n const responseSchema = endpoint.responses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n }\n}\n\n/**\n * Extract filename from Content-Disposition header\n */\nfunction extractFilename(contentDisposition: string | null): string | null {\n if (!contentDisposition) return null;\n // Try filename*= (RFC 5987) first\n const filenameStarMatch = contentDisposition.match(/filename\\*=(?:UTF-8'')?([^;\\s]+)/i);\n if (filenameStarMatch && filenameStarMatch[1]) {\n return decodeURIComponent(filenameStarMatch[1]);\n }\n // Try filename= (standard)\n const filenameMatch = contentDisposition.match(/filename=[\"']?([^\"';\\s]+)[\"']?/i);\n if (filenameMatch && filenameMatch[1]) {\n return filenameMatch[1];\n }\n return null;\n}\n\n/**\n * Validate download request data before sending\n */\nfunction validateDownloadRequest<T extends DownloadEndpointDefinition>(\n endpoint: T,\n options: DownloadRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n}\n\n/**\n * Validate download error response data\n */\nfunction validateDownloadErrorResponse<T extends DownloadEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): void {\n if (endpoint.errorResponses) {\n const responseSchema = endpoint.errorResponses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n }\n }\n}\n\n/**\n * Make a download request using fetch with progress support\n */\nasync function makeDownloadRequest<T extends DownloadEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: DownloadRequestOptions<T> = {},\n): Promise<DownloadResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateDownloadRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: 'GET',\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Handle success (200) - return File\n if (response.status === 200) {\n const contentLength = response.headers.get('content-length');\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n\n let blob: Blob;\n\n if (options.onDownloadProgress && response.body) {\n // Stream the response to track progress\n const reader = response.body.getReader();\n const chunks: BlobPart[] = [];\n let loaded = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n chunks.push(value);\n loaded += value.length;\n\n options.onDownloadProgress({\n loaded,\n total,\n progress: total > 0 ? loaded / total : NaN,\n });\n }\n\n blob = new Blob(chunks);\n } else {\n blob = await response.blob();\n }\n\n const contentDisposition = response.headers.get('content-disposition');\n const filename = extractFilename(contentDisposition) || 'download';\n const contentType = response.headers.get('content-type') || 'application/octet-stream';\n\n const file = new File([blob], filename, { type: contentType });\n\n return {\n status: 200,\n data: file,\n } as DownloadResponse<T>;\n }\n\n // Handle error responses\n let data: unknown;\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n // Check for HTTP errors not in errorResponses\n if (endpoint.errorResponses && !(response.status in endpoint.errorResponses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Validate error response if enabled\n if (config.validateResponse !== false) {\n validateDownloadErrorResponse(endpoint, response.status, data);\n }\n\n return {\n status: response.status,\n data,\n } as DownloadResponse<T>;\n}\n\n/**\n * Make a request using XMLHttpRequest for upload progress support\n */\nfunction makeRequestWithXHR<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n url: string,\n): Promise<EndpointResponse<T>> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.open(endpoint.method, url);\n\n // Set base headers from config\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n xhr.setRequestHeader(key, value);\n }\n }\n\n // Set request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n xhr.setRequestHeader(key, String(value));\n }\n }\n\n // Upload progress callback\n if (options.onUploadProgress) {\n xhr.upload.onprogress = (e) => {\n if (e.lengthComputable && options.onUploadProgress) {\n options.onUploadProgress({\n loaded: e.loaded,\n total: e.total,\n progress: e.loaded / e.total,\n });\n }\n };\n }\n\n // Handle abort signal\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n xhr.abort();\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n options.abortSignal.addEventListener('abort', () => {\n xhr.abort();\n });\n }\n\n xhr.onload = () => {\n let data: unknown;\n const responseContentType = xhr.getResponseHeader('content-type') || '';\n\n if (xhr.status === 204) {\n data = {};\n } else if (responseContentType.includes('application/json')) {\n try {\n data = JSON.parse(xhr.responseText);\n } catch {\n data = xhr.responseText || {};\n }\n } else if (responseContentType.includes('text/')) {\n data = xhr.responseText;\n } else {\n data = xhr.responseText || {};\n }\n\n // Check for HTTP errors\n if (xhr.status >= 400 && !(xhr.status in endpoint.responses)) {\n reject(new HTTPError(xhr.status, xhr.statusText, data));\n return;\n }\n\n // Validate response if enabled\n if (config.validateResponse !== false) {\n try {\n validateResponse(endpoint, xhr.status, data);\n } catch (err) {\n reject(err);\n return;\n }\n }\n\n resolve({\n status: xhr.status,\n data,\n } as EndpointResponse<T>);\n };\n\n xhr.onerror = () => reject(new Error('Network error'));\n xhr.onabort = () => reject(new DOMException('Aborted', 'AbortError'));\n\n // Prepare and send body\n const contentType = endpoint.contentType ?? 'application/json';\n if (options.body !== undefined) {\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n xhr.send(objectToFormData(options.body as Record<string, unknown>));\n } else {\n xhr.setRequestHeader('content-type', 'application/json');\n xhr.send(JSON.stringify(options.body));\n }\n } else {\n xhr.send();\n }\n });\n}\n\n/**\n * Make a request to a standard endpoint\n */\nasync function makeRequest<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<EndpointResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Use XHR for upload progress support\n if (options.onUploadProgress && options.body !== undefined) {\n return makeRequestWithXHR(config, endpoint, options, url);\n }\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Parse response\n let data: unknown;\n\n // Handle 204 No Content\n if (response.status === 204) {\n data = {};\n } else {\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else if (contentType.includes('text/')) {\n data = await response.text();\n } else {\n // Check if there's any content\n const text = await response.text();\n if (text) {\n data = text;\n } else {\n data = {};\n }\n }\n }\n\n // Check for HTTP errors\n if (!response.ok && !(response.status in endpoint.responses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Validate response if enabled\n if (config.validateResponse !== false) {\n validateResponse(endpoint, response.status, data);\n }\n\n return {\n status: response.status,\n data,\n } as EndpointResponse<T>;\n}\n\n/**\n * Create a streaming result from an NDJSON response\n */\nfunction createStreamingResult<T extends StreamingEndpointDefinition>(\n response: Response,\n controller: AbortController,\n): StreamingResult<T> {\n type ChunkHandler = (chunk: ExtractChunk<T>) => void;\n type CloseHandler = (final?: ExtractFinalResponse<T>) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners = {\n chunk: new Set<ChunkHandler>(),\n close: new Set<CloseHandler>(),\n error: new Set<ErrorHandler>(),\n };\n\n // Start reading in background\n (async () => {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line);\n if (parsed.__final__) {\n listeners.close.forEach((h) => h(parsed.data));\n } else {\n listeners.chunk.forEach((h) => h(parsed as ExtractChunk<T>));\n }\n } catch (parseErr) {\n listeners.error.forEach((h) => h(parseErr as Error));\n }\n }\n }\n\n // Process any remaining buffer content\n if (buffer.trim()) {\n try {\n const parsed = JSON.parse(buffer);\n if (parsed.__final__) {\n listeners.close.forEach((h) => h(parsed.data));\n } else {\n listeners.chunk.forEach((h) => h(parsed as ExtractChunk<T>));\n }\n } catch {\n // Ignore incomplete JSON at end\n }\n }\n\n // Stream ended without final message\n listeners.close.forEach((h) => h());\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n listeners.error.forEach((h) => h(err as Error));\n }\n }\n })();\n\n return {\n on(event: 'chunk' | 'close' | 'error', handler: ChunkHandler | CloseHandler | ErrorHandler) {\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n abort() {\n controller.abort();\n },\n get aborted() {\n return controller.signal.aborted;\n },\n } as StreamingResult<T>;\n}\n\n/**\n * Validate streaming request data before sending\n */\nfunction validateStreamingRequest<T extends StreamingEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Make a streaming request to an endpoint\n */\nasync function makeStreamingRequest<T extends StreamingEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<StreamingResult<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateStreamingRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init - create our own controller for abort() method\n const controller = new AbortController();\n\n // Link to external abort signal if provided\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n controller.abort();\n } else {\n options.abortSignal.addEventListener('abort', () => controller.abort());\n }\n }\n\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n signal: controller.signal,\n };\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Check for error responses before streaming\n if (!response.ok) {\n const contentType = response.headers.get('content-type') || '';\n let data: unknown;\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Return streaming result\n return createStreamingResult<T>(response, controller);\n}\n\n/**\n * Create an SSE connection\n */\nfunction createSSEConnection<T extends SSEEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'> = {},\n): SSEConnection<T> {\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // EventSource doesn't support custom headers, but we can include query params\n // Note: If auth headers are needed, consider using fetch-based SSE or passing auth in query\n const eventSource = new EventSource(url);\n\n type EventHandler = (data: unknown, id?: string) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners: Record<string, Set<EventHandler | ErrorHandler>> = {\n error: new Set<ErrorHandler>(),\n };\n\n // Get event names from the endpoint\n const eventNames = Object.keys(endpoint.events);\n\n // Register listeners for each event type\n for (const eventName of eventNames) {\n listeners[eventName] = new Set<EventHandler>();\n eventSource.addEventListener(eventName, (e) => {\n const messageEvent = e as MessageEvent;\n try {\n const data = JSON.parse(messageEvent.data);\n (listeners[eventName] as Set<EventHandler>).forEach((h) =>\n h(data, messageEvent.lastEventId || undefined),\n );\n } catch (err) {\n (listeners.error as Set<ErrorHandler>).forEach((h) =>\n h(new Error(`Failed to parse SSE data: ${(err as Error).message}`)),\n );\n }\n });\n }\n\n // Handle errors\n eventSource.onerror = () => {\n (listeners.error as Set<ErrorHandler>).forEach((h) => h(new Error('SSE connection error')));\n };\n\n return {\n on(event: string, handler: EventHandler | ErrorHandler) {\n if (!listeners[event]) {\n listeners[event] = new Set();\n }\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n close() {\n eventSource.close();\n },\n get state() {\n const states = ['connecting', 'open', 'closed'] as const;\n return states[eventSource.readyState];\n },\n } as SSEConnection<T>;\n}\n\n/**\n * Resolve relative baseUrl to absolute URL in browser contexts\n */\nfunction resolveBaseUrl(baseUrl: string): string {\n // If baseUrl is already absolute, return as-is\n if (baseUrl.startsWith('http://') || baseUrl.startsWith('https://')) {\n return baseUrl;\n }\n\n // If baseUrl is relative (starts with /), resolve it using window.location in browser\n if (baseUrl.startsWith('/')) {\n const g = globalThis as unknown as { location?: { origin?: string } };\n const origin = g?.location?.origin || 'http://localhost';\n return origin + baseUrl;\n }\n\n // Otherwise, assume it's a full URL\n return baseUrl;\n}\n\n/**\n * Create a typesafe client for a contract\n */\nexport function createClient<T extends Contract>(contract: T, config: ClientConfig): Client<T> {\n // Resolve relative baseUrl to absolute URL\n const resolvedConfig = {\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n };\n\n const client: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n if (endpoint.type === 'standard') {\n client[name] = (options: EndpointRequestOptions<StandardEndpointDefinition> = {}) => {\n return makeRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'streaming') {\n client[name] = (options: EndpointRequestOptions<StreamingEndpointDefinition> = {}) => {\n return makeStreamingRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'sse') {\n client[name] = (\n options: Omit<\n EndpointRequestOptions<SSEEndpointDefinition>,\n 'body' | 'onUploadProgress'\n > = {},\n ) => {\n return createSSEConnection(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'download') {\n client[name] = (options: DownloadRequestOptions<DownloadEndpointDefinition> = {}) => {\n return makeDownloadRequest(resolvedConfig, endpoint, options);\n };\n } else {\n throw new Error(`Endpoint \"${name}\" has unknown type \"${(endpoint as any).type}\".`);\n }\n }\n\n return client as Client<T>;\n}\n\n/**\n * Create a client without providing the contract at runtime\n * Useful when you only need types and want a lighter bundle\n */\nexport function createTypedClient<T extends Contract>(_config: ClientConfig): Client<T> {\n return new Proxy({} as Client<T>, {\n get(_target, _prop: string) {\n return async (_options: EndpointRequestOptions<EndpointDefinition> = {}) => {\n // Without the contract, we can't validate or infer the endpoint\n // This is just a basic fetch wrapper with typing\n throw new Error(\n 'createTypedClient requires contract at runtime for validation. Use createClient instead.',\n );\n };\n },\n });\n}\n\nexport * from './websocket.cjs';\n"
|
|
5
|
+
"/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n Contract,\n DownloadEndpointDefinition,\n DownloadProgressEvent,\n EndpointDefinition,\n ExtractBody,\n ExtractChunk,\n ExtractFinalResponse,\n ExtractHeaders,\n ExtractParams,\n ExtractQuery,\n ExtractSSEEventData,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n UploadProgressEvent,\n} from '@richie-rpc/core';\nimport { buildUrl, interpolatePath, objectToFormData } from '@richie-rpc/core';\n\n// Re-export for convenience\nexport type { UploadProgressEvent, DownloadProgressEvent };\nimport type { z } from 'zod';\n\n// Client configuration\nexport interface ClientConfig {\n baseUrl: string;\n headers?: Record<string, string>;\n validateRequest?: boolean;\n parseResponse?: boolean;\n}\n\n// Request options for an endpoint\nexport type EndpointRequestOptions<T extends EndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n body?: ExtractBody<T> extends never ? never : ExtractBody<T>;\n abortSignal?: AbortSignal;\n /** Upload progress callback (uses XHR for progress tracking) */\n onUploadProgress?: (event: UploadProgressEvent) => void;\n};\n\n// Response type for a standard endpoint (union of all possible responses)\nexport type EndpointResponse<T extends StandardEndpointDefinition> = {\n [Status in keyof T['responses']]: {\n status: Status;\n data: T['responses'][Status] extends z.ZodTypeAny ? z.infer<T['responses'][Status]> : never;\n };\n}[keyof T['responses']];\n\n// Client method type for a standard endpoint\nexport type ClientMethod<T extends StandardEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<EndpointResponse<T>>;\n\n// ============================================\n// Streaming Endpoint Client Types\n// ============================================\n\n/**\n * Result object for streaming endpoints - event-based API\n */\nexport interface StreamingResult<T extends StreamingEndpointDefinition> {\n /** Subscribe to chunks */\n on(event: 'chunk', handler: (chunk: ExtractChunk<T>) => void): () => void;\n /** Subscribe to stream close (with optional final response) */\n on(event: 'close', handler: (final?: ExtractFinalResponse<T>) => void): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Abort the stream */\n abort(): void;\n /** Check if aborted */\n readonly aborted: boolean;\n}\n\n/**\n * Client method type for streaming endpoints\n */\nexport type StreamingClientMethod<T extends StreamingEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<StreamingResult<T>>;\n\n// ============================================\n// SSE Endpoint Client Types\n// ============================================\n\n/**\n * Connection object for SSE endpoints - event-based API\n */\nexport interface SSEConnection<T extends SSEEndpointDefinition> {\n /** Subscribe to a specific event type */\n on<K extends keyof T['events']>(\n event: K,\n handler: (data: ExtractSSEEventData<T, K>, id?: string) => void,\n ): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Close the connection */\n close(): void;\n /** Current connection state */\n readonly state: 'connecting' | 'open' | 'closed';\n}\n\n/**\n * Client method type for SSE endpoints\n */\nexport type SSEClientMethod<T extends SSEEndpointDefinition> = (\n options?: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'>,\n) => SSEConnection<T>;\n\n// ============================================\n// Download Endpoint Client Types\n// ============================================\n\n/**\n * Request options for download endpoints\n */\nexport type DownloadRequestOptions<T extends DownloadEndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n abortSignal?: AbortSignal;\n /** Download progress callback */\n onDownloadProgress?: (event: DownloadProgressEvent) => void;\n};\n\n/**\n * Response type for download endpoints\n * Success (200) returns File, errors return typed error response\n */\nexport type DownloadResponse<T extends DownloadEndpointDefinition> =\n | { status: 200; data: File }\n | (T['errorResponses'] extends Record<number, z.ZodTypeAny>\n ? {\n [S in keyof T['errorResponses']]: {\n status: S;\n data: T['errorResponses'][S] extends z.ZodTypeAny\n ? z.infer<T['errorResponses'][S]>\n : never;\n };\n }[keyof T['errorResponses']]\n : never);\n\n/**\n * Client method type for download endpoints\n */\nexport type DownloadClientMethod<T extends DownloadEndpointDefinition> = (\n options?: DownloadRequestOptions<T>,\n) => Promise<DownloadResponse<T>>;\n\n// Client type for a contract (supports all endpoint types)\nexport type Client<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? ClientMethod<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingClientMethod<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEClientMethod<T[K]>\n : T[K] extends DownloadEndpointDefinition\n ? DownloadClientMethod<T[K]>\n : never;\n};\n\n// Validation error\nexport class ClientValidationError extends Error {\n constructor(\n public field: string,\n public issues: z.ZodIssue[],\n ) {\n super(`Validation failed for ${field}`);\n this.name = 'ClientValidationError';\n }\n}\n\n// HTTP error\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public statusText: string,\n public body: unknown,\n ) {\n super(`HTTP Error ${status}: ${statusText}`);\n this.name = 'HTTPError';\n }\n}\n\n/**\n * Validate request data before sending\n */\nfunction validateRequest<T extends StandardEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Parse and transform response data using Zod schema\n */\nfunction parseResponse<T extends StandardEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): unknown {\n const responseSchema = endpoint.responses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n return result.data;\n }\n return data;\n}\n\n/**\n * Extract filename from Content-Disposition header\n */\nfunction extractFilename(contentDisposition: string | null): string | null {\n if (!contentDisposition) return null;\n // Try filename*= (RFC 5987) first\n const filenameStarMatch = contentDisposition.match(/filename\\*=(?:UTF-8'')?([^;\\s]+)/i);\n if (filenameStarMatch && filenameStarMatch[1]) {\n return decodeURIComponent(filenameStarMatch[1]);\n }\n // Try filename= (standard)\n const filenameMatch = contentDisposition.match(/filename=[\"']?([^\"';\\s]+)[\"']?/i);\n if (filenameMatch && filenameMatch[1]) {\n return filenameMatch[1];\n }\n return null;\n}\n\n/**\n * Validate download request data before sending\n */\nfunction validateDownloadRequest<T extends DownloadEndpointDefinition>(\n endpoint: T,\n options: DownloadRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n}\n\n/**\n * Parse and transform download error response data using Zod schema\n */\nfunction parseDownloadErrorResponse<T extends DownloadEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): unknown {\n if (endpoint.errorResponses) {\n const responseSchema = endpoint.errorResponses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n return result.data;\n }\n }\n return data;\n}\n\n/**\n * Make a download request using fetch with progress support\n */\nasync function makeDownloadRequest<T extends DownloadEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: DownloadRequestOptions<T> = {},\n): Promise<DownloadResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateDownloadRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: 'GET',\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Handle success (200) - return File\n if (response.status === 200) {\n const contentLength = response.headers.get('content-length');\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n\n let blob: Blob;\n\n if (options.onDownloadProgress && response.body) {\n // Stream the response to track progress\n const reader = response.body.getReader();\n const chunks: BlobPart[] = [];\n let loaded = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n chunks.push(value);\n loaded += value.length;\n\n options.onDownloadProgress({\n loaded,\n total,\n progress: total > 0 ? loaded / total : NaN,\n });\n }\n\n blob = new Blob(chunks);\n } else {\n blob = await response.blob();\n }\n\n const contentDisposition = response.headers.get('content-disposition');\n const filename = extractFilename(contentDisposition) || 'download';\n const contentType = response.headers.get('content-type') || 'application/octet-stream';\n\n const file = new File([blob], filename, { type: contentType });\n\n return {\n status: 200,\n data: file,\n } as DownloadResponse<T>;\n }\n\n // Handle error responses\n let data: unknown;\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n // Check for HTTP errors not in errorResponses\n if (endpoint.errorResponses && !(response.status in endpoint.errorResponses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Parse error response if enabled\n const parsedData =\n config.parseResponse !== false\n ? parseDownloadErrorResponse(endpoint, response.status, data)\n : data;\n\n return {\n status: response.status,\n data: parsedData,\n } as DownloadResponse<T>;\n}\n\n/**\n * Make a request using XMLHttpRequest for upload progress support\n */\nfunction makeRequestWithXHR<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n url: string,\n): Promise<EndpointResponse<T>> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.open(endpoint.method, url);\n\n // Set base headers from config\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n xhr.setRequestHeader(key, value);\n }\n }\n\n // Set request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n xhr.setRequestHeader(key, String(value));\n }\n }\n\n // Upload progress callback\n if (options.onUploadProgress) {\n xhr.upload.onprogress = (e) => {\n if (e.lengthComputable && options.onUploadProgress) {\n options.onUploadProgress({\n loaded: e.loaded,\n total: e.total,\n progress: e.loaded / e.total,\n });\n }\n };\n }\n\n // Handle abort signal\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n xhr.abort();\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n options.abortSignal.addEventListener('abort', () => {\n xhr.abort();\n });\n }\n\n xhr.onload = () => {\n let data: unknown;\n const responseContentType = xhr.getResponseHeader('content-type') || '';\n\n if (xhr.status === 204) {\n data = {};\n } else if (responseContentType.includes('application/json')) {\n try {\n data = JSON.parse(xhr.responseText);\n } catch {\n data = xhr.responseText || {};\n }\n } else if (responseContentType.includes('text/')) {\n data = xhr.responseText;\n } else {\n data = xhr.responseText || {};\n }\n\n // Check for HTTP errors\n if (xhr.status >= 400 && !(xhr.status in endpoint.responses)) {\n reject(new HTTPError(xhr.status, xhr.statusText, data));\n return;\n }\n\n // Parse response if enabled\n let parsedData = data;\n if (config.parseResponse !== false) {\n try {\n parsedData = parseResponse(endpoint, xhr.status, data);\n } catch (err) {\n reject(err);\n return;\n }\n }\n\n resolve({\n status: xhr.status,\n data: parsedData,\n } as EndpointResponse<T>);\n };\n\n xhr.onerror = () => reject(new Error('Network error'));\n xhr.onabort = () => reject(new DOMException('Aborted', 'AbortError'));\n\n // Prepare and send body\n const contentType = endpoint.contentType ?? 'application/json';\n if (options.body !== undefined) {\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n xhr.send(objectToFormData(options.body as Record<string, unknown>));\n } else {\n xhr.setRequestHeader('content-type', 'application/json');\n xhr.send(JSON.stringify(options.body));\n }\n } else {\n xhr.send();\n }\n });\n}\n\n/**\n * Make a request to a standard endpoint\n */\nasync function makeRequest<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<EndpointResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Use XHR for upload progress support\n if (options.onUploadProgress && options.body !== undefined) {\n return makeRequestWithXHR(config, endpoint, options, url);\n }\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Parse response\n let data: unknown;\n\n // Handle 204 No Content\n if (response.status === 204) {\n data = {};\n } else {\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else if (contentType.includes('text/')) {\n data = await response.text();\n } else {\n // Check if there's any content\n const text = await response.text();\n if (text) {\n data = text;\n } else {\n data = {};\n }\n }\n }\n\n // Check for HTTP errors\n if (!response.ok && !(response.status in endpoint.responses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Parse response if enabled\n const parsedData =\n config.parseResponse !== false ? parseResponse(endpoint, response.status, data) : data;\n\n return {\n status: response.status,\n data: parsedData,\n } as EndpointResponse<T>;\n}\n\n/**\n * Create a streaming result from an NDJSON response\n */\nfunction createStreamingResult<T extends StreamingEndpointDefinition>(\n response: Response,\n controller: AbortController,\n endpoint: T,\n config: ClientConfig,\n): StreamingResult<T> {\n type ChunkHandler = (chunk: ExtractChunk<T>) => void;\n type CloseHandler = (final?: ExtractFinalResponse<T>) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners = {\n chunk: new Set<ChunkHandler>(),\n close: new Set<CloseHandler>(),\n error: new Set<ErrorHandler>(),\n };\n\n // Helper to parse chunk data\n const parseChunk = (data: unknown): unknown => {\n if (config.parseResponse !== false && endpoint.chunk) {\n const result = endpoint.chunk.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError('chunk', result.error.issues);\n }\n return result.data;\n }\n return data;\n };\n\n // Helper to parse final response data\n const parseFinalResponse = (data: unknown): unknown => {\n if (config.parseResponse !== false && endpoint.finalResponse) {\n const result = endpoint.finalResponse.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError('finalResponse', result.error.issues);\n }\n return result.data;\n }\n return data;\n };\n\n // Start reading in background\n (async () => {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line);\n if (parsed.__final__) {\n const finalData = parseFinalResponse(parsed.data);\n listeners.close.forEach((h) => h(finalData as ExtractFinalResponse<T>));\n } else {\n const chunkData = parseChunk(parsed);\n listeners.chunk.forEach((h) => h(chunkData as ExtractChunk<T>));\n }\n } catch (parseErr) {\n listeners.error.forEach((h) => h(parseErr as Error));\n }\n }\n }\n\n // Process any remaining buffer content\n if (buffer.trim()) {\n try {\n const parsed = JSON.parse(buffer);\n if (parsed.__final__) {\n const finalData = parseFinalResponse(parsed.data);\n listeners.close.forEach((h) => h(finalData as ExtractFinalResponse<T>));\n } else {\n const chunkData = parseChunk(parsed);\n listeners.chunk.forEach((h) => h(chunkData as ExtractChunk<T>));\n }\n } catch {\n // Ignore incomplete JSON at end\n }\n }\n\n // Stream ended without final message\n listeners.close.forEach((h) => h());\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n listeners.error.forEach((h) => h(err as Error));\n }\n }\n })();\n\n return {\n on(event: 'chunk' | 'close' | 'error', handler: ChunkHandler | CloseHandler | ErrorHandler) {\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n abort() {\n controller.abort();\n },\n get aborted() {\n return controller.signal.aborted;\n },\n } as StreamingResult<T>;\n}\n\n/**\n * Validate streaming request data before sending\n */\nfunction validateStreamingRequest<T extends StreamingEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Make a streaming request to an endpoint\n */\nasync function makeStreamingRequest<T extends StreamingEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<StreamingResult<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateStreamingRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init - create our own controller for abort() method\n const controller = new AbortController();\n\n // Link to external abort signal if provided\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n controller.abort();\n } else {\n options.abortSignal.addEventListener('abort', () => controller.abort());\n }\n }\n\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n signal: controller.signal,\n };\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Check for error responses before streaming\n if (!response.ok) {\n const contentType = response.headers.get('content-type') || '';\n let data: unknown;\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Return streaming result\n return createStreamingResult<T>(response, controller, endpoint, config);\n}\n\n/**\n * Create an SSE connection\n */\nfunction createSSEConnection<T extends SSEEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'> = {},\n): SSEConnection<T> {\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // EventSource doesn't support custom headers, but we can include query params\n // Note: If auth headers are needed, consider using fetch-based SSE or passing auth in query\n const eventSource = new EventSource(url);\n\n type EventHandler = (data: unknown, id?: string) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners: Record<string, Set<EventHandler | ErrorHandler>> = {\n error: new Set<ErrorHandler>(),\n };\n\n // Get event names from the endpoint\n const eventNames = Object.keys(endpoint.events);\n\n // Register listeners for each event type\n for (const eventName of eventNames) {\n listeners[eventName] = new Set<EventHandler>();\n eventSource.addEventListener(eventName, (e) => {\n const messageEvent = e as MessageEvent;\n try {\n const rawData = JSON.parse(messageEvent.data);\n\n // Parse event data using Zod schema if enabled\n let parsedData = rawData;\n if (config.parseResponse !== false) {\n const eventSchema = endpoint.events[eventName];\n if (eventSchema) {\n const result = eventSchema.safeParse(rawData);\n if (!result.success) {\n (listeners.error as Set<ErrorHandler>).forEach((h) =>\n h(new ClientValidationError(`event[${eventName}]`, result.error.issues)),\n );\n return;\n }\n parsedData = result.data;\n }\n }\n\n (listeners[eventName] as Set<EventHandler>).forEach((h) =>\n h(parsedData, messageEvent.lastEventId || undefined),\n );\n } catch (err) {\n (listeners.error as Set<ErrorHandler>).forEach((h) =>\n h(new Error(`Failed to parse SSE data: ${(err as Error).message}`)),\n );\n }\n });\n }\n\n // Handle errors\n eventSource.onerror = () => {\n (listeners.error as Set<ErrorHandler>).forEach((h) => h(new Error('SSE connection error')));\n };\n\n return {\n on(event: string, handler: EventHandler | ErrorHandler) {\n if (!listeners[event]) {\n listeners[event] = new Set();\n }\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n close() {\n eventSource.close();\n },\n get state() {\n const states = ['connecting', 'open', 'closed'] as const;\n return states[eventSource.readyState];\n },\n } as SSEConnection<T>;\n}\n\n/**\n * Resolve relative baseUrl to absolute URL in browser contexts\n */\nfunction resolveBaseUrl(baseUrl: string): string {\n // If baseUrl is already absolute, return as-is\n if (baseUrl.startsWith('http://') || baseUrl.startsWith('https://')) {\n return baseUrl;\n }\n\n // If baseUrl is relative (starts with /), resolve it using window.location in browser\n if (baseUrl.startsWith('/')) {\n const g = globalThis as unknown as { location?: { origin?: string } };\n const origin = g?.location?.origin || 'http://localhost';\n return origin + baseUrl;\n }\n\n // Otherwise, assume it's a full URL\n return baseUrl;\n}\n\n/**\n * Create a typesafe client for a contract\n */\nexport function createClient<T extends Contract>(contract: T, config: ClientConfig): Client<T> {\n // Resolve relative baseUrl to absolute URL\n const resolvedConfig = {\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n };\n\n const client: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n if (endpoint.type === 'standard') {\n client[name] = (options: EndpointRequestOptions<StandardEndpointDefinition> = {}) => {\n return makeRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'streaming') {\n client[name] = (options: EndpointRequestOptions<StreamingEndpointDefinition> = {}) => {\n return makeStreamingRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'sse') {\n client[name] = (\n options: Omit<\n EndpointRequestOptions<SSEEndpointDefinition>,\n 'body' | 'onUploadProgress'\n > = {},\n ) => {\n return createSSEConnection(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'download') {\n client[name] = (options: DownloadRequestOptions<DownloadEndpointDefinition> = {}) => {\n return makeDownloadRequest(resolvedConfig, endpoint, options);\n };\n } else {\n throw new Error(`Endpoint \"${name}\" has unknown type \"${(endpoint as any).type}\".`);\n }\n }\n\n return client as Client<T>;\n}\n\n/**\n * Create a client without providing the contract at runtime\n * Useful when you only need types and want a lighter bundle\n */\nexport function createTypedClient<T extends Contract>(_config: ClientConfig): Client<T> {\n return new Proxy({} as Client<T>, {\n get(_target, _prop: string) {\n return async (_options: EndpointRequestOptions<EndpointDefinition> = {}) => {\n // Without the contract, we can't validate or infer the endpoint\n // This is just a basic fetch wrapper with typing\n throw new Error(\n 'createTypedClient requires contract at runtime for validation. Use createClient instead.',\n );\n };\n },\n });\n}\n\nexport * from './websocket.cjs';\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "FF579F2ABF9D24DD64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/cjs/package.json
CHANGED
package/dist/mjs/index.mjs
CHANGED
|
@@ -53,14 +53,16 @@ function validateRequest(endpoint, options) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
function
|
|
56
|
+
function parseResponse(endpoint, status, data) {
|
|
57
57
|
const responseSchema = endpoint.responses[status];
|
|
58
58
|
if (responseSchema) {
|
|
59
59
|
const result = responseSchema.safeParse(data);
|
|
60
60
|
if (!result.success) {
|
|
61
61
|
throw new ClientValidationError(`response[${status}]`, result.error.issues);
|
|
62
62
|
}
|
|
63
|
+
return result.data;
|
|
63
64
|
}
|
|
65
|
+
return data;
|
|
64
66
|
}
|
|
65
67
|
function extractFilename(contentDisposition) {
|
|
66
68
|
if (!contentDisposition)
|
|
@@ -95,7 +97,7 @@ function validateDownloadRequest(endpoint, options) {
|
|
|
95
97
|
}
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
|
-
function
|
|
100
|
+
function parseDownloadErrorResponse(endpoint, status, data) {
|
|
99
101
|
if (endpoint.errorResponses) {
|
|
100
102
|
const responseSchema = endpoint.errorResponses[status];
|
|
101
103
|
if (responseSchema) {
|
|
@@ -103,8 +105,10 @@ function validateDownloadErrorResponse(endpoint, status, data) {
|
|
|
103
105
|
if (!result.success) {
|
|
104
106
|
throw new ClientValidationError(`response[${status}]`, result.error.issues);
|
|
105
107
|
}
|
|
108
|
+
return result.data;
|
|
106
109
|
}
|
|
107
110
|
}
|
|
111
|
+
return data;
|
|
108
112
|
}
|
|
109
113
|
async function makeDownloadRequest(config, endpoint, options = {}) {
|
|
110
114
|
if (config.validateRequest !== false) {
|
|
@@ -172,12 +176,10 @@ async function makeDownloadRequest(config, endpoint, options = {}) {
|
|
|
172
176
|
if (endpoint.errorResponses && !(response.status in endpoint.errorResponses)) {
|
|
173
177
|
throw new HTTPError(response.status, response.statusText, data);
|
|
174
178
|
}
|
|
175
|
-
|
|
176
|
-
validateDownloadErrorResponse(endpoint, response.status, data);
|
|
177
|
-
}
|
|
179
|
+
const parsedData = config.parseResponse !== false ? parseDownloadErrorResponse(endpoint, response.status, data) : data;
|
|
178
180
|
return {
|
|
179
181
|
status: response.status,
|
|
180
|
-
data
|
|
182
|
+
data: parsedData
|
|
181
183
|
};
|
|
182
184
|
}
|
|
183
185
|
function makeRequestWithXHR(config, endpoint, options, url) {
|
|
@@ -235,9 +237,10 @@ function makeRequestWithXHR(config, endpoint, options, url) {
|
|
|
235
237
|
reject(new HTTPError(xhr.status, xhr.statusText, data));
|
|
236
238
|
return;
|
|
237
239
|
}
|
|
238
|
-
|
|
240
|
+
let parsedData = data;
|
|
241
|
+
if (config.parseResponse !== false) {
|
|
239
242
|
try {
|
|
240
|
-
|
|
243
|
+
parsedData = parseResponse(endpoint, xhr.status, data);
|
|
241
244
|
} catch (err) {
|
|
242
245
|
reject(err);
|
|
243
246
|
return;
|
|
@@ -245,7 +248,7 @@ function makeRequestWithXHR(config, endpoint, options, url) {
|
|
|
245
248
|
}
|
|
246
249
|
resolve({
|
|
247
250
|
status: xhr.status,
|
|
248
|
-
data
|
|
251
|
+
data: parsedData
|
|
249
252
|
});
|
|
250
253
|
};
|
|
251
254
|
xhr.onerror = () => reject(new Error("Network error"));
|
|
@@ -319,20 +322,38 @@ async function makeRequest(config, endpoint, options) {
|
|
|
319
322
|
if (!response.ok && !(response.status in endpoint.responses)) {
|
|
320
323
|
throw new HTTPError(response.status, response.statusText, data);
|
|
321
324
|
}
|
|
322
|
-
|
|
323
|
-
validateResponse(endpoint, response.status, data);
|
|
324
|
-
}
|
|
325
|
+
const parsedData = config.parseResponse !== false ? parseResponse(endpoint, response.status, data) : data;
|
|
325
326
|
return {
|
|
326
327
|
status: response.status,
|
|
327
|
-
data
|
|
328
|
+
data: parsedData
|
|
328
329
|
};
|
|
329
330
|
}
|
|
330
|
-
function createStreamingResult(response, controller) {
|
|
331
|
+
function createStreamingResult(response, controller, endpoint, config) {
|
|
331
332
|
const listeners = {
|
|
332
333
|
chunk: new Set,
|
|
333
334
|
close: new Set,
|
|
334
335
|
error: new Set
|
|
335
336
|
};
|
|
337
|
+
const parseChunk = (data) => {
|
|
338
|
+
if (config.parseResponse !== false && endpoint.chunk) {
|
|
339
|
+
const result = endpoint.chunk.safeParse(data);
|
|
340
|
+
if (!result.success) {
|
|
341
|
+
throw new ClientValidationError("chunk", result.error.issues);
|
|
342
|
+
}
|
|
343
|
+
return result.data;
|
|
344
|
+
}
|
|
345
|
+
return data;
|
|
346
|
+
};
|
|
347
|
+
const parseFinalResponse = (data) => {
|
|
348
|
+
if (config.parseResponse !== false && endpoint.finalResponse) {
|
|
349
|
+
const result = endpoint.finalResponse.safeParse(data);
|
|
350
|
+
if (!result.success) {
|
|
351
|
+
throw new ClientValidationError("finalResponse", result.error.issues);
|
|
352
|
+
}
|
|
353
|
+
return result.data;
|
|
354
|
+
}
|
|
355
|
+
return data;
|
|
356
|
+
};
|
|
336
357
|
(async () => {
|
|
337
358
|
const reader = response.body.getReader();
|
|
338
359
|
const decoder = new TextDecoder;
|
|
@@ -352,9 +373,11 @@ function createStreamingResult(response, controller) {
|
|
|
352
373
|
try {
|
|
353
374
|
const parsed = JSON.parse(line);
|
|
354
375
|
if (parsed.__final__) {
|
|
355
|
-
|
|
376
|
+
const finalData = parseFinalResponse(parsed.data);
|
|
377
|
+
listeners.close.forEach((h) => h(finalData));
|
|
356
378
|
} else {
|
|
357
|
-
|
|
379
|
+
const chunkData = parseChunk(parsed);
|
|
380
|
+
listeners.chunk.forEach((h) => h(chunkData));
|
|
358
381
|
}
|
|
359
382
|
} catch (parseErr) {
|
|
360
383
|
listeners.error.forEach((h) => h(parseErr));
|
|
@@ -365,9 +388,11 @@ function createStreamingResult(response, controller) {
|
|
|
365
388
|
try {
|
|
366
389
|
const parsed = JSON.parse(buffer);
|
|
367
390
|
if (parsed.__final__) {
|
|
368
|
-
|
|
391
|
+
const finalData = parseFinalResponse(parsed.data);
|
|
392
|
+
listeners.close.forEach((h) => h(finalData));
|
|
369
393
|
} else {
|
|
370
|
-
|
|
394
|
+
const chunkData = parseChunk(parsed);
|
|
395
|
+
listeners.chunk.forEach((h) => h(chunkData));
|
|
371
396
|
}
|
|
372
397
|
} catch {}
|
|
373
398
|
}
|
|
@@ -465,7 +490,7 @@ async function makeStreamingRequest(config, endpoint, options) {
|
|
|
465
490
|
}
|
|
466
491
|
throw new HTTPError(response.status, response.statusText, data);
|
|
467
492
|
}
|
|
468
|
-
return createStreamingResult(response, controller);
|
|
493
|
+
return createStreamingResult(response, controller, endpoint, config);
|
|
469
494
|
}
|
|
470
495
|
function createSSEConnection(config, endpoint, options = {}) {
|
|
471
496
|
let path = endpoint.path;
|
|
@@ -483,8 +508,20 @@ function createSSEConnection(config, endpoint, options = {}) {
|
|
|
483
508
|
eventSource.addEventListener(eventName, (e) => {
|
|
484
509
|
const messageEvent = e;
|
|
485
510
|
try {
|
|
486
|
-
const
|
|
487
|
-
|
|
511
|
+
const rawData = JSON.parse(messageEvent.data);
|
|
512
|
+
let parsedData = rawData;
|
|
513
|
+
if (config.parseResponse !== false) {
|
|
514
|
+
const eventSchema = endpoint.events[eventName];
|
|
515
|
+
if (eventSchema) {
|
|
516
|
+
const result = eventSchema.safeParse(rawData);
|
|
517
|
+
if (!result.success) {
|
|
518
|
+
listeners.error.forEach((h) => h(new ClientValidationError(`event[${eventName}]`, result.error.issues)));
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
parsedData = result.data;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
listeners[eventName].forEach((h) => h(parsedData, messageEvent.lastEventId || undefined));
|
|
488
525
|
} catch (err) {
|
|
489
526
|
listeners.error.forEach((h) => h(new Error(`Failed to parse SSE data: ${err.message}`)));
|
|
490
527
|
}
|
|
@@ -566,4 +603,4 @@ export {
|
|
|
566
603
|
ClientValidationError
|
|
567
604
|
};
|
|
568
605
|
|
|
569
|
-
//# debugId=
|
|
606
|
+
//# debugId=2002C2CDD59A58E164756E2164756E21
|
package/dist/mjs/index.mjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n Contract,\n DownloadEndpointDefinition,\n DownloadProgressEvent,\n EndpointDefinition,\n ExtractBody,\n ExtractChunk,\n ExtractFinalResponse,\n ExtractHeaders,\n ExtractParams,\n ExtractQuery,\n ExtractSSEEventData,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n UploadProgressEvent,\n} from '@richie-rpc/core';\nimport { buildUrl, interpolatePath, objectToFormData } from '@richie-rpc/core';\n\n// Re-export for convenience\nexport type { UploadProgressEvent, DownloadProgressEvent };\nimport type { z } from 'zod';\n\n// Client configuration\nexport interface ClientConfig {\n baseUrl: string;\n headers?: Record<string, string>;\n validateRequest?: boolean;\n validateResponse?: boolean;\n}\n\n// Request options for an endpoint\nexport type EndpointRequestOptions<T extends EndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n body?: ExtractBody<T> extends never ? never : ExtractBody<T>;\n abortSignal?: AbortSignal;\n /** Upload progress callback (uses XHR for progress tracking) */\n onUploadProgress?: (event: UploadProgressEvent) => void;\n};\n\n// Response type for a standard endpoint (union of all possible responses)\nexport type EndpointResponse<T extends StandardEndpointDefinition> = {\n [Status in keyof T['responses']]: {\n status: Status;\n data: T['responses'][Status] extends z.ZodTypeAny ? z.infer<T['responses'][Status]> : never;\n };\n}[keyof T['responses']];\n\n// Client method type for a standard endpoint\nexport type ClientMethod<T extends StandardEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<EndpointResponse<T>>;\n\n// ============================================\n// Streaming Endpoint Client Types\n// ============================================\n\n/**\n * Result object for streaming endpoints - event-based API\n */\nexport interface StreamingResult<T extends StreamingEndpointDefinition> {\n /** Subscribe to chunks */\n on(event: 'chunk', handler: (chunk: ExtractChunk<T>) => void): () => void;\n /** Subscribe to stream close (with optional final response) */\n on(event: 'close', handler: (final?: ExtractFinalResponse<T>) => void): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Abort the stream */\n abort(): void;\n /** Check if aborted */\n readonly aborted: boolean;\n}\n\n/**\n * Client method type for streaming endpoints\n */\nexport type StreamingClientMethod<T extends StreamingEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<StreamingResult<T>>;\n\n// ============================================\n// SSE Endpoint Client Types\n// ============================================\n\n/**\n * Connection object for SSE endpoints - event-based API\n */\nexport interface SSEConnection<T extends SSEEndpointDefinition> {\n /** Subscribe to a specific event type */\n on<K extends keyof T['events']>(\n event: K,\n handler: (data: ExtractSSEEventData<T, K>, id?: string) => void,\n ): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Close the connection */\n close(): void;\n /** Current connection state */\n readonly state: 'connecting' | 'open' | 'closed';\n}\n\n/**\n * Client method type for SSE endpoints\n */\nexport type SSEClientMethod<T extends SSEEndpointDefinition> = (\n options?: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'>,\n) => SSEConnection<T>;\n\n// ============================================\n// Download Endpoint Client Types\n// ============================================\n\n/**\n * Request options for download endpoints\n */\nexport type DownloadRequestOptions<T extends DownloadEndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n abortSignal?: AbortSignal;\n /** Download progress callback */\n onDownloadProgress?: (event: DownloadProgressEvent) => void;\n};\n\n/**\n * Response type for download endpoints\n * Success (200) returns File, errors return typed error response\n */\nexport type DownloadResponse<T extends DownloadEndpointDefinition> =\n | { status: 200; data: File }\n | (T['errorResponses'] extends Record<number, z.ZodTypeAny>\n ? {\n [S in keyof T['errorResponses']]: {\n status: S;\n data: T['errorResponses'][S] extends z.ZodTypeAny\n ? z.infer<T['errorResponses'][S]>\n : never;\n };\n }[keyof T['errorResponses']]\n : never);\n\n/**\n * Client method type for download endpoints\n */\nexport type DownloadClientMethod<T extends DownloadEndpointDefinition> = (\n options?: DownloadRequestOptions<T>,\n) => Promise<DownloadResponse<T>>;\n\n// Client type for a contract (supports all endpoint types)\nexport type Client<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? ClientMethod<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingClientMethod<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEClientMethod<T[K]>\n : T[K] extends DownloadEndpointDefinition\n ? DownloadClientMethod<T[K]>\n : never;\n};\n\n// Validation error\nexport class ClientValidationError extends Error {\n constructor(\n public field: string,\n public issues: z.ZodIssue[],\n ) {\n super(`Validation failed for ${field}`);\n this.name = 'ClientValidationError';\n }\n}\n\n// HTTP error\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public statusText: string,\n public body: unknown,\n ) {\n super(`HTTP Error ${status}: ${statusText}`);\n this.name = 'HTTPError';\n }\n}\n\n/**\n * Validate request data before sending\n */\nfunction validateRequest<T extends StandardEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Validate response data after receiving\n */\nfunction validateResponse<T extends StandardEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): void {\n const responseSchema = endpoint.responses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n }\n}\n\n/**\n * Extract filename from Content-Disposition header\n */\nfunction extractFilename(contentDisposition: string | null): string | null {\n if (!contentDisposition) return null;\n // Try filename*= (RFC 5987) first\n const filenameStarMatch = contentDisposition.match(/filename\\*=(?:UTF-8'')?([^;\\s]+)/i);\n if (filenameStarMatch && filenameStarMatch[1]) {\n return decodeURIComponent(filenameStarMatch[1]);\n }\n // Try filename= (standard)\n const filenameMatch = contentDisposition.match(/filename=[\"']?([^\"';\\s]+)[\"']?/i);\n if (filenameMatch && filenameMatch[1]) {\n return filenameMatch[1];\n }\n return null;\n}\n\n/**\n * Validate download request data before sending\n */\nfunction validateDownloadRequest<T extends DownloadEndpointDefinition>(\n endpoint: T,\n options: DownloadRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n}\n\n/**\n * Validate download error response data\n */\nfunction validateDownloadErrorResponse<T extends DownloadEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): void {\n if (endpoint.errorResponses) {\n const responseSchema = endpoint.errorResponses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n }\n }\n}\n\n/**\n * Make a download request using fetch with progress support\n */\nasync function makeDownloadRequest<T extends DownloadEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: DownloadRequestOptions<T> = {},\n): Promise<DownloadResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateDownloadRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: 'GET',\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Handle success (200) - return File\n if (response.status === 200) {\n const contentLength = response.headers.get('content-length');\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n\n let blob: Blob;\n\n if (options.onDownloadProgress && response.body) {\n // Stream the response to track progress\n const reader = response.body.getReader();\n const chunks: BlobPart[] = [];\n let loaded = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n chunks.push(value);\n loaded += value.length;\n\n options.onDownloadProgress({\n loaded,\n total,\n progress: total > 0 ? loaded / total : NaN,\n });\n }\n\n blob = new Blob(chunks);\n } else {\n blob = await response.blob();\n }\n\n const contentDisposition = response.headers.get('content-disposition');\n const filename = extractFilename(contentDisposition) || 'download';\n const contentType = response.headers.get('content-type') || 'application/octet-stream';\n\n const file = new File([blob], filename, { type: contentType });\n\n return {\n status: 200,\n data: file,\n } as DownloadResponse<T>;\n }\n\n // Handle error responses\n let data: unknown;\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n // Check for HTTP errors not in errorResponses\n if (endpoint.errorResponses && !(response.status in endpoint.errorResponses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Validate error response if enabled\n if (config.validateResponse !== false) {\n validateDownloadErrorResponse(endpoint, response.status, data);\n }\n\n return {\n status: response.status,\n data,\n } as DownloadResponse<T>;\n}\n\n/**\n * Make a request using XMLHttpRequest for upload progress support\n */\nfunction makeRequestWithXHR<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n url: string,\n): Promise<EndpointResponse<T>> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.open(endpoint.method, url);\n\n // Set base headers from config\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n xhr.setRequestHeader(key, value);\n }\n }\n\n // Set request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n xhr.setRequestHeader(key, String(value));\n }\n }\n\n // Upload progress callback\n if (options.onUploadProgress) {\n xhr.upload.onprogress = (e) => {\n if (e.lengthComputable && options.onUploadProgress) {\n options.onUploadProgress({\n loaded: e.loaded,\n total: e.total,\n progress: e.loaded / e.total,\n });\n }\n };\n }\n\n // Handle abort signal\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n xhr.abort();\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n options.abortSignal.addEventListener('abort', () => {\n xhr.abort();\n });\n }\n\n xhr.onload = () => {\n let data: unknown;\n const responseContentType = xhr.getResponseHeader('content-type') || '';\n\n if (xhr.status === 204) {\n data = {};\n } else if (responseContentType.includes('application/json')) {\n try {\n data = JSON.parse(xhr.responseText);\n } catch {\n data = xhr.responseText || {};\n }\n } else if (responseContentType.includes('text/')) {\n data = xhr.responseText;\n } else {\n data = xhr.responseText || {};\n }\n\n // Check for HTTP errors\n if (xhr.status >= 400 && !(xhr.status in endpoint.responses)) {\n reject(new HTTPError(xhr.status, xhr.statusText, data));\n return;\n }\n\n // Validate response if enabled\n if (config.validateResponse !== false) {\n try {\n validateResponse(endpoint, xhr.status, data);\n } catch (err) {\n reject(err);\n return;\n }\n }\n\n resolve({\n status: xhr.status,\n data,\n } as EndpointResponse<T>);\n };\n\n xhr.onerror = () => reject(new Error('Network error'));\n xhr.onabort = () => reject(new DOMException('Aborted', 'AbortError'));\n\n // Prepare and send body\n const contentType = endpoint.contentType ?? 'application/json';\n if (options.body !== undefined) {\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n xhr.send(objectToFormData(options.body as Record<string, unknown>));\n } else {\n xhr.setRequestHeader('content-type', 'application/json');\n xhr.send(JSON.stringify(options.body));\n }\n } else {\n xhr.send();\n }\n });\n}\n\n/**\n * Make a request to a standard endpoint\n */\nasync function makeRequest<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<EndpointResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Use XHR for upload progress support\n if (options.onUploadProgress && options.body !== undefined) {\n return makeRequestWithXHR(config, endpoint, options, url);\n }\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Parse response\n let data: unknown;\n\n // Handle 204 No Content\n if (response.status === 204) {\n data = {};\n } else {\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else if (contentType.includes('text/')) {\n data = await response.text();\n } else {\n // Check if there's any content\n const text = await response.text();\n if (text) {\n data = text;\n } else {\n data = {};\n }\n }\n }\n\n // Check for HTTP errors\n if (!response.ok && !(response.status in endpoint.responses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Validate response if enabled\n if (config.validateResponse !== false) {\n validateResponse(endpoint, response.status, data);\n }\n\n return {\n status: response.status,\n data,\n } as EndpointResponse<T>;\n}\n\n/**\n * Create a streaming result from an NDJSON response\n */\nfunction createStreamingResult<T extends StreamingEndpointDefinition>(\n response: Response,\n controller: AbortController,\n): StreamingResult<T> {\n type ChunkHandler = (chunk: ExtractChunk<T>) => void;\n type CloseHandler = (final?: ExtractFinalResponse<T>) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners = {\n chunk: new Set<ChunkHandler>(),\n close: new Set<CloseHandler>(),\n error: new Set<ErrorHandler>(),\n };\n\n // Start reading in background\n (async () => {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line);\n if (parsed.__final__) {\n listeners.close.forEach((h) => h(parsed.data));\n } else {\n listeners.chunk.forEach((h) => h(parsed as ExtractChunk<T>));\n }\n } catch (parseErr) {\n listeners.error.forEach((h) => h(parseErr as Error));\n }\n }\n }\n\n // Process any remaining buffer content\n if (buffer.trim()) {\n try {\n const parsed = JSON.parse(buffer);\n if (parsed.__final__) {\n listeners.close.forEach((h) => h(parsed.data));\n } else {\n listeners.chunk.forEach((h) => h(parsed as ExtractChunk<T>));\n }\n } catch {\n // Ignore incomplete JSON at end\n }\n }\n\n // Stream ended without final message\n listeners.close.forEach((h) => h());\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n listeners.error.forEach((h) => h(err as Error));\n }\n }\n })();\n\n return {\n on(event: 'chunk' | 'close' | 'error', handler: ChunkHandler | CloseHandler | ErrorHandler) {\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n abort() {\n controller.abort();\n },\n get aborted() {\n return controller.signal.aborted;\n },\n } as StreamingResult<T>;\n}\n\n/**\n * Validate streaming request data before sending\n */\nfunction validateStreamingRequest<T extends StreamingEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Make a streaming request to an endpoint\n */\nasync function makeStreamingRequest<T extends StreamingEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<StreamingResult<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateStreamingRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init - create our own controller for abort() method\n const controller = new AbortController();\n\n // Link to external abort signal if provided\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n controller.abort();\n } else {\n options.abortSignal.addEventListener('abort', () => controller.abort());\n }\n }\n\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n signal: controller.signal,\n };\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Check for error responses before streaming\n if (!response.ok) {\n const contentType = response.headers.get('content-type') || '';\n let data: unknown;\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Return streaming result\n return createStreamingResult<T>(response, controller);\n}\n\n/**\n * Create an SSE connection\n */\nfunction createSSEConnection<T extends SSEEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'> = {},\n): SSEConnection<T> {\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // EventSource doesn't support custom headers, but we can include query params\n // Note: If auth headers are needed, consider using fetch-based SSE or passing auth in query\n const eventSource = new EventSource(url);\n\n type EventHandler = (data: unknown, id?: string) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners: Record<string, Set<EventHandler | ErrorHandler>> = {\n error: new Set<ErrorHandler>(),\n };\n\n // Get event names from the endpoint\n const eventNames = Object.keys(endpoint.events);\n\n // Register listeners for each event type\n for (const eventName of eventNames) {\n listeners[eventName] = new Set<EventHandler>();\n eventSource.addEventListener(eventName, (e) => {\n const messageEvent = e as MessageEvent;\n try {\n const data = JSON.parse(messageEvent.data);\n (listeners[eventName] as Set<EventHandler>).forEach((h) =>\n h(data, messageEvent.lastEventId || undefined),\n );\n } catch (err) {\n (listeners.error as Set<ErrorHandler>).forEach((h) =>\n h(new Error(`Failed to parse SSE data: ${(err as Error).message}`)),\n );\n }\n });\n }\n\n // Handle errors\n eventSource.onerror = () => {\n (listeners.error as Set<ErrorHandler>).forEach((h) => h(new Error('SSE connection error')));\n };\n\n return {\n on(event: string, handler: EventHandler | ErrorHandler) {\n if (!listeners[event]) {\n listeners[event] = new Set();\n }\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n close() {\n eventSource.close();\n },\n get state() {\n const states = ['connecting', 'open', 'closed'] as const;\n return states[eventSource.readyState];\n },\n } as SSEConnection<T>;\n}\n\n/**\n * Resolve relative baseUrl to absolute URL in browser contexts\n */\nfunction resolveBaseUrl(baseUrl: string): string {\n // If baseUrl is already absolute, return as-is\n if (baseUrl.startsWith('http://') || baseUrl.startsWith('https://')) {\n return baseUrl;\n }\n\n // If baseUrl is relative (starts with /), resolve it using window.location in browser\n if (baseUrl.startsWith('/')) {\n const g = globalThis as unknown as { location?: { origin?: string } };\n const origin = g?.location?.origin || 'http://localhost';\n return origin + baseUrl;\n }\n\n // Otherwise, assume it's a full URL\n return baseUrl;\n}\n\n/**\n * Create a typesafe client for a contract\n */\nexport function createClient<T extends Contract>(contract: T, config: ClientConfig): Client<T> {\n // Resolve relative baseUrl to absolute URL\n const resolvedConfig = {\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n };\n\n const client: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n if (endpoint.type === 'standard') {\n client[name] = (options: EndpointRequestOptions<StandardEndpointDefinition> = {}) => {\n return makeRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'streaming') {\n client[name] = (options: EndpointRequestOptions<StreamingEndpointDefinition> = {}) => {\n return makeStreamingRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'sse') {\n client[name] = (\n options: Omit<\n EndpointRequestOptions<SSEEndpointDefinition>,\n 'body' | 'onUploadProgress'\n > = {},\n ) => {\n return createSSEConnection(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'download') {\n client[name] = (options: DownloadRequestOptions<DownloadEndpointDefinition> = {}) => {\n return makeDownloadRequest(resolvedConfig, endpoint, options);\n };\n } else {\n throw new Error(`Endpoint \"${name}\" has unknown type \"${(endpoint as any).type}\".`);\n }\n }\n\n return client as Client<T>;\n}\n\n/**\n * Create a client without providing the contract at runtime\n * Useful when you only need types and want a lighter bundle\n */\nexport function createTypedClient<T extends Contract>(_config: ClientConfig): Client<T> {\n return new Proxy({} as Client<T>, {\n get(_target, _prop: string) {\n return async (_options: EndpointRequestOptions<EndpointDefinition> = {}) => {\n // Without the contract, we can't validate or infer the endpoint\n // This is just a basic fetch wrapper with typing\n throw new Error(\n 'createTypedClient requires contract at runtime for validation. Use createClient instead.',\n );\n };\n },\n });\n}\n\nexport * from './websocket.mjs';\n"
|
|
5
|
+
"/* eslint-disable @typescript-eslint/no-non-null-assertion */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n Contract,\n DownloadEndpointDefinition,\n DownloadProgressEvent,\n EndpointDefinition,\n ExtractBody,\n ExtractChunk,\n ExtractFinalResponse,\n ExtractHeaders,\n ExtractParams,\n ExtractQuery,\n ExtractSSEEventData,\n SSEEndpointDefinition,\n StandardEndpointDefinition,\n StreamingEndpointDefinition,\n UploadProgressEvent,\n} from '@richie-rpc/core';\nimport { buildUrl, interpolatePath, objectToFormData } from '@richie-rpc/core';\n\n// Re-export for convenience\nexport type { UploadProgressEvent, DownloadProgressEvent };\nimport type { z } from 'zod';\n\n// Client configuration\nexport interface ClientConfig {\n baseUrl: string;\n headers?: Record<string, string>;\n validateRequest?: boolean;\n parseResponse?: boolean;\n}\n\n// Request options for an endpoint\nexport type EndpointRequestOptions<T extends EndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n body?: ExtractBody<T> extends never ? never : ExtractBody<T>;\n abortSignal?: AbortSignal;\n /** Upload progress callback (uses XHR for progress tracking) */\n onUploadProgress?: (event: UploadProgressEvent) => void;\n};\n\n// Response type for a standard endpoint (union of all possible responses)\nexport type EndpointResponse<T extends StandardEndpointDefinition> = {\n [Status in keyof T['responses']]: {\n status: Status;\n data: T['responses'][Status] extends z.ZodTypeAny ? z.infer<T['responses'][Status]> : never;\n };\n}[keyof T['responses']];\n\n// Client method type for a standard endpoint\nexport type ClientMethod<T extends StandardEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<EndpointResponse<T>>;\n\n// ============================================\n// Streaming Endpoint Client Types\n// ============================================\n\n/**\n * Result object for streaming endpoints - event-based API\n */\nexport interface StreamingResult<T extends StreamingEndpointDefinition> {\n /** Subscribe to chunks */\n on(event: 'chunk', handler: (chunk: ExtractChunk<T>) => void): () => void;\n /** Subscribe to stream close (with optional final response) */\n on(event: 'close', handler: (final?: ExtractFinalResponse<T>) => void): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Abort the stream */\n abort(): void;\n /** Check if aborted */\n readonly aborted: boolean;\n}\n\n/**\n * Client method type for streaming endpoints\n */\nexport type StreamingClientMethod<T extends StreamingEndpointDefinition> = (\n options: EndpointRequestOptions<T>,\n) => Promise<StreamingResult<T>>;\n\n// ============================================\n// SSE Endpoint Client Types\n// ============================================\n\n/**\n * Connection object for SSE endpoints - event-based API\n */\nexport interface SSEConnection<T extends SSEEndpointDefinition> {\n /** Subscribe to a specific event type */\n on<K extends keyof T['events']>(\n event: K,\n handler: (data: ExtractSSEEventData<T, K>, id?: string) => void,\n ): () => void;\n /** Subscribe to errors */\n on(event: 'error', handler: (error: Error) => void): () => void;\n /** Close the connection */\n close(): void;\n /** Current connection state */\n readonly state: 'connecting' | 'open' | 'closed';\n}\n\n/**\n * Client method type for SSE endpoints\n */\nexport type SSEClientMethod<T extends SSEEndpointDefinition> = (\n options?: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'>,\n) => SSEConnection<T>;\n\n// ============================================\n// Download Endpoint Client Types\n// ============================================\n\n/**\n * Request options for download endpoints\n */\nexport type DownloadRequestOptions<T extends DownloadEndpointDefinition> = {\n params?: ExtractParams<T> extends never ? never : ExtractParams<T>;\n query?: ExtractQuery<T> extends never ? never : ExtractQuery<T>;\n headers?: ExtractHeaders<T> extends never ? never : ExtractHeaders<T>;\n abortSignal?: AbortSignal;\n /** Download progress callback */\n onDownloadProgress?: (event: DownloadProgressEvent) => void;\n};\n\n/**\n * Response type for download endpoints\n * Success (200) returns File, errors return typed error response\n */\nexport type DownloadResponse<T extends DownloadEndpointDefinition> =\n | { status: 200; data: File }\n | (T['errorResponses'] extends Record<number, z.ZodTypeAny>\n ? {\n [S in keyof T['errorResponses']]: {\n status: S;\n data: T['errorResponses'][S] extends z.ZodTypeAny\n ? z.infer<T['errorResponses'][S]>\n : never;\n };\n }[keyof T['errorResponses']]\n : never);\n\n/**\n * Client method type for download endpoints\n */\nexport type DownloadClientMethod<T extends DownloadEndpointDefinition> = (\n options?: DownloadRequestOptions<T>,\n) => Promise<DownloadResponse<T>>;\n\n// Client type for a contract (supports all endpoint types)\nexport type Client<T extends Contract> = {\n [K in keyof T]: T[K] extends StandardEndpointDefinition\n ? ClientMethod<T[K]>\n : T[K] extends StreamingEndpointDefinition\n ? StreamingClientMethod<T[K]>\n : T[K] extends SSEEndpointDefinition\n ? SSEClientMethod<T[K]>\n : T[K] extends DownloadEndpointDefinition\n ? DownloadClientMethod<T[K]>\n : never;\n};\n\n// Validation error\nexport class ClientValidationError extends Error {\n constructor(\n public field: string,\n public issues: z.ZodIssue[],\n ) {\n super(`Validation failed for ${field}`);\n this.name = 'ClientValidationError';\n }\n}\n\n// HTTP error\nexport class HTTPError extends Error {\n constructor(\n public status: number,\n public statusText: string,\n public body: unknown,\n ) {\n super(`HTTP Error ${status}: ${statusText}`);\n this.name = 'HTTPError';\n }\n}\n\n/**\n * Validate request data before sending\n */\nfunction validateRequest<T extends StandardEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Parse and transform response data using Zod schema\n */\nfunction parseResponse<T extends StandardEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): unknown {\n const responseSchema = endpoint.responses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n return result.data;\n }\n return data;\n}\n\n/**\n * Extract filename from Content-Disposition header\n */\nfunction extractFilename(contentDisposition: string | null): string | null {\n if (!contentDisposition) return null;\n // Try filename*= (RFC 5987) first\n const filenameStarMatch = contentDisposition.match(/filename\\*=(?:UTF-8'')?([^;\\s]+)/i);\n if (filenameStarMatch && filenameStarMatch[1]) {\n return decodeURIComponent(filenameStarMatch[1]);\n }\n // Try filename= (standard)\n const filenameMatch = contentDisposition.match(/filename=[\"']?([^\"';\\s]+)[\"']?/i);\n if (filenameMatch && filenameMatch[1]) {\n return filenameMatch[1];\n }\n return null;\n}\n\n/**\n * Validate download request data before sending\n */\nfunction validateDownloadRequest<T extends DownloadEndpointDefinition>(\n endpoint: T,\n options: DownloadRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n}\n\n/**\n * Parse and transform download error response data using Zod schema\n */\nfunction parseDownloadErrorResponse<T extends DownloadEndpointDefinition>(\n endpoint: T,\n status: number,\n data: unknown,\n): unknown {\n if (endpoint.errorResponses) {\n const responseSchema = endpoint.errorResponses[status];\n if (responseSchema) {\n const result = responseSchema.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError(`response[${status}]`, result.error.issues);\n }\n return result.data;\n }\n }\n return data;\n}\n\n/**\n * Make a download request using fetch with progress support\n */\nasync function makeDownloadRequest<T extends DownloadEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: DownloadRequestOptions<T> = {},\n): Promise<DownloadResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateDownloadRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: 'GET',\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Handle success (200) - return File\n if (response.status === 200) {\n const contentLength = response.headers.get('content-length');\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n\n let blob: Blob;\n\n if (options.onDownloadProgress && response.body) {\n // Stream the response to track progress\n const reader = response.body.getReader();\n const chunks: BlobPart[] = [];\n let loaded = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n chunks.push(value);\n loaded += value.length;\n\n options.onDownloadProgress({\n loaded,\n total,\n progress: total > 0 ? loaded / total : NaN,\n });\n }\n\n blob = new Blob(chunks);\n } else {\n blob = await response.blob();\n }\n\n const contentDisposition = response.headers.get('content-disposition');\n const filename = extractFilename(contentDisposition) || 'download';\n const contentType = response.headers.get('content-type') || 'application/octet-stream';\n\n const file = new File([blob], filename, { type: contentType });\n\n return {\n status: 200,\n data: file,\n } as DownloadResponse<T>;\n }\n\n // Handle error responses\n let data: unknown;\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n // Check for HTTP errors not in errorResponses\n if (endpoint.errorResponses && !(response.status in endpoint.errorResponses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Parse error response if enabled\n const parsedData =\n config.parseResponse !== false\n ? parseDownloadErrorResponse(endpoint, response.status, data)\n : data;\n\n return {\n status: response.status,\n data: parsedData,\n } as DownloadResponse<T>;\n}\n\n/**\n * Make a request using XMLHttpRequest for upload progress support\n */\nfunction makeRequestWithXHR<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n url: string,\n): Promise<EndpointResponse<T>> {\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.open(endpoint.method, url);\n\n // Set base headers from config\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n xhr.setRequestHeader(key, value);\n }\n }\n\n // Set request-specific headers\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n xhr.setRequestHeader(key, String(value));\n }\n }\n\n // Upload progress callback\n if (options.onUploadProgress) {\n xhr.upload.onprogress = (e) => {\n if (e.lengthComputable && options.onUploadProgress) {\n options.onUploadProgress({\n loaded: e.loaded,\n total: e.total,\n progress: e.loaded / e.total,\n });\n }\n };\n }\n\n // Handle abort signal\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n xhr.abort();\n reject(new DOMException('Aborted', 'AbortError'));\n return;\n }\n options.abortSignal.addEventListener('abort', () => {\n xhr.abort();\n });\n }\n\n xhr.onload = () => {\n let data: unknown;\n const responseContentType = xhr.getResponseHeader('content-type') || '';\n\n if (xhr.status === 204) {\n data = {};\n } else if (responseContentType.includes('application/json')) {\n try {\n data = JSON.parse(xhr.responseText);\n } catch {\n data = xhr.responseText || {};\n }\n } else if (responseContentType.includes('text/')) {\n data = xhr.responseText;\n } else {\n data = xhr.responseText || {};\n }\n\n // Check for HTTP errors\n if (xhr.status >= 400 && !(xhr.status in endpoint.responses)) {\n reject(new HTTPError(xhr.status, xhr.statusText, data));\n return;\n }\n\n // Parse response if enabled\n let parsedData = data;\n if (config.parseResponse !== false) {\n try {\n parsedData = parseResponse(endpoint, xhr.status, data);\n } catch (err) {\n reject(err);\n return;\n }\n }\n\n resolve({\n status: xhr.status,\n data: parsedData,\n } as EndpointResponse<T>);\n };\n\n xhr.onerror = () => reject(new Error('Network error'));\n xhr.onabort = () => reject(new DOMException('Aborted', 'AbortError'));\n\n // Prepare and send body\n const contentType = endpoint.contentType ?? 'application/json';\n if (options.body !== undefined) {\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n xhr.send(objectToFormData(options.body as Record<string, unknown>));\n } else {\n xhr.setRequestHeader('content-type', 'application/json');\n xhr.send(JSON.stringify(options.body));\n }\n } else {\n xhr.send();\n }\n });\n}\n\n/**\n * Make a request to a standard endpoint\n */\nasync function makeRequest<T extends StandardEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<EndpointResponse<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Use XHR for upload progress support\n if (options.onUploadProgress && options.body !== undefined) {\n return makeRequestWithXHR(config, endpoint, options, url);\n }\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n };\n\n // Add abort signal if present\n if (options.abortSignal) {\n init.signal = options.abortSignal;\n }\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n // Don't set Content-Type header - browser sets boundary automatically\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Parse response\n let data: unknown;\n\n // Handle 204 No Content\n if (response.status === 204) {\n data = {};\n } else {\n const contentType = response.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else if (contentType.includes('text/')) {\n data = await response.text();\n } else {\n // Check if there's any content\n const text = await response.text();\n if (text) {\n data = text;\n } else {\n data = {};\n }\n }\n }\n\n // Check for HTTP errors\n if (!response.ok && !(response.status in endpoint.responses)) {\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Parse response if enabled\n const parsedData =\n config.parseResponse !== false ? parseResponse(endpoint, response.status, data) : data;\n\n return {\n status: response.status,\n data: parsedData,\n } as EndpointResponse<T>;\n}\n\n/**\n * Create a streaming result from an NDJSON response\n */\nfunction createStreamingResult<T extends StreamingEndpointDefinition>(\n response: Response,\n controller: AbortController,\n endpoint: T,\n config: ClientConfig,\n): StreamingResult<T> {\n type ChunkHandler = (chunk: ExtractChunk<T>) => void;\n type CloseHandler = (final?: ExtractFinalResponse<T>) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners = {\n chunk: new Set<ChunkHandler>(),\n close: new Set<CloseHandler>(),\n error: new Set<ErrorHandler>(),\n };\n\n // Helper to parse chunk data\n const parseChunk = (data: unknown): unknown => {\n if (config.parseResponse !== false && endpoint.chunk) {\n const result = endpoint.chunk.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError('chunk', result.error.issues);\n }\n return result.data;\n }\n return data;\n };\n\n // Helper to parse final response data\n const parseFinalResponse = (data: unknown): unknown => {\n if (config.parseResponse !== false && endpoint.finalResponse) {\n const result = endpoint.finalResponse.safeParse(data);\n if (!result.success) {\n throw new ClientValidationError('finalResponse', result.error.issues);\n }\n return result.data;\n }\n return data;\n };\n\n // Start reading in background\n (async () => {\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const parsed = JSON.parse(line);\n if (parsed.__final__) {\n const finalData = parseFinalResponse(parsed.data);\n listeners.close.forEach((h) => h(finalData as ExtractFinalResponse<T>));\n } else {\n const chunkData = parseChunk(parsed);\n listeners.chunk.forEach((h) => h(chunkData as ExtractChunk<T>));\n }\n } catch (parseErr) {\n listeners.error.forEach((h) => h(parseErr as Error));\n }\n }\n }\n\n // Process any remaining buffer content\n if (buffer.trim()) {\n try {\n const parsed = JSON.parse(buffer);\n if (parsed.__final__) {\n const finalData = parseFinalResponse(parsed.data);\n listeners.close.forEach((h) => h(finalData as ExtractFinalResponse<T>));\n } else {\n const chunkData = parseChunk(parsed);\n listeners.chunk.forEach((h) => h(chunkData as ExtractChunk<T>));\n }\n } catch {\n // Ignore incomplete JSON at end\n }\n }\n\n // Stream ended without final message\n listeners.close.forEach((h) => h());\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n listeners.error.forEach((h) => h(err as Error));\n }\n }\n })();\n\n return {\n on(event: 'chunk' | 'close' | 'error', handler: ChunkHandler | CloseHandler | ErrorHandler) {\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n abort() {\n controller.abort();\n },\n get aborted() {\n return controller.signal.aborted;\n },\n } as StreamingResult<T>;\n}\n\n/**\n * Validate streaming request data before sending\n */\nfunction validateStreamingRequest<T extends StreamingEndpointDefinition>(\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): void {\n // Validate params\n if (endpoint.params && options.params) {\n const result = endpoint.params.safeParse(options.params);\n if (!result.success) {\n throw new ClientValidationError('params', result.error.issues);\n }\n }\n\n // Validate query\n if (endpoint.query && options.query) {\n const result = endpoint.query.safeParse(options.query);\n if (!result.success) {\n throw new ClientValidationError('query', result.error.issues);\n }\n }\n\n // Validate headers\n if (endpoint.headers && options.headers) {\n const result = endpoint.headers.safeParse(options.headers);\n if (!result.success) {\n throw new ClientValidationError('headers', result.error.issues);\n }\n }\n\n // Validate body\n if (endpoint.body && options.body) {\n const result = endpoint.body.safeParse(options.body);\n if (!result.success) {\n throw new ClientValidationError('body', result.error.issues);\n }\n }\n}\n\n/**\n * Make a streaming request to an endpoint\n */\nasync function makeStreamingRequest<T extends StreamingEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: EndpointRequestOptions<T>,\n): Promise<StreamingResult<T>> {\n // Validate request if enabled\n if (config.validateRequest !== false) {\n validateStreamingRequest(endpoint, options);\n }\n\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // Build headers\n const headers = new Headers(config.headers);\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n headers.set(key, String(value));\n }\n }\n\n // Build request init - create our own controller for abort() method\n const controller = new AbortController();\n\n // Link to external abort signal if provided\n if (options.abortSignal) {\n if (options.abortSignal.aborted) {\n controller.abort();\n } else {\n options.abortSignal.addEventListener('abort', () => controller.abort());\n }\n }\n\n const init: RequestInit = {\n method: endpoint.method,\n headers,\n signal: controller.signal,\n };\n\n // Add body if present\n if (options.body !== undefined) {\n const contentType = endpoint.contentType ?? 'application/json';\n\n if (contentType === 'multipart/form-data') {\n init.body = objectToFormData(options.body as Record<string, unknown>);\n } else {\n headers.set('content-type', 'application/json');\n init.body = JSON.stringify(options.body);\n }\n }\n\n // Make request\n const response = await fetch(url, init);\n\n // Check for error responses before streaming\n if (!response.ok) {\n const contentType = response.headers.get('content-type') || '';\n let data: unknown;\n\n if (contentType.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n throw new HTTPError(response.status, response.statusText, data);\n }\n\n // Return streaming result\n return createStreamingResult<T>(response, controller, endpoint, config);\n}\n\n/**\n * Create an SSE connection\n */\nfunction createSSEConnection<T extends SSEEndpointDefinition>(\n config: ClientConfig,\n endpoint: T,\n options: Omit<EndpointRequestOptions<T>, 'body' | 'onUploadProgress'> = {},\n): SSEConnection<T> {\n // Build URL\n let path = endpoint.path;\n if (options.params) {\n path = interpolatePath(path, options.params as Record<string, string | number>);\n }\n\n const url = buildUrl(\n config.baseUrl,\n path,\n options.query as Record<string, string | number | boolean | string[]> | undefined,\n );\n\n // EventSource doesn't support custom headers, but we can include query params\n // Note: If auth headers are needed, consider using fetch-based SSE or passing auth in query\n const eventSource = new EventSource(url);\n\n type EventHandler = (data: unknown, id?: string) => void;\n type ErrorHandler = (error: Error) => void;\n\n const listeners: Record<string, Set<EventHandler | ErrorHandler>> = {\n error: new Set<ErrorHandler>(),\n };\n\n // Get event names from the endpoint\n const eventNames = Object.keys(endpoint.events);\n\n // Register listeners for each event type\n for (const eventName of eventNames) {\n listeners[eventName] = new Set<EventHandler>();\n eventSource.addEventListener(eventName, (e) => {\n const messageEvent = e as MessageEvent;\n try {\n const rawData = JSON.parse(messageEvent.data);\n\n // Parse event data using Zod schema if enabled\n let parsedData = rawData;\n if (config.parseResponse !== false) {\n const eventSchema = endpoint.events[eventName];\n if (eventSchema) {\n const result = eventSchema.safeParse(rawData);\n if (!result.success) {\n (listeners.error as Set<ErrorHandler>).forEach((h) =>\n h(new ClientValidationError(`event[${eventName}]`, result.error.issues)),\n );\n return;\n }\n parsedData = result.data;\n }\n }\n\n (listeners[eventName] as Set<EventHandler>).forEach((h) =>\n h(parsedData, messageEvent.lastEventId || undefined),\n );\n } catch (err) {\n (listeners.error as Set<ErrorHandler>).forEach((h) =>\n h(new Error(`Failed to parse SSE data: ${(err as Error).message}`)),\n );\n }\n });\n }\n\n // Handle errors\n eventSource.onerror = () => {\n (listeners.error as Set<ErrorHandler>).forEach((h) => h(new Error('SSE connection error')));\n };\n\n return {\n on(event: string, handler: EventHandler | ErrorHandler) {\n if (!listeners[event]) {\n listeners[event] = new Set();\n }\n (listeners[event] as Set<typeof handler>).add(handler);\n return () => (listeners[event] as Set<typeof handler>).delete(handler);\n },\n close() {\n eventSource.close();\n },\n get state() {\n const states = ['connecting', 'open', 'closed'] as const;\n return states[eventSource.readyState];\n },\n } as SSEConnection<T>;\n}\n\n/**\n * Resolve relative baseUrl to absolute URL in browser contexts\n */\nfunction resolveBaseUrl(baseUrl: string): string {\n // If baseUrl is already absolute, return as-is\n if (baseUrl.startsWith('http://') || baseUrl.startsWith('https://')) {\n return baseUrl;\n }\n\n // If baseUrl is relative (starts with /), resolve it using window.location in browser\n if (baseUrl.startsWith('/')) {\n const g = globalThis as unknown as { location?: { origin?: string } };\n const origin = g?.location?.origin || 'http://localhost';\n return origin + baseUrl;\n }\n\n // Otherwise, assume it's a full URL\n return baseUrl;\n}\n\n/**\n * Create a typesafe client for a contract\n */\nexport function createClient<T extends Contract>(contract: T, config: ClientConfig): Client<T> {\n // Resolve relative baseUrl to absolute URL\n const resolvedConfig = {\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n };\n\n const client: Record<string, unknown> = {};\n\n for (const [name, endpoint] of Object.entries(contract)) {\n if (endpoint.type === 'standard') {\n client[name] = (options: EndpointRequestOptions<StandardEndpointDefinition> = {}) => {\n return makeRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'streaming') {\n client[name] = (options: EndpointRequestOptions<StreamingEndpointDefinition> = {}) => {\n return makeStreamingRequest(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'sse') {\n client[name] = (\n options: Omit<\n EndpointRequestOptions<SSEEndpointDefinition>,\n 'body' | 'onUploadProgress'\n > = {},\n ) => {\n return createSSEConnection(resolvedConfig, endpoint, options);\n };\n } else if (endpoint.type === 'download') {\n client[name] = (options: DownloadRequestOptions<DownloadEndpointDefinition> = {}) => {\n return makeDownloadRequest(resolvedConfig, endpoint, options);\n };\n } else {\n throw new Error(`Endpoint \"${name}\" has unknown type \"${(endpoint as any).type}\".`);\n }\n }\n\n return client as Client<T>;\n}\n\n/**\n * Create a client without providing the contract at runtime\n * Useful when you only need types and want a lighter bundle\n */\nexport function createTypedClient<T extends Contract>(_config: ClientConfig): Client<T> {\n return new Proxy({} as Client<T>, {\n get(_target, _prop: string) {\n return async (_options: EndpointRequestOptions<EndpointDefinition> = {}) => {\n // Without the contract, we can't validate or infer the endpoint\n // This is just a basic fetch wrapper with typing\n throw new Error(\n 'createTypedClient requires contract at runtime for validation. Use createClient instead.',\n );\n };\n },\n });\n}\n\nexport * from './websocket.mjs';\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "2002C2CDD59A58E164756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/package.json
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface ClientConfig {
|
|
|
5
5
|
baseUrl: string;
|
|
6
6
|
headers?: Record<string, string>;
|
|
7
7
|
validateRequest?: boolean;
|
|
8
|
-
|
|
8
|
+
parseResponse?: boolean;
|
|
9
9
|
}
|
|
10
10
|
export type EndpointRequestOptions<T extends EndpointDefinition> = {
|
|
11
11
|
params?: ExtractParams<T> extends never ? never : ExtractParams<T>;
|