@orpc/client 0.41.2 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,212 @@
1
+ import {
2
+ ORPCError,
3
+ mapEventIterator,
4
+ toORPCError
5
+ } from "./chunk-X34KXUAJ.js";
6
+
7
+ // src/rpc/json-serializer.ts
8
+ import { isObject } from "@orpc/shared";
9
+ var RPCJsonSerializer = class {
10
+ serialize(data, segments = [], meta = [], maps = [], blobs = []) {
11
+ if (data instanceof Blob) {
12
+ maps.push(segments);
13
+ blobs.push(data);
14
+ return [data, meta, maps, blobs];
15
+ }
16
+ if (typeof data === "bigint") {
17
+ meta.push([0, segments]);
18
+ return [data.toString(), meta, maps, blobs];
19
+ }
20
+ if (data instanceof Date) {
21
+ meta.push([1, segments]);
22
+ if (Number.isNaN(data.getTime())) {
23
+ return [null, meta, maps, blobs];
24
+ }
25
+ return [data.toISOString(), meta, maps, blobs];
26
+ }
27
+ if (Number.isNaN(data)) {
28
+ meta.push([2, segments]);
29
+ return [null, meta, maps, blobs];
30
+ }
31
+ if (data instanceof URL) {
32
+ meta.push([4, segments]);
33
+ return [data.toString(), meta, maps, blobs];
34
+ }
35
+ if (data instanceof RegExp) {
36
+ meta.push([5, segments]);
37
+ return [data.toString(), meta, maps, blobs];
38
+ }
39
+ if (data instanceof Set) {
40
+ const result = this.serialize(Array.from(data), segments, meta, maps, blobs);
41
+ meta.push([6, segments]);
42
+ return result;
43
+ }
44
+ if (data instanceof Map) {
45
+ const result = this.serialize(Array.from(data.entries()), segments, meta, maps, blobs);
46
+ meta.push([7, segments]);
47
+ return result;
48
+ }
49
+ if (Array.isArray(data)) {
50
+ const json = data.map((v, i) => {
51
+ if (v === void 0) {
52
+ meta.push([3, [...segments, i]]);
53
+ return v;
54
+ }
55
+ return this.serialize(v, [...segments, i], meta, maps, blobs)[0];
56
+ });
57
+ return [json, meta, maps, blobs];
58
+ }
59
+ if (isObject(data)) {
60
+ const json = {};
61
+ for (const k in data) {
62
+ json[k] = this.serialize(data[k], [...segments, k], meta, maps, blobs)[0];
63
+ }
64
+ return [json, meta, maps, blobs];
65
+ }
66
+ return [data, meta, maps, blobs];
67
+ }
68
+ deserialize(json, meta, maps, getBlob) {
69
+ const ref = { data: json };
70
+ if (maps && getBlob) {
71
+ maps.forEach((segments, i) => {
72
+ let currentRef = ref;
73
+ let preSegment = "data";
74
+ segments.forEach((segment) => {
75
+ currentRef = currentRef[preSegment];
76
+ preSegment = segment;
77
+ });
78
+ currentRef[preSegment] = getBlob(i);
79
+ });
80
+ }
81
+ for (const [type, segments] of meta) {
82
+ let currentRef = ref;
83
+ let preSegment = "data";
84
+ segments.forEach((segment) => {
85
+ currentRef = currentRef[preSegment];
86
+ preSegment = segment;
87
+ });
88
+ switch (type) {
89
+ case 0:
90
+ currentRef[preSegment] = BigInt(currentRef[preSegment]);
91
+ break;
92
+ case 1:
93
+ currentRef[preSegment] = new Date(currentRef[preSegment] ?? "Invalid Date");
94
+ break;
95
+ case 2:
96
+ currentRef[preSegment] = Number.NaN;
97
+ break;
98
+ case 3:
99
+ currentRef[preSegment] = void 0;
100
+ break;
101
+ case 4:
102
+ currentRef[preSegment] = new URL(currentRef[preSegment]);
103
+ break;
104
+ case 5: {
105
+ const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/);
106
+ currentRef[preSegment] = new RegExp(pattern, flags);
107
+ break;
108
+ }
109
+ case 6:
110
+ currentRef[preSegment] = new Set(currentRef[preSegment]);
111
+ break;
112
+ case 7:
113
+ currentRef[preSegment] = new Map(currentRef[preSegment]);
114
+ break;
115
+ /* v8 ignore next 3 */
116
+ default: {
117
+ const _expected = type;
118
+ }
119
+ }
120
+ }
121
+ return ref.data;
122
+ }
123
+ };
124
+
125
+ // src/rpc/serializer.ts
126
+ import { ErrorEvent, isAsyncIteratorObject } from "@orpc/standard-server";
127
+ var RPCSerializer = class {
128
+ constructor(jsonSerializer = new RPCJsonSerializer()) {
129
+ this.jsonSerializer = jsonSerializer;
130
+ }
131
+ serialize(data) {
132
+ if (isAsyncIteratorObject(data)) {
133
+ return mapEventIterator(data, {
134
+ value: async (value) => this.#serialize(value, false),
135
+ error: async (e) => {
136
+ if (e instanceof ErrorEvent) {
137
+ return new ErrorEvent({
138
+ data: this.#serialize(e.data, false),
139
+ cause: e
140
+ });
141
+ }
142
+ return new ErrorEvent({
143
+ data: this.#serialize(toORPCError(e).toJSON(), false),
144
+ cause: e
145
+ });
146
+ }
147
+ });
148
+ }
149
+ return this.#serialize(data, true);
150
+ }
151
+ #serialize(data, enableFormData) {
152
+ if (data === void 0 || data instanceof Blob) {
153
+ return data;
154
+ }
155
+ const [json, meta_, maps, blobs] = this.jsonSerializer.serialize(data);
156
+ const meta = meta_.length === 0 ? void 0 : meta_;
157
+ if (!enableFormData || blobs.length === 0) {
158
+ return {
159
+ json,
160
+ meta
161
+ };
162
+ }
163
+ const form = new FormData();
164
+ form.set("data", JSON.stringify({ json, meta, maps }));
165
+ blobs.forEach((blob, i) => {
166
+ form.set(i.toString(), blob);
167
+ });
168
+ return form;
169
+ }
170
+ deserialize(data) {
171
+ if (isAsyncIteratorObject(data)) {
172
+ return mapEventIterator(data, {
173
+ value: async (value) => this.#deserialize(value),
174
+ error: async (e) => {
175
+ if (!(e instanceof ErrorEvent)) {
176
+ return e;
177
+ }
178
+ const deserialized = this.#deserialize(e.data);
179
+ if (ORPCError.isValidJSON(deserialized)) {
180
+ return ORPCError.fromJSON(deserialized, { cause: e });
181
+ }
182
+ return new ErrorEvent({
183
+ data: deserialized,
184
+ cause: e
185
+ });
186
+ }
187
+ });
188
+ }
189
+ return this.#deserialize(data);
190
+ }
191
+ #deserialize(data) {
192
+ if (data === void 0 || data instanceof Blob) {
193
+ return data;
194
+ }
195
+ if (!(data instanceof FormData)) {
196
+ return this.jsonSerializer.deserialize(data.json, data.meta ?? []);
197
+ }
198
+ const serialized = JSON.parse(data.get("data"));
199
+ return this.jsonSerializer.deserialize(
200
+ serialized.json,
201
+ serialized.meta ?? [],
202
+ serialized.maps,
203
+ (i) => data.get(i.toString())
204
+ );
205
+ }
206
+ };
207
+
208
+ export {
209
+ RPCJsonSerializer,
210
+ RPCSerializer
211
+ };
212
+ //# sourceMappingURL=chunk-4HZVK3GJ.js.map
@@ -1,9 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
5
- };
6
-
7
1
  // src/error.ts
