@orpc/client
Advanced tools
| import { toArray, runWithSpan, ORPC_NAME, isAsyncIteratorObject, asyncIteratorWithSpan, intercept, getGlobalOtelConfig, isObject, value, stringifyJSON } from '@orpc/shared'; | ||
| import { mergeStandardHeaders, ErrorEvent } from '@orpc/standard-server'; | ||
| import { C as COMMON_ORPC_ERROR_DEFS, d as isORPCErrorStatus, e as isORPCErrorJson, g as createORPCErrorFromJson, c as ORPCError, t as toORPCError } from './client.BOWJmQzx.mjs'; | ||
| import { toStandardHeaders as toStandardHeaders$1 } from '@orpc/standard-server-fetch'; | ||
| import { m as mapEventIterator } from './client.BLtwTQUg.mjs'; | ||
| class CompositeStandardLinkPlugin { | ||
| plugins; | ||
| constructor(plugins = []) { | ||
| this.plugins = [...plugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)); | ||
| } | ||
| init(options) { | ||
| for (const plugin of this.plugins) { | ||
| plugin.init?.(options); | ||
| } | ||
| } | ||
| } | ||
| class StandardLink { | ||
| constructor(codec, sender, options = {}) { | ||
| this.codec = codec; | ||
| this.sender = sender; | ||
| const plugin = new CompositeStandardLinkPlugin(options.plugins); | ||
| plugin.init(options); | ||
| this.interceptors = toArray(options.interceptors); | ||
| this.clientInterceptors = toArray(options.clientInterceptors); | ||
| } | ||
| interceptors; | ||
| clientInterceptors; | ||
| call(path, input, options) { | ||
| return runWithSpan( | ||
| { name: `${ORPC_NAME}.${path.join("/")}`, signal: options.signal }, | ||
| (span) => { | ||
| span?.setAttribute("rpc.system", ORPC_NAME); | ||
| span?.setAttribute("rpc.method", path.join(".")); | ||
| if (isAsyncIteratorObject(input)) { | ||
| input = asyncIteratorWithSpan( | ||
| { name: "consume_event_iterator_input", signal: options.signal }, | ||
| input | ||
| ); | ||
| } | ||
| return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => { | ||
| const otelConfig = getGlobalOtelConfig(); | ||
| let otelContext; | ||
| const currentSpan = otelConfig?.trace.getActiveSpan() ?? span; | ||
| if (currentSpan && otelConfig) { | ||
| otelContext = otelConfig?.trace.setSpan(otelConfig.context.active(), currentSpan); | ||
| } | ||
| const request = await runWithSpan( | ||
| { name: "encode_request", context: otelContext }, | ||
| () => this.codec.encode(path2, input2, options2) | ||
| ); | ||
| const response = await intercept( | ||
| this.clientInterceptors, | ||
| { ...options2, input: input2, path: path2, request }, | ||
| ({ input: input3, path: path3, request: request2, ...options3 }) => { | ||
| return runWithSpan( | ||
| { name: "send_request", signal: options3.signal, context: otelContext }, | ||
| () => this.sender.call(request2, options3, path3, input3) | ||
| ); | ||
| } | ||
| ); | ||
| const output = await runWithSpan( | ||
| { name: "decode_response", context: otelContext }, | ||
| () => this.codec.decode(response, options2, path2, input2) | ||
| ); | ||
| if (isAsyncIteratorObject(output)) { | ||
| return asyncIteratorWithSpan( | ||
| { name: "consume_event_iterator_output", signal: options2.signal }, | ||
| output | ||
| ); | ||
| } | ||
| return output; | ||
| }); | ||
| } | ||
| ); | ||
| } | ||
| } | ||
| const STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES = { | ||
| BIGINT: 0, | ||
| DATE: 1, | ||
| NAN: 2, | ||
| UNDEFINED: 3, | ||
| URL: 4, | ||
| REGEXP: 5, | ||
| SET: 6, | ||
| MAP: 7 | ||
| }; | ||
| class StandardRPCJsonSerializer { | ||
| customSerializers; | ||
| constructor(options = {}) { | ||
| this.customSerializers = options.customJsonSerializers ?? []; | ||
| if (this.customSerializers.length !== new Set(this.customSerializers.map((custom) => custom.type)).size) { | ||
| throw new Error("Custom serializer type must be unique."); | ||
| } | ||
| } | ||
| serialize(data, segments = [], meta = [], maps = [], blobs = []) { | ||
| for (const custom of this.customSerializers) { | ||
| if (custom.condition(data)) { | ||
| const result = this.serialize(custom.serialize(data), segments, meta, maps, blobs); | ||
| meta.push([custom.type, ...segments]); | ||
| return result; | ||
| } | ||
| } | ||
| if (data instanceof Blob) { | ||
| maps.push(segments); | ||
| blobs.push(data); | ||
| return [data, meta, maps, blobs]; | ||
| } | ||
| if (typeof data === "bigint") { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT, ...segments]); | ||
| return [data.toString(), meta, maps, blobs]; | ||
| } | ||
| if (data instanceof Date) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE, ...segments]); | ||
| if (Number.isNaN(data.getTime())) { | ||
| return [null, meta, maps, blobs]; | ||
| } | ||
| return [data.toISOString(), meta, maps, blobs]; | ||
| } | ||
| if (Number.isNaN(data)) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN, ...segments]); | ||
| return [null, meta, maps, blobs]; | ||
| } | ||
| if (data instanceof URL) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL, ...segments]); | ||
| return [data.toString(), meta, maps, blobs]; | ||
| } | ||
| if (data instanceof RegExp) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP, ...segments]); | ||
| return [data.toString(), meta, maps, blobs]; | ||
| } | ||
| if (data instanceof Set) { | ||
| const result = this.serialize(Array.from(data), segments, meta, maps, blobs); | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET, ...segments]); | ||
| return result; | ||
| } | ||
| if (data instanceof Map) { | ||
| const result = this.serialize(Array.from(data.entries()), segments, meta, maps, blobs); | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP, ...segments]); | ||
| return result; | ||
| } | ||
| if (Array.isArray(data)) { | ||
| const json = data.map((v, i) => { | ||
| if (v === void 0) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED, ...segments, i]); | ||
| return null; | ||
| } | ||
| return this.serialize(v, [...segments, i], meta, maps, blobs)[0]; | ||
| }); | ||
| return [json, meta, maps, blobs]; | ||
| } | ||
| if (isObject(data)) { | ||
| const json = {}; | ||
| for (const k in data) { | ||
| if (k === "toJSON" && typeof data[k] === "function") { | ||
| continue; | ||
| } | ||
| json[k] = this.serialize(data[k], [...segments, k], meta, maps, blobs)[0]; | ||
| } | ||
| return [json, meta, maps, blobs]; | ||
| } | ||
| return [data, meta, maps, blobs]; | ||
| } | ||
| deserialize(json, meta, maps, getBlob) { | ||
| const ref = { data: json }; | ||
| if (maps && getBlob) { | ||
| maps.forEach((segments, i) => { | ||
| let currentRef = ref; | ||
| let preSegment = "data"; | ||
| segments.forEach((segment) => { | ||
| currentRef = currentRef[preSegment]; | ||
| preSegment = segment; | ||
| if (!Object.hasOwn(currentRef, preSegment)) { | ||
| throw new Error(`Security error: accessing non-existent path during deserialization. Path segment: ${preSegment}`); | ||
| } | ||
| }); | ||
| currentRef[preSegment] = getBlob(i); | ||
| }); | ||
| } | ||
| for (const item of meta) { | ||
| const type = item[0]; | ||
| let currentRef = ref; | ||
| let preSegment = "data"; | ||
| for (let i = 1; i < item.length; i++) { | ||
| currentRef = currentRef[preSegment]; | ||
| preSegment = item[i]; | ||
| if (!Object.hasOwn(currentRef, preSegment)) { | ||
| throw new Error(`Security error: accessing non-existent path during deserialization. Path segment: ${preSegment}`); | ||
| } | ||
| } | ||
| for (const custom of this.customSerializers) { | ||
| if (custom.type === type) { | ||
| currentRef[preSegment] = custom.deserialize(currentRef[preSegment]); | ||
| break; | ||
| } | ||
| } | ||
| switch (type) { | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT: | ||
| currentRef[preSegment] = BigInt(currentRef[preSegment]); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE: | ||
| currentRef[preSegment] = new Date(currentRef[preSegment] ?? "Invalid Date"); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN: | ||
| currentRef[preSegment] = Number.NaN; | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED: | ||
| currentRef[preSegment] = void 0; | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL: | ||
| currentRef[preSegment] = new URL(currentRef[preSegment]); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP: { | ||
| const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/); | ||
| currentRef[preSegment] = new RegExp(pattern, flags); | ||
| break; | ||
| } | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET: | ||
| currentRef[preSegment] = new Set(currentRef[preSegment]); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP: | ||
| currentRef[preSegment] = new Map(currentRef[preSegment]); | ||
| break; | ||
| } | ||
| } | ||
| return ref.data; | ||
| } | ||
| } | ||
| function toHttpPath(path) { | ||
| return `/${path.map(encodeURIComponent).join("/")}`; | ||
| } | ||
| function toStandardHeaders(headers) { | ||
| if (typeof headers.forEach === "function") { | ||
| return toStandardHeaders$1(headers); | ||
| } | ||
| return headers; | ||
| } | ||
| function getMalformedResponseErrorCode(status) { | ||
| return Object.entries(COMMON_ORPC_ERROR_DEFS).find(([, def]) => def.status === status)?.[0] ?? "MALFORMED_ORPC_ERROR_RESPONSE"; | ||
| } | ||
| class StandardRPCLinkCodec { | ||
| constructor(serializer, options) { | ||
| this.serializer = serializer; | ||
| this.baseUrl = options.url; | ||
| this.maxUrlLength = options.maxUrlLength ?? 2083; | ||
| this.fallbackMethod = options.fallbackMethod ?? "POST"; | ||
| this.expectedMethod = options.method ?? this.fallbackMethod; | ||
| this.headers = options.headers ?? {}; | ||
| } | ||
| baseUrl; | ||
| maxUrlLength; | ||
| fallbackMethod; | ||
| expectedMethod; | ||
| headers; | ||
| async encode(path, input, options) { | ||
| let headers = toStandardHeaders(await value(this.headers, options, path, input)); | ||
| if (options.lastEventId !== void 0) { | ||
| headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId }); | ||
| } | ||
| const expectedMethod = await value(this.expectedMethod, options, path, input); | ||
| const baseUrl = await value(this.baseUrl, options, path, input); | ||
| const url = new URL(baseUrl); | ||
| url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`; | ||
| const serialized = this.serializer.serialize(input); | ||
| if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) { | ||
| const maxUrlLength = await value(this.maxUrlLength, options, path, input); | ||
| const getUrl = new URL(url); | ||
| getUrl.searchParams.append("data", stringifyJSON(serialized)); | ||
| if (getUrl.toString().length <= maxUrlLength) { | ||
| return { | ||
| body: void 0, | ||
| method: expectedMethod, | ||
| headers, | ||
| url: getUrl, | ||
| signal: options.signal | ||
| }; | ||
| } | ||
| } | ||
| return { | ||
| url, | ||
| method: expectedMethod === "GET" ? this.fallbackMethod : expectedMethod, | ||
| headers, | ||
| body: serialized, | ||
| signal: options.signal | ||
| }; | ||
| } | ||
| async decode(response) { | ||
| const isOk = !isORPCErrorStatus(response.status); | ||
| const deserialized = await (async () => { | ||
| let isBodyOk = false; | ||
| try { | ||
| const body = await response.body(); | ||
| isBodyOk = true; | ||
| return this.serializer.deserialize(body); | ||
| } catch (error) { | ||
| if (!isBodyOk) { | ||
| throw new Error("Cannot parse response body, please check the response body and content-type.", { | ||
| cause: error | ||
| }); | ||
| } | ||
| throw new Error("Invalid RPC response format.", { | ||
| cause: error | ||
| }); | ||
| } | ||
| })(); | ||
| if (!isOk) { | ||
| if (isORPCErrorJson(deserialized)) { | ||
| throw createORPCErrorFromJson(deserialized); | ||
| } | ||
| throw new ORPCError(getMalformedResponseErrorCode(response.status), { | ||
| status: response.status, | ||
| data: { ...response, body: deserialized } | ||
| }); | ||
| } | ||
| return deserialized; | ||
| } | ||
| } | ||
| class StandardRPCSerializer { | ||
| constructor(jsonSerializer) { | ||
| this.jsonSerializer = jsonSerializer; | ||
| } | ||
| serialize(data) { | ||
| if (isAsyncIteratorObject(data)) { | ||
| return mapEventIterator(data, { | ||
| value: async (value) => this.#serialize(value, false), | ||
| error: async (e) => { | ||
| return new ErrorEvent({ | ||
| data: this.#serialize(toORPCError(e).toJSON(), false), | ||
| cause: e | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| return this.#serialize(data, true); | ||
| } | ||
| #serialize(data, enableFormData) { | ||
| const [json, meta_, maps, blobs] = this.jsonSerializer.serialize(data); | ||
| const meta = meta_.length === 0 ? void 0 : meta_; | ||
| if (!enableFormData || blobs.length === 0) { | ||
| return { | ||
| json, | ||
| meta | ||
| }; | ||
| } | ||
| const form = new FormData(); | ||
| form.set("data", stringifyJSON({ json, meta, maps })); | ||
| blobs.forEach((blob, i) => { | ||
| form.set(i.toString(), blob); | ||
| }); | ||
| return form; | ||
| } | ||
| deserialize(data) { | ||
| if (isAsyncIteratorObject(data)) { | ||
| return mapEventIterator(data, { | ||
| value: async (value) => this.#deserialize(value), | ||
| error: async (e) => { | ||
| if (!(e instanceof ErrorEvent)) { | ||
| return e; | ||
| } | ||
| const deserialized = this.#deserialize(e.data); | ||
| if (isORPCErrorJson(deserialized)) { | ||
| return createORPCErrorFromJson(deserialized, { cause: e }); | ||
| } | ||
| return new ErrorEvent({ | ||
| data: deserialized, | ||
| cause: e | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| return this.#deserialize(data); | ||
| } | ||
| #deserialize(data) { | ||
| if (data === void 0) { | ||
| return void 0; | ||
| } | ||
| if (!(data instanceof FormData)) { | ||
| return this.jsonSerializer.deserialize(data.json, data.meta ?? []); | ||
| } | ||
| const serialized = JSON.parse(data.get("data")); | ||
| return this.jsonSerializer.deserialize( | ||
| serialized.json, | ||
| serialized.meta ?? [], | ||
| serialized.maps, | ||
| (i) => data.get(i.toString()) | ||
| ); | ||
| } | ||
| } | ||
| class StandardRPCLink extends StandardLink { | ||
| constructor(linkClient, options) { | ||
| const jsonSerializer = new StandardRPCJsonSerializer(options); | ||
| const serializer = new StandardRPCSerializer(jsonSerializer); | ||
| const linkCodec = new StandardRPCLinkCodec(serializer, options); | ||
| super(linkCodec, linkClient, options); | ||
| } | ||
| } | ||
| export { CompositeStandardLinkPlugin as C, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLink as c, StandardRPCLinkCodec as d, StandardRPCSerializer as e, toStandardHeaders as f, getMalformedResponseErrorCode as g, toHttpPath as t }; |
| import { resolveMaybeOptionalOptions, getConstructor, isObject } from '@orpc/shared'; | ||
| const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client"; | ||
| const ORPC_CLIENT_PACKAGE_VERSION = "1.14.3"; | ||
| const COMMON_ORPC_ERROR_DEFS = { | ||
| BAD_REQUEST: { | ||
| status: 400, | ||
| message: "Bad Request" | ||
| }, | ||
| UNAUTHORIZED: { | ||
| status: 401, | ||
| message: "Unauthorized" | ||
| }, | ||
| FORBIDDEN: { | ||
| status: 403, | ||
| message: "Forbidden" | ||
| }, | ||
| NOT_FOUND: { | ||
| status: 404, | ||
| message: "Not Found" | ||
| }, | ||
| METHOD_NOT_SUPPORTED: { | ||
| status: 405, | ||
| message: "Method Not Supported" | ||
| }, | ||
| NOT_ACCEPTABLE: { | ||
| status: 406, | ||
| message: "Not Acceptable" | ||
| }, | ||
| TIMEOUT: { | ||
| status: 408, | ||
| message: "Request Timeout" | ||
| }, | ||
| CONFLICT: { | ||
| status: 409, | ||
| message: "Conflict" | ||
| }, | ||
| PRECONDITION_FAILED: { | ||
| status: 412, | ||
| message: "Precondition Failed" | ||
| }, | ||
| PAYLOAD_TOO_LARGE: { | ||
| status: 413, | ||
| message: "Payload Too Large" | ||
| }, | ||
| UNSUPPORTED_MEDIA_TYPE: { | ||
| status: 415, | ||
| message: "Unsupported Media Type" | ||
| }, | ||
| UNPROCESSABLE_CONTENT: { | ||
| status: 422, | ||
| message: "Unprocessable Content" | ||
| }, | ||
| TOO_MANY_REQUESTS: { | ||
| status: 429, | ||
| message: "Too Many Requests" | ||
| }, | ||
| CLIENT_CLOSED_REQUEST: { | ||
| status: 499, | ||
| message: "Client Closed Request" | ||
| }, | ||
| INTERNAL_SERVER_ERROR: { | ||
| status: 500, | ||
| message: "Internal Server Error" | ||
| }, | ||
| NOT_IMPLEMENTED: { | ||
| status: 501, | ||
| message: "Not Implemented" | ||
| }, | ||
| BAD_GATEWAY: { | ||
| status: 502, | ||
| message: "Bad Gateway" | ||
| }, | ||
| SERVICE_UNAVAILABLE: { | ||
| status: 503, | ||
| message: "Service Unavailable" | ||
| }, | ||
| GATEWAY_TIMEOUT: { | ||
| status: 504, | ||
| message: "Gateway Timeout" | ||
| } | ||
| }; | ||
| function fallbackORPCErrorStatus(code, status) { | ||
| return status ?? COMMON_ORPC_ERROR_DEFS[code]?.status ?? 500; | ||
| } | ||
| function fallbackORPCErrorMessage(code, message) { | ||
| return message || COMMON_ORPC_ERROR_DEFS[code]?.message || code; | ||
| } | ||
| const GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL = Symbol.for(`__${ORPC_CLIENT_PACKAGE_NAME}@${ORPC_CLIENT_PACKAGE_VERSION}/error/ORPC_ERROR_CONSTRUCTORS__`); | ||
| void (globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL] ??= /* @__PURE__ */ new WeakSet()); | ||
| const globalORPCErrorConstructors = globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL]; | ||
| class ORPCError extends Error { | ||
| defined; | ||
| code; | ||
| status; | ||
| data; | ||
| constructor(code, ...rest) { | ||
| const options = resolveMaybeOptionalOptions(rest); | ||
| if (options.status !== void 0 && !isORPCErrorStatus(options.status)) { | ||
| throw new Error("[ORPCError] Invalid error status code."); | ||
| } | ||
| const message = fallbackORPCErrorMessage(code, options.message); | ||
| super(message, options); | ||
| this.code = code; | ||
| this.status = fallbackORPCErrorStatus(code, options.status); | ||
| this.defined = options.defined ?? false; | ||
| this.data = options.data; | ||
| } | ||
| toJSON() { | ||
| return { | ||
| defined: this.defined, | ||
| code: this.code, | ||
| status: this.status, | ||
| message: this.message, | ||
| data: this.data | ||
| }; | ||
| } | ||
| /** | ||
| * Workaround for Next.js where different contexts use separate | ||
| * dependency graphs, causing multiple ORPCError constructors existing and breaking | ||
| * `instanceof` checks across contexts. | ||
| * | ||
| * This is particularly problematic with "Optimized SSR", where orpc-client | ||
| * executes in one context but is invoked from another. When an error is thrown | ||
| * in the execution context, `instanceof ORPCError` checks fail in the | ||
| * invocation context due to separate class constructors. | ||
| * | ||
| * @todo Remove this and related code if Next.js resolves the multiple dependency graph issue. | ||
| */ | ||
| static [Symbol.hasInstance](instance) { | ||
| if (globalORPCErrorConstructors.has(this)) { | ||
| const constructor = getConstructor(instance); | ||
| if (constructor && globalORPCErrorConstructors.has(constructor)) { | ||
| return true; | ||
| } | ||
| } | ||
| return super[Symbol.hasInstance](instance); | ||
| } | ||
| } | ||
| globalORPCErrorConstructors.add(ORPCError); | ||
| function isDefinedError(error) { | ||
| return error instanceof ORPCError && error.defined; | ||
| } | ||
| function toORPCError(error) { | ||
| return error instanceof ORPCError ? error : new ORPCError("INTERNAL_SERVER_ERROR", { | ||
| message: "Internal server error", | ||
| cause: error | ||
| }); | ||
| } | ||
| function isORPCErrorStatus(status) { | ||
| return status < 200 || status >= 400; | ||
| } | ||
| function isORPCErrorJson(json) { | ||
| if (!isObject(json)) { | ||
| return false; | ||
| } | ||
| const validKeys = ["defined", "code", "status", "message", "data"]; | ||
| if (Object.keys(json).some((k) => !validKeys.includes(k))) { | ||
| return false; | ||
| } | ||
| return "defined" in json && typeof json.defined === "boolean" && "code" in json && typeof json.code === "string" && "status" in json && typeof json.status === "number" && isORPCErrorStatus(json.status) && "message" in json && typeof json.message === "string"; | ||
| } | ||
| function createORPCErrorFromJson(json, options = {}) { | ||
| return new ORPCError(json.code, { | ||
| ...options, | ||
| ...json | ||
| }); | ||
| } | ||
| export { COMMON_ORPC_ERROR_DEFS as C, ORPC_CLIENT_PACKAGE_NAME as O, ORPC_CLIENT_PACKAGE_VERSION as a, fallbackORPCErrorMessage as b, ORPCError as c, isORPCErrorStatus as d, isORPCErrorJson as e, fallbackORPCErrorStatus as f, createORPCErrorFromJson as g, isDefinedError as i, toORPCError as t }; |
| import { toArray, intercept } from '@orpc/shared'; | ||
| import { toFetchRequest, toStandardLazyResponse } from '@orpc/standard-server-fetch'; | ||
| import { C as CompositeStandardLinkPlugin, c as StandardRPCLink } from '../../shared/client.DeBTBp5q.mjs'; | ||
| import { C as CompositeStandardLinkPlugin, c as StandardRPCLink } from '../../shared/client.BCGbA0RK.mjs'; | ||
| import '@orpc/standard-server'; | ||
| import '../../shared/client.DmJexYYZ.mjs'; | ||
| import '../../shared/client.BOWJmQzx.mjs'; | ||
| import '../../shared/client.BLtwTQUg.mjs'; | ||
@@ -7,0 +7,0 @@ |
| import { value, isObject } from '@orpc/shared'; | ||
| import { experimental_ClientPeerWithoutCodec, serializeRequestMessage, encodeRequestMessage, deserializeResponseMessage, decodeResponseMessage } from '@orpc/standard-server-peer'; | ||
| import { c as StandardRPCLink } from '../../shared/client.DeBTBp5q.mjs'; | ||
| import { c as StandardRPCLink } from '../../shared/client.BCGbA0RK.mjs'; | ||
| import '@orpc/standard-server'; | ||
| import '../../shared/client.DmJexYYZ.mjs'; | ||
| import '../../shared/client.BOWJmQzx.mjs'; | ||
| import '@orpc/standard-server-fetch'; | ||
@@ -7,0 +7,0 @@ import '../../shared/client.BLtwTQUg.mjs'; |
@@ -1,6 +0,6 @@ | ||
| export { C as CompositeStandardLinkPlugin, a as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, S as StandardLink, b as StandardRPCJsonSerializer, c as StandardRPCLink, d as StandardRPCLinkCodec, e as StandardRPCSerializer, g as getMalformedResponseErrorCode, t as toHttpPath, f as toStandardHeaders } from '../../shared/client.DeBTBp5q.mjs'; | ||
| export { C as CompositeStandardLinkPlugin, a as STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES, S as StandardLink, b as StandardRPCJsonSerializer, c as StandardRPCLink, d as StandardRPCLinkCodec, e as StandardRPCSerializer, g as getMalformedResponseErrorCode, t as toHttpPath, f as toStandardHeaders } from '../../shared/client.BCGbA0RK.mjs'; | ||
| import '@orpc/shared'; | ||
| import '@orpc/standard-server'; | ||
| import '../../shared/client.DmJexYYZ.mjs'; | ||
| import '../../shared/client.BOWJmQzx.mjs'; | ||
| import '@orpc/standard-server-fetch'; | ||
| import '../../shared/client.BLtwTQUg.mjs'; |
| import { readAsBuffer } from '@orpc/shared'; | ||
| import { ClientPeer } from '@orpc/standard-server-peer'; | ||
| import { c as StandardRPCLink } from '../../shared/client.DeBTBp5q.mjs'; | ||
| import { c as StandardRPCLink } from '../../shared/client.BCGbA0RK.mjs'; | ||
| import '@orpc/standard-server'; | ||
| import '../../shared/client.DmJexYYZ.mjs'; | ||
| import '../../shared/client.BOWJmQzx.mjs'; | ||
| import '@orpc/standard-server-fetch'; | ||
@@ -7,0 +7,0 @@ import '../../shared/client.BLtwTQUg.mjs'; |
+1
-1
@@ -210,3 +210,3 @@ import { N as NestedClient, C as ClientLink, I as InferClientContext, a as ClientPromiseResult, b as ClientContext, F as FriendlyClientOptions, c as ClientOptions, d as Client, e as ClientRest } from './shared/client.i2uoJbEp.mjs'; | ||
| declare const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client"; | ||
| declare const ORPC_CLIENT_PACKAGE_VERSION = "1.14.2"; | ||
| declare const ORPC_CLIENT_PACKAGE_VERSION = "1.14.3"; | ||
@@ -213,0 +213,0 @@ /** |
+1
-1
@@ -210,3 +210,3 @@ import { N as NestedClient, C as ClientLink, I as InferClientContext, a as ClientPromiseResult, b as ClientContext, F as FriendlyClientOptions, c as ClientOptions, d as Client, e as ClientRest } from './shared/client.i2uoJbEp.js'; | ||
| declare const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client"; | ||
| declare const ORPC_CLIENT_PACKAGE_VERSION = "1.14.2"; | ||
| declare const ORPC_CLIENT_PACKAGE_VERSION = "1.14.3"; | ||
@@ -213,0 +213,0 @@ /** |
+2
-2
| import { preventNativeAwait, isTypescriptObject } from '@orpc/shared'; | ||
| export { AsyncIteratorClass, EventPublisher, asyncIteratorToStream as eventIteratorToStream, asyncIteratorToUnproxiedDataStream as eventIteratorToUnproxiedDataStream, onError, onFinish, onStart, onSuccess, streamToAsyncIteratorClass as streamToEventIterator } from '@orpc/shared'; | ||
| import { i as isDefinedError } from './shared/client.DmJexYYZ.mjs'; | ||
| export { C as COMMON_ORPC_ERROR_DEFS, c as ORPCError, O as ORPC_CLIENT_PACKAGE_NAME, a as ORPC_CLIENT_PACKAGE_VERSION, g as createORPCErrorFromJson, b as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, e as isORPCErrorJson, d as isORPCErrorStatus, t as toORPCError } from './shared/client.DmJexYYZ.mjs'; | ||
| import { i as isDefinedError } from './shared/client.BOWJmQzx.mjs'; | ||
| export { C as COMMON_ORPC_ERROR_DEFS, c as ORPCError, O as ORPC_CLIENT_PACKAGE_NAME, a as ORPC_CLIENT_PACKAGE_VERSION, g as createORPCErrorFromJson, b as fallbackORPCErrorMessage, f as fallbackORPCErrorStatus, e as isORPCErrorJson, d as isORPCErrorStatus, t as toORPCError } from './shared/client.BOWJmQzx.mjs'; | ||
| export { m as mapEventIterator } from './shared/client.BLtwTQUg.mjs'; | ||
@@ -6,0 +6,0 @@ export { ErrorEvent, getEventMeta, withEventMeta } from '@orpc/standard-server'; |
| import { isAsyncIteratorObject, defer, value, splitInHalf, toArray, stringifyJSON, overlayProxy, AsyncIteratorClass } from '@orpc/shared'; | ||
| import { toBatchRequest, parseBatchResponse, toBatchAbortSignal } from '@orpc/standard-server/batch'; | ||
| import { replicateStandardLazyResponse, getEventMeta, flattenHeader } from '@orpc/standard-server'; | ||
| import { C as COMMON_ORPC_ERROR_DEFS } from '../shared/client.DmJexYYZ.mjs'; | ||
| import { C as COMMON_ORPC_ERROR_DEFS } from '../shared/client.BOWJmQzx.mjs'; | ||
@@ -6,0 +6,0 @@ class BatchLinkPlugin { |
+5
-5
| { | ||
| "name": "@orpc/client", | ||
| "type": "module", | ||
| "version": "1.14.2", | ||
| "version": "1.14.3", | ||
| "license": "MIT", | ||
@@ -52,6 +52,6 @@ "homepage": "https://orpc.dev", | ||
| "dependencies": { | ||
| "@orpc/shared": "1.14.2", | ||
| "@orpc/standard-server": "1.14.2", | ||
| "@orpc/standard-server-fetch": "1.14.2", | ||
| "@orpc/standard-server-peer": "1.14.2" | ||
| "@orpc/shared": "1.14.3", | ||
| "@orpc/standard-server": "1.14.3", | ||
| "@orpc/standard-server-fetch": "1.14.3", | ||
| "@orpc/standard-server-peer": "1.14.3" | ||
| }, | ||
@@ -58,0 +58,0 @@ "devDependencies": { |
+1
-1
@@ -193,3 +193,3 @@ <div align="center"> | ||
| <a href="https://github.com/YuSabo90002?ref=orpc" target="_blank" rel="noopener" title="Yu-Sabo"><img src="https://avatars.githubusercontent.com/u/13120582?v=4" width="32" height="32" alt="Yu-Sabo" /></a> | ||
| <a href="https://github.com/bapspatil?ref=orpc" target="_blank" rel="noopener" title="Bapusaheb Patil"><img src="https://avatars.githubusercontent.com/u/16699418?v=4" width="32" height="32" alt="Bapusaheb Patil" /></a> | ||
| <a href="https://github.com/bapspatil?ref=orpc" target="_blank" rel="noopener" title="Bapusaheb Patil"><img src="https://avatars.githubusercontent.com/u/16699418?u=6d9d8e0a64a6f91ca1c4d559c72d931172bdcbbd&v=4" width="32" height="32" alt="Bapusaheb Patil" /></a> | ||
| <a href="https://github.com/ripgrim?ref=orpc" target="_blank" rel="noopener" title="grim"><img src="https://avatars.githubusercontent.com/u/75869731?u=b17c42ec2309552fdb822a86b25a2f99146a4d72&v=4" width="32" height="32" alt="grim" /></a> | ||
@@ -196,0 +196,0 @@ <a href="https://github.com/nelsonlaidev?ref=orpc" target="_blank" rel="noopener" title="Nelson Lai"><img src="https://avatars.githubusercontent.com/u/75498339?u=2fc0e0b95dd184c5ffb744df977cb15a18b60672&v=4" width="32" height="32" alt="Nelson Lai" /></a> |
| import { toArray, runWithSpan, ORPC_NAME, isAsyncIteratorObject, asyncIteratorWithSpan, intercept, getGlobalOtelConfig, isObject, value, stringifyJSON } from '@orpc/shared'; | ||
| import { mergeStandardHeaders, ErrorEvent } from '@orpc/standard-server'; | ||
| import { C as COMMON_ORPC_ERROR_DEFS, d as isORPCErrorStatus, e as isORPCErrorJson, g as createORPCErrorFromJson, c as ORPCError, t as toORPCError } from './client.DmJexYYZ.mjs'; | ||
| import { toStandardHeaders as toStandardHeaders$1 } from '@orpc/standard-server-fetch'; | ||
| import { m as mapEventIterator } from './client.BLtwTQUg.mjs'; | ||
| class CompositeStandardLinkPlugin { | ||
| plugins; | ||
| constructor(plugins = []) { | ||
| this.plugins = [...plugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)); | ||
| } | ||
| init(options) { | ||
| for (const plugin of this.plugins) { | ||
| plugin.init?.(options); | ||
| } | ||
| } | ||
| } | ||
| class StandardLink { | ||
| constructor(codec, sender, options = {}) { | ||
| this.codec = codec; | ||
| this.sender = sender; | ||
| const plugin = new CompositeStandardLinkPlugin(options.plugins); | ||
| plugin.init(options); | ||
| this.interceptors = toArray(options.interceptors); | ||
| this.clientInterceptors = toArray(options.clientInterceptors); | ||
| } | ||
| interceptors; | ||
| clientInterceptors; | ||
| call(path, input, options) { | ||
| return runWithSpan( | ||
| { name: `${ORPC_NAME}.${path.join("/")}`, signal: options.signal }, | ||
| (span) => { | ||
| span?.setAttribute("rpc.system", ORPC_NAME); | ||
| span?.setAttribute("rpc.method", path.join(".")); | ||
| if (isAsyncIteratorObject(input)) { | ||
| input = asyncIteratorWithSpan( | ||
| { name: "consume_event_iterator_input", signal: options.signal }, | ||
| input | ||
| ); | ||
| } | ||
| return intercept(this.interceptors, { ...options, path, input }, async ({ path: path2, input: input2, ...options2 }) => { | ||
| const otelConfig = getGlobalOtelConfig(); | ||
| let otelContext; | ||
| const currentSpan = otelConfig?.trace.getActiveSpan() ?? span; | ||
| if (currentSpan && otelConfig) { | ||
| otelContext = otelConfig?.trace.setSpan(otelConfig.context.active(), currentSpan); | ||
| } | ||
| const request = await runWithSpan( | ||
| { name: "encode_request", context: otelContext }, | ||
| () => this.codec.encode(path2, input2, options2) | ||
| ); | ||
| const response = await intercept( | ||
| this.clientInterceptors, | ||
| { ...options2, input: input2, path: path2, request }, | ||
| ({ input: input3, path: path3, request: request2, ...options3 }) => { | ||
| return runWithSpan( | ||
| { name: "send_request", signal: options3.signal, context: otelContext }, | ||
| () => this.sender.call(request2, options3, path3, input3) | ||
| ); | ||
| } | ||
| ); | ||
| const output = await runWithSpan( | ||
| { name: "decode_response", context: otelContext }, | ||
| () => this.codec.decode(response, options2, path2, input2) | ||
| ); | ||
| if (isAsyncIteratorObject(output)) { | ||
| return asyncIteratorWithSpan( | ||
| { name: "consume_event_iterator_output", signal: options2.signal }, | ||
| output | ||
| ); | ||
| } | ||
| return output; | ||
| }); | ||
| } | ||
| ); | ||
| } | ||
| } | ||
| const STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES = { | ||
| BIGINT: 0, | ||
| DATE: 1, | ||
| NAN: 2, | ||
| UNDEFINED: 3, | ||
| URL: 4, | ||
| REGEXP: 5, | ||
| SET: 6, | ||
| MAP: 7 | ||
| }; | ||
| class StandardRPCJsonSerializer { | ||
| customSerializers; | ||
| constructor(options = {}) { | ||
| this.customSerializers = options.customJsonSerializers ?? []; | ||
| if (this.customSerializers.length !== new Set(this.customSerializers.map((custom) => custom.type)).size) { | ||
| throw new Error("Custom serializer type must be unique."); | ||
| } | ||
| } | ||
| serialize(data, segments = [], meta = [], maps = [], blobs = []) { | ||
| for (const custom of this.customSerializers) { | ||
| if (custom.condition(data)) { | ||
| const result = this.serialize(custom.serialize(data), segments, meta, maps, blobs); | ||
| meta.push([custom.type, ...segments]); | ||
| return result; | ||
| } | ||
| } | ||
| if (data instanceof Blob) { | ||
| maps.push(segments); | ||
| blobs.push(data); | ||
| return [data, meta, maps, blobs]; | ||
| } | ||
| if (typeof data === "bigint") { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT, ...segments]); | ||
| return [data.toString(), meta, maps, blobs]; | ||
| } | ||
| if (data instanceof Date) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE, ...segments]); | ||
| if (Number.isNaN(data.getTime())) { | ||
| return [null, meta, maps, blobs]; | ||
| } | ||
| return [data.toISOString(), meta, maps, blobs]; | ||
| } | ||
| if (Number.isNaN(data)) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN, ...segments]); | ||
| return [null, meta, maps, blobs]; | ||
| } | ||
| if (data instanceof URL) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL, ...segments]); | ||
| return [data.toString(), meta, maps, blobs]; | ||
| } | ||
| if (data instanceof RegExp) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP, ...segments]); | ||
| return [data.toString(), meta, maps, blobs]; | ||
| } | ||
| if (data instanceof Set) { | ||
| const result = this.serialize(Array.from(data), segments, meta, maps, blobs); | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET, ...segments]); | ||
| return result; | ||
| } | ||
| if (data instanceof Map) { | ||
| const result = this.serialize(Array.from(data.entries()), segments, meta, maps, blobs); | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP, ...segments]); | ||
| return result; | ||
| } | ||
| if (Array.isArray(data)) { | ||
| const json = data.map((v, i) => { | ||
| if (v === void 0) { | ||
| meta.push([STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED, ...segments, i]); | ||
| return null; | ||
| } | ||
| return this.serialize(v, [...segments, i], meta, maps, blobs)[0]; | ||
| }); | ||
| return [json, meta, maps, blobs]; | ||
| } | ||
| if (isObject(data)) { | ||
| const json = {}; | ||
| for (const k in data) { | ||
| if (k === "toJSON" && typeof data[k] === "function") { | ||
| continue; | ||
| } | ||
| json[k] = this.serialize(data[k], [...segments, k], meta, maps, blobs)[0]; | ||
| } | ||
| return [json, meta, maps, blobs]; | ||
| } | ||
| return [data, meta, maps, blobs]; | ||
| } | ||
| deserialize(json, meta, maps, getBlob) { | ||
| const ref = { data: json }; | ||
| if (maps && getBlob) { | ||
| maps.forEach((segments, i) => { | ||
| let currentRef = ref; | ||
| let preSegment = "data"; | ||
| segments.forEach((segment) => { | ||
| currentRef = currentRef[preSegment]; | ||
| preSegment = segment; | ||
| if (!Object.hasOwn(currentRef, preSegment)) { | ||
| throw new Error(`Security error: accessing non-existent path during deserialization. Path segment: ${preSegment}`); | ||
| } | ||
| }); | ||
| currentRef[preSegment] = getBlob(i); | ||
| }); | ||
| } | ||
| for (const item of meta) { | ||
| const type = item[0]; | ||
| let currentRef = ref; | ||
| let preSegment = "data"; | ||
| for (let i = 1; i < item.length; i++) { | ||
| currentRef = currentRef[preSegment]; | ||
| preSegment = item[i]; | ||
| if (!Object.hasOwn(currentRef, preSegment)) { | ||
| throw new Error(`Security error: accessing non-existent path during deserialization. Path segment: ${preSegment}`); | ||
| } | ||
| } | ||
| for (const custom of this.customSerializers) { | ||
| if (custom.type === type) { | ||
| currentRef[preSegment] = custom.deserialize(currentRef[preSegment]); | ||
| break; | ||
| } | ||
| } | ||
| switch (type) { | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.BIGINT: | ||
| currentRef[preSegment] = BigInt(currentRef[preSegment]); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.DATE: | ||
| currentRef[preSegment] = new Date(currentRef[preSegment] ?? "Invalid Date"); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.NAN: | ||
| currentRef[preSegment] = Number.NaN; | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.UNDEFINED: | ||
| currentRef[preSegment] = void 0; | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.URL: | ||
| currentRef[preSegment] = new URL(currentRef[preSegment]); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.REGEXP: { | ||
| const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/); | ||
| currentRef[preSegment] = new RegExp(pattern, flags); | ||
| break; | ||
| } | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.SET: | ||
| currentRef[preSegment] = new Set(currentRef[preSegment]); | ||
| break; | ||
| case STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES.MAP: | ||
| currentRef[preSegment] = new Map(currentRef[preSegment]); | ||
| break; | ||
| } | ||
| } | ||
| return ref.data; | ||
| } | ||
| } | ||
| function toHttpPath(path) { | ||
| return `/${path.map(encodeURIComponent).join("/")}`; | ||
| } | ||
| function toStandardHeaders(headers) { | ||
| if (typeof headers.forEach === "function") { | ||
| return toStandardHeaders$1(headers); | ||
| } | ||
| return headers; | ||
| } | ||
| function getMalformedResponseErrorCode(status) { | ||
| return Object.entries(COMMON_ORPC_ERROR_DEFS).find(([, def]) => def.status === status)?.[0] ?? "MALFORMED_ORPC_ERROR_RESPONSE"; | ||
| } | ||
| class StandardRPCLinkCodec { | ||
| constructor(serializer, options) { | ||
| this.serializer = serializer; | ||
| this.baseUrl = options.url; | ||
| this.maxUrlLength = options.maxUrlLength ?? 2083; | ||
| this.fallbackMethod = options.fallbackMethod ?? "POST"; | ||
| this.expectedMethod = options.method ?? this.fallbackMethod; | ||
| this.headers = options.headers ?? {}; | ||
| } | ||
| baseUrl; | ||
| maxUrlLength; | ||
| fallbackMethod; | ||
| expectedMethod; | ||
| headers; | ||
| async encode(path, input, options) { | ||
| let headers = toStandardHeaders(await value(this.headers, options, path, input)); | ||
| if (options.lastEventId !== void 0) { | ||
| headers = mergeStandardHeaders(headers, { "last-event-id": options.lastEventId }); | ||
| } | ||
| const expectedMethod = await value(this.expectedMethod, options, path, input); | ||
| const baseUrl = await value(this.baseUrl, options, path, input); | ||
| const url = new URL(baseUrl); | ||
| url.pathname = `${url.pathname.replace(/\/$/, "")}${toHttpPath(path)}`; | ||
| const serialized = this.serializer.serialize(input); | ||
| if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) { | ||
| const maxUrlLength = await value(this.maxUrlLength, options, path, input); | ||
| const getUrl = new URL(url); | ||
| getUrl.searchParams.append("data", stringifyJSON(serialized)); | ||
| if (getUrl.toString().length <= maxUrlLength) { | ||
| return { | ||
| body: void 0, | ||
| method: expectedMethod, | ||
| headers, | ||
| url: getUrl, | ||
| signal: options.signal | ||
| }; | ||
| } | ||
| } | ||
| return { | ||
| url, | ||
| method: expectedMethod === "GET" ? this.fallbackMethod : expectedMethod, | ||
| headers, | ||
| body: serialized, | ||
| signal: options.signal | ||
| }; | ||
| } | ||
| async decode(response) { | ||
| const isOk = !isORPCErrorStatus(response.status); | ||
| const deserialized = await (async () => { | ||
| let isBodyOk = false; | ||
| try { | ||
| const body = await response.body(); | ||
| isBodyOk = true; | ||
| return this.serializer.deserialize(body); | ||
| } catch (error) { | ||
| if (!isBodyOk) { | ||
| throw new Error("Cannot parse response body, please check the response body and content-type.", { | ||
| cause: error | ||
| }); | ||
| } | ||
| throw new Error("Invalid RPC response format.", { | ||
| cause: error | ||
| }); | ||
| } | ||
| })(); | ||
| if (!isOk) { | ||
| if (isORPCErrorJson(deserialized)) { | ||
| throw createORPCErrorFromJson(deserialized); | ||
| } | ||
| throw new ORPCError(getMalformedResponseErrorCode(response.status), { | ||
| status: response.status, | ||
| data: { ...response, body: deserialized } | ||
| }); | ||
| } | ||
| return deserialized; | ||
| } | ||
| } | ||
| class StandardRPCSerializer { | ||
| constructor(jsonSerializer) { | ||
| this.jsonSerializer = jsonSerializer; | ||
| } | ||
| serialize(data) { | ||
| if (isAsyncIteratorObject(data)) { | ||
| return mapEventIterator(data, { | ||
| value: async (value) => this.#serialize(value, false), | ||
| error: async (e) => { | ||
| return new ErrorEvent({ | ||
| data: this.#serialize(toORPCError(e).toJSON(), false), | ||
| cause: e | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| return this.#serialize(data, true); | ||
| } | ||
| #serialize(data, enableFormData) { | ||
| const [json, meta_, maps, blobs] = this.jsonSerializer.serialize(data); | ||
| const meta = meta_.length === 0 ? void 0 : meta_; | ||
| if (!enableFormData || blobs.length === 0) { | ||
| return { | ||
| json, | ||
| meta | ||
| }; | ||
| } | ||
| const form = new FormData(); | ||
| form.set("data", stringifyJSON({ json, meta, maps })); | ||
| blobs.forEach((blob, i) => { | ||
| form.set(i.toString(), blob); | ||
| }); | ||
| return form; | ||
| } | ||
| deserialize(data) { | ||
| if (isAsyncIteratorObject(data)) { | ||
| return mapEventIterator(data, { | ||
| value: async (value) => this.#deserialize(value), | ||
| error: async (e) => { | ||
| if (!(e instanceof ErrorEvent)) { | ||
| return e; | ||
| } | ||
| const deserialized = this.#deserialize(e.data); | ||
| if (isORPCErrorJson(deserialized)) { | ||
| return createORPCErrorFromJson(deserialized, { cause: e }); | ||
| } | ||
| return new ErrorEvent({ | ||
| data: deserialized, | ||
| cause: e | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| return this.#deserialize(data); | ||
| } | ||
| #deserialize(data) { | ||
| if (data === void 0) { | ||
| return void 0; | ||
| } | ||
| if (!(data instanceof FormData)) { | ||
| return this.jsonSerializer.deserialize(data.json, data.meta ?? []); | ||
| } | ||
| const serialized = JSON.parse(data.get("data")); | ||
| return this.jsonSerializer.deserialize( | ||
| serialized.json, | ||
| serialized.meta ?? [], | ||
| serialized.maps, | ||
| (i) => data.get(i.toString()) | ||
| ); | ||
| } | ||
| } | ||
| class StandardRPCLink extends StandardLink { | ||
| constructor(linkClient, options) { | ||
| const jsonSerializer = new StandardRPCJsonSerializer(options); | ||
| const serializer = new StandardRPCSerializer(jsonSerializer); | ||
| const linkCodec = new StandardRPCLinkCodec(serializer, options); | ||
| super(linkCodec, linkClient, options); | ||
| } | ||
| } | ||
| export { CompositeStandardLinkPlugin as C, StandardLink as S, STANDARD_RPC_JSON_SERIALIZER_BUILT_IN_TYPES as a, StandardRPCJsonSerializer as b, StandardRPCLink as c, StandardRPCLinkCodec as d, StandardRPCSerializer as e, toStandardHeaders as f, getMalformedResponseErrorCode as g, toHttpPath as t }; |
| import { resolveMaybeOptionalOptions, getConstructor, isObject } from '@orpc/shared'; | ||
| const ORPC_CLIENT_PACKAGE_NAME = "@orpc/client"; | ||
| const ORPC_CLIENT_PACKAGE_VERSION = "1.14.2"; | ||
| const COMMON_ORPC_ERROR_DEFS = { | ||
| BAD_REQUEST: { | ||
| status: 400, | ||
| message: "Bad Request" | ||
| }, | ||
| UNAUTHORIZED: { | ||
| status: 401, | ||
| message: "Unauthorized" | ||
| }, | ||
| FORBIDDEN: { | ||
| status: 403, | ||
| message: "Forbidden" | ||
| }, | ||
| NOT_FOUND: { | ||
| status: 404, | ||
| message: "Not Found" | ||
| }, | ||
| METHOD_NOT_SUPPORTED: { | ||
| status: 405, | ||
| message: "Method Not Supported" | ||
| }, | ||
| NOT_ACCEPTABLE: { | ||
| status: 406, | ||
| message: "Not Acceptable" | ||
| }, | ||
| TIMEOUT: { | ||
| status: 408, | ||
| message: "Request Timeout" | ||
| }, | ||
| CONFLICT: { | ||
| status: 409, | ||
| message: "Conflict" | ||
| }, | ||
| PRECONDITION_FAILED: { | ||
| status: 412, | ||
| message: "Precondition Failed" | ||
| }, | ||
| PAYLOAD_TOO_LARGE: { | ||
| status: 413, | ||
| message: "Payload Too Large" | ||
| }, | ||
| UNSUPPORTED_MEDIA_TYPE: { | ||
| status: 415, | ||
| message: "Unsupported Media Type" | ||
| }, | ||
| UNPROCESSABLE_CONTENT: { | ||
| status: 422, | ||
| message: "Unprocessable Content" | ||
| }, | ||
| TOO_MANY_REQUESTS: { | ||
| status: 429, | ||
| message: "Too Many Requests" | ||
| }, | ||
| CLIENT_CLOSED_REQUEST: { | ||
| status: 499, | ||
| message: "Client Closed Request" | ||
| }, | ||
| INTERNAL_SERVER_ERROR: { | ||
| status: 500, | ||
| message: "Internal Server Error" | ||
| }, | ||
| NOT_IMPLEMENTED: { | ||
| status: 501, | ||
| message: "Not Implemented" | ||
| }, | ||
| BAD_GATEWAY: { | ||
| status: 502, | ||
| message: "Bad Gateway" | ||
| }, | ||
| SERVICE_UNAVAILABLE: { | ||
| status: 503, | ||
| message: "Service Unavailable" | ||
| }, | ||
| GATEWAY_TIMEOUT: { | ||
| status: 504, | ||
| message: "Gateway Timeout" | ||
| } | ||
| }; | ||
| function fallbackORPCErrorStatus(code, status) { | ||
| return status ?? COMMON_ORPC_ERROR_DEFS[code]?.status ?? 500; | ||
| } | ||
| function fallbackORPCErrorMessage(code, message) { | ||
| return message || COMMON_ORPC_ERROR_DEFS[code]?.message || code; | ||
| } | ||
| const GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL = Symbol.for(`__${ORPC_CLIENT_PACKAGE_NAME}@${ORPC_CLIENT_PACKAGE_VERSION}/error/ORPC_ERROR_CONSTRUCTORS__`); | ||
| void (globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL] ??= /* @__PURE__ */ new WeakSet()); | ||
| const globalORPCErrorConstructors = globalThis[GLOBAL_ORPC_ERROR_CONSTRUCTORS_SYMBOL]; | ||
| class ORPCError extends Error { | ||
| defined; | ||
| code; | ||
| status; | ||
| data; | ||
| constructor(code, ...rest) { | ||
| const options = resolveMaybeOptionalOptions(rest); | ||
| if (options.status !== void 0 && !isORPCErrorStatus(options.status)) { | ||
| throw new Error("[ORPCError] Invalid error status code."); | ||
| } | ||
| const message = fallbackORPCErrorMessage(code, options.message); | ||
| super(message, options); | ||
| this.code = code; | ||
| this.status = fallbackORPCErrorStatus(code, options.status); | ||
| this.defined = options.defined ?? false; | ||
| this.data = options.data; | ||
| } | ||
| toJSON() { | ||
| return { | ||
| defined: this.defined, | ||
| code: this.code, | ||
| status: this.status, | ||
| message: this.message, | ||
| data: this.data | ||
| }; | ||
| } | ||
| /** | ||
| * Workaround for Next.js where different contexts use separate | ||
| * dependency graphs, causing multiple ORPCError constructors existing and breaking | ||
| * `instanceof` checks across contexts. | ||
| * | ||
| * This is particularly problematic with "Optimized SSR", where orpc-client | ||
| * executes in one context but is invoked from another. When an error is thrown | ||
| * in the execution context, `instanceof ORPCError` checks fail in the | ||
| * invocation context due to separate class constructors. | ||
| * | ||
| * @todo Remove this and related code if Next.js resolves the multiple dependency graph issue. | ||
| */ | ||
| static [Symbol.hasInstance](instance) { | ||
| if (globalORPCErrorConstructors.has(this)) { | ||
| const constructor = getConstructor(instance); | ||
| if (constructor && globalORPCErrorConstructors.has(constructor)) { | ||
| return true; | ||
| } | ||
| } | ||
| return super[Symbol.hasInstance](instance); | ||
| } | ||
| } | ||
| globalORPCErrorConstructors.add(ORPCError); | ||
| function isDefinedError(error) { | ||
| return error instanceof ORPCError && error.defined; | ||
| } | ||
| function toORPCError(error) { | ||
| return error instanceof ORPCError ? error : new ORPCError("INTERNAL_SERVER_ERROR", { | ||
| message: "Internal server error", | ||
| cause: error | ||
| }); | ||
| } | ||
| function isORPCErrorStatus(status) { | ||
| return status < 200 || status >= 400; | ||
| } | ||
| function isORPCErrorJson(json) { | ||
| if (!isObject(json)) { | ||
| return false; | ||
| } | ||
| const validKeys = ["defined", "code", "status", "message", "data"]; | ||
| if (Object.keys(json).some((k) => !validKeys.includes(k))) { | ||
| return false; | ||
| } | ||
| return "defined" in json && typeof json.defined === "boolean" && "code" in json && typeof json.code === "string" && "status" in json && typeof json.status === "number" && isORPCErrorStatus(json.status) && "message" in json && typeof json.message === "string"; | ||
| } | ||
| function createORPCErrorFromJson(json, options = {}) { | ||
| return new ORPCError(json.code, { | ||
| ...options, | ||
| ...json | ||
| }); | ||
| } | ||
| export { COMMON_ORPC_ERROR_DEFS as C, ORPC_CLIENT_PACKAGE_NAME as O, ORPC_CLIENT_PACKAGE_VERSION as a, fallbackORPCErrorMessage as b, ORPCError as c, isORPCErrorStatus as d, isORPCErrorJson as e, fallbackORPCErrorStatus as f, createORPCErrorFromJson as g, isDefinedError as i, toORPCError as t }; |
153712
0.03%+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
Updated
Updated