schema-components 0.0.0 → 1.1.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.
- package/CHANGELOG.md +59 -0
- package/LICENSE +21 -0
- package/README.md +526 -0
- package/dist/core/adapter.d.mts +19 -0
- package/dist/core/adapter.mjs +140 -0
- package/dist/core/errors.d.mts +2 -0
- package/dist/core/errors.mjs +74 -0
- package/dist/core/guards.d.mts +44 -0
- package/dist/core/guards.mjs +58 -0
- package/dist/core/renderer.d.mts +2 -0
- package/dist/core/renderer.mjs +71 -0
- package/dist/core/types.d.mts +3 -0
- package/dist/core/types.mjs +40 -0
- package/dist/core/walker.d.mts +14 -0
- package/dist/core/walker.mjs +366 -0
- package/dist/errors-DIKI2C78.d.mts +57 -0
- package/dist/html/a11y.d.mts +47 -0
- package/dist/html/a11y.mjs +81 -0
- package/dist/html/html.d.mts +135 -0
- package/dist/html/html.mjs +168 -0
- package/dist/html/renderToHtml.d.mts +32 -0
- package/dist/html/renderToHtml.mjs +352 -0
- package/dist/html/renderToHtmlStream.d.mts +58 -0
- package/dist/html/renderToHtmlStream.mjs +285 -0
- package/dist/html/styles.css +151 -0
- package/dist/openapi/components.d.mts +76 -0
- package/dist/openapi/components.mjs +223 -0
- package/dist/openapi/parser.d.mts +45 -0
- package/dist/openapi/parser.mjs +159 -0
- package/dist/react/SchemaComponent.d.mts +96 -0
- package/dist/react/SchemaComponent.mjs +283 -0
- package/dist/react/SchemaErrorBoundary.d.mts +26 -0
- package/dist/react/SchemaErrorBoundary.mjs +47 -0
- package/dist/react/headless.d.mts +13 -0
- package/dist/react/headless.mjs +163 -0
- package/dist/themes/shadcn.d.mts +6 -0
- package/dist/themes/shadcn.mjs +166 -0
- package/dist/types-BU0ETFHk.d.mts +326 -0
- package/package.json +113 -3
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { isObject, toRecordOrUndefined } from "../core/guards.mjs";
|
|
2
|
+
import { normaliseSchema } from "../core/adapter.mjs";
|
|
3
|
+
import { SchemaNormalisationError } from "../core/errors.mjs";
|
|
4
|
+
import { walk } from "../core/walker.mjs";
|
|
5
|
+
import { getParameters, getRequestBody, getResponses, listOperations, parseOpenApiDocument } from "./parser.mjs";
|
|
6
|
+
import { renderField } from "../react/SchemaComponent.mjs";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/openapi/components.tsx
|
|
9
|
+
const docCache = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
function getParsed(doc) {
|
|
11
|
+
const cached = docCache.get(doc);
|
|
12
|
+
if (cached !== void 0) return cached;
|
|
13
|
+
const parsed = parseOpenApiDocument(doc);
|
|
14
|
+
docCache.set(doc, parsed);
|
|
15
|
+
return parsed;
|
|
16
|
+
}
|
|
17
|
+
function noop() {}
|
|
18
|
+
function toDoc(value) {
|
|
19
|
+
return isObject(value) ? value : {};
|
|
20
|
+
}
|
|
21
|
+
function renderSchema(schema, rootDocument, options) {
|
|
22
|
+
let jsonSchema;
|
|
23
|
+
let rootMeta;
|
|
24
|
+
try {
|
|
25
|
+
const normalised = normaliseSchema(schema);
|
|
26
|
+
jsonSchema = normalised.jsonSchema;
|
|
27
|
+
rootMeta = normalised.rootMeta;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
throw new SchemaNormalisationError(err instanceof Error ? err.message : "Failed to normalise schema", schema, "unknown");
|
|
30
|
+
}
|
|
31
|
+
const componentMeta = {};
|
|
32
|
+
if (options.readOnly === true) componentMeta.readOnly = true;
|
|
33
|
+
if (options.meta !== void 0) for (const [k, v] of Object.entries(options.meta)) componentMeta[k] = v;
|
|
34
|
+
const walkOpts = {
|
|
35
|
+
componentMeta,
|
|
36
|
+
rootMeta,
|
|
37
|
+
fieldOverrides: toRecordOrUndefined(options.fields),
|
|
38
|
+
rootDocument
|
|
39
|
+
};
|
|
40
|
+
const tree = walk(jsonSchema, walkOpts);
|
|
41
|
+
const renderChild = (childTree, childValue, childOnChange) => renderField(childTree, childValue, childOnChange, void 0, renderChild);
|
|
42
|
+
return renderField(tree, options.value, options.onChange ?? noop, void 0, renderChild);
|
|
43
|
+
}
|
|
44
|
+
function ApiOperation({ schema: doc, path, method, requestBodyValue, onRequestBodyChange, responseValue, meta, requestBodyFields }) {
|
|
45
|
+
const parsed = getParsed(toDoc(doc));
|
|
46
|
+
const rootDoc = toDoc(doc);
|
|
47
|
+
const operation = listOperations(parsed).find((op) => op.path === path && op.method === method);
|
|
48
|
+
if (operation === void 0) throw new SchemaNormalisationError(`Operation not found: ${method.toUpperCase()} ${path}`, doc, "openapi-invalid");
|
|
49
|
+
const params = getParameters(parsed, path, method);
|
|
50
|
+
const requestBody = getRequestBody(parsed, path, method);
|
|
51
|
+
const responses = getResponses(parsed, path, method);
|
|
52
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
53
|
+
"data-operation": `${method.toUpperCase()} ${path}`,
|
|
54
|
+
children: [
|
|
55
|
+
/* @__PURE__ */ jsx(OperationHeader, { operation }),
|
|
56
|
+
params.length > 0 && /* @__PURE__ */ jsxs("section", {
|
|
57
|
+
"data-parameters": true,
|
|
58
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Parameters" }), /* @__PURE__ */ jsx(ParameterList, {
|
|
59
|
+
parameters: params,
|
|
60
|
+
rootDoc,
|
|
61
|
+
meta
|
|
62
|
+
})]
|
|
63
|
+
}),
|
|
64
|
+
requestBody?.schema !== void 0 && /* @__PURE__ */ jsxs("section", {
|
|
65
|
+
"data-request-body": true,
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ jsxs("h4", { children: ["Request Body", requestBody.required && /* @__PURE__ */ jsx("span", {
|
|
68
|
+
"data-required": true,
|
|
69
|
+
children: "*"
|
|
70
|
+
})] }),
|
|
71
|
+
requestBody.description && /* @__PURE__ */ jsx("p", { children: requestBody.description }),
|
|
72
|
+
requestBody.contentTypes.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
73
|
+
"data-content-type": true,
|
|
74
|
+
children: requestBody.contentTypes[0]
|
|
75
|
+
}),
|
|
76
|
+
renderSchema(requestBody.schema, rootDoc, {
|
|
77
|
+
value: requestBodyValue,
|
|
78
|
+
onChange: onRequestBodyChange,
|
|
79
|
+
fields: requestBodyFields,
|
|
80
|
+
meta
|
|
81
|
+
})
|
|
82
|
+
]
|
|
83
|
+
}),
|
|
84
|
+
responses.length > 0 && /* @__PURE__ */ jsxs("section", {
|
|
85
|
+
"data-responses": true,
|
|
86
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Responses" }), responses.map((response) => /* @__PURE__ */ jsx(ResponseCard, {
|
|
87
|
+
response,
|
|
88
|
+
rootDoc,
|
|
89
|
+
value: responseValue,
|
|
90
|
+
meta
|
|
91
|
+
}, response.statusCode))]
|
|
92
|
+
})
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function ApiParameters({ schema: doc, path, method, meta, overrides }) {
|
|
97
|
+
const parsed = getParsed(toDoc(doc));
|
|
98
|
+
const rootDoc = toDoc(doc);
|
|
99
|
+
const params = getParameters(parsed, path, method);
|
|
100
|
+
if (params.length === 0) return null;
|
|
101
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
102
|
+
"data-parameters": true,
|
|
103
|
+
children: [/* @__PURE__ */ jsx("h4", { children: "Parameters" }), /* @__PURE__ */ jsx(ParameterList, {
|
|
104
|
+
parameters: params,
|
|
105
|
+
rootDoc,
|
|
106
|
+
overrides,
|
|
107
|
+
meta
|
|
108
|
+
})]
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function ApiRequestBody({ schema: doc, path, method, value, onChange, meta, fields }) {
|
|
112
|
+
const parsed = getParsed(toDoc(doc));
|
|
113
|
+
const rootDoc = toDoc(doc);
|
|
114
|
+
const requestBody = getRequestBody(parsed, path, method);
|
|
115
|
+
if (requestBody?.schema === void 0) return null;
|
|
116
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
117
|
+
"data-request-body": true,
|
|
118
|
+
children: [
|
|
119
|
+
/* @__PURE__ */ jsxs("h4", { children: ["Request Body", requestBody.required && /* @__PURE__ */ jsx("span", {
|
|
120
|
+
"data-required": true,
|
|
121
|
+
children: "*"
|
|
122
|
+
})] }),
|
|
123
|
+
requestBody.description && /* @__PURE__ */ jsx("p", { children: requestBody.description }),
|
|
124
|
+
requestBody.contentTypes.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
125
|
+
"data-content-type": true,
|
|
126
|
+
children: requestBody.contentTypes[0]
|
|
127
|
+
}),
|
|
128
|
+
renderSchema(requestBody.schema, rootDoc, {
|
|
129
|
+
value,
|
|
130
|
+
onChange,
|
|
131
|
+
fields,
|
|
132
|
+
meta
|
|
133
|
+
})
|
|
134
|
+
]
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function ApiResponse({ schema: doc, path, method, status, value, meta, fields }) {
|
|
138
|
+
const parsed = getParsed(toDoc(doc));
|
|
139
|
+
const rootDoc = toDoc(doc);
|
|
140
|
+
const response = getResponses(parsed, path, method).find((r) => r.statusCode === status);
|
|
141
|
+
if (response === void 0) throw new SchemaNormalisationError(`Response not found: ${status}`, doc, "openapi-invalid");
|
|
142
|
+
if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
|
|
143
|
+
"data-status": status,
|
|
144
|
+
children: [
|
|
145
|
+
/* @__PURE__ */ jsx("h4", { children: status }),
|
|
146
|
+
response.description && /* @__PURE__ */ jsx("p", { children: response.description }),
|
|
147
|
+
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("em", { children: "No schema" }) })
|
|
148
|
+
]
|
|
149
|
+
});
|
|
150
|
+
return /* @__PURE__ */ jsx(ResponseCard, {
|
|
151
|
+
response,
|
|
152
|
+
rootDoc,
|
|
153
|
+
value,
|
|
154
|
+
fields,
|
|
155
|
+
meta
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function OperationHeader({ operation }) {
|
|
159
|
+
return /* @__PURE__ */ jsxs("header", { children: [
|
|
160
|
+
/* @__PURE__ */ jsxs("h3", { children: [
|
|
161
|
+
operation.method.toUpperCase(),
|
|
162
|
+
" ",
|
|
163
|
+
operation.path
|
|
164
|
+
] }),
|
|
165
|
+
operation.summary && /* @__PURE__ */ jsx("p", { children: operation.summary }),
|
|
166
|
+
operation.deprecated && /* @__PURE__ */ jsx("span", {
|
|
167
|
+
"data-deprecated": true,
|
|
168
|
+
children: "Deprecated"
|
|
169
|
+
})
|
|
170
|
+
] });
|
|
171
|
+
}
|
|
172
|
+
function ParameterList({ parameters, rootDoc, overrides, meta }) {
|
|
173
|
+
return /* @__PURE__ */ jsx(Fragment, { children: parameters.map((param) => /* @__PURE__ */ jsxs("div", {
|
|
174
|
+
"data-parameter": param.name,
|
|
175
|
+
children: [
|
|
176
|
+
/* @__PURE__ */ jsxs("label", { children: [param.name, param.required && /* @__PURE__ */ jsx("span", {
|
|
177
|
+
"data-required": true,
|
|
178
|
+
children: "*"
|
|
179
|
+
})] }),
|
|
180
|
+
param.description && /* @__PURE__ */ jsx("span", {
|
|
181
|
+
"data-description": true,
|
|
182
|
+
children: param.description
|
|
183
|
+
}),
|
|
184
|
+
renderSchema(param.schema ?? { type: "string" }, rootDoc, { meta: buildParamMeta(param, overrides, meta) })
|
|
185
|
+
]
|
|
186
|
+
}, param.name)) });
|
|
187
|
+
}
|
|
188
|
+
function ResponseCard({ response, rootDoc, value, fields, meta }) {
|
|
189
|
+
if (response.schema === void 0) return /* @__PURE__ */ jsxs("div", {
|
|
190
|
+
"data-status": response.statusCode,
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ jsx("h5", { children: response.statusCode }),
|
|
193
|
+
response.description && /* @__PURE__ */ jsx("p", { children: response.description }),
|
|
194
|
+
/* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("em", { children: "No schema" }) })
|
|
195
|
+
]
|
|
196
|
+
});
|
|
197
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
198
|
+
"data-status": response.statusCode,
|
|
199
|
+
children: [
|
|
200
|
+
/* @__PURE__ */ jsx("h5", { children: response.statusCode }),
|
|
201
|
+
response.description && /* @__PURE__ */ jsx("p", { children: response.description }),
|
|
202
|
+
renderSchema(response.schema, rootDoc, {
|
|
203
|
+
value,
|
|
204
|
+
fields,
|
|
205
|
+
meta: {
|
|
206
|
+
readOnly: true,
|
|
207
|
+
...meta
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
]
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function buildParamMeta(param, overrides, meta) {
|
|
214
|
+
const result = {};
|
|
215
|
+
if (param.description !== void 0) result.description = param.description;
|
|
216
|
+
if (param.deprecated) result.deprecated = true;
|
|
217
|
+
const override = toRecordOrUndefined(toRecordOrUndefined(overrides)?.[param.name]);
|
|
218
|
+
if (override !== void 0) for (const [k, v] of Object.entries(override)) result[k] = v;
|
|
219
|
+
if (meta !== void 0) for (const [k, v] of Object.entries(meta)) result[k] = v;
|
|
220
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
221
|
+
}
|
|
222
|
+
//#endregion
|
|
223
|
+
export { ApiOperation, ApiParameters, ApiRequestBody, ApiResponse };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { l as JsonObject } from "../types-BU0ETFHk.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/openapi/parser.d.ts
|
|
4
|
+
interface OpenApiDocument {
|
|
5
|
+
doc: JsonObject;
|
|
6
|
+
schemas: Map<string, JsonObject>;
|
|
7
|
+
}
|
|
8
|
+
interface OperationInfo {
|
|
9
|
+
path: string;
|
|
10
|
+
method: string;
|
|
11
|
+
operationId: string | undefined;
|
|
12
|
+
summary: string | undefined;
|
|
13
|
+
description: string | undefined;
|
|
14
|
+
deprecated: boolean;
|
|
15
|
+
operation: JsonObject;
|
|
16
|
+
}
|
|
17
|
+
type ParameterLocation = "query" | "path" | "header" | "cookie";
|
|
18
|
+
interface ParameterInfo {
|
|
19
|
+
name: string;
|
|
20
|
+
location: ParameterLocation;
|
|
21
|
+
required: boolean;
|
|
22
|
+
deprecated: boolean;
|
|
23
|
+
description: string | undefined;
|
|
24
|
+
schema: JsonObject | undefined;
|
|
25
|
+
}
|
|
26
|
+
interface ResponseInfo {
|
|
27
|
+
statusCode: string;
|
|
28
|
+
description: string | undefined;
|
|
29
|
+
contentTypes: string[];
|
|
30
|
+
schema: JsonObject | undefined;
|
|
31
|
+
}
|
|
32
|
+
interface RequestBodyInfo {
|
|
33
|
+
required: boolean;
|
|
34
|
+
description: string | undefined;
|
|
35
|
+
contentTypes: string[];
|
|
36
|
+
schema: JsonObject | undefined;
|
|
37
|
+
}
|
|
38
|
+
declare function parseOpenApiDocument(doc: JsonObject): OpenApiDocument;
|
|
39
|
+
declare function getSchema(parsed: OpenApiDocument, ref: string): JsonObject | undefined;
|
|
40
|
+
declare function listOperations(parsed: OpenApiDocument): OperationInfo[];
|
|
41
|
+
declare function getParameters(parsed: OpenApiDocument, path: string, method: string): ParameterInfo[];
|
|
42
|
+
declare function getRequestBody(parsed: OpenApiDocument, path: string, method: string): RequestBodyInfo | undefined;
|
|
43
|
+
declare function getResponses(parsed: OpenApiDocument, path: string, method: string): ResponseInfo[];
|
|
44
|
+
//#endregion
|
|
45
|
+
export { OpenApiDocument, OperationInfo, ParameterInfo, ParameterLocation, RequestBodyInfo, ResponseInfo, getParameters, getRequestBody, getResponses, getSchema, listOperations, parseOpenApiDocument };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { getProperty, isObject } from "../core/guards.mjs";
|
|
2
|
+
//#region src/openapi/parser.ts
|
|
3
|
+
function getString(value, key) {
|
|
4
|
+
const result = isObject(value) ? value[key] : void 0;
|
|
5
|
+
return typeof result === "string" ? result : void 0;
|
|
6
|
+
}
|
|
7
|
+
function toParameterLocation(value) {
|
|
8
|
+
if (value === "query" || value === "path" || value === "header" || value === "cookie") return value;
|
|
9
|
+
return "query";
|
|
10
|
+
}
|
|
11
|
+
function parseOpenApiDocument(doc) {
|
|
12
|
+
const schemas = /* @__PURE__ */ new Map();
|
|
13
|
+
const componentSchemas = getProperty(getProperty(doc, "components"), "schemas");
|
|
14
|
+
if (isObject(componentSchemas)) {
|
|
15
|
+
for (const [name, schema] of Object.entries(componentSchemas)) if (isObject(schema)) schemas.set(`#/components/schemas/${name}`, schema);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
doc,
|
|
19
|
+
schemas
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function getSchema(parsed, ref) {
|
|
23
|
+
const cached = parsed.schemas.get(ref);
|
|
24
|
+
if (cached !== void 0) return cached;
|
|
25
|
+
const resolved = resolveRefInDoc(parsed.doc, ref);
|
|
26
|
+
if (resolved !== void 0) {
|
|
27
|
+
parsed.schemas.set(ref, resolved);
|
|
28
|
+
return resolved;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const METHODS = [
|
|
32
|
+
"get",
|
|
33
|
+
"post",
|
|
34
|
+
"put",
|
|
35
|
+
"patch",
|
|
36
|
+
"delete"
|
|
37
|
+
];
|
|
38
|
+
function listOperations(parsed) {
|
|
39
|
+
const operations = [];
|
|
40
|
+
const paths = getProperty(parsed.doc, "paths");
|
|
41
|
+
if (!isObject(paths)) return operations;
|
|
42
|
+
for (const [path, pathItem] of Object.entries(paths)) {
|
|
43
|
+
if (!isObject(pathItem)) continue;
|
|
44
|
+
for (const method of METHODS) {
|
|
45
|
+
const operation = getProperty(pathItem, method);
|
|
46
|
+
if (!isObject(operation)) continue;
|
|
47
|
+
operations.push({
|
|
48
|
+
path,
|
|
49
|
+
method,
|
|
50
|
+
operationId: getString(operation, "operationId"),
|
|
51
|
+
summary: getString(operation, "summary"),
|
|
52
|
+
description: getString(operation, "description"),
|
|
53
|
+
deprecated: getProperty(operation, "deprecated") === true,
|
|
54
|
+
operation
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return operations;
|
|
59
|
+
}
|
|
60
|
+
function getParameters(parsed, path, method) {
|
|
61
|
+
const pathItem = getProperty(getProperty(parsed.doc, "paths"), path);
|
|
62
|
+
if (!isObject(pathItem)) return [];
|
|
63
|
+
const operation = getProperty(pathItem, method);
|
|
64
|
+
if (!isObject(operation)) return [];
|
|
65
|
+
const pathParams = extractParameterList(getProperty(pathItem, "parameters"));
|
|
66
|
+
const opParams = extractParameterList(getProperty(operation, "parameters"));
|
|
67
|
+
const map = /* @__PURE__ */ new Map();
|
|
68
|
+
for (const param of pathParams) map.set(`${param.name}:${param.location}`, param);
|
|
69
|
+
for (const param of opParams) map.set(`${param.name}:${param.location}`, param);
|
|
70
|
+
return [...map.values()];
|
|
71
|
+
}
|
|
72
|
+
function extractParameterList(parameters) {
|
|
73
|
+
if (!Array.isArray(parameters)) return [];
|
|
74
|
+
const result = [];
|
|
75
|
+
for (const param of parameters) {
|
|
76
|
+
if (!isObject(param)) continue;
|
|
77
|
+
const name = getProperty(param, "name");
|
|
78
|
+
const location = getProperty(param, "in");
|
|
79
|
+
if (typeof name !== "string" || typeof location !== "string") continue;
|
|
80
|
+
const resolved = resolveParam(param);
|
|
81
|
+
const schema = getProperty(resolved, "schema");
|
|
82
|
+
result.push({
|
|
83
|
+
name,
|
|
84
|
+
location: toParameterLocation(location),
|
|
85
|
+
required: getProperty(resolved, "required") === true,
|
|
86
|
+
deprecated: getProperty(resolved, "deprecated") === true,
|
|
87
|
+
description: getString(resolved, "description"),
|
|
88
|
+
schema: isObject(schema) ? schema : void 0
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function resolveParam(param) {
|
|
94
|
+
const ref = getProperty(param, "$ref");
|
|
95
|
+
if (typeof ref === "string" && ref.startsWith("#/")) {
|
|
96
|
+
const resolved = resolveRefInDoc(param, ref);
|
|
97
|
+
if (resolved !== void 0) return resolved;
|
|
98
|
+
}
|
|
99
|
+
return param;
|
|
100
|
+
}
|
|
101
|
+
function getRequestBody(parsed, path, method) {
|
|
102
|
+
const requestBody = getProperty(getProperty(getProperty(getProperty(parsed.doc, "paths"), path), method), "requestBody");
|
|
103
|
+
if (!isObject(requestBody)) return void 0;
|
|
104
|
+
const content = getProperty(requestBody, "content");
|
|
105
|
+
if (!isObject(content)) return {
|
|
106
|
+
required: getProperty(requestBody, "required") === true,
|
|
107
|
+
description: getString(requestBody, "description"),
|
|
108
|
+
contentTypes: [],
|
|
109
|
+
schema: void 0
|
|
110
|
+
};
|
|
111
|
+
const contentTypes = Object.keys(content);
|
|
112
|
+
const schema = extractSchemaFromContent(content);
|
|
113
|
+
return {
|
|
114
|
+
required: getProperty(requestBody, "required") === true,
|
|
115
|
+
description: getString(requestBody, "description"),
|
|
116
|
+
contentTypes,
|
|
117
|
+
schema
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function getResponses(parsed, path, method) {
|
|
121
|
+
const responses = getProperty(getProperty(getProperty(getProperty(parsed.doc, "paths"), path), method), "responses");
|
|
122
|
+
if (!isObject(responses)) return [];
|
|
123
|
+
const result = [];
|
|
124
|
+
for (const [statusCode, response] of Object.entries(responses)) {
|
|
125
|
+
if (!isObject(response)) continue;
|
|
126
|
+
const content = getProperty(response, "content");
|
|
127
|
+
const contentTypes = isObject(content) ? Object.keys(content) : [];
|
|
128
|
+
const schema = isObject(content) ? extractSchemaFromContent(content) : void 0;
|
|
129
|
+
result.push({
|
|
130
|
+
statusCode,
|
|
131
|
+
description: getString(response, "description"),
|
|
132
|
+
contentTypes,
|
|
133
|
+
schema
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
function extractSchemaFromContent(content) {
|
|
139
|
+
const jsonSchema = getProperty(getProperty(content, "application/json"), "schema");
|
|
140
|
+
if (isObject(jsonSchema)) return jsonSchema;
|
|
141
|
+
for (const mediaType of Object.values(content)) {
|
|
142
|
+
if (!isObject(mediaType)) continue;
|
|
143
|
+
const schema = getProperty(mediaType, "schema");
|
|
144
|
+
if (isObject(schema)) return schema;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function resolveRefInDoc(doc, ref) {
|
|
148
|
+
if (!ref.startsWith("#/")) return void 0;
|
|
149
|
+
const parts = ref.slice(2).split("/");
|
|
150
|
+
let current = doc;
|
|
151
|
+
for (const part of parts) {
|
|
152
|
+
if (!isObject(current)) return void 0;
|
|
153
|
+
const decoded = part.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
154
|
+
current = current[decoded];
|
|
155
|
+
}
|
|
156
|
+
return isObject(current) ? current : void 0;
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { getParameters, getRequestBody, getResponses, getSchema, listOperations, parseOpenApiDocument };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { E as RenderProps, _ as WalkedField, a as FromJSONSchema, b as ComponentResolver, f as PathOfType, i as FieldOverrides, m as SchemaMeta, p as ResolveOpenAPIRef, r as FieldOverride } from "../types-BU0ETFHk.mjs";
|
|
2
|
+
import { t as SchemaError } from "../errors-DIKI2C78.mjs";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { ReactNode } from "react";
|
|
5
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/react/SchemaComponent.d.ts
|
|
8
|
+
declare function SchemaProvider({
|
|
9
|
+
resolver,
|
|
10
|
+
children
|
|
11
|
+
}: {
|
|
12
|
+
resolver: ComponentResolver;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}): _$react_jsx_runtime0.JSX.Element;
|
|
15
|
+
declare function registerWidget(name: string, render: (props: RenderProps) => unknown): void;
|
|
16
|
+
type InferFields<T, Ref extends string | undefined> = T extends z.ZodType ? FieldOverrides<z.infer<T>> : T extends {
|
|
17
|
+
openapi: unknown;
|
|
18
|
+
} ? Ref extends string ? FieldOverrides<ResolveOpenAPIRef<T & Record<string, unknown>, Ref>> : Record<string, FieldOverride> : T extends object ? unknown extends FromJSONSchema<T> ? Record<string, FieldOverride> : FieldOverrides<FromJSONSchema<T>> : Record<string, FieldOverride>;
|
|
19
|
+
interface SchemaComponentProps<T = unknown, Ref extends string | undefined = undefined> {
|
|
20
|
+
/** Zod schema, JSON Schema object, or OpenAPI document. */
|
|
21
|
+
schema: T;
|
|
22
|
+
/** For OpenAPI: a ref string like "#/components/schemas/User" or "/users/post". */
|
|
23
|
+
ref?: Ref;
|
|
24
|
+
/** Current value to render. */
|
|
25
|
+
value?: unknown;
|
|
26
|
+
/** Called when the value changes (editable fields). */
|
|
27
|
+
onChange?: (value: unknown) => void;
|
|
28
|
+
/** Run schema.safeParse() on change and surface errors via onValidationError. */
|
|
29
|
+
validate?: boolean;
|
|
30
|
+
/** Called with the ZodError when validation fails. */
|
|
31
|
+
onValidationError?: (error: unknown) => void;
|
|
32
|
+
/** Called when schema normalisation or rendering fails. */
|
|
33
|
+
onError?: (error: SchemaError) => void;
|
|
34
|
+
/** Per-field meta overrides — nested object mirroring schema shape. */
|
|
35
|
+
fields?: InferFields<T, Ref>;
|
|
36
|
+
/** Meta overrides applied to the root schema. */
|
|
37
|
+
meta?: SchemaMeta;
|
|
38
|
+
/** Convenience: sets readOnly on all fields. */
|
|
39
|
+
readOnly?: boolean;
|
|
40
|
+
/** Convenience: sets writeOnly on all fields. */
|
|
41
|
+
writeOnly?: boolean;
|
|
42
|
+
/** Convenience: sets description on the root. */
|
|
43
|
+
description?: string;
|
|
44
|
+
}
|
|
45
|
+
declare function SchemaComponent<T = unknown, Ref extends string | undefined = undefined>({
|
|
46
|
+
schema: schemaInput,
|
|
47
|
+
ref: refInput,
|
|
48
|
+
value,
|
|
49
|
+
onChange,
|
|
50
|
+
validate,
|
|
51
|
+
onValidationError,
|
|
52
|
+
onError,
|
|
53
|
+
fields,
|
|
54
|
+
meta: componentMeta,
|
|
55
|
+
readOnly,
|
|
56
|
+
writeOnly,
|
|
57
|
+
description
|
|
58
|
+
}: SchemaComponentProps<T, Ref>): ReactNode;
|
|
59
|
+
declare function renderField(tree: WalkedField, value: unknown, onChange: (v: unknown) => void, userResolver: ComponentResolver | undefined, renderChild: (tree: WalkedField, value: unknown, onChange: (v: unknown) => void) => ReactNode): ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* Infer the schema's output type for SchemaField path inference.
|
|
62
|
+
*/
|
|
63
|
+
type InferSchemaType<T> = T extends z.ZodType ? z.infer<T> : T extends object ? unknown extends FromJSONSchema<T> ? unknown : FromJSONSchema<T> : unknown;
|
|
64
|
+
interface SchemaFieldProps<T = unknown, Ref extends string | undefined = undefined, P extends string = PathOfType<InferSchemaType<T>> | (string extends PathOfType<InferSchemaType<T>> ? string : never)> {
|
|
65
|
+
/**
|
|
66
|
+
* Dot-separated path to the field (e.g. "address.city").
|
|
67
|
+
* When the schema is a Zod schema or typed `as const`, only valid
|
|
68
|
+
* paths are accepted. Falls back to `string` for runtime schemas.
|
|
69
|
+
*/
|
|
70
|
+
path: P;
|
|
71
|
+
/** The schema to extract the field from. */
|
|
72
|
+
schema: T;
|
|
73
|
+
/** For OpenAPI: a ref string. */
|
|
74
|
+
ref?: Ref;
|
|
75
|
+
/** Current value of the field at the given path. */
|
|
76
|
+
value?: unknown;
|
|
77
|
+
/** Called with the updated root value when this field changes. */
|
|
78
|
+
onChange?: (value: unknown) => void;
|
|
79
|
+
/** Override meta for this specific field. */
|
|
80
|
+
meta?: SchemaMeta;
|
|
81
|
+
/** Run validation on change. */
|
|
82
|
+
validate?: boolean;
|
|
83
|
+
onValidationError?: (error: unknown) => void;
|
|
84
|
+
}
|
|
85
|
+
declare function SchemaField<T = unknown, Ref extends string | undefined = undefined, P extends string = string>({
|
|
86
|
+
path,
|
|
87
|
+
schema: schemaInput,
|
|
88
|
+
ref: refInput,
|
|
89
|
+
value,
|
|
90
|
+
onChange,
|
|
91
|
+
meta: fieldMeta,
|
|
92
|
+
validate,
|
|
93
|
+
onValidationError
|
|
94
|
+
}: SchemaFieldProps<T, Ref, P>): ReactNode;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { SchemaComponent, SchemaComponentProps, SchemaField, SchemaFieldProps, SchemaProvider, registerWidget, renderField };
|