@orpc/openapi 1.14.5 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -109
- package/dist/adapters/fetch/index.d.mts +20 -16
- package/dist/adapters/fetch/index.d.ts +20 -16
- package/dist/adapters/fetch/index.mjs +24 -8
- package/dist/adapters/node/index.d.mts +8 -13
- package/dist/adapters/node/index.d.ts +8 -13
- package/dist/adapters/node/index.mjs +10 -7
- package/dist/adapters/standard/index.d.mts +46 -16
- package/dist/adapters/standard/index.d.ts +46 -16
- package/dist/adapters/standard/index.mjs +9 -6
- package/dist/extensions/route.d.mts +43 -0
- package/dist/extensions/route.d.ts +43 -0
- package/dist/extensions/route.mjs +14 -0
- package/dist/helpers/index.d.mts +51 -0
- package/dist/helpers/index.d.ts +51 -0
- package/dist/helpers/index.mjs +39 -0
- package/dist/index.d.mts +92 -111
- package/dist/index.d.ts +92 -111
- package/dist/index.mjs +894 -34
- package/dist/plugins/index.d.mts +55 -51
- package/dist/plugins/index.d.ts +55 -51
- package/dist/plugins/index.mjs +147 -142
- package/dist/shared/openapi.B2SK0ZAr.mjs +359 -0
- package/dist/shared/openapi.B9PQzqBn.mjs +49 -0
- package/dist/shared/openapi.BQzzr4-4.d.ts +299 -0
- package/dist/shared/openapi.BcEtAxQj.d.mts +299 -0
- package/dist/shared/openapi.Bt87OzTt.mjs +131 -0
- package/dist/shared/openapi.C7m7NAmH.d.mts +142 -0
- package/dist/shared/openapi.C7m7NAmH.d.ts +142 -0
- package/dist/shared/openapi.C9Olbxd5.d.ts +75 -0
- package/dist/shared/openapi.CYgMBSUF.d.mts +18 -0
- package/dist/shared/openapi.CYgMBSUF.d.ts +18 -0
- package/dist/shared/openapi.CcyUEuTs.mjs +313 -0
- package/dist/shared/openapi.DmAa7YPO.mjs +275 -0
- package/dist/shared/openapi.Drd1OtzG.d.mts +75 -0
- package/package.json +29 -23
- package/dist/adapters/aws-lambda/index.d.mts +0 -20
- package/dist/adapters/aws-lambda/index.d.ts +0 -20
- package/dist/adapters/aws-lambda/index.mjs +0 -18
- package/dist/adapters/fastify/index.d.mts +0 -23
- package/dist/adapters/fastify/index.d.ts +0 -23
- package/dist/adapters/fastify/index.mjs +0 -18
- package/dist/shared/openapi.BB-W-NKv.mjs +0 -204
- package/dist/shared/openapi.BGy4N6eR.d.mts +0 -120
- package/dist/shared/openapi.BGy4N6eR.d.ts +0 -120
- package/dist/shared/openapi.BwdtJjDu.mjs +0 -878
- package/dist/shared/openapi.DwaweYRb.d.mts +0 -54
- package/dist/shared/openapi.DwaweYRb.d.ts +0 -54
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { isPlainObject, NullProtoObj } from '@orpc/shared';
|
|
2
|
+
|
|
3
|
+
class BracketNotationSerializer {
|
|
4
|
+
maxExplicitDeserializingArrayIndex;
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.maxExplicitDeserializingArrayIndex = options.maxExplicitDeserializingArrayIndex ?? 999;
|
|
7
|
+
}
|
|
8
|
+
serialize(data) {
|
|
9
|
+
return this.internalSerialize(data, [], []);
|
|
10
|
+
}
|
|
11
|
+
internalSerialize(data, segments, result) {
|
|
12
|
+
if (Array.isArray(data)) {
|
|
13
|
+
data.forEach((item, i) => {
|
|
14
|
+
this.internalSerialize(item, [...segments, i], result);
|
|
15
|
+
});
|
|
16
|
+
} else if (isPlainObject(data)) {
|
|
17
|
+
for (const key in data) {
|
|
18
|
+
this.internalSerialize(data[key], [...segments, key], result);
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
result.push([this.stringifyPath(segments), data]);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
deserialize(serialized) {
|
|
26
|
+
if (serialized.length === 0) {
|
|
27
|
+
return new NullProtoObj();
|
|
28
|
+
}
|
|
29
|
+
const arrayPushStyles = /* @__PURE__ */ new WeakSet();
|
|
30
|
+
const ref = { value: new NullProtoObj() };
|
|
31
|
+
for (const [path, value] of serialized) {
|
|
32
|
+
const segments = this.parsePath(path);
|
|
33
|
+
let currentRef = ref;
|
|
34
|
+
let nextSegment = "value";
|
|
35
|
+
segments.forEach((segment, i) => {
|
|
36
|
+
if (!Array.isArray(currentRef[nextSegment]) && !isPlainObject(currentRef[nextSegment])) {
|
|
37
|
+
currentRef[nextSegment] = [];
|
|
38
|
+
}
|
|
39
|
+
if (i !== segments.length - 1) {
|
|
40
|
+
if (Array.isArray(currentRef[nextSegment]) && !internalIsValidArrayIndex(segment, this.maxExplicitDeserializingArrayIndex)) {
|
|
41
|
+
if (arrayPushStyles.has(currentRef[nextSegment])) {
|
|
42
|
+
arrayPushStyles.delete(currentRef[nextSegment]);
|
|
43
|
+
currentRef[nextSegment] = internalPushStyleArrayToObject(currentRef[nextSegment]);
|
|
44
|
+
} else {
|
|
45
|
+
currentRef[nextSegment] = internalArrayToObject(currentRef[nextSegment]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
if (Array.isArray(currentRef[nextSegment])) {
|
|
50
|
+
if (segment === "") {
|
|
51
|
+
if (currentRef[nextSegment].length && !arrayPushStyles.has(currentRef[nextSegment])) {
|
|
52
|
+
currentRef[nextSegment] = internalArrayToObject(currentRef[nextSegment]);
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
if (arrayPushStyles.has(currentRef[nextSegment])) {
|
|
56
|
+
arrayPushStyles.delete(currentRef[nextSegment]);
|
|
57
|
+
currentRef[nextSegment] = internalPushStyleArrayToObject(currentRef[nextSegment]);
|
|
58
|
+
} else if (!internalIsValidArrayIndex(segment, this.maxExplicitDeserializingArrayIndex)) {
|
|
59
|
+
currentRef[nextSegment] = internalArrayToObject(currentRef[nextSegment]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
currentRef = currentRef[nextSegment];
|
|
65
|
+
nextSegment = segment;
|
|
66
|
+
});
|
|
67
|
+
if (Array.isArray(currentRef) && nextSegment === "") {
|
|
68
|
+
arrayPushStyles.add(currentRef);
|
|
69
|
+
currentRef.push(value);
|
|
70
|
+
} else if (nextSegment in currentRef) {
|
|
71
|
+
if (Array.isArray(currentRef[nextSegment])) {
|
|
72
|
+
currentRef[nextSegment].push(value);
|
|
73
|
+
} else {
|
|
74
|
+
currentRef[nextSegment] = [currentRef[nextSegment], value];
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
currentRef[nextSegment] = value;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return ref.value;
|
|
81
|
+
}
|
|
82
|
+
stringifyPath(segments) {
|
|
83
|
+
return segments.reduce((result, segment, i) => {
|
|
84
|
+
if (i === 0) {
|
|
85
|
+
return segment.toString();
|
|
86
|
+
}
|
|
87
|
+
return `${result}[${segment}]`;
|
|
88
|
+
}, "");
|
|
89
|
+
}
|
|
90
|
+
parsePath(path) {
|
|
91
|
+
const segments = [];
|
|
92
|
+
let inBrackets = false;
|
|
93
|
+
let currentSegment = "";
|
|
94
|
+
for (let i = 0; i < path.length; i++) {
|
|
95
|
+
const char = path[i];
|
|
96
|
+
const nextChar = path[i + 1];
|
|
97
|
+
if (inBrackets && char === "]" && (nextChar === void 0 || nextChar === "[")) {
|
|
98
|
+
if (nextChar === void 0) {
|
|
99
|
+
inBrackets = false;
|
|
100
|
+
}
|
|
101
|
+
segments.push(currentSegment);
|
|
102
|
+
currentSegment = "";
|
|
103
|
+
i++;
|
|
104
|
+
} else if (segments.length === 0 && char === "[") {
|
|
105
|
+
inBrackets = true;
|
|
106
|
+
segments.push(currentSegment);
|
|
107
|
+
currentSegment = "";
|
|
108
|
+
} else {
|
|
109
|
+
currentSegment += char;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return inBrackets || segments.length === 0 ? [path] : segments;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function internalIsValidArrayIndex(value, maxIndex) {
|
|
116
|
+
return /^0$|^[1-9]\d*$/.test(value) && Number(value) <= maxIndex;
|
|
117
|
+
}
|
|
118
|
+
function internalArrayToObject(array) {
|
|
119
|
+
const obj = new NullProtoObj();
|
|
120
|
+
array.forEach((item, i) => {
|
|
121
|
+
obj[i] = item;
|
|
122
|
+
});
|
|
123
|
+
return obj;
|
|
124
|
+
}
|
|
125
|
+
function internalPushStyleArrayToObject(array) {
|
|
126
|
+
const obj = new NullProtoObj();
|
|
127
|
+
obj[""] = array.length === 1 ? array[0] : array;
|
|
128
|
+
return obj;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { BracketNotationSerializer as B };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { StandardBody } from '@standardserver/core';
|
|
2
|
+
import { Segment } from '@orpc/shared';
|
|
3
|
+
|
|
4
|
+
type BracketNotationSerializeResult = [string, unknown][];
|
|
5
|
+
interface BracketNotationSerializerOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Maximum explicit array index allowed during deserialization (e.g., `arr[0]`, `arr[999]`).
|
|
8
|
+
* If the index exceeds this limit, the array is deserialized as an object instead.
|
|
9
|
+
*
|
|
10
|
+
* This guards against memory exhaustion attacks where malicious input uses extremely large
|
|
11
|
+
* indices (e.g., `?arr[4294967296]=value`). Although orpc uses sparse arrays handle large indices
|
|
12
|
+
* efficiently, downstream code may inadvertently densify them - creating millions of
|
|
13
|
+
* undefined slots and exhausting memory.
|
|
14
|
+
*
|
|
15
|
+
* NOTE: Does not apply to append-style notation (e.g., `arr[]`).
|
|
16
|
+
*
|
|
17
|
+
* @default 999 (array with 1,000 elements)
|
|
18
|
+
*/
|
|
19
|
+
maxExplicitDeserializingArrayIndex?: number;
|
|
20
|
+
}
|
|
21
|
+
declare class BracketNotationSerializer {
|
|
22
|
+
private readonly maxExplicitDeserializingArrayIndex;
|
|
23
|
+
constructor(options?: BracketNotationSerializerOptions);
|
|
24
|
+
serialize(data: unknown): BracketNotationSerializeResult;
|
|
25
|
+
private internalSerialize;
|
|
26
|
+
deserialize(serialized: BracketNotationSerializeResult): Record<string, unknown>;
|
|
27
|
+
stringifyPath(segments: readonly Segment[]): string;
|
|
28
|
+
parsePath(path: string): string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type OpenAPIJsonSerialization = {
|
|
32
|
+
json: unknown;
|
|
33
|
+
maps?: undefined;
|
|
34
|
+
blobs?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
json: unknown;
|
|
37
|
+
maps: Segment[][];
|
|
38
|
+
blobs: Blob[];
|
|
39
|
+
};
|
|
40
|
+
interface OpenAPIJsonSerializerHandler {
|
|
41
|
+
condition(value: unknown): boolean;
|
|
42
|
+
serialize(value: any): unknown;
|
|
43
|
+
/**
|
|
44
|
+
* If false, the result of this serializer will not be further processed by other serializers,
|
|
45
|
+
* even if it matches their conditions and treat it as final serialized value.
|
|
46
|
+
* This can be useful for serializers that return primitive values, which should not be further processed.
|
|
47
|
+
* to improve performance and avoid potential issues with other serializers.
|
|
48
|
+
*
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
isTerminal?: boolean;
|
|
52
|
+
}
|
|
53
|
+
interface OpenAPIJsonSerializerOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Extend or override the built-in type handlers used during serialization.
|
|
56
|
+
*
|
|
57
|
+
* Each key is a unique type identifier (e.g. `"date"`, `"bigint"`) and maps to a handler
|
|
58
|
+
* that defines how to detect and serialize values of that type.
|
|
59
|
+
*
|
|
60
|
+
* **Extending:** Add new keys to support custom types:
|
|
61
|
+
* ```ts
|
|
62
|
+
* handlers: {
|
|
63
|
+
* buffer: {
|
|
64
|
+
* condition: (v) => v instanceof Buffer,
|
|
65
|
+
* serialize: (v: Buffer) => v.toString('base64'),
|
|
66
|
+
* isTerminal: true,
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* **Overriding:** Use an existing key to replace a built-in handler:
|
|
72
|
+
* ```ts
|
|
73
|
+
* handlers: {
|
|
74
|
+
* date: {
|
|
75
|
+
* condition: (v) => v instanceof Date,
|
|
76
|
+
* serialize: (v: Date) => v.getTime(),
|
|
77
|
+
* isTerminal: true,
|
|
78
|
+
* }
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* **Disabling:** Set a key to `undefined` to remove a built-in handler:
|
|
83
|
+
* ```ts
|
|
84
|
+
* handlers: { regexp: undefined }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
|
|
88
|
+
*/
|
|
89
|
+
handlers?: Record<string, undefined | OpenAPIJsonSerializerHandler> | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* If true, properties with undefined values will be omitted during serialization.
|
|
92
|
+
*
|
|
93
|
+
* @default true
|
|
94
|
+
*/
|
|
95
|
+
omitUndefinedProperties?: boolean | undefined;
|
|
96
|
+
}
|
|
97
|
+
declare class OpenAPIJsonSerializer {
|
|
98
|
+
private readonly handlers;
|
|
99
|
+
private readonly omitUndefinedProperties;
|
|
100
|
+
constructor(options?: OpenAPIJsonSerializerOptions);
|
|
101
|
+
serialize(data: unknown): OpenAPIJsonSerialization;
|
|
102
|
+
private serializeValue;
|
|
103
|
+
deserialize(serialized: OpenAPIJsonSerialization): unknown;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface OpenAPISerializerSerializeOptions {
|
|
107
|
+
/**
|
|
108
|
+
* Use FormData for serialization when nested blobs are present.
|
|
109
|
+
* Does not apply to root-level Blob values.
|
|
110
|
+
*
|
|
111
|
+
* @default true
|
|
112
|
+
*/
|
|
113
|
+
useFormDataForBlobFields?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* When enabled, the serialized output is always returned as a FormData instance using bracket notation.
|
|
116
|
+
*
|
|
117
|
+
* @default false
|
|
118
|
+
*/
|
|
119
|
+
asFormData?: boolean | undefined;
|
|
120
|
+
}
|
|
121
|
+
interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPISerializerSerializeOptions {
|
|
122
|
+
/**
|
|
123
|
+
* Options for bracket notation serializer, like maxExplicitDeserializingArrayIndex
|
|
124
|
+
*/
|
|
125
|
+
bracketNotation?: BracketNotationSerializerOptions | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Default options for serialize method
|
|
128
|
+
*/
|
|
129
|
+
serialize?: OpenAPISerializerSerializeOptions | undefined;
|
|
130
|
+
}
|
|
131
|
+
declare class OpenAPISerializer {
|
|
132
|
+
private readonly jsonSerializer;
|
|
133
|
+
private readonly bracketNotation;
|
|
134
|
+
private readonly defaultSerializeOptions;
|
|
135
|
+
constructor({ bracketNotation, serialize, ...options }?: OpenAPISerializerOptions);
|
|
136
|
+
serialize(data: unknown, options?: OpenAPISerializerSerializeOptions): StandardBody;
|
|
137
|
+
private serializeValue;
|
|
138
|
+
deserialize(data: StandardBody): unknown;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { OpenAPISerializer as O, BracketNotationSerializer as a, OpenAPIJsonSerializer as d };
|
|
142
|
+
export type { BracketNotationSerializeResult as B, BracketNotationSerializerOptions as b, OpenAPIJsonSerialization as c, OpenAPIJsonSerializerHandler as e, OpenAPIJsonSerializerOptions as f, OpenAPISerializerOptions as g, OpenAPISerializerSerializeOptions as h };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { StandardBody } from '@standardserver/core';
|
|
2
|
+
import { Segment } from '@orpc/shared';
|
|
3
|
+
|
|
4
|
+
type BracketNotationSerializeResult = [string, unknown][];
|
|
5
|
+
interface BracketNotationSerializerOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Maximum explicit array index allowed during deserialization (e.g., `arr[0]`, `arr[999]`).
|
|
8
|
+
* If the index exceeds this limit, the array is deserialized as an object instead.
|
|
9
|
+
*
|
|
10
|
+
* This guards against memory exhaustion attacks where malicious input uses extremely large
|
|
11
|
+
* indices (e.g., `?arr[4294967296]=value`). Although orpc uses sparse arrays handle large indices
|
|
12
|
+
* efficiently, downstream code may inadvertently densify them - creating millions of
|
|
13
|
+
* undefined slots and exhausting memory.
|
|
14
|
+
*
|
|
15
|
+
* NOTE: Does not apply to append-style notation (e.g., `arr[]`).
|
|
16
|
+
*
|
|
17
|
+
* @default 999 (array with 1,000 elements)
|
|
18
|
+
*/
|
|
19
|
+
maxExplicitDeserializingArrayIndex?: number;
|
|
20
|
+
}
|
|
21
|
+
declare class BracketNotationSerializer {
|
|
22
|
+
private readonly maxExplicitDeserializingArrayIndex;
|
|
23
|
+
constructor(options?: BracketNotationSerializerOptions);
|
|
24
|
+
serialize(data: unknown): BracketNotationSerializeResult;
|
|
25
|
+
private internalSerialize;
|
|
26
|
+
deserialize(serialized: BracketNotationSerializeResult): Record<string, unknown>;
|
|
27
|
+
stringifyPath(segments: readonly Segment[]): string;
|
|
28
|
+
parsePath(path: string): string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type OpenAPIJsonSerialization = {
|
|
32
|
+
json: unknown;
|
|
33
|
+
maps?: undefined;
|
|
34
|
+
blobs?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
json: unknown;
|
|
37
|
+
maps: Segment[][];
|
|
38
|
+
blobs: Blob[];
|
|
39
|
+
};
|
|
40
|
+
interface OpenAPIJsonSerializerHandler {
|
|
41
|
+
condition(value: unknown): boolean;
|
|
42
|
+
serialize(value: any): unknown;
|
|
43
|
+
/**
|
|
44
|
+
* If false, the result of this serializer will not be further processed by other serializers,
|
|
45
|
+
* even if it matches their conditions and treat it as final serialized value.
|
|
46
|
+
* This can be useful for serializers that return primitive values, which should not be further processed.
|
|
47
|
+
* to improve performance and avoid potential issues with other serializers.
|
|
48
|
+
*
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
isTerminal?: boolean;
|
|
52
|
+
}
|
|
53
|
+
interface OpenAPIJsonSerializerOptions {
|
|
54
|
+
/**
|
|
55
|
+
* Extend or override the built-in type handlers used during serialization.
|
|
56
|
+
*
|
|
57
|
+
* Each key is a unique type identifier (e.g. `"date"`, `"bigint"`) and maps to a handler
|
|
58
|
+
* that defines how to detect and serialize values of that type.
|
|
59
|
+
*
|
|
60
|
+
* **Extending:** Add new keys to support custom types:
|
|
61
|
+
* ```ts
|
|
62
|
+
* handlers: {
|
|
63
|
+
* buffer: {
|
|
64
|
+
* condition: (v) => v instanceof Buffer,
|
|
65
|
+
* serialize: (v: Buffer) => v.toString('base64'),
|
|
66
|
+
* isTerminal: true,
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* **Overriding:** Use an existing key to replace a built-in handler:
|
|
72
|
+
* ```ts
|
|
73
|
+
* handlers: {
|
|
74
|
+
* date: {
|
|
75
|
+
* condition: (v) => v instanceof Date,
|
|
76
|
+
* serialize: (v: Date) => v.getTime(),
|
|
77
|
+
* isTerminal: true,
|
|
78
|
+
* }
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* **Disabling:** Set a key to `undefined` to remove a built-in handler:
|
|
83
|
+
* ```ts
|
|
84
|
+
* handlers: { regexp: undefined }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* Built-in type keys: `undefined`, `bigint`, `date`, `nan`, `url`, `regexp`, `set`, `map`.
|
|
88
|
+
*/
|
|
89
|
+
handlers?: Record<string, undefined | OpenAPIJsonSerializerHandler> | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* If true, properties with undefined values will be omitted during serialization.
|
|
92
|
+
*
|
|
93
|
+
* @default true
|
|
94
|
+
*/
|
|
95
|
+
omitUndefinedProperties?: boolean | undefined;
|
|
96
|
+
}
|
|
97
|
+
declare class OpenAPIJsonSerializer {
|
|
98
|
+
private readonly handlers;
|
|
99
|
+
private readonly omitUndefinedProperties;
|
|
100
|
+
constructor(options?: OpenAPIJsonSerializerOptions);
|
|
101
|
+
serialize(data: unknown): OpenAPIJsonSerialization;
|
|
102
|
+
private serializeValue;
|
|
103
|
+
deserialize(serialized: OpenAPIJsonSerialization): unknown;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
interface OpenAPISerializerSerializeOptions {
|
|
107
|
+
/**
|
|
108
|
+
* Use FormData for serialization when nested blobs are present.
|
|
109
|
+
* Does not apply to root-level Blob values.
|
|
110
|
+
*
|
|
111
|
+
* @default true
|
|
112
|
+
*/
|
|
113
|
+
useFormDataForBlobFields?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* When enabled, the serialized output is always returned as a FormData instance using bracket notation.
|
|
116
|
+
*
|
|
117
|
+
* @default false
|
|
118
|
+
*/
|
|
119
|
+
asFormData?: boolean | undefined;
|
|
120
|
+
}
|
|
121
|
+
interface OpenAPISerializerOptions extends OpenAPIJsonSerializerOptions, OpenAPISerializerSerializeOptions {
|
|
122
|
+
/**
|
|
123
|
+
* Options for bracket notation serializer, like maxExplicitDeserializingArrayIndex
|
|
124
|
+
*/
|
|
125
|
+
bracketNotation?: BracketNotationSerializerOptions | undefined;
|
|
126
|
+
/**
|
|
127
|
+
* Default options for serialize method
|
|
128
|
+
*/
|
|
129
|
+
serialize?: OpenAPISerializerSerializeOptions | undefined;
|
|
130
|
+
}
|
|
131
|
+
declare class OpenAPISerializer {
|
|
132
|
+
private readonly jsonSerializer;
|
|
133
|
+
private readonly bracketNotation;
|
|
134
|
+
private readonly defaultSerializeOptions;
|
|
135
|
+
constructor({ bracketNotation, serialize, ...options }?: OpenAPISerializerOptions);
|
|
136
|
+
serialize(data: unknown, options?: OpenAPISerializerSerializeOptions): StandardBody;
|
|
137
|
+
private serializeValue;
|
|
138
|
+
deserialize(data: StandardBody): unknown;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { OpenAPISerializer as O, BracketNotationSerializer as a, OpenAPIJsonSerializer as d };
|
|
142
|
+
export type { BracketNotationSerializeResult as B, BracketNotationSerializerOptions as b, OpenAPIJsonSerialization as c, OpenAPIJsonSerializerHandler as e, OpenAPIJsonSerializerOptions as f, OpenAPISerializerOptions as g, OpenAPISerializerSerializeOptions as h };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AnyORPCError } from '@orpc/client';
|
|
2
|
+
import { AnyProcedure, AnyRouter, Context } from '@orpc/server';
|
|
3
|
+
import { StandardHandlerCodec, StandardHandlerHandleOptions, StandardHandlerCodecResolvedProcedure } from '@orpc/server/standard';
|
|
4
|
+
import { Value, Promisable } from '@orpc/shared';
|
|
5
|
+
import { StandardLazyRequest, StandardResponse } from '@standardserver/core';
|
|
6
|
+
import { AnyProcedureContract } from '@orpc/contract';
|
|
7
|
+
import { O as OpenAPISerializer } from './openapi.C7m7NAmH.js';
|
|
8
|
+
|
|
9
|
+
interface OpenAPIMatcherOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Filter which procedures are exposed for matching. Return `false` to exclude.
|
|
12
|
+
*
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
filter?: Value<boolean, [contract: AnyProcedureContract | AnyProcedure, path: string[]]>;
|
|
16
|
+
}
|
|
17
|
+
declare class OpenAPIMatcher {
|
|
18
|
+
private readonly filter;
|
|
19
|
+
private readonly rootRouter;
|
|
20
|
+
private readonly tree;
|
|
21
|
+
private pendingLazyRouters;
|
|
22
|
+
constructor(router: AnyRouter, options?: OpenAPIMatcherOptions);
|
|
23
|
+
private index;
|
|
24
|
+
match(method: string, pathname: `/${string}`, prefix: `/${string}` | undefined): Promise<{
|
|
25
|
+
path: string[];
|
|
26
|
+
procedure: AnyProcedure;
|
|
27
|
+
params?: Record<string, string> | undefined;
|
|
28
|
+
} | undefined>;
|
|
29
|
+
private matchPathname;
|
|
30
|
+
private resolvePendingLazyRouters;
|
|
31
|
+
private resolveProcedure;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declare class OpenAPIHandlerCodecError extends TypeError {
|
|
35
|
+
}
|
|
36
|
+
interface OpenAPIHandlerCodecOptions<_T extends Context> extends OpenAPIMatcherOptions {
|
|
37
|
+
/**
|
|
38
|
+
* Override the default OpenAPI serializer.
|
|
39
|
+
*/
|
|
40
|
+
serializer?: Pick<OpenAPISerializer, keyof OpenAPISerializer>;
|
|
41
|
+
/**
|
|
42
|
+
* Mapping ORPCError Code -> HTTP Status Code
|
|
43
|
+
*
|
|
44
|
+
* @default COMMON_ERROR_STATUS_MAP, DEFAULT_ERROR_STATUS
|
|
45
|
+
*/
|
|
46
|
+
errorStatusMap?: Record<string, number> | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Customize how an ORPC error is serialized into a response body.
|
|
49
|
+
* Use this if your API needs a different error output structure.
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* - Return `null | undefined` to fallback to default behavior
|
|
53
|
+
*
|
|
54
|
+
* @default ((e) => e.toJSON())
|
|
55
|
+
*/
|
|
56
|
+
customErrorResponseBodyEncoder?: (error: AnyORPCError) => unknown;
|
|
57
|
+
}
|
|
58
|
+
declare class OpenAPIHandlerCodec<T extends Context> implements StandardHandlerCodec<T> {
|
|
59
|
+
private readonly matcher;
|
|
60
|
+
private readonly serializer;
|
|
61
|
+
private readonly errorStatusMap;
|
|
62
|
+
private readonly customErrorResponseBodySerializer;
|
|
63
|
+
constructor(router: AnyRouter, options?: OpenAPIHandlerCodecOptions<T>);
|
|
64
|
+
resolveProcedure(request: StandardLazyRequest, options: StandardHandlerHandleOptions<T>): Promise<StandardHandlerCodecResolvedProcedure | undefined>;
|
|
65
|
+
/**
|
|
66
|
+
* @throws {Error} If `outputStructure` is "detailed" and the output doesn't match the expected structure.
|
|
67
|
+
*/
|
|
68
|
+
encodeOutput(output: unknown, procedure: AnyProcedure, path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
69
|
+
encodeError(error: AnyORPCError, _procedure: AnyProcedure, _path: string[], _options: StandardHandlerHandleOptions<T>): Promisable<StandardResponse>;
|
|
70
|
+
private deserializeQuery;
|
|
71
|
+
private deserializeParams;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { OpenAPIHandlerCodec as a, OpenAPIHandlerCodecError as b, OpenAPIMatcher as c };
|
|
75
|
+
export type { OpenAPIHandlerCodecOptions as O, OpenAPIMatcherOptions as d };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OpenAPIV3_1 } from '@hey-api/spec-types';
|
|
2
|
+
import { ORPCError, AnyNestedClient, Client } from '@orpc/client';
|
|
3
|
+
|
|
4
|
+
type OpenAPIDocument = OpenAPIV3_1.Document;
|
|
5
|
+
type OpenAPIOperationObject = OpenAPIV3_1.OperationObject;
|
|
6
|
+
type JsonifiedValue<T> = T extends string ? T : T extends number ? T : T extends boolean ? T : T extends null ? T : T extends undefined ? T : T extends Array<unknown> ? JsonifiedArray<T> : T extends Record<string, unknown> ? {
|
|
7
|
+
[K in keyof T]: JsonifiedValue<T[K]>;
|
|
8
|
+
} : T extends Date ? string : T extends bigint ? string : T extends File ? File : T extends Blob ? Blob : T extends RegExp ? string : T extends URL ? string : T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]> : T extends Set<infer U> ? JsonifiedArray<U[]> : T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>> : unknown;
|
|
9
|
+
type JsonifiedArray<T extends Array<unknown>> = T extends readonly [] ? [] : T extends readonly [infer U, ...infer V] ? [U extends undefined ? null : JsonifiedValue<U>, ...JsonifiedArray<V>] : T extends Array<infer U> ? Array<JsonifiedValue<U>> : unknown;
|
|
10
|
+
type JsonifiedClientError<T> = T extends ORPCError<infer UCode, infer UData> ? ORPCError<UCode, JsonifiedValue<UData>> : T;
|
|
11
|
+
/**
|
|
12
|
+
* Convert types that JSON not support to corresponding json types
|
|
13
|
+
*/
|
|
14
|
+
type JsonifiedClient<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Client<UClientContext, UInput, JsonifiedValue<UOutput>, JsonifiedClientError<UError>> : {
|
|
15
|
+
[K in keyof T]: T[K] extends AnyNestedClient ? JsonifiedClient<T[K]> : T[K];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type { JsonifiedValue as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedClientError as b, JsonifiedClient as c, JsonifiedArray as d };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OpenAPIV3_1 } from '@hey-api/spec-types';
|
|
2
|
+
import { ORPCError, AnyNestedClient, Client } from '@orpc/client';
|
|
3
|
+
|
|
4
|
+
type OpenAPIDocument = OpenAPIV3_1.Document;
|
|
5
|
+
type OpenAPIOperationObject = OpenAPIV3_1.OperationObject;
|
|
6
|
+
type JsonifiedValue<T> = T extends string ? T : T extends number ? T : T extends boolean ? T : T extends null ? T : T extends undefined ? T : T extends Array<unknown> ? JsonifiedArray<T> : T extends Record<string, unknown> ? {
|
|
7
|
+
[K in keyof T]: JsonifiedValue<T[K]>;
|
|
8
|
+
} : T extends Date ? string : T extends bigint ? string : T extends File ? File : T extends Blob ? Blob : T extends RegExp ? string : T extends URL ? string : T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]> : T extends Set<infer U> ? JsonifiedArray<U[]> : T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>> : unknown;
|
|
9
|
+
type JsonifiedArray<T extends Array<unknown>> = T extends readonly [] ? [] : T extends readonly [infer U, ...infer V] ? [U extends undefined ? null : JsonifiedValue<U>, ...JsonifiedArray<V>] : T extends Array<infer U> ? Array<JsonifiedValue<U>> : unknown;
|
|
10
|
+
type JsonifiedClientError<T> = T extends ORPCError<infer UCode, infer UData> ? ORPCError<UCode, JsonifiedValue<UData>> : T;
|
|
11
|
+
/**
|
|
12
|
+
* Convert types that JSON not support to corresponding json types
|
|
13
|
+
*/
|
|
14
|
+
type JsonifiedClient<T extends AnyNestedClient> = T extends Client<infer UClientContext, infer UInput, infer UOutput, infer UError> ? Client<UClientContext, UInput, JsonifiedValue<UOutput>, JsonifiedClientError<UError>> : {
|
|
15
|
+
[K in keyof T]: T[K] extends AnyNestedClient ? JsonifiedClient<T[K]> : T[K];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type { JsonifiedValue as J, OpenAPIOperationObject as O, OpenAPIDocument as a, JsonifiedClientError as b, JsonifiedClient as c, JsonifiedArray as d };
|