@orpc/openapi 2.0.0-beta.20 → 2.0.0-beta.22
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 +5 -5
- package/dist/adapters/fetch/index.d.mts +3 -3
- package/dist/adapters/fetch/index.d.ts +3 -3
- package/dist/adapters/fetch/index.mjs +4 -4
- package/dist/adapters/node/index.d.mts +2 -2
- package/dist/adapters/node/index.d.ts +2 -2
- package/dist/adapters/node/index.mjs +3 -3
- package/dist/adapters/standard/index.d.mts +10 -46
- package/dist/adapters/standard/index.d.ts +10 -46
- package/dist/adapters/standard/index.mjs +4 -4
- package/dist/extensions/route.d.mts +2 -2
- package/dist/extensions/route.d.ts +2 -2
- package/dist/helpers/index.mjs +1 -1
- package/dist/index.d.mts +13 -8
- package/dist/index.d.ts +13 -8
- package/dist/index.mjs +43 -106
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/shared/{openapi.zZH_UksW.mjs → openapi.0yE-t1W-.mjs} +113 -38
- package/dist/shared/{openapi.C-p_Q2lb.mjs → openapi.B48raJ3F.mjs} +6 -5
- package/dist/shared/openapi.BWJ1qv3c.d.ts +47 -0
- package/dist/shared/{openapi.CVgUshDP.mjs → openapi.BaqI61Xi.mjs} +88 -39
- package/dist/shared/{openapi.ByT4oUeY.d.mts → openapi.Bsz7d8xx.d.mts} +1 -1
- package/dist/shared/{openapi.ByT4oUeY.d.ts → openapi.Bsz7d8xx.d.ts} +1 -1
- package/dist/shared/{openapi.hg_rhZ4x.d.mts → openapi.COG_72WY.d.mts} +1 -1
- package/dist/shared/openapi.CTxN9oam.d.mts +47 -0
- package/dist/shared/{openapi.B6hEbRyF.d.ts → openapi.D7Fpk6aV.d.ts} +5 -3
- package/dist/shared/{openapi.BOOA-bde.d.mts → openapi.DBFXInk5.d.mts} +6 -1
- package/dist/shared/{openapi.BOOA-bde.d.ts → openapi.DBFXInk5.d.ts} +6 -1
- package/dist/shared/{openapi.BafbB3uM.d.mts → openapi.Dam82YDK.d.mts} +5 -3
- package/dist/shared/{openapi.DNNo0V-l.d.ts → openapi.Du7gMjyF.d.ts} +1 -1
- package/dist/shared/{openapi.Bt87OzTt.mjs → openapi.s_p5sN-P.mjs} +20 -15
- package/package.json +10 -10
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export { B as BracketNotationSerializer } from './shared/openapi.
|
|
1
|
+
export { B as BracketNotationSerializer } from './shared/openapi.s_p5sN-P.mjs';
|
|
2
2
|
import { createContractClientFactory, getAsyncIteratorObjectSchemaDetails, ProcedureContract, resolveMetaPlugins } from '@orpc/contract';
|
|
3
|
-
import { D as DEFAULT_OPENAPI_METHOD, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, c as DEFAULT_OPENAPI_SUCCESS_DESCRIPTION, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE, i as isBodylessMethod, O as OpenAPISerializer, g as getDynamicPathParams } from './shared/openapi.
|
|
4
|
-
export { d as OpenAPIJsonSerializer } from './shared/openapi.
|
|
3
|
+
import { D as DEFAULT_OPENAPI_METHOD, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, c as DEFAULT_OPENAPI_SUCCESS_DESCRIPTION, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE, i as isBodylessMethod, O as OpenAPISerializer, g as getDynamicPathParams } from './shared/openapi.0yE-t1W-.mjs';
|
|
4
|
+
export { d as OpenAPIJsonSerializer } from './shared/openapi.0yE-t1W-.mjs';
|
|
5
5
|
import { g as getOpenAPIMeta, o as openapi } from './shared/openapi.B9PQzqBn.mjs';
|
|
6
6
|
import { COMMON_ERROR_STATUS_MAP } from '@orpc/client';
|
|
7
7
|
export { COMMON_ERROR_STATUS_MAP } from '@orpc/client';
|
|
8
|
-
import { encodeJsonPointerSegment, ensureJsonSchemaObject, mapJsonSchemaRefs,
|
|
8
|
+
import { encodeJsonPointerSegment, ensureJsonSchemaObject, mapJsonSchemaRefs, decodeJsonPointerSegment, isUnconstrainedSchema, combineJsonSchemasWithComposition, extractJsonObjectSchemaEntries, combineJsonObjectSchemaEntries, flattenJsonUnionSchema, isJsonPrimitiveSchema, matchArrayableJsonSchema, isJsonFileSchema, DelegatingJsonSchemaConverter, StandardJsonSchemaConverter } from '@orpc/json-schema';
|
|
9
9
|
import { DEFAULT_SUCCESS_STATUS, DEFAULT_ERROR_STATUS, walkProcedureContractsAsync } from '@orpc/server';
|
|
10
|
-
import {
|
|
10
|
+
import { isDeepEqual, value, findDeepMatches, isPlainObject, stringifyJSON, toArray, clone, pathToHttpPath, mergeHttpPath, isTypescriptObject } from '@orpc/shared';
|
|
11
11
|
import '@standardserver/core';
|
|
12
12
|
|
|
13
13
|
function createContractJsonifiedClientFactory(link, options = {}) {
|
|
@@ -15,14 +15,13 @@ function createContractJsonifiedClientFactory(link, options = {}) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
class OpenAPIComponentRegistry {
|
|
18
|
-
constructor(doc,
|
|
18
|
+
constructor(doc, customComponentName) {
|
|
19
19
|
this.doc = doc;
|
|
20
|
-
this.
|
|
20
|
+
this.customComponentName = customComponentName;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Registers `schema` as a component under `preferredName` (or an equivalent/postfixed name)
|
|
24
|
-
* and returns a `$ref` to it.
|
|
25
|
-
* returned in its local `$defs` form instead.
|
|
24
|
+
* and returns a `$ref` to it.
|
|
26
25
|
*/
|
|
27
26
|
register(preferredName, schema) {
|
|
28
27
|
const { $defs, ...body } = schema;
|
|
@@ -39,59 +38,53 @@ class OpenAPIComponentRegistry {
|
|
|
39
38
|
}
|
|
40
39
|
/**
|
|
41
40
|
* Moves a schema's root-level `$defs` into `doc.components.schemas` and rewrites
|
|
42
|
-
* its refs accordingly.
|
|
43
|
-
* hoisted def references them.
|
|
41
|
+
* its refs accordingly.
|
|
44
42
|
*/
|
|
45
43
|
hoistDefs(schema, direction) {
|
|
46
44
|
if (typeof schema !== "object" || !schema.$defs) {
|
|
47
45
|
return schema;
|
|
48
46
|
}
|
|
49
47
|
const { $defs, ...rest } = schema;
|
|
50
|
-
const
|
|
51
|
-
const
|
|
48
|
+
const defs = {};
|
|
49
|
+
const preferredNames = {};
|
|
52
50
|
for (const defName of Object.keys($defs)) {
|
|
53
51
|
const defSchema = $defs[defName];
|
|
54
52
|
if (defSchema === void 0) {
|
|
55
53
|
continue;
|
|
56
54
|
}
|
|
57
55
|
const normalized = ensureJsonSchemaObject(defSchema);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
} else {
|
|
61
|
-
localDefs[defName] = normalized;
|
|
62
|
-
}
|
|
56
|
+
defs[defName] = normalized;
|
|
57
|
+
preferredNames[defName] = this.customComponentName?.(defName, normalized) ?? defName;
|
|
63
58
|
}
|
|
64
|
-
|
|
65
|
-
if (
|
|
59
|
+
const defNames = Object.keys(defs);
|
|
60
|
+
if (defNames.length === 0) {
|
|
66
61
|
return schema;
|
|
67
62
|
}
|
|
68
63
|
this.doc.components ??= {};
|
|
69
64
|
this.doc.components.schemas ??= {};
|
|
70
65
|
const componentsSchemas = this.doc.components.schemas;
|
|
71
66
|
const identityRenameMap = Object.fromEntries(
|
|
72
|
-
|
|
67
|
+
defNames.map((defName) => [defName, preferredNames[defName]])
|
|
73
68
|
);
|
|
74
69
|
const renameMap = {};
|
|
75
70
|
const pendingSchemas = [];
|
|
76
|
-
for (const defName of
|
|
77
|
-
const cleanSchema =
|
|
71
|
+
for (const defName of defNames) {
|
|
72
|
+
const cleanSchema = defs[defName];
|
|
78
73
|
const candidateSchemas = Object.fromEntries(
|
|
79
|
-
|
|
80
|
-
currentDefName,
|
|
81
|
-
rewriteComponentSchemaRefs(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
...renameMap
|
|
86
|
-
}
|
|
87
|
-
)
|
|
74
|
+
defNames.map((currentDefName) => [
|
|
75
|
+
preferredNames[currentDefName],
|
|
76
|
+
rewriteComponentSchemaRefs(defs[currentDefName], {
|
|
77
|
+
...identityRenameMap,
|
|
78
|
+
...renameMap
|
|
79
|
+
})
|
|
88
80
|
])
|
|
89
81
|
);
|
|
90
|
-
const
|
|
82
|
+
const preferredName = preferredNames[defName];
|
|
83
|
+
const prelimSchema = candidateSchemas[preferredName];
|
|
91
84
|
const [componentName, reuseExisting] = resolveComponentName(
|
|
92
85
|
componentsSchemas,
|
|
93
86
|
new Set(Object.values(renameMap)),
|
|
94
|
-
|
|
87
|
+
preferredName,
|
|
95
88
|
prelimSchema,
|
|
96
89
|
candidateSchemas,
|
|
97
90
|
direction
|
|
@@ -103,77 +96,20 @@ class OpenAPIComponentRegistry {
|
|
|
103
96
|
}
|
|
104
97
|
for (const { cleanSchema, componentName } of pendingSchemas) {
|
|
105
98
|
componentsSchemas[componentName] = rewriteComponentSchemaRefs(
|
|
106
|
-
|
|
99
|
+
cleanSchema,
|
|
107
100
|
renameMap
|
|
108
101
|
);
|
|
109
102
|
}
|
|
110
|
-
return rewriteComponentSchemaRefs(
|
|
103
|
+
return rewriteComponentSchemaRefs(rest, renameMap);
|
|
111
104
|
}
|
|
112
105
|
toOpenAPISchema(schema, direction) {
|
|
113
106
|
return ensureJsonSchemaObject(this.hoistDefs(schema, direction));
|
|
114
107
|
}
|
|
115
108
|
}
|
|
116
|
-
function
|
|
117
|
-
visitJsonSchemaRefs(schema, (ref) => {
|
|
118
|
-
const refName = parseLocalDefRefName(ref);
|
|
119
|
-
if (refName !== void 0) {
|
|
120
|
-
onRef(refName);
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
function hoistReferencedLocalDefs(hoistedDefs, localDefs) {
|
|
125
|
-
const queue = Object.values(hoistedDefs);
|
|
126
|
-
while (queue.length > 0) {
|
|
127
|
-
const current = queue.shift();
|
|
128
|
-
visitLocalDefRefs(current, (refName) => {
|
|
129
|
-
const referenced = localDefs[refName];
|
|
130
|
-
if (referenced === void 0) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
hoistedDefs[refName] = referenced;
|
|
134
|
-
delete localDefs[refName];
|
|
135
|
-
queue.push(referenced);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
function withReferencedLocalDefs(schema, localDefs) {
|
|
140
|
-
const referencedLocalDefs = collectReferencedLocalDefNames(schema, localDefs);
|
|
141
|
-
if (referencedLocalDefs.length === 0) {
|
|
142
|
-
return schema;
|
|
143
|
-
}
|
|
144
|
-
const mergedDefs = {
|
|
145
|
-
...schema.$defs
|
|
146
|
-
};
|
|
147
|
-
for (const defName of referencedLocalDefs) {
|
|
148
|
-
mergedDefs[defName] = localDefs[defName];
|
|
149
|
-
}
|
|
150
|
-
return {
|
|
151
|
-
...schema,
|
|
152
|
-
$defs: mergedDefs
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function collectReferencedLocalDefNames(schema, localDefs) {
|
|
156
|
-
if (Object.keys(localDefs).length === 0) {
|
|
157
|
-
return [];
|
|
158
|
-
}
|
|
159
|
-
const referenced = /* @__PURE__ */ new Set();
|
|
160
|
-
const queue = [schema];
|
|
161
|
-
while (queue.length > 0) {
|
|
162
|
-
const current = queue.shift();
|
|
163
|
-
visitLocalDefRefs(current, (refName) => {
|
|
164
|
-
if (localDefs[refName] === void 0 || referenced.has(refName)) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
referenced.add(refName);
|
|
168
|
-
queue.push(localDefs[refName]);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
return [...referenced];
|
|
172
|
-
}
|
|
173
|
-
function resolveComponentName(componentsSchemas, claimedNames, defName, schema, candidateSchemas, direction) {
|
|
109
|
+
function resolveComponentName(componentsSchemas, claimedNames, preferredName, schema, candidateSchemas, direction) {
|
|
174
110
|
let mintName;
|
|
175
111
|
for (let i = 1; ; i++) {
|
|
176
|
-
const [componentName, mintable, tail] = componentNameCandidate(
|
|
112
|
+
const [componentName, mintable, tail] = componentNameCandidate(preferredName, direction, i);
|
|
177
113
|
const existingSchema = componentsSchemas[componentName];
|
|
178
114
|
if (existingSchema === void 0) {
|
|
179
115
|
if (mintable && !claimedNames.has(componentName)) {
|
|
@@ -191,27 +127,27 @@ function resolveComponentName(componentsSchemas, claimedNames, defName, schema,
|
|
|
191
127
|
existingSchema,
|
|
192
128
|
candidateSchemas,
|
|
193
129
|
componentsSchemas,
|
|
194
|
-
/* @__PURE__ */ new Map([[
|
|
195
|
-
/* @__PURE__ */ new Map([[componentName,
|
|
130
|
+
/* @__PURE__ */ new Map([[preferredName, componentName]]),
|
|
131
|
+
/* @__PURE__ */ new Map([[componentName, preferredName]])
|
|
196
132
|
)) {
|
|
197
133
|
return [componentName, true];
|
|
198
134
|
}
|
|
199
135
|
}
|
|
200
136
|
}
|
|
201
|
-
function componentNameCandidate(
|
|
137
|
+
function componentNameCandidate(preferredName, direction, attempt) {
|
|
202
138
|
if (attempt === 1) {
|
|
203
|
-
return [
|
|
139
|
+
return [preferredName, true, false];
|
|
204
140
|
}
|
|
205
141
|
if (direction !== void 0) {
|
|
206
142
|
if (attempt === 2) {
|
|
207
|
-
return [`${
|
|
143
|
+
return [`${preferredName}${direction === "input" ? "Input" : "Output"}`, true, false];
|
|
208
144
|
}
|
|
209
145
|
if (attempt === 3) {
|
|
210
|
-
return [`${
|
|
146
|
+
return [`${preferredName}${direction === "input" ? "Output" : "Input"}`, false, false];
|
|
211
147
|
}
|
|
212
|
-
return [`${
|
|
148
|
+
return [`${preferredName}${attempt - 2}`, true, true];
|
|
213
149
|
}
|
|
214
|
-
return [`${
|
|
150
|
+
return [`${preferredName}${attempt}`, true, true];
|
|
215
151
|
}
|
|
216
152
|
function definedKeysOf(object) {
|
|
217
153
|
return Object.keys(object).filter((key) => object[key] !== void 0).sort();
|
|
@@ -678,13 +614,14 @@ function buildErrorResponse(ctx, operation, def) {
|
|
|
678
614
|
status
|
|
679
615
|
);
|
|
680
616
|
const responseSchema = customBodySchema ?? combineJsonSchemasWithComposition("oneOf", [
|
|
681
|
-
...definitions.map(({ code, dataJsonSchema, dataOptional
|
|
617
|
+
...definitions.map(({ code, dataJsonSchema, dataOptional }) => {
|
|
682
618
|
return ctx.registry.register(toErrorComponentName(code), combineJsonObjectSchemaEntries([
|
|
683
619
|
["defined", { const: true }, false],
|
|
684
620
|
["inferable", { type: "boolean" }, false],
|
|
685
621
|
["code", { const: code }, false],
|
|
686
622
|
["status", { const: status }, false],
|
|
687
|
-
|
|
623
|
+
// avoid using the defaultMessage here to improve component reusability
|
|
624
|
+
["message", { type: "string" }, false],
|
|
688
625
|
["data", ctx.registry.hoistDefs(dataJsonSchema, "output"), dataOptional]
|
|
689
626
|
]));
|
|
690
627
|
}),
|
|
@@ -811,7 +748,7 @@ class OpenAPIGenerator {
|
|
|
811
748
|
info: options.base?.info ?? { title: "API Reference", version: "0.0.0" }
|
|
812
749
|
};
|
|
813
750
|
const ctx = {
|
|
814
|
-
registry: new OpenAPIComponentRegistry(doc, options.
|
|
751
|
+
registry: new OpenAPIComponentRegistry(doc, options.customComponentName),
|
|
815
752
|
convertSchemas: (schemas, direction) => this.convertSchemas(schemas, direction),
|
|
816
753
|
errorStatusMap: options.errorStatusMap ?? COMMON_ERROR_STATUS_MAP,
|
|
817
754
|
customErrorResponseBodySchema: options.customErrorResponseBodySchema
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ import { Value, Promisable } from '@orpc/shared';
|
|
|
4
4
|
import { ApiReferenceConfiguration } from '@scalar/api-reference';
|
|
5
5
|
import { StandardUrl } from '@standardserver/core';
|
|
6
6
|
import { SwaggerUIOptions } from 'swagger-ui';
|
|
7
|
-
import {
|
|
7
|
+
import { O as OpenAPIDocument } from '../shared/openapi.Bsz7d8xx.mjs';
|
|
8
8
|
import '@hey-api/spec-types';
|
|
9
9
|
import '@orpc/client';
|
|
10
10
|
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Value, Promisable } from '@orpc/shared';
|
|
|
4
4
|
import { ApiReferenceConfiguration } from '@scalar/api-reference';
|
|
5
5
|
import { StandardUrl } from '@standardserver/core';
|
|
6
6
|
import { SwaggerUIOptions } from 'swagger-ui';
|
|
7
|
-
import {
|
|
7
|
+
import { O as OpenAPIDocument } from '../shared/openapi.Bsz7d8xx.js';
|
|
8
8
|
import '@hey-api/spec-types';
|
|
9
9
|
import '@orpc/client';
|
|
10
10
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { wrapAsyncIteratorPreservingEventMeta, toORPCError, isORPCErrorJson, createORPCErrorFromJson } from '@orpc/client';
|
|
2
|
-
import { isPlainObject, isAsyncIteratorObject } from '@orpc/shared';
|
|
2
|
+
import { isPlainObject, NullProtoObj, isAsyncIteratorObject } from '@orpc/shared';
|
|
3
3
|
import { ErrorEvent } from '@standardserver/core';
|
|
4
|
-
import { B as BracketNotationSerializer } from './openapi.
|
|
4
|
+
import { B as BracketNotationSerializer } from './openapi.s_p5sN-P.mjs';
|
|
5
5
|
|
|
6
6
|
const DEFAULT_OPENAPI_METHOD = "POST";
|
|
7
7
|
const DEFAULT_OPENAPI_SUCCESS_DESCRIPTION = "OK";
|
|
@@ -84,44 +84,116 @@ const DEFAULT_OPEN_API_JSON_SERIALIZER_HANDLERS = {
|
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
class OpenAPIJsonSerializer {
|
|
87
|
-
|
|
87
|
+
inlineBuiltInHandlers;
|
|
88
|
+
handlerEntries;
|
|
88
89
|
omitUndefinedProperties;
|
|
89
90
|
constructor(options = {}) {
|
|
90
|
-
this.handlers = {
|
|
91
|
-
...DEFAULT_OPEN_API_JSON_SERIALIZER_HANDLERS,
|
|
92
|
-
...options.handlers
|
|
93
|
-
};
|
|
94
91
|
this.omitUndefinedProperties = options.omitUndefinedProperties !== false;
|
|
92
|
+
const customHandlers = options.handlers;
|
|
93
|
+
if (customHandlers === void 0) {
|
|
94
|
+
this.inlineBuiltInHandlers = true;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
let inlineBuiltInHandlers = true;
|
|
98
|
+
let handlerEntries = [];
|
|
99
|
+
for (const key in customHandlers) {
|
|
100
|
+
const handler = customHandlers[key];
|
|
101
|
+
if (inlineBuiltInHandlers && key in DEFAULT_OPEN_API_JSON_SERIALIZER_HANDLERS) {
|
|
102
|
+
inlineBuiltInHandlers = false;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
if (handler !== void 0) {
|
|
106
|
+
handlerEntries.push(handler);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!inlineBuiltInHandlers) {
|
|
110
|
+
handlerEntries = [];
|
|
111
|
+
for (const handler of Object.values({ ...DEFAULT_OPEN_API_JSON_SERIALIZER_HANDLERS, ...customHandlers })) {
|
|
112
|
+
if (handler !== void 0) {
|
|
113
|
+
handlerEntries.push(handler);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.inlineBuiltInHandlers = inlineBuiltInHandlers;
|
|
118
|
+
this.handlerEntries = handlerEntries;
|
|
95
119
|
}
|
|
96
120
|
serialize(data) {
|
|
97
|
-
const
|
|
121
|
+
const maps = [];
|
|
122
|
+
const blobs = [];
|
|
123
|
+
const json = this.serializeValue(data, [], maps, blobs);
|
|
98
124
|
return { json, maps, blobs };
|
|
99
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* `segments` is a shared mutable stack (push/pop while walking),
|
|
128
|
+
* so it must be copied before being stored in `maps`.
|
|
129
|
+
*/
|
|
100
130
|
serializeValue(data, segments, maps, blobs) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
131
|
+
if (this.inlineBuiltInHandlers) {
|
|
132
|
+
switch (typeof data) {
|
|
133
|
+
case "string":
|
|
134
|
+
case "boolean":
|
|
135
|
+
return data;
|
|
136
|
+
case "number":
|
|
137
|
+
return Number.isNaN(data) ? null : data;
|
|
138
|
+
case "undefined":
|
|
139
|
+
return null;
|
|
140
|
+
case "bigint":
|
|
141
|
+
return data.toString();
|
|
142
|
+
case "object": {
|
|
143
|
+
if (data === null) {
|
|
144
|
+
return data;
|
|
145
|
+
}
|
|
146
|
+
if (data instanceof Date) {
|
|
147
|
+
return Number.isNaN(data.getTime()) ? null : data.toISOString();
|
|
148
|
+
}
|
|
149
|
+
if (data instanceof URL) {
|
|
150
|
+
return data.toString();
|
|
151
|
+
}
|
|
152
|
+
if (data instanceof RegExp) {
|
|
153
|
+
return data.toString();
|
|
154
|
+
}
|
|
155
|
+
if (data instanceof Set) {
|
|
156
|
+
return this.serializeValue(Array.from(data), segments, maps, blobs);
|
|
157
|
+
}
|
|
158
|
+
if (data instanceof Map) {
|
|
159
|
+
return this.serializeValue(Array.from(data.entries()), segments, maps, blobs);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const handlerEntries = this.handlerEntries;
|
|
165
|
+
if (handlerEntries) {
|
|
166
|
+
for (let i = 0; i < handlerEntries.length; i++) {
|
|
167
|
+
const handler = handlerEntries[i];
|
|
168
|
+
if (handler.condition(data)) {
|
|
169
|
+
const serialized = handler.serialize(data);
|
|
170
|
+
if (handler.isTerminal) {
|
|
171
|
+
if (serialized instanceof Blob) {
|
|
172
|
+
maps.push(segments.slice());
|
|
173
|
+
blobs.push(serialized);
|
|
174
|
+
}
|
|
175
|
+
return serialized;
|
|
176
|
+
}
|
|
177
|
+
return this.serializeValue(serialized, segments, maps, blobs);
|
|
107
178
|
}
|
|
108
|
-
const result = this.serializeValue(serialized, segments, maps, blobs);
|
|
109
|
-
return result;
|
|
110
179
|
}
|
|
111
180
|
}
|
|
112
181
|
if (data instanceof Blob) {
|
|
113
|
-
maps.push(segments);
|
|
182
|
+
maps.push(segments.slice());
|
|
114
183
|
blobs.push(data);
|
|
115
|
-
return
|
|
184
|
+
return data;
|
|
116
185
|
}
|
|
117
186
|
if (Array.isArray(data)) {
|
|
118
|
-
const json =
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
187
|
+
const json = [];
|
|
188
|
+
for (let i = 0; i < data.length; i++) {
|
|
189
|
+
segments.push(i);
|
|
190
|
+
json.push(this.serializeValue(data[i], segments, maps, blobs));
|
|
191
|
+
segments.pop();
|
|
192
|
+
}
|
|
193
|
+
return json;
|
|
122
194
|
}
|
|
123
195
|
if (isPlainObject(data)) {
|
|
124
|
-
const json =
|
|
196
|
+
const json = new NullProtoObj();
|
|
125
197
|
for (const k in data) {
|
|
126
198
|
const v = data[k];
|
|
127
199
|
if (k === "toJSON" && typeof v === "function") {
|
|
@@ -130,27 +202,30 @@ class OpenAPIJsonSerializer {
|
|
|
130
202
|
if (v === void 0 && this.omitUndefinedProperties) {
|
|
131
203
|
continue;
|
|
132
204
|
}
|
|
133
|
-
|
|
205
|
+
segments.push(k);
|
|
206
|
+
json[k] = this.serializeValue(v, segments, maps, blobs);
|
|
207
|
+
segments.pop();
|
|
134
208
|
}
|
|
135
|
-
return
|
|
209
|
+
return json;
|
|
136
210
|
}
|
|
137
|
-
return
|
|
211
|
+
return data;
|
|
138
212
|
}
|
|
139
213
|
deserialize(serialized) {
|
|
140
214
|
const ref = { data: serialized.json };
|
|
141
215
|
if (serialized.blobs?.length) {
|
|
142
|
-
serialized.maps.
|
|
216
|
+
for (let i = 0; i < serialized.maps.length; i++) {
|
|
217
|
+
const segments = serialized.maps[i];
|
|
143
218
|
let currentRef = ref;
|
|
144
219
|
let preSegment = "data";
|
|
145
|
-
segments.
|
|
220
|
+
for (let j = 0; j < segments.length; j++) {
|
|
146
221
|
currentRef = currentRef[preSegment];
|
|
147
|
-
preSegment =
|
|
222
|
+
preSegment = segments[j];
|
|
148
223
|
if (!Object.hasOwn(currentRef, preSegment)) {
|
|
149
224
|
throw new Error(`Security error: Invalid serialized data. Segment "${preSegment}" does not exist.`);
|
|
150
225
|
}
|
|
151
|
-
}
|
|
226
|
+
}
|
|
152
227
|
currentRef[preSegment] = serialized.blobs[i];
|
|
153
|
-
}
|
|
228
|
+
}
|
|
154
229
|
}
|
|
155
230
|
return ref.data;
|
|
156
231
|
}
|
|
@@ -166,8 +241,6 @@ class OpenAPISerializer {
|
|
|
166
241
|
this.defaultSerializeOptions = serialize;
|
|
167
242
|
}
|
|
168
243
|
serialize(data, options = {}) {
|
|
169
|
-
const useFormDataForBlobFields = options.useFormDataForBlobFields ?? this.defaultSerializeOptions?.useFormDataForBlobFields ?? true;
|
|
170
|
-
const asFormData = options.asFormData ?? this.defaultSerializeOptions?.asFormData ?? false;
|
|
171
244
|
if (!options.asFormData) {
|
|
172
245
|
if (data === void 0 || data instanceof ReadableStream || data instanceof Blob) {
|
|
173
246
|
return data;
|
|
@@ -178,22 +251,24 @@ class OpenAPISerializer {
|
|
|
178
251
|
if (result.value === void 0) {
|
|
179
252
|
return result;
|
|
180
253
|
}
|
|
181
|
-
return { done: result.done, value: this.serializeValue(result.value,
|
|
254
|
+
return { done: result.done, value: this.serializeValue(result.value, false, false) };
|
|
182
255
|
},
|
|
183
256
|
mapError: (e) => {
|
|
184
257
|
return new ErrorEvent({
|
|
185
|
-
data: this.serializeValue(toORPCError(e).toJSON(),
|
|
258
|
+
data: this.serializeValue(toORPCError(e).toJSON(), false, false),
|
|
186
259
|
cause: e
|
|
187
260
|
});
|
|
188
261
|
}
|
|
189
262
|
});
|
|
190
263
|
}
|
|
191
264
|
}
|
|
192
|
-
|
|
265
|
+
const useFormDataForBlobFields = options.useFormDataForBlobFields ?? this.defaultSerializeOptions?.useFormDataForBlobFields ?? true;
|
|
266
|
+
const asFormData = options.asFormData ?? this.defaultSerializeOptions?.asFormData ?? false;
|
|
267
|
+
return this.serializeValue(data, useFormDataForBlobFields, asFormData);
|
|
193
268
|
}
|
|
194
|
-
serializeValue(value,
|
|
269
|
+
serializeValue(value, useFormDataForBlobFields, asFormData) {
|
|
195
270
|
const { json, blobs } = this.jsonSerializer.serialize(value);
|
|
196
|
-
if (!
|
|
271
|
+
if (!asFormData && (json instanceof Blob || json === void 0 || !blobs?.length || !useFormDataForBlobFields)) {
|
|
197
272
|
return json;
|
|
198
273
|
}
|
|
199
274
|
const form = new FormData();
|
|
@@ -2,10 +2,11 @@ import { isORPCErrorJson, createORPCErrorFromJson, ORPCError } from '@orpc/clien
|
|
|
2
2
|
import { getRouterContract, ProcedureContract } from '@orpc/contract';
|
|
3
3
|
import { unlazy } from '@orpc/server';
|
|
4
4
|
import { value, pathToHttpPath, mergeHttpPath, isTypescriptObject, stringifyJSON } from '@orpc/shared';
|
|
5
|
-
import { mergeStandardHeaders, parseStandardUrl
|
|
5
|
+
import { mergeStandardHeaders, parseStandardUrl } from '@standardserver/core';
|
|
6
6
|
import { toStandardHeaders } from '@standardserver/fetch';
|
|
7
|
-
import { O as OpenAPISerializer, D as DEFAULT_OPENAPI_METHOD, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, g as getDynamicPathParams, i as isBodylessMethod, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE } from './openapi.
|
|
7
|
+
import { O as OpenAPISerializer, D as DEFAULT_OPENAPI_METHOD, a as DEFAULT_OPENAPI_INPUT_STRUCTURE, g as getDynamicPathParams, i as isBodylessMethod, b as DEFAULT_OPENAPI_OUTPUT_STRUCTURE } from './openapi.0yE-t1W-.mjs';
|
|
8
8
|
import { g as getOpenAPIMeta } from './openapi.B9PQzqBn.mjs';
|
|
9
|
+
import { s as serializeHeaders } from './openapi.BaqI61Xi.mjs';
|
|
9
10
|
|
|
10
11
|
class OpenAPILinkCodecError extends TypeError {
|
|
11
12
|
}
|
|
@@ -83,7 +84,7 @@ class OpenAPILinkCodec {
|
|
|
83
84
|
\u2022 Expected an object or undefined with optional properties:
|
|
84
85
|
- params (object, required when the path has dynamic params)
|
|
85
86
|
- query (object)
|
|
86
|
-
- headers (
|
|
87
|
+
- headers (object)
|
|
87
88
|
- body (any)
|
|
88
89
|
|
|
89
90
|
Actual value:
|
|
@@ -104,7 +105,7 @@ class OpenAPILinkCodec {
|
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
if (input?.headers) {
|
|
107
|
-
headers = mergeStandardHeaders(headers, input.headers);
|
|
108
|
+
headers = mergeStandardHeaders(headers, serializeHeaders(input.headers, this.serializer));
|
|
108
109
|
}
|
|
109
110
|
pathname = `${basePathname.replace(END_SLASH_REGEX, "")}${pathname}`;
|
|
110
111
|
const queryString = this.serializeQueryString(input?.query, meta?.queryStyles);
|
|
@@ -324,7 +325,7 @@ function isValidDetailedInput(input) {
|
|
|
324
325
|
if (input.query !== void 0 && !isTypescriptObject(input.query)) {
|
|
325
326
|
return false;
|
|
326
327
|
}
|
|
327
|
-
if (input.headers !== void 0 && !
|
|
328
|
+
if (input.headers !== void 0 && !isTypescriptObject(input.headers)) {
|
|
328
329
|
return false;
|
|
329
330
|
}
|
|
330
331
|
return true;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ClientContext, ClientOptions, AnyORPCError } from '@orpc/client';
|
|
2
|
+
import { StandardLinkCodec, StandardLinkCodecDecodedResponse } from '@orpc/client/standard';
|
|
3
|
+
import { RouterContract } from '@orpc/contract';
|
|
4
|
+
import { Value, Promisable } from '@orpc/shared';
|
|
5
|
+
import { StandardUrl, StandardHeaders, StandardLazyResponse, StandardRequest } from '@standardserver/core';
|
|
6
|
+
import { O as OpenAPISerializer } from './openapi.DBFXInk5.js';
|
|
7
|
+
|
|
8
|
+
declare class OpenAPILinkCodecError extends TypeError {
|
|
9
|
+
}
|
|
10
|
+
interface OpenAPILinkCodecOptions<T extends ClientContext> {
|
|
11
|
+
/**
|
|
12
|
+
* Base URL for all requests, without origin. Should match the OpenAPI handler mount path.
|
|
13
|
+
*
|
|
14
|
+
* @example '/api'
|
|
15
|
+
* @default '/'
|
|
16
|
+
*/
|
|
17
|
+
url?: Value<Promisable<StandardUrl>, [options: ClientOptions<T>, path: string[], input: unknown]>;
|
|
18
|
+
/**
|
|
19
|
+
* Inject headers into the request.
|
|
20
|
+
*/
|
|
21
|
+
headers?: Value<Promisable<StandardHeaders | Headers>, [options: ClientOptions<T>, path: string[], input: unknown]>;
|
|
22
|
+
/**
|
|
23
|
+
* Override the default OpenAPI serializer.
|
|
24
|
+
*/
|
|
25
|
+
serializer?: Pick<OpenAPISerializer, keyof OpenAPISerializer>;
|
|
26
|
+
/**
|
|
27
|
+
* Customize how an error response body is converted into an ORPC error.
|
|
28
|
+
* Return `null` or `undefined` to fall back to the default decoding behavior.
|
|
29
|
+
*/
|
|
30
|
+
customErrorResponseBodyDecoder?: (deserializedBody: unknown, response: StandardLazyResponse) => AnyORPCError | null | undefined;
|
|
31
|
+
}
|
|
32
|
+
declare class OpenAPILinkCodec<T extends ClientContext> implements StandardLinkCodec<T> {
|
|
33
|
+
private readonly router;
|
|
34
|
+
private readonly baseUrl;
|
|
35
|
+
private readonly headers;
|
|
36
|
+
private readonly serializer;
|
|
37
|
+
private readonly customErrorResponseBodyDecoder;
|
|
38
|
+
constructor(router: RouterContract, options?: OpenAPILinkCodecOptions<T>);
|
|
39
|
+
encodeInput(input: unknown, path: string[], options: ClientOptions<T>): Promise<StandardRequest>;
|
|
40
|
+
private encodePathParam;
|
|
41
|
+
private serializeQueryString;
|
|
42
|
+
decodeResponse(response: StandardLazyResponse, path: string[], _options: ClientOptions<T>): Promise<StandardLinkCodecDecodedResponse>;
|
|
43
|
+
private resolveProcedure;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { OpenAPILinkCodec as a, OpenAPILinkCodecError as b };
|
|
47
|
+
export type { OpenAPILinkCodecOptions as O };
|