matrix-nodejs-homeserver 0.2.0 → 0.3.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 +29 -7
- package/dist/api/account.js +385 -351
- package/dist/api/admin.js +76 -60
- package/dist/api/appservice.js +37 -25
- package/dist/api/backup.js +73 -62
- package/dist/api/federation.js +172 -138
- package/dist/api/filters.js +4 -3
- package/dist/api/legacy.js +91 -78
- package/dist/api/media.js +70 -54
- package/dist/api/misc.js +46 -37
- package/dist/api/preview.js +4 -3
- package/dist/api/profile.js +108 -97
- package/dist/api/push.js +114 -99
- package/dist/api/relationships.js +64 -58
- package/dist/api/rooms.js +703 -580
- package/dist/api/rtc.d.ts +0 -1
- package/dist/api/rtc.js +48 -34
- package/dist/api/search.js +133 -127
- package/dist/api/slidingsync.js +41 -31
- package/dist/api/spaces.js +82 -77
- package/dist/api/sync.js +59 -50
- package/dist/api/threadsubs.js +72 -61
- package/dist/api/threepid.js +99 -66
- package/dist/api/uia.js +17 -16
- package/dist/api/user.js +221 -178
- package/dist/core/admin.d.ts +0 -1
- package/dist/core/admin.js +6 -5
- package/dist/core/adminroom.js +9 -8
- package/dist/core/appservices.d.ts +2 -1
- package/dist/core/appservices.js +5 -4
- package/dist/core/audit.d.ts +0 -1
- package/dist/core/authrules.js +26 -25
- package/dist/core/delayed.js +2 -1
- package/dist/core/events.js +11 -10
- package/dist/core/invitefilter.js +2 -1
- package/dist/core/keys.js +2 -1
- package/dist/core/m.d.ts +209 -0
- package/dist/core/m.js +182 -0
- package/dist/core/partialstate.js +2 -1
- package/dist/core/policy.js +4 -3
- package/dist/core/push.d.ts +0 -1
- package/dist/core/push.js +12 -11
- package/dist/core/pushrules.js +36 -35
- package/dist/core/rooms.js +76 -74
- package/dist/core/stateres.js +7 -6
- package/dist/federation/client.js +2 -1
- package/dist/federation/index.d.ts +1 -1
- package/dist/federation/index.js +30 -29
- package/dist/homeserver.d.ts +2 -1
- package/dist/homeserver.js +1 -0
- package/dist/http/handler.js +2 -23
- package/dist/http/input.js +2 -2
- package/dist/http/procedure.js +25 -0
- package/dist/http/router.d.ts +9 -26
- package/dist/http/router.js +10 -30
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/vendor/zod/LICENSE +21 -0
- package/dist/vendor/zod/v4/classic/errors.js +54 -0
- package/dist/vendor/zod/v4/classic/parse.js +17 -0
- package/dist/vendor/zod/v4/classic/schemas.js +865 -0
- package/dist/vendor/zod/v4/core/api.js +512 -0
- package/dist/vendor/zod/v4/core/checks.js +300 -0
- package/dist/vendor/zod/v4/core/core.js +109 -0
- package/dist/vendor/zod/v4/core/doc.js +35 -0
- package/dist/vendor/zod/v4/core/errors.js +118 -0
- package/dist/vendor/zod/v4/core/json-schema-processors.js +428 -0
- package/dist/vendor/zod/v4/core/memoizer.js +255 -0
- package/dist/vendor/zod/v4/core/parse.js +206 -0
- package/dist/vendor/zod/v4/core/regexes.js +73 -0
- package/dist/vendor/zod/v4/core/registries.js +48 -0
- package/dist/vendor/zod/v4/core/schemas.js +1378 -0
- package/dist/vendor/zod/v4/core/to-json-schema.js +448 -0
- package/dist/vendor/zod/v4/core/util.js +537 -0
- package/dist/vendor/zod/v4/core/versions.js +8 -0
- package/dist/vendor/zod/v4/locales/en.js +110 -0
- package/package.json +3 -5
- package/dist/core/pushrules.d.ts +0 -1
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import { assignProp } from "./util.js";
|
|
2
|
+
import { globalRegistry } from "./registries.js";
|
|
3
|
+
//#region node_modules/zod/v4/core/to-json-schema.js
|
|
4
|
+
function assignProps(target, ...sources) {
|
|
5
|
+
for (const source of sources) for (const key of Reflect.ownKeys(source)) if (Object.prototype.propertyIsEnumerable.call(source, key)) assignProp(target, key, source[key]);
|
|
6
|
+
return target;
|
|
7
|
+
}
|
|
8
|
+
function initializeContext(params) {
|
|
9
|
+
let target = params?.target ?? "draft-2020-12";
|
|
10
|
+
if (target === "draft-4") target = "draft-04";
|
|
11
|
+
if (target === "draft-7") target = "draft-07";
|
|
12
|
+
return {
|
|
13
|
+
processors: params.processors ?? {},
|
|
14
|
+
metadataRegistry: params?.metadata ?? globalRegistry,
|
|
15
|
+
target,
|
|
16
|
+
unrepresentable: params?.unrepresentable ?? "throw",
|
|
17
|
+
override: params?.override ?? (() => {}),
|
|
18
|
+
io: params?.io ?? "output",
|
|
19
|
+
counter: 0,
|
|
20
|
+
seen: /* @__PURE__ */ new Map(),
|
|
21
|
+
sharedDefsExtractedFor: void 0,
|
|
22
|
+
sharedEmitDoneFor: void 0,
|
|
23
|
+
cycles: params?.cycles ?? "ref",
|
|
24
|
+
reused: params?.reused ?? "inline",
|
|
25
|
+
intersections: [],
|
|
26
|
+
deferred: [],
|
|
27
|
+
external: params?.external ?? void 0
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Applies the `unrepresentable` setting at a site that has no JSON Schema equivalent. Throws
|
|
32
|
+
* `message` unless the setting (or the handler's return value) says otherwise. Returns `true` if a
|
|
33
|
+
* custom JSON Schema was written into `json`, in which case the caller must not write its own.
|
|
34
|
+
*/
|
|
35
|
+
function handleUnrepresentable(schema, ctx, json, params, message) {
|
|
36
|
+
const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({
|
|
37
|
+
zodSchema: schema,
|
|
38
|
+
path: params.path,
|
|
39
|
+
message
|
|
40
|
+
}) : ctx.unrepresentable;
|
|
41
|
+
if (result === "any") return false;
|
|
42
|
+
if (result === void 0 || result === "throw") throw new Error(message);
|
|
43
|
+
Object.assign(json, result);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
function processSchema(schema, ctx, _params = {
|
|
47
|
+
path: [],
|
|
48
|
+
schemaPath: []
|
|
49
|
+
}) {
|
|
50
|
+
var _a;
|
|
51
|
+
const def = schema._zod.def;
|
|
52
|
+
const seen = ctx.seen.get(schema);
|
|
53
|
+
if (seen) {
|
|
54
|
+
seen.count++;
|
|
55
|
+
if (_params.schemaPath.includes(schema)) seen.cycle = _params.path;
|
|
56
|
+
return seen.schema;
|
|
57
|
+
}
|
|
58
|
+
const result = {
|
|
59
|
+
schema: {},
|
|
60
|
+
count: 1,
|
|
61
|
+
cycle: void 0,
|
|
62
|
+
path: _params.path
|
|
63
|
+
};
|
|
64
|
+
ctx.seen.set(schema, result);
|
|
65
|
+
ctx.sharedDefsExtractedFor = void 0;
|
|
66
|
+
ctx.sharedEmitDoneFor = void 0;
|
|
67
|
+
const overrideSchema = schema._zod.toJSONSchema?.();
|
|
68
|
+
if (overrideSchema) result.schema = overrideSchema;
|
|
69
|
+
else {
|
|
70
|
+
const params = {
|
|
71
|
+
..._params,
|
|
72
|
+
schemaPath: [..._params.schemaPath, schema],
|
|
73
|
+
path: _params.path
|
|
74
|
+
};
|
|
75
|
+
if (schema._zod.processJSONSchema) schema._zod.processJSONSchema(ctx, result.schema, params);
|
|
76
|
+
else {
|
|
77
|
+
const _json = result.schema;
|
|
78
|
+
const processor = ctx.processors[def.type];
|
|
79
|
+
if (!processor) throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`);
|
|
80
|
+
processor(schema, ctx, _json, params);
|
|
81
|
+
}
|
|
82
|
+
const parent = schema._zod.parent;
|
|
83
|
+
if (parent) {
|
|
84
|
+
if (!result.ref) result.ref = parent;
|
|
85
|
+
processSchema(parent, ctx, params);
|
|
86
|
+
ctx.seen.get(parent).isParent = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const meta = ctx.metadataRegistry.get(schema);
|
|
90
|
+
if (meta) assignProps(result.schema, meta);
|
|
91
|
+
if (ctx.io === "input" && isTransforming(schema)) {
|
|
92
|
+
delete result.schema.examples;
|
|
93
|
+
delete result.schema.default;
|
|
94
|
+
}
|
|
95
|
+
if (ctx.io === "input" && "_prefault" in result.schema) (_a = result.schema).default ?? (_a.default = result.schema._prefault);
|
|
96
|
+
delete result.schema._prefault;
|
|
97
|
+
return ctx.seen.get(schema).schema;
|
|
98
|
+
}
|
|
99
|
+
function encodeJSONPointerSegment(segment) {
|
|
100
|
+
return segment.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
101
|
+
}
|
|
102
|
+
function extractDefs(ctx, schema) {
|
|
103
|
+
const root = ctx.seen.get(schema);
|
|
104
|
+
if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
105
|
+
if (ctx.external && ctx.sharedDefsExtractedFor === ctx.external) return;
|
|
106
|
+
const idToSchema = /* @__PURE__ */ new Map();
|
|
107
|
+
for (const entry of ctx.seen.entries()) {
|
|
108
|
+
const id = ctx.metadataRegistry.get(entry[0])?.id;
|
|
109
|
+
if (id) {
|
|
110
|
+
const existing = idToSchema.get(id);
|
|
111
|
+
if (existing && existing !== entry[0]) throw new Error(`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
|
|
112
|
+
idToSchema.set(id, entry[0]);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const makeURI = (entry) => {
|
|
116
|
+
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
117
|
+
if (ctx.external) {
|
|
118
|
+
const externalId = ctx.external.registry.get(entry[0])?.id;
|
|
119
|
+
const uriGenerator = ctx.external.uri ?? ((id) => id);
|
|
120
|
+
if (externalId) return { ref: uriGenerator(externalId) };
|
|
121
|
+
const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
|
|
122
|
+
entry[1].defId = id;
|
|
123
|
+
return {
|
|
124
|
+
defId: id,
|
|
125
|
+
ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id)}`
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const uriPrefix = `#`;
|
|
129
|
+
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
|
130
|
+
if (entry[1] === root && !entry[1].schema.id) return { ref: uriPrefix };
|
|
131
|
+
const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`;
|
|
132
|
+
return {
|
|
133
|
+
defId,
|
|
134
|
+
ref: defUriPrefix + encodeJSONPointerSegment(defId)
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
const extractToDef = (entry) => {
|
|
138
|
+
if (entry[1].schema.$ref) return;
|
|
139
|
+
const seen = entry[1];
|
|
140
|
+
const { ref, defId } = makeURI(entry);
|
|
141
|
+
seen.def = { ...seen.schema };
|
|
142
|
+
if (defId) seen.defId = defId;
|
|
143
|
+
const schema = seen.schema;
|
|
144
|
+
for (const key in schema) delete schema[key];
|
|
145
|
+
schema.$ref = ref;
|
|
146
|
+
};
|
|
147
|
+
if (ctx.cycles === "throw") for (const entry of ctx.seen.entries()) {
|
|
148
|
+
const seen = entry[1];
|
|
149
|
+
if (seen.cycle) throw new Error(`Cycle detected: #/${seen.cycle?.join("/")}/<root>
|
|
150
|
+
|
|
151
|
+
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`);
|
|
152
|
+
}
|
|
153
|
+
for (const entry of ctx.seen.entries()) {
|
|
154
|
+
const seen = entry[1];
|
|
155
|
+
if (schema === entry[0]) {
|
|
156
|
+
extractToDef(entry);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (ctx.external) {
|
|
160
|
+
const ext = ctx.external.registry.get(entry[0])?.id;
|
|
161
|
+
if (schema !== entry[0] && ext) {
|
|
162
|
+
extractToDef(entry);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (ctx.metadataRegistry.get(entry[0])?.id) {
|
|
167
|
+
extractToDef(entry);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (seen.cycle) {
|
|
171
|
+
extractToDef(entry);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (seen.count > 1) {
|
|
175
|
+
if (ctx.reused === "ref") extractToDef(entry);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (ctx.external) ctx.sharedDefsExtractedFor = ctx.external;
|
|
179
|
+
}
|
|
180
|
+
/** Rewrites `anyOf: [{type: "a"}, {type: "b"}]` to `type: ["a", "b"]`, which every JSON Schema draft treats as equivalent and most consumers render far better for the nullable case. Only branches that are a bare type assertion qualify — anything carrying a constraint, `$ref`, `const` or metadata is left alone. Runs after `flattenRef`, so a branch an override decorated or `$defs` extraction turned into a `$ref` is no longer bare and correctly stays in `anyOf`. `oneOf` is excluded: `integer` and `number` overlap, so "exactly one" and "at least one" are not the same there. OpenAPI 3.0 is excluded: its `type` must be a single string. */
|
|
181
|
+
function compactTypeUnion(schema) {
|
|
182
|
+
const options = schema.anyOf;
|
|
183
|
+
if (!Array.isArray(options) || options.length === 0 || schema.type !== void 0) return;
|
|
184
|
+
const types = [];
|
|
185
|
+
for (const option of options) {
|
|
186
|
+
if (!option || typeof option !== "object") return;
|
|
187
|
+
compactTypeUnion(option);
|
|
188
|
+
const keys = Object.keys(option);
|
|
189
|
+
if (keys.length !== 1 || keys[0] !== "type") return;
|
|
190
|
+
const type = option.type;
|
|
191
|
+
for (const member of Array.isArray(type) ? type : [type]) {
|
|
192
|
+
if (typeof member !== "string") return;
|
|
193
|
+
if (!types.includes(member)) types.push(member);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
delete schema.anyOf;
|
|
197
|
+
schema.type = types.length === 1 ? types[0] : types;
|
|
198
|
+
}
|
|
199
|
+
/** Keywords `foldIntersection` knows how to combine. Anything else — `$ref`, `patternProperties`,
|
|
200
|
+
* an annotation like `description` — makes a member unfoldable, so a constraint this does not
|
|
201
|
+
* understand leaves the `allOf` alone instead of being silently dropped or misattributed. */
|
|
202
|
+
const FOLDABLE_KEYS = /* @__PURE__ */ new Set([
|
|
203
|
+
"type",
|
|
204
|
+
"properties",
|
|
205
|
+
"required",
|
|
206
|
+
"additionalProperties"
|
|
207
|
+
]);
|
|
208
|
+
const UNION_KEYS = ["oneOf", "anyOf"];
|
|
209
|
+
/** A member's constraint on a key it does not declare itself. A `catchall` states one; `false`, an absent `additionalProperties`, and the empty schema a loose object emits state nothing. */
|
|
210
|
+
function undeclaredConstraint(member) {
|
|
211
|
+
const extra = member.additionalProperties;
|
|
212
|
+
if (extra === void 0 || extra === false || typeof extra !== "object" || extra === null) return null;
|
|
213
|
+
return Object.keys(extra).length ? extra : null;
|
|
214
|
+
}
|
|
215
|
+
/** Combines object members into the single object they describe together, or returns `null` if any of them carries a keyword outside {@link FOLDABLE_KEYS}. */
|
|
216
|
+
function foldObjects(members) {
|
|
217
|
+
const objects = [];
|
|
218
|
+
for (const member of members) {
|
|
219
|
+
if (typeof member !== "object" || member.type !== "object") return null;
|
|
220
|
+
for (const key in member) if (!FOLDABLE_KEYS.has(key)) return null;
|
|
221
|
+
objects.push(member);
|
|
222
|
+
}
|
|
223
|
+
const properties = {};
|
|
224
|
+
const required = /* @__PURE__ */ new Set();
|
|
225
|
+
for (const object of objects) {
|
|
226
|
+
for (const key in object.properties) {
|
|
227
|
+
if (Object.prototype.hasOwnProperty.call(properties, key)) continue;
|
|
228
|
+
const parts = [];
|
|
229
|
+
for (const other of objects) {
|
|
230
|
+
const part = other.properties?.[key] ?? undeclaredConstraint(other);
|
|
231
|
+
if (part === null || part === void 0) continue;
|
|
232
|
+
if (!parts.some((seen) => JSON.stringify(seen) === JSON.stringify(part))) parts.push(part);
|
|
233
|
+
}
|
|
234
|
+
const merged = parts.length === 1 ? parts[0] : foldObjects(parts) ?? { allOf: parts };
|
|
235
|
+
assignProp(properties, key, merged);
|
|
236
|
+
}
|
|
237
|
+
for (const key of object.required ?? []) required.add(key);
|
|
238
|
+
}
|
|
239
|
+
const folded = {
|
|
240
|
+
type: "object",
|
|
241
|
+
properties
|
|
242
|
+
};
|
|
243
|
+
if (required.size) folded.required = [...required];
|
|
244
|
+
if (objects.every((object) => object.additionalProperties === false)) folded.additionalProperties = false;
|
|
245
|
+
else {
|
|
246
|
+
const constraints = [];
|
|
247
|
+
for (const object of objects) {
|
|
248
|
+
const constraint = undeclaredConstraint(object);
|
|
249
|
+
if (constraint && !constraints.some((seen) => JSON.stringify(seen) === JSON.stringify(constraint))) constraints.push(constraint);
|
|
250
|
+
}
|
|
251
|
+
if (constraints.length === 1) folded.additionalProperties = constraints[0];
|
|
252
|
+
else if (constraints.length > 1) folded.additionalProperties = { allOf: constraints };
|
|
253
|
+
}
|
|
254
|
+
return folded;
|
|
255
|
+
}
|
|
256
|
+
/** `additionalProperties` in an `allOf` member sees only that member's own `properties`, so two
|
|
257
|
+
* closed object members reject each other's keys and the schema validates nothing. Zod's parser
|
|
258
|
+
* pools the key sets instead — `handleIntersectionResults` reports a key as unrecognized only when
|
|
259
|
+
* *every* side rejects it — so the emitted schema has to pool them too, and folding the members
|
|
260
|
+
* into one object is the encoding that says so on every target.
|
|
261
|
+
*
|
|
262
|
+
* This runs from `finalize`, after `extractDefs`, which is what keeps it clear of the `$ref`
|
|
263
|
+
* machinery: a member extracted into `$defs` is already a `$ref` by now and declines to fold, so it
|
|
264
|
+
* keeps its reference and its own closedness rather than being inlined as a stale copy. */
|
|
265
|
+
function foldIntersection(json) {
|
|
266
|
+
const allOf = json.allOf;
|
|
267
|
+
if (!Array.isArray(allOf) || allOf.length < 2) return;
|
|
268
|
+
for (const key of FOLDABLE_KEYS) if (key in json) return;
|
|
269
|
+
const unions = allOf.filter((m) => UNION_KEYS.some((k) => Array.isArray(m[k])));
|
|
270
|
+
let folded = null;
|
|
271
|
+
if (!unions.length) folded = foldObjects(allOf);
|
|
272
|
+
else {
|
|
273
|
+
const union = unions[0];
|
|
274
|
+
const keyword = UNION_KEYS.find((k) => Array.isArray(union[k]));
|
|
275
|
+
if (Object.keys(union).length !== 1) return;
|
|
276
|
+
const rest = allOf.filter((m) => m !== union);
|
|
277
|
+
const branches = union[keyword].map((branch) => foldObjects([...rest, branch]));
|
|
278
|
+
if (branches.some((b) => !b)) return;
|
|
279
|
+
folded = { [keyword]: branches };
|
|
280
|
+
}
|
|
281
|
+
if (!folded) return;
|
|
282
|
+
delete json.allOf;
|
|
283
|
+
assignProps(json, folded);
|
|
284
|
+
}
|
|
285
|
+
function finalize(ctx, schema) {
|
|
286
|
+
const root = ctx.seen.get(schema);
|
|
287
|
+
if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
288
|
+
const flattenRef = (zodSchema) => {
|
|
289
|
+
const seen = ctx.seen.get(zodSchema);
|
|
290
|
+
if (seen.ref === null) return;
|
|
291
|
+
const schema = seen.def ?? seen.schema;
|
|
292
|
+
const _cached = { ...schema };
|
|
293
|
+
const ref = seen.ref;
|
|
294
|
+
seen.ref = null;
|
|
295
|
+
if (ref) {
|
|
296
|
+
flattenRef(ref);
|
|
297
|
+
const refSeen = ctx.seen.get(ref);
|
|
298
|
+
const refSchema = refSeen.schema;
|
|
299
|
+
if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) {
|
|
300
|
+
schema.allOf = schema.allOf ?? [];
|
|
301
|
+
schema.allOf.push(refSchema);
|
|
302
|
+
} else assignProps(schema, refSchema);
|
|
303
|
+
assignProps(schema, _cached);
|
|
304
|
+
if (zodSchema._zod.parent === ref) for (const key in schema) {
|
|
305
|
+
if (key === "$ref" || key === "allOf") continue;
|
|
306
|
+
if (!(key in _cached)) delete schema[key];
|
|
307
|
+
}
|
|
308
|
+
if (refSchema.$ref && refSeen.def) for (const key in schema) {
|
|
309
|
+
if (key === "$ref" || key === "allOf") continue;
|
|
310
|
+
if (key in refSeen.def && JSON.stringify(schema[key]) === JSON.stringify(refSeen.def[key])) delete schema[key];
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const parent = zodSchema._zod.parent;
|
|
314
|
+
if (parent && parent !== ref) {
|
|
315
|
+
flattenRef(parent);
|
|
316
|
+
const parentSeen = ctx.seen.get(parent);
|
|
317
|
+
if (parentSeen?.schema.$ref) {
|
|
318
|
+
schema.$ref = parentSeen.schema.$ref;
|
|
319
|
+
if (parentSeen.def) for (const key in schema) {
|
|
320
|
+
if (key === "$ref" || key === "allOf") continue;
|
|
321
|
+
if (key in parentSeen.def && JSON.stringify(schema[key]) === JSON.stringify(parentSeen.def[key])) delete schema[key];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
ctx.override({
|
|
326
|
+
zodSchema,
|
|
327
|
+
jsonSchema: schema,
|
|
328
|
+
path: seen.path ?? []
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
if (!ctx.external || ctx.sharedEmitDoneFor !== ctx.external) {
|
|
332
|
+
for (const entry of [...ctx.seen.entries()].reverse()) flattenRef(entry[0]);
|
|
333
|
+
if (ctx.target !== "openapi-3.0") for (const entry of ctx.seen.entries()) compactTypeUnion(entry[1].def ?? entry[1].schema);
|
|
334
|
+
for (const rewrite of ctx.deferred) rewrite();
|
|
335
|
+
if (ctx.intersections.length) {
|
|
336
|
+
const carriers = /* @__PURE__ */ new Map();
|
|
337
|
+
for (const seen of ctx.seen.values()) for (const json of [seen.schema, seen.def]) {
|
|
338
|
+
const allOf = json?.allOf;
|
|
339
|
+
if (!Array.isArray(allOf)) continue;
|
|
340
|
+
const existing = carriers.get(allOf);
|
|
341
|
+
if (existing) existing.push(json);
|
|
342
|
+
else carriers.set(allOf, [json]);
|
|
343
|
+
}
|
|
344
|
+
for (const allOf of ctx.intersections) for (const json of carriers.get(allOf) ?? []) foldIntersection(json);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const result = {};
|
|
348
|
+
if (ctx.target === "draft-2020-12") result.$schema = "https://json-schema.org/draft/2020-12/schema";
|
|
349
|
+
else if (ctx.target === "draft-07") result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
350
|
+
else if (ctx.target === "draft-04") result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
351
|
+
else if (ctx.target === "openapi-3.0") {}
|
|
352
|
+
if (ctx.external?.uri) {
|
|
353
|
+
const id = ctx.external.registry.get(schema)?.id;
|
|
354
|
+
if (!id) throw new Error("Schema is missing an `id` property");
|
|
355
|
+
result.$id = ctx.external.uri(id);
|
|
356
|
+
}
|
|
357
|
+
assignProps(result, root.defId ? root.schema : root.def ?? root.schema);
|
|
358
|
+
const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
|
|
359
|
+
if (rootMetaId !== void 0 && result.id === rootMetaId) delete result.id;
|
|
360
|
+
const defs = ctx.external?.defs ?? {};
|
|
361
|
+
if (!ctx.external || ctx.sharedEmitDoneFor !== ctx.external) for (const entry of ctx.seen.entries()) {
|
|
362
|
+
const seen = entry[1];
|
|
363
|
+
if (seen.def && seen.defId) {
|
|
364
|
+
if (seen.def.id === seen.defId) delete seen.def.id;
|
|
365
|
+
assignProp(defs, seen.defId, seen.def);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (ctx.external) ctx.sharedEmitDoneFor = ctx.external;
|
|
369
|
+
if (ctx.external) {} else if (Object.keys(defs).length > 0) {
|
|
370
|
+
if (ctx.target === "draft-2020-12") result.$defs = defs;
|
|
371
|
+
else result.definitions = defs;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
const finalized = JSON.parse(JSON.stringify(result));
|
|
375
|
+
Object.defineProperty(finalized, "~standard", {
|
|
376
|
+
value: {
|
|
377
|
+
...schema["~standard"],
|
|
378
|
+
jsonSchema: {
|
|
379
|
+
input: createStandardJSONSchemaMethod(schema, "input", ctx.processors),
|
|
380
|
+
output: createStandardJSONSchemaMethod(schema, "output", ctx.processors)
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
enumerable: false,
|
|
384
|
+
writable: false
|
|
385
|
+
});
|
|
386
|
+
return finalized;
|
|
387
|
+
} catch (_err) {
|
|
388
|
+
throw new Error("Error converting schema to JSON.");
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
function isTransforming(_schema, _ctx) {
|
|
392
|
+
const ctx = _ctx ?? { seen: /* @__PURE__ */ new Set() };
|
|
393
|
+
if (ctx.seen.has(_schema)) return false;
|
|
394
|
+
ctx.seen.add(_schema);
|
|
395
|
+
const def = _schema._zod.def;
|
|
396
|
+
if (def.type === "transform") return true;
|
|
397
|
+
if (def.type === "array") return isTransforming(def.element, ctx);
|
|
398
|
+
if (def.type === "set") return isTransforming(def.valueType, ctx);
|
|
399
|
+
if (def.type === "lazy") return isTransforming(def.getter(), ctx);
|
|
400
|
+
if (def.type === "promise" || def.type === "optional" || def.type === "nonoptional" || def.type === "nullable" || def.type === "readonly" || def.type === "default" || def.type === "prefault" || def.type === "catch") return isTransforming(def.innerType, ctx);
|
|
401
|
+
if (def.type === "intersection") return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
|
402
|
+
if (def.type === "record" || def.type === "map") return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
|
403
|
+
if (def.type === "pipe") {
|
|
404
|
+
if (_schema._zod.traits.has("$ZodCodec")) return true;
|
|
405
|
+
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
|
406
|
+
}
|
|
407
|
+
if (def.type === "object") {
|
|
408
|
+
for (const key in def.shape) if (isTransforming(def.shape[key], ctx)) return true;
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
if (def.type === "union") {
|
|
412
|
+
for (const option of def.options) if (isTransforming(option, ctx)) return true;
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
if (def.type === "tuple") {
|
|
416
|
+
for (const item of def.items) if (isTransforming(item, ctx)) return true;
|
|
417
|
+
if (def.rest && isTransforming(def.rest, ctx)) return true;
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
return false;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Creates a toJSONSchema method for a schema instance.
|
|
424
|
+
* This encapsulates the logic of initializing context, processing, extracting defs, and finalizing.
|
|
425
|
+
*/
|
|
426
|
+
const createToJSONSchemaMethod = (schema, processors = {}) => (params) => {
|
|
427
|
+
const ctx = initializeContext({
|
|
428
|
+
...params,
|
|
429
|
+
processors
|
|
430
|
+
});
|
|
431
|
+
processSchema(schema, ctx);
|
|
432
|
+
extractDefs(ctx, schema);
|
|
433
|
+
return finalize(ctx, schema);
|
|
434
|
+
};
|
|
435
|
+
const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
|
|
436
|
+
const { libraryOptions, target } = params ?? {};
|
|
437
|
+
const ctx = initializeContext({
|
|
438
|
+
...libraryOptions ?? {},
|
|
439
|
+
target,
|
|
440
|
+
io,
|
|
441
|
+
processors
|
|
442
|
+
});
|
|
443
|
+
processSchema(schema, ctx);
|
|
444
|
+
extractDefs(ctx, schema);
|
|
445
|
+
return finalize(ctx, schema);
|
|
446
|
+
};
|
|
447
|
+
//#endregion
|
|
448
|
+
export { createStandardJSONSchemaMethod, createToJSONSchemaMethod, extractDefs, finalize, handleUnrepresentable, initializeContext, processSchema as process, processSchema };
|