8
2
  import { isObject } from "@orpc/shared";
9
3
  var COMMON_ORPC_ERROR_DEFS = {
@@ -171,8 +165,8 @@ function onEventIteratorStatusChange(iterator, callback, notifyImmediately = tru
171
165
  }
172
166
 
173
167
  // src/event-iterator.ts
174
- import { getEventMeta, isEventMetaContainer, withEventMeta } from "@orpc/server-standard";
175
168
  import { retry } from "@orpc/shared";
169
+ import { getEventMeta, isEventMetaContainer, withEventMeta } from "@orpc/standard-server";
176
170
  function mapEventIterator(iterator, maps) {
177
171
  return async function* () {
178
172
  try {
@@ -272,7 +266,6 @@ function createAutoRetryEventIterator(initial, reconnect, initialLastEventId) {
272
266
  }
273
267
 
274
268
  export {
275
- __export,
276
269
  COMMON_ORPC_ERROR_DEFS,
277
270
  fallbackORPCErrorStatus,
278
271
  fallbackORPCErrorMessage,
@@ -285,4 +278,4 @@ export {
285
278
  mapEventIterator,
286
279
  createAutoRetryEventIterator
287
280
  };
288
- //# sourceMappingURL=chunk-2UPNYYFF.js.map
281
+ //# sourceMappingURL=chunk-X34KXUAJ.js.map
package/dist/fetch.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  RPCSerializer
3
- } from "./chunk-TPEMQB7D.js";
3
+ } from "./chunk-4HZVK3GJ.js";
4
4
  import {
5
5
  ORPCError,
6
6
  createAutoRetryEventIterator
7
- } from "./chunk-2UPNYYFF.js";
7
+ } from "./chunk-X34KXUAJ.js";
8
8
 
9
9
  // src/adapters/fetch/rpc-link.ts
10
- import { isAsyncIteratorObject } from "@orpc/server-standard";
11
- import { toFetchBody, toStandardBody } from "@orpc/server-standard-fetch";
12
10
  import { trim, value } from "@orpc/shared";
11
+ import { isAsyncIteratorObject } from "@orpc/standard-server";
12
+ import { toFetchBody, toStandardBody } from "@orpc/standard-server-fetch";
13
13
  var InvalidEventSourceRetryResponse = class extends Error {
14
14
  };
15
15
  var RPCLink = class {
@@ -101,9 +101,9 @@ var RPCLink = class {
101
101
  const headers = new Headers(await value(this.headers, options, path, input));
102
102
  const url = new URL(`${trim(this.url, "/")}/${path.map(encodeURIComponent).join("/")}`);
103
103
  const serialized = this.rpcSerializer.serialize(input);
104
- if (expectedMethod === "GET" && !(serialized instanceof FormData) && !isAsyncIteratorObject(serialized)) {
104
+ if (expectedMethod === "GET" && !(serialized instanceof FormData) && !(serialized instanceof Blob) && !isAsyncIteratorObject(serialized)) {
105
105
  const getUrl = new URL(url);
106
- getUrl.searchParams.append("data", JSON.stringify(serialized));
106
+ getUrl.searchParams.append("data", JSON.stringify(serialized) ?? "");
107
107
  if (getUrl.toString().length <= this.maxUrlLength) {
108
108
  return {
109
109
  body: void 0,
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  registerEventIteratorState,
11
11
  toORPCError,
12
12
  updateEventIteratorStatus
13
- } from "./chunk-2UPNYYFF.js";
13
+ } from "./chunk-X34KXUAJ.js";
14
14
 
15
15
  // src/client.ts
16
16
  function createORPCClient(link, options) {
@@ -53,13 +53,22 @@ var DynamicLink = class {
53
53
  async function safe(promise) {
54
54
  try {
55
55
  const output = await promise;
56
- return [output, void 0, false];
56
+ return Object.assign(
57
+ [null, output, false],
58
+ { error: null, data: output, isDefined: false }
59
+ );
57
60
  } catch (e) {
58
61
  const error = e;
59
62
  if (isDefinedError(error)) {
60
- return [void 0, error, true];
63
+ return Object.assign(
64
+ [error, void 0, true],
65
+ { error, data: void 0, isDefined: true }
66
+ );
61
67
  }
62
- return [void 0, error, false];
68
+ return Object.assign(
69
+ [error, void 0, false],
70
+ { error, data: void 0, isDefined: false }
71
+ );
63
72
  }
64
73
  }
65
74
  export {
package/dist/openapi.js CHANGED
@@ -1,314 +1,216 @@
1
1
  import {
2
2
  ORPCError,
3
- __export,
4
3
  mapEventIterator,
5
4
  toORPCError
6
- } from "./chunk-2UPNYYFF.js";
5
+ } from "./chunk-X34KXUAJ.js";
7
6
 
8
7
  // src/openapi/bracket-notation.ts
9
- var bracket_notation_exports = {};
10
- __export(bracket_notation_exports, {
11
- deserialize: () => deserialize,
12
- escapeSegment: () => escapeSegment,
13
- parsePath: () => parsePath,
14
- serialize: () => serialize,
15
- stringifyPath: () => stringifyPath
16
- });
17
8
  import { isObject } from "@orpc/shared";
18
- function serialize(payload, parentKey = "") {
19
- if (!Array.isArray(payload) && !isObject(payload))
20
- return [["", payload]];
21
- const result = [];
22
- function helper(value, path) {
23
- if (Array.isArray(value)) {
24
- value.forEach((item, index) => {
25
- helper(item, [...path, String(index)]);
9
+ var BracketNotationSerializer = class {
10
+ serialize(data, segments = [], result = []) {
11
+ if (Array.isArray(data)) {
12
+ data.forEach((item, i) => {
13
+ this.serialize(item, [...segments, i], result);
26
14
  });
27
- } else if (isObject(value)) {
28
- for (const [key, val] of Object.entries(value)) {
29
- helper(val, [...path, key]);
15
+ } else if (isObject(data)) {
16
+ for (const key in data) {
17
+ this.serialize(data[key], [...segments, key], result);
30
18
  }
31
19
  } else {
32
- result.push([stringifyPath(path), value]);
20
+ result.push([this.stringifyPath(segments), data]);
33
21
  }
22
+ return result;
34
23
  }
35
- helper(payload, parentKey ? [parentKey] : []);
36
- return result;
37
- }
38
- function deserialize(entities) {
39
- if (entities.length === 0) {
40
- return void 0;
41
- }
42
- const isRootArray = entities.every(([path]) => path === "");
43
- const result = isRootArray ? [] : {};
44
- const arrayPushPaths = /* @__PURE__ */ new Set();
45
- for (const [path, _] of entities) {
46
- const segments = parsePath(path);
47
- const base = segments.slice(0, -1).join(".");
48
- const last = segments[segments.length - 1];
49
- if (last === "") {
50
- arrayPushPaths.add(base);
51
- } else {
52
- arrayPushPaths.delete(base);
53
- }
54
- }
55
- function setValue(obj, segments, value, fullPath) {
56
- const [first, ...rest_] = segments;
57
- if (Array.isArray(obj) && first === "") {
58
- ;
59
- obj.push(value);
60
- return;
61
- }
62
- const objAsRecord = obj;
63
- if (rest_.length === 0) {
64
- objAsRecord[first] = value;
65
- return;
66
- }
67
- const rest = rest_;
68
- if (rest[0] === "") {
69
- const pathToCheck = segments.slice(0, -1).join(".");
70
- if (rest.length === 1 && arrayPushPaths.has(pathToCheck)) {
71
- if (!(first in objAsRecord)) {
72
- objAsRecord[first] = [];
73
- }
74
- if (Array.isArray(objAsRecord[first])) {
75
- ;
76
- objAsRecord[first].push(value);
77
- return;
24
+ deserialize(serialized) {
25
+ const arrayPushStyles = /* @__PURE__ */ new WeakSet();
26
+ const ref = { value: [] };
27
+ for (const [path, value] of serialized) {
28
+ const segments = this.parsePath(path);
29
+ let currentRef = ref;
30
+ let nextSegment = "value";
31
+ segments.forEach((segment, i) => {
32
+ if (!Array.isArray(currentRef[nextSegment]) && !isObject(currentRef[nextSegment])) {
33
+ currentRef[nextSegment] = [];
78
34
  }
79
- }
80
- if (!(first in objAsRecord)) {
81
- objAsRecord[first] = {};
82
- }
83
- const target = objAsRecord[first];
84
- target[""] = value;
85
- return;
86
- }
87
- if (!(first in objAsRecord)) {
88
- objAsRecord[first] = {};
89
- }
90
- setValue(
91
- objAsRecord[first],
92
- rest,
93
- value,
94
- fullPath
95
- );
96
- }
97
- for (const [path, value] of entities) {
98
- const segments = parsePath(path);
99
- setValue(result, segments, value, path);
100
- }
101
- return result;
102
- }
103
- function escapeSegment(segment) {
104
- return segment.replace(/[\\[\]]/g, (match) => {
105
- switch (match) {
106
- case "\\":
107
- return "\\\\";
108
- case "[":
109
- return "\\[";
110
- case "]":
111
- return "\\]";
112
- default:
113
- return match;
114
- }
115
- });
116
- }
117
- function stringifyPath(path) {
118
- const [first, ...rest] = path;
119
- const firstSegment = escapeSegment(first);
120
- const base = first === "" ? "" : firstSegment;
121
- return rest.reduce(
122
- (result, segment) => `${result}[${escapeSegment(segment)}]`,
123
- base
124
- );
125
- }
126
- function parsePath(path) {
127
- if (path === "")
128
- return [""];
129
- const result = [];
130
- let currentSegment = "";
131
- let inBracket = false;
132
- let bracketContent = "";
133
- let backslashCount = 0;
134
- for (let i = 0; i < path.length; i++) {
135
- const char = path[i];
136
- if (char === "\\") {
137
- backslashCount++;
138
- continue;
139
- }
140
- if (backslashCount > 0) {
141
- const literalBackslashes = "\\".repeat(Math.floor(backslashCount / 2));
142
- if (char === "[" || char === "]") {
143
- if (backslashCount % 2 === 1) {
144
- if (inBracket) {
145
- bracketContent += literalBackslashes + char;
146
- } else {
147
- currentSegment += literalBackslashes + char;
35
+ if (i !== segments.length - 1) {
36
+ if (Array.isArray(currentRef[nextSegment]) && !isValidArrayIndex(segment)) {
37
+ currentRef[nextSegment] = { ...currentRef[nextSegment] };
148
38
  }
149
39
  } else {
150
- if (inBracket) {
151
- bracketContent += literalBackslashes;
152
- } else {
153
- currentSegment += literalBackslashes;
154
- }
155
- if (char === "[" && !inBracket) {
156
- if (currentSegment !== "" || result.length === 0) {
157
- result.push(currentSegment);
158
- }
159
- inBracket = true;
160
- bracketContent = "";
161
- currentSegment = "";
162
- } else if (char === "]" && inBracket) {
163
- result.push(bracketContent);
164
- inBracket = false;
165
- bracketContent = "";
166
- } else {
167
- if (inBracket) {
168
- bracketContent += char;
40
+ if (Array.isArray(currentRef[nextSegment])) {
41
+ if (segment === "") {
42
+ if (currentRef[nextSegment].length && !arrayPushStyles.has(currentRef[nextSegment])) {
43
+ currentRef[nextSegment] = { ...currentRef[nextSegment] };
44
+ }
169
45
  } else {
170
- currentSegment += char;
46
+ if (arrayPushStyles.has(currentRef[nextSegment])) {
47
+ currentRef[nextSegment] = { "": currentRef[nextSegment].at(-1) };
48
+ } else if (!isValidArrayIndex(segment)) {
49
+ currentRef[nextSegment] = { ...currentRef[nextSegment] };
50
+ }
171
51
  }
172
52
  }
173
53
  }
174
- } else {
175
- const allBackslashes = "\\".repeat(backslashCount);
176
- if (inBracket) {
177
- bracketContent += allBackslashes + char;
54
+ currentRef = currentRef[nextSegment];
55
+ nextSegment = segment;
56
+ });
57
+ if (Array.isArray(currentRef)) {
58
+ if (nextSegment === "") {
59
+ arrayPushStyles.add(currentRef);
60
+ currentRef.push(value);
178
61
  } else {
179
- currentSegment += allBackslashes + char;
62
+ currentRef[Number(nextSegment)] = value;
180
63
  }
64
+ } else {
65
+ currentRef[nextSegment] = value;
181
66
  }
182
- backslashCount = 0;
183
- continue;
184
- }
185
- if (char === "[" && !inBracket) {
186
- if (currentSegment !== "" || result.length === 0) {
187
- result.push(currentSegment);
188
- }
189
- inBracket = true;
190
- bracketContent = "";
191
- currentSegment = "";
192
- continue;
193
- }
194
- if (char === "]" && inBracket) {
195
- result.push(bracketContent);
196
- inBracket = false;
197
- bracketContent = "";
198
- continue;
199
- }
200
- if (inBracket) {
201
- bracketContent += char;
202
- } else {
203
- currentSegment += char;
204
67
  }
68
+ return ref.value;
205
69
  }
206
- if (backslashCount > 0) {
207
- const remainingBackslashes = "\\".repeat(backslashCount);
208
- if (inBracket) {
209
- bracketContent += remainingBackslashes;
210
- } else {
211
- currentSegment += remainingBackslashes;
212
- }
70
+ stringifyPath(segments) {
71
+ return segments.map((segment) => {
72
+ return segment.toString().replace(/[\\[\]]/g, (match) => {
73
+ switch (match) {
74
+ case "\\":
75
+ return "\\\\";
76
+ case "[":
77
+ return "\\[";
78
+ case "]":
79
+ return "\\]";
80
+ /* v8 ignore next 2 */
81
+ default:
82
+ return match;
83
+ }
84
+ });
85
+ }).reduce((result, segment, i) => {
86
+ if (i === 0) {
87
+ return segment;
88
+ }
89
+ return `${result}[${segment}]`;
90
+ }, "");
213
91
  }
214
- if (inBracket) {
215
- if (currentSegment !== "" || result.length === 0) {
216
- result.push(currentSegment);
92
+ parsePath(path) {
93
+ const segments = [];
94
+ let inBrackets = false;
95
+ let currentSegment = "";
96
+ let backslashCount = 0;
97
+ for (let i = 0; i < path.length; i++) {
98
+ const char = path[i];
99
+ const nextChar = path[i + 1];
100
+ if (inBrackets && char === "]" && (nextChar === void 0 || nextChar === "[") && backslashCount % 2 === 0) {
101
+ if (nextChar === void 0) {
102
+ inBrackets = false;
103
+ }
104
+ segments.push(currentSegment);
105
+ currentSegment = "";
106
+ i++;
107
+ } else if (segments.length === 0 && char === "[" && backslashCount % 2 === 0) {
108
+ inBrackets = true;
109
+ segments.push(currentSegment);
110
+ currentSegment = "";
111
+ } else if (char === "\\") {
112
+ backslashCount++;
113
+ } else {
114
+ currentSegment += "\\".repeat(backslashCount / 2) + char;
115
+ backslashCount = 0;
116
+ }
217
117
  }
218
- result.push(`[${bracketContent}`);
219
- } else if (currentSegment !== "" || result.length === 0) {
220
- result.push(currentSegment);
118
+ return inBrackets || segments.length === 0 ? [path] : segments;
221
119
  }
222
- return result;
120
+ };
121
+ function isValidArrayIndex(value) {
122
+ return /^0$|^[1-9]\d*$/.test(value);
223
123
  }
224
124
 
225
125
  // src/openapi/json-serializer.ts
226
126
  import { isObject as isObject2 } from "@orpc/shared";
227
127
  var OpenAPIJsonSerializer = class {
228
- serialize(payload) {
229
- if (payload instanceof Set)
230
- return this.serialize([...payload]);
231
- if (payload instanceof Map)
232
- return this.serialize([...payload.entries()]);
233
- if (Array.isArray(payload)) {
234
- return payload.map((v) => v === void 0 ? "undefined" : this.serialize(v));
128
+ serialize(data, hasBlobRef = { value: false }) {
129
+ if (data instanceof Blob) {
130
+ hasBlobRef.value = true;
131
+ return [data, hasBlobRef.value];
132
+ }
133
+ if (data instanceof Set) {
134
+ return this.serialize(Array.from(data), hasBlobRef);
135
+ }
136
+ if (data instanceof Map) {
137
+ return this.serialize(Array.from(data.entries()), hasBlobRef);
138
+ }
139
+ if (Array.isArray(data)) {
140
+ const json = data.map((v) => v === void 0 ? null : this.serialize(v, hasBlobRef)[0]);
141
+ return [json, hasBlobRef.value];
235
142
  }
236
- if (Number.isNaN(payload))
237
- return "NaN";
238
- if (typeof payload === "bigint")
239
- return payload.toString();
240
- if (payload instanceof Date && Number.isNaN(payload.getTime())) {
241
- return "Invalid Date";
143
+ if (isObject2(data)) {
144
+ const json = {};
145
+ for (const k in data) {
146
+ json[k] = this.serialize(data[k], hasBlobRef)[0];
147
+ }
148
+ return [json, hasBlobRef.value];
149
+ }
150
+ if (typeof data === "bigint" || data instanceof RegExp || data instanceof URL) {
151
+ return [data.toString(), hasBlobRef.value];
152
+ }
153
+ if (data instanceof Date) {
154
+ return [Number.isNaN(data.getTime()) ? null : data.toISOString(), hasBlobRef.value];
155
+ }
156
+ if (Number.isNaN(data)) {
157
+ return [null, hasBlobRef.value];
242
158
  }
243
- if (payload instanceof RegExp)
244
- return payload.toString();
245
- if (payload instanceof URL)
246
- return payload.toString();
247
- if (!isObject2(payload))
248
- return payload;
249
- return Object.keys(payload).reduce(
250
- (carry, key) => {
251
- const val = payload[key];
252
- carry[key] = this.serialize(val);
253
- return carry;
254
- },
255
- {}
256
- );
159
+ return [data, hasBlobRef.value];
257
160
  }
258
161
  };
259
162
 
260
163
  // src/openapi/serializer.ts
261
- import { ErrorEvent, isAsyncIteratorObject } from "@orpc/server-standard";
262
- import { findDeepMatches } from "@orpc/shared";
164
+ import { ErrorEvent, isAsyncIteratorObject } from "@orpc/standard-server";
263
165
  var OpenAPISerializer = class {
264
- jsonSerializer;
265
- constructor(options) {
266
- this.jsonSerializer = options?.jsonSerializer ?? new OpenAPIJsonSerializer();
166
+ constructor(jsonSerializer = new OpenAPIJsonSerializer(), bracketNotation = new BracketNotationSerializer()) {
167
+ this.jsonSerializer = jsonSerializer;
168
+ this.bracketNotation = bracketNotation;
267
169
  }
268
170
  serialize(data) {
269
- if (data instanceof Blob || data === void 0) {
270
- return data;
271
- }
272
171
  if (isAsyncIteratorObject(data)) {
273
172
  return mapEventIterator(data, {
274
- value: async (value) => this.jsonSerializer.serialize(value),
173
+ value: async (value) => this.#serialize(value, false),
275
174
  error: async (e) => {
276
175
  if (e instanceof ErrorEvent) {
277
176
  return new ErrorEvent({
278
- data: this.jsonSerializer.serialize(e.data),
177
+ data: this.#serialize(e.data, false),
279
178
  cause: e
280
179
  });
281
180
  }
282
181
  return new ErrorEvent({
283
- data: this.jsonSerializer.serialize(toORPCError(e).toJSON()),
182
+ data: this.#serialize(toORPCError(e).toJSON(), false),
284
183
  cause: e
285
184
  });
286
185
  }
287
186
  });
288
187
  }
289
- const serializedJSON = this.jsonSerializer.serialize(data);
290
- const { values: blobs } = findDeepMatches((v) => v instanceof Blob, serializedJSON);
291
- if (blobs.length === 0) {
292
- return serializedJSON;
188
+ return this.#serialize(data, true);
189
+ }
190
+ #serialize(data, enableFormData) {
191
+ if (data instanceof Blob || data === void 0) {
192
+ return data;
193
+ }
194
+ const [json, hasBlob] = this.jsonSerializer.serialize(data);
195
+ if (!enableFormData || !hasBlob) {
196
+ return json;
293
197
  }
294
198
  const form = new FormData();
295
- for (const [path, value] of serialize(serializedJSON)) {
199
+ for (const [path, value] of this.bracketNotation.serialize(json)) {
296
200
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
297
201
  form.append(path, value.toString());
298
- } else if (value instanceof Date) {
299
- form.append(path, value.toISOString());
300
202
  } else if (value instanceof Blob) {
301
203
  form.append(path, value);
302
204
  }
303
205
  }
304
206
  return form;
305
207
  }
306
- deserialize(serialized) {
307
- if (serialized instanceof URLSearchParams || serialized instanceof FormData) {
308
- return deserialize([...serialized.entries()]);
208
+ deserialize(data) {
209
+ if (data instanceof URLSearchParams || data instanceof FormData) {
210
+ return this.bracketNotation.deserialize(Array.from(data.entries()));
309
211
  }
310
- if (isAsyncIteratorObject(serialized)) {
311
- return mapEventIterator(serialized, {
212
+ if (isAsyncIteratorObject(data)) {
213
+ return mapEventIterator(data, {
312
214
  value: async (value) => value,
313
215
  error: async (e) => {
314
216
  if (e instanceof ErrorEvent && ORPCError.isValidJSON(e.data)) {
@@ -318,11 +220,11 @@ var OpenAPISerializer = class {
318
220
  }
319
221
  });
320
222
  }
321
- return serialized;
223
+ return data;
322
224
  }
323
225
  };
324
226
  export {
325
- bracket_notation_exports as BracketNotation,
227
+ BracketNotationSerializer,
326
228
  OpenAPIJsonSerializer,
327
229
  OpenAPISerializer
328
230
  };
package/dist/rpc.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
- RPCSerializer,
3
- serializeRPCJson
4
- } from "./chunk-TPEMQB7D.js";
5
- import "./chunk-2UPNYYFF.js";
2
+ RPCJsonSerializer,
3
+ RPCSerializer
4
+ } from "./chunk-4HZVK3GJ.js";
5
+ import "./chunk-X34KXUAJ.js";
6
6
  export {
7
- RPCSerializer,
8
- serializeRPCJson
7
+ RPCJsonSerializer,
8
+ RPCSerializer
9
9
  };
10
10
  //# sourceMappingURL=rpc.js.map
@@ -1,84 +1,9 @@
1
- /**
2
- * Serialize an object or array into a list of [key, value] pairs.
3
- * The key will express by using bracket-notation.
4
- *
5
- * Notice: This way cannot express the empty object or array.
6
- *
7
- * @example
8
- * ```ts
9
- * const payload = {
10
- * name: 'John Doe',
11
- * pets: ['dog', 'cat'],
12
- * }
13
- *
14
- * const entities = serialize(payload)
15
- *
16
- * expect(entities).toEqual([
17
- * ['name', 'John Doe'],
18
- * ['name[pets][0]', 'dog'],
19
- * ['name[pets][1]', 'cat'],
20
- * ])
21
- * ```
22
- */
23
- export declare function serialize(payload: unknown, parentKey?: string): [string, unknown][];
24
- /**
25
- * Deserialize a list of [key, value] pairs into an object or array.
26
- * The key is expressed by using bracket-notation.
27
- *
28
- * @example
29
- * ```ts
30
- * const entities = [
31
- * ['name', 'John Doe'],
32
- * ['name[pets][0]', 'dog'],
33
- * ['name[pets][1]', 'cat'],
34
- * ['name[dogs][]', 'hello'],
35
- * ['name[dogs][]', 'kitty'],
36
- * ]
37
- *
38
- * const payload = deserialize(entities)
39
- *
40
- * expect(payload).toEqual({
41
- * name: 'John Doe',
42
- * pets: { 0: 'dog', 1: 'cat' },
43
- * dogs: ['hello', 'kitty'],
44
- * })
45
- * ```
46
- */
47
- export declare function deserialize(entities: readonly (readonly [string, unknown])[]): Record<string, unknown> | unknown[] | undefined;
48
- /**
49
- * Escape the `[`, `]`, and `\` chars in a path segment.
50
- *
51
- * @example
52
- * ```ts
53
- * expect(escapeSegment('name[pets')).toEqual('name\\[pets')
54
- * ```
55
- */
56
- export declare function escapeSegment(segment: string): string;
57
- /**
58
- * Convert an array of path segments into a path string using bracket-notation.
59
- *
60
- * For the special char `[`, `]`, and `\` will be escaped by adding `\` at start.
61
- *
62
- * @example
63
- * ```ts
64
- * expect(stringifyPath(['name', 'pets', '0'])).toEqual('name[pets][0]')
65
- * ```
66
- */
67
- export declare function stringifyPath(path: readonly [string, ...string[]]): string;
68
- /**
69
- * Convert a path string using bracket-notation into an array of path segments.
70
- *
71
- * For the special char `[`, `]`, and `\` you should escape by adding `\` at start.
72
- * It only treats a pair `[${string}]` as a path segment.
73
- * If missing or escape it will bypass and treat as normal string.
74
- *
75
- * @example
76
- * ```ts
77
- * expect(parsePath('name[pets][0]')).toEqual(['name', 'pets', '0'])
78
- * expect(parsePath('name[pets][0')).toEqual(['name', 'pets', '[0'])
79
- * expect(parsePath('name[pets[0]')).toEqual(['name', 'pets[0')
80
- * expect(parsePath('name\\[pets][0]')).toEqual(['name[pets]', '0'])
81
- * ```
82
- */
83
- export declare function parsePath(path: string): [string, ...string[]];
1
+ import { type Segment } from '@orpc/shared';
2
+ export type BracketNotationSerialized = [string, unknown][];
3
+ export declare class BracketNotationSerializer {
4
+ serialize(data: unknown, segments?: Segment[], result?: BracketNotationSerialized): BracketNotationSerialized;
5
+ deserialize(serialized: BracketNotationSerialized): unknown;
6
+ stringifyPath(segments: readonly Segment[]): string;
7
+ parsePath(path: string): string[];
8
+ }
84
9
  //# sourceMappingURL=bracket-notation.d.ts.map
@@ -1,4 +1,4 @@
1
- export * as BracketNotation from './bracket-notation';
1
+ export * from './bracket-notation';
2
2
  export * from './json-serializer';
3
3
  export * from './serializer';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1,5 +1,7 @@
1
+ export type OpenAPIJsonSerialized = [json: unknown, hasBlob: boolean];
1
2
  export declare class OpenAPIJsonSerializer {
2
- serialize(payload: unknown): unknown;
3
+ serialize(data: unknown, hasBlobRef?: {
4
+ value: boolean;
5
+ }): OpenAPIJsonSerialized;
3
6
  }
4
- export type PublicOpenAPIJsonSerializer = Pick<OpenAPIJsonSerializer, keyof OpenAPIJsonSerializer>;
5
7
  //# sourceMappingURL=json-serializer.d.ts.map
@@ -1,11 +1,11 @@
1
- import type { PublicOpenAPIJsonSerializer } from './json-serializer';
2
- export interface OpenAPISerializerOptions {
3
- jsonSerializer?: PublicOpenAPIJsonSerializer;
4
- }
1
+ import { BracketNotationSerializer } from './bracket-notation';
2
+ import { OpenAPIJsonSerializer } from './json-serializer';
5
3
  export declare class OpenAPISerializer {
4
+ #private;
6
5
  private readonly jsonSerializer;
7
- constructor(options?: OpenAPISerializerOptions);
6
+ private readonly bracketNotation;
7
+ constructor(jsonSerializer?: OpenAPIJsonSerializer, bracketNotation?: BracketNotationSerializer);
8
8
  serialize(data: unknown): unknown;
9
- deserialize(serialized: unknown): unknown;
9
+ deserialize(data: unknown): unknown;
10
10
  }
11
11
  //# sourceMappingURL=serializer.d.ts.map
@@ -1,2 +1,3 @@
1
+ export * from './json-serializer';
1
2
  export * from './serializer';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { type Segment } from '@orpc/shared';
2
+ export type RPCJsonSerializedMeta = [
3
+ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7,
4
+ Segment[]
5
+ ][];
6
+ export type RPCJsonSerialized = [json: unknown, meta: RPCJsonSerializedMeta, maps: Segment[][], blobs: Blob[]];
7
+ export declare class RPCJsonSerializer {
8
+ serialize(data: unknown, segments?: Segment[], meta?: RPCJsonSerializedMeta, maps?: Segment[][], blobs?: Blob[]): RPCJsonSerialized;
9
+ deserialize(json: unknown, meta: RPCJsonSerializedMeta): unknown;
10
+ deserialize(json: unknown, meta: RPCJsonSerializedMeta, maps: Segment[][], getBlob: (index: number) => Blob): unknown;
11
+ }
12
+ //# sourceMappingURL=json-serializer.d.ts.map
@@ -1,22 +1,9 @@
1
- import type { Segment } from '@orpc/shared';
2
- export type RPCSerializedJsonMeta = ['bigint' | 'date' | 'nan' | 'undefined' | 'set' | 'map' | 'regexp' | 'url', Segment[]][];
3
- export type RPCSerialized = {
4
- json: unknown;
5
- meta: RPCSerializedJsonMeta;
6
- } | FormData | AsyncIteratorObject<{
7
- json: unknown;
8
- meta: RPCSerializedJsonMeta;
9
- }, {
10
- json: unknown;
11
- meta: RPCSerializedJsonMeta;
12
- }, void>;
13
- export type RPCSerializedFormDataMaps = Segment[][];
1
+ import { RPCJsonSerializer } from './json-serializer';
14
2
  export declare class RPCSerializer {
15
- serialize(data: unknown): RPCSerialized;
16
- deserialize(serialized: RPCSerialized): unknown;
3
+ #private;
4
+ private readonly jsonSerializer;
5
+ constructor(jsonSerializer?: RPCJsonSerializer);
6
+ serialize(data: unknown): unknown;
7
+ deserialize(data: unknown): unknown;
17
8
  }
18
- export declare function serializeRPCJson(value: unknown, segments?: Segment[], meta?: RPCSerializedJsonMeta): {
19
- json: unknown;
20
- meta: RPCSerializedJsonMeta;
21
- };
22
9
  //# sourceMappingURL=serializer.d.ts.map
@@ -1,5 +1,17 @@
1
1
  import type { ORPCError } from './error';
2
2
  import type { ClientPromiseResult } from './types';
3
- export type SafeResult<TOutput, TError extends Error> = [output: TOutput, error: undefined, isDefinedError: false] | [output: undefined, error: TError, isDefinedError: false] | [output: undefined, error: Extract<TError, ORPCError<any, any>>, isDefinedError: true];
3
+ export type SafeResult<TOutput, TError extends Error> = [error: null, data: TOutput, isDefined: false] & {
4
+ error: null;
5
+ data: TOutput;
6
+ isDefined: false;
7
+ } | [error: Exclude<TError, ORPCError<any, any>>, data: undefined, isDefined: false] & {
8
+ error: Exclude<TError, ORPCError<any, any>>;
9
+ data: undefined;
10
+ isDefined: false;
11
+ } | [error: Extract<TError, ORPCError<any, any>>, data: undefined, isDefined: true] & {
12
+ error: Extract<TError, ORPCError<any, any>>;
13
+ data: undefined;
14
+ isDefined: true;
15
+ };
4
16
  export declare function safe<TOutput, TError extends Error>(promise: ClientPromiseResult<TOutput, TError>): Promise<SafeResult<TOutput, TError>>;
5
17
  //# sourceMappingURL=utils.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@orpc/client",
3
3
  "type": "module",
4
- "version": "0.41.2",
4
+ "version": "0.43.0",
5
5
  "license": "MIT",
6
6
  "homepage": "https://orpc.unnoq.com",
7
7
  "repository": {
@@ -44,9 +44,9 @@
44
44
  "dist"
45
45
  ],
46
46
  "dependencies": {
47
- "@orpc/server-standard": "^0.4.0",
48
- "@orpc/server-standard-fetch": "^0.4.0",
49
- "@orpc/shared": "0.41.2"
47
+ "@orpc/shared": "0.43.0",
48
+ "@orpc/standard-server-fetch": "0.43.0",
49
+ "@orpc/standard-server": "0.43.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "zod": "^3.24.1"
@@ -1,178 +0,0 @@
1
- import {
2
- ORPCError,
3
- mapEventIterator,
4
- toORPCError
5
- } from "./chunk-2UPNYYFF.js";
6
-
7
- // src/rpc/serializer.ts
8
- import { ErrorEvent, isAsyncIteratorObject } from "@orpc/server-standard";
9
- import { findDeepMatches, isObject, set } from "@orpc/shared";
10
- var RPCSerializer = class {
11
- serialize(data) {
12
- if (isAsyncIteratorObject(data)) {
13
- return mapEventIterator(data, {
14
- value: async (value) => serializeRPCJson(value),
15
- error: async (e) => {
16
- if (e instanceof ErrorEvent) {
17
- return new ErrorEvent({
18
- data: serializeRPCJson(e.data),
19
- cause: e
20
- });
21
- }
22
- return new ErrorEvent({
23
- data: serializeRPCJson(toORPCError(e).toJSON()),
24
- cause: e
25
- });
26
- }
27
- });
28
- }
29
- const serializedJSON = serializeRPCJson(data);
30
- const { maps, values: blobs } = findDeepMatches((v) => v instanceof Blob, serializedJSON.json);
31
- if (blobs.length === 0) {
32
- return serializedJSON;
33
- }
34
- const form = new FormData();
35
- form.set("data", JSON.stringify(serializedJSON));
36
- form.set("maps", JSON.stringify(maps));
37
- for (const i in blobs) {
38
- form.set(i, blobs[i]);
39
- }
40
- return form;
41
- }
42
- deserialize(serialized) {
43
- if (isAsyncIteratorObject(serialized)) {
44
- return mapEventIterator(serialized, {
45
- value: async (value) => deserializeRPCJson(value),
46
- error: async (e) => {
47
- if (!(e instanceof ErrorEvent)) {
48
- return e;
49
- }
50
- const deserialized = deserializeRPCJson(e.data);
51
- if (ORPCError.isValidJSON(deserialized)) {
52
- return ORPCError.fromJSON(deserialized, { cause: e });
53
- }
54
- return new ErrorEvent({
55
- data: deserialized,
56
- cause: e
57
- });
58
- }
59
- });
60
- }
61
- if (!(serialized instanceof FormData)) {
62
- return deserializeRPCJson(serialized);
63
- }
64
- const data = JSON.parse(serialized.get("data"));
65
- const maps = JSON.parse(serialized.get("maps"));
66
- for (const i in maps) {
67
- data.json = set(data.json, maps[i], serialized.get(i));
68
- }
69
- return deserializeRPCJson(data);
70
- }
71
- };
72
- function serializeRPCJson(value, segments = [], meta = []) {
73
- if (typeof value === "bigint") {
74
- meta.push(["bigint", segments]);
75
- return { json: value.toString(), meta };
76
- }
77
- if (value instanceof Date) {
78
- meta.push(["date", segments]);
79
- const data = Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
80
- return { json: data, meta };
81
- }
82
- if (Number.isNaN(value)) {
83
- meta.push(["nan", segments]);
84
- return { json: "NaN", meta };
85
- }
86
- if (value instanceof RegExp) {
87
- meta.push(["regexp", segments]);
88
- return { json: value.toString(), meta };
89
- }
90
- if (value instanceof URL) {
91
- meta.push(["url", segments]);
92
- return { json: value.toString(), meta };
93
- }
94
- if (isObject(value)) {
95
- const json = {};
96
- for (const k in value) {
97
- json[k] = serializeRPCJson(value[k], [...segments, k], meta).json;
98
- }
99
- return { json, meta };
100
- }
101
- if (Array.isArray(value)) {
102
- const json = value.map((v, i) => {
103
- if (v === void 0) {
104
- meta.push(["undefined", [...segments, i]]);
105
- return null;
106
- }
107
- return serializeRPCJson(v, [...segments, i], meta).json;
108
- });
109
- return { json, meta };
110
- }
111
- if (value instanceof Set) {
112
- const result = serializeRPCJson(Array.from(value), segments, meta);
113
- meta.push(["set", segments]);
114
- return result;
115
- }
116
- if (value instanceof Map) {
117
- const result = serializeRPCJson(Array.from(value.entries()), segments, meta);
118
- meta.push(["map", segments]);
119
- return result;
120
- }
121
- return { json: value, meta };
122
- }
123
- function deserializeRPCJson({
124
- json,
125
- meta
126
- }) {
127
- if (meta.length === 0) {
128
- return json;
129
- }
130
- const ref = { data: json };
131
- for (const [type, segments] of meta) {
132
- let currentRef = ref;
133
- let preSegment = "data";
134
- for (let i = 0; i < segments.length; i++) {
135
- currentRef = currentRef[preSegment];
136
- preSegment = segments[i];
137
- }
138
- switch (type) {
139
- case "nan":
140
- currentRef[preSegment] = Number.NaN;
141
- break;
142
- case "bigint":
143
- currentRef[preSegment] = BigInt(currentRef[preSegment]);
144
- break;
145
- case "date":
146
- currentRef[preSegment] = new Date(currentRef[preSegment]);
147
- break;
148
- case "regexp": {
149
- const [, pattern, flags] = currentRef[preSegment].match(/^\/(.*)\/([a-z]*)$/);
150
- currentRef[preSegment] = new RegExp(pattern, flags);
151
- break;
152
- }
153
- case "url":
154
- currentRef[preSegment] = new URL(currentRef[preSegment]);
155
- break;
156
- case "undefined":
157
- currentRef[preSegment] = void 0;
158
- break;
159
- case "map":
160
- currentRef[preSegment] = new Map(currentRef[preSegment]);
161
- break;
162
- case "set":
163
- currentRef[preSegment] = new Set(currentRef[preSegment]);
164
- break;
165
- /* v8 ignore next 3 */
166
- default: {
167
- const _expected = type;
168
- }
169
- }
170
- }
171
- return ref.data;
172
- }
173
-
174
- export {
175
- RPCSerializer,
176
- serializeRPCJson
177
- };
178
- //# sourceMappingURL=chunk-TPEMQB7D.js.map