matrix-nodejs-homeserver 0.2.0 → 0.3.2
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 +89 -11
- package/dist/adapters/cluster.d.ts +1 -26
- package/dist/adapters/cluster.js +50 -103
- package/dist/api/account.js +407 -354
- package/dist/api/admin.js +82 -61
- 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 +71 -55
- package/dist/api/misc.js +46 -37
- package/dist/api/preview.js +37 -73
- 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 +325 -135
- 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/cluster.d.ts +12 -5
- package/dist/core/cluster.js +46 -29
- package/dist/core/delayed.js +2 -1
- package/dist/core/events.js +11 -10
- package/dist/core/html.js +13 -0
- package/dist/core/identity.js +1 -1
- package/dist/core/invitefilter.js +2 -1
- package/dist/core/json.js +10 -1
- package/dist/core/keys.d.ts +10 -1
- package/dist/core/keys.js +62 -42
- package/dist/core/m.d.ts +209 -0
- package/dist/core/m.js +182 -0
- package/dist/core/outbound.d.ts +16 -0
- package/dist/core/outbound.js +172 -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 +41 -28
- package/dist/core/pushrules.js +36 -35
- package/dist/core/ratelimit.d.ts +1 -1
- package/dist/core/rooms.d.ts +10 -1
- package/dist/core/rooms.js +101 -74
- package/dist/core/semaphore.js +23 -0
- package/dist/core/sso.d.ts +15 -1
- package/dist/core/sso.js +38 -2
- package/dist/core/stateres.js +7 -6
- package/dist/core/threepid.js +1 -9
- package/dist/federation/client.js +9 -1
- package/dist/federation/index.d.ts +2 -2
- package/dist/federation/index.js +43 -35
- package/dist/homeserver.d.ts +23 -4
- package/dist/homeserver.js +12 -3
- 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 +4 -3
- package/dist/index.js +3 -2
- package/dist/storage/batch.js +11 -0
- package/dist/storage/memory.js +1 -0
- package/dist/storage/schema.js +1 -1
- package/dist/storage/sql.js +20 -1
- package/dist/storage/types.d.ts +16 -0
- 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 +8 -6
- package/dist/core/pushrules.d.ts +0 -1
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { BIGINT_FORMAT_RANGES, NUMBER_FORMAT_RANGES, assignProp, getEnumValues } from "./util.js";
|
|
2
|
+
import { base64, base64url, integer, number } from "./regexes.js";
|
|
3
|
+
import { base64Charset, base64urlCharset } from "./schemas.js";
|
|
4
|
+
import { handleUnrepresentable, process as processSchema } from "./to-json-schema.js";
|
|
5
|
+
//#region node_modules/zod/v4/core/json-schema-processors.js
|
|
6
|
+
const narrowMin = (agg, key, value) => {
|
|
7
|
+
if (agg[key] === void 0 || value > agg[key]) agg[key] = value;
|
|
8
|
+
};
|
|
9
|
+
const narrowMax = (agg, key, value) => {
|
|
10
|
+
if (agg[key] === void 0 || value < agg[key]) agg[key] = value;
|
|
11
|
+
};
|
|
12
|
+
const narrowBoth = (agg, value) => {
|
|
13
|
+
narrowMin(agg, "minimum", value);
|
|
14
|
+
narrowMax(agg, "maximum", value);
|
|
15
|
+
};
|
|
16
|
+
const addDivisor = (agg, value) => {
|
|
17
|
+
agg.multipleOf ?? (agg.multipleOf = []);
|
|
18
|
+
if (!agg.multipleOf.includes(value)) agg.multipleOf.push(value);
|
|
19
|
+
};
|
|
20
|
+
const addPattern = (agg, pattern) => {
|
|
21
|
+
agg.patterns ?? (agg.patterns = /* @__PURE__ */ new Set());
|
|
22
|
+
agg.patterns.add(pattern);
|
|
23
|
+
};
|
|
24
|
+
const intersectMime = (agg, mime) => {
|
|
25
|
+
agg.mime = agg.mime ? agg.mime.filter((m) => mime.includes(m)) : [...mime];
|
|
26
|
+
};
|
|
27
|
+
const setFormat = (agg, format) => {
|
|
28
|
+
agg.format = format;
|
|
29
|
+
if (format.includes("int")) agg.isInt = true;
|
|
30
|
+
};
|
|
31
|
+
const minContributor = (agg, def) => narrowMin(agg, "minimum", def.minimum);
|
|
32
|
+
const maxContributor = (agg, def) => narrowMax(agg, "maximum", def.maximum);
|
|
33
|
+
const formatContributor = (ranges) => (agg, def) => {
|
|
34
|
+
setFormat(agg, def.format);
|
|
35
|
+
const [minimum, maximum] = ranges[def.format];
|
|
36
|
+
narrowMin(agg, "minimum", minimum);
|
|
37
|
+
narrowMax(agg, "maximum", maximum);
|
|
38
|
+
};
|
|
39
|
+
const contributors = {
|
|
40
|
+
greater_than: (agg, def) => narrowMin(agg, def.inclusive ? "minimum" : "exclusiveMinimum", def.value),
|
|
41
|
+
less_than: (agg, def) => narrowMax(agg, def.inclusive ? "maximum" : "exclusiveMaximum", def.value),
|
|
42
|
+
multiple_of: (agg, def) => addDivisor(agg, def.value),
|
|
43
|
+
number_format: formatContributor(NUMBER_FORMAT_RANGES),
|
|
44
|
+
bigint_format: formatContributor(BIGINT_FORMAT_RANGES),
|
|
45
|
+
min_length: minContributor,
|
|
46
|
+
max_length: maxContributor,
|
|
47
|
+
length_equals: (agg, def) => narrowBoth(agg, def.length),
|
|
48
|
+
min_size: minContributor,
|
|
49
|
+
max_size: maxContributor,
|
|
50
|
+
size_equals: (agg, def) => narrowBoth(agg, def.size),
|
|
51
|
+
string_format: (agg, def) => {
|
|
52
|
+
setFormat(agg, def.format);
|
|
53
|
+
if (def.pattern) addPattern(agg, def.pattern);
|
|
54
|
+
if (def.format === "base64" || def.format === "base64url") agg.contentEncoding = def.format;
|
|
55
|
+
if (def.local || def.precision === -1) agg.laxFormat = true;
|
|
56
|
+
},
|
|
57
|
+
mime_type: (agg, def) => intersectMime(agg, def.mime)
|
|
58
|
+
};
|
|
59
|
+
function aggregateChecks(schema) {
|
|
60
|
+
const agg = {};
|
|
61
|
+
const def = schema._zod.def;
|
|
62
|
+
const list = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? [];
|
|
63
|
+
for (const ch of list) contributors[ch._zod.def.check]?.(agg, ch._zod.def);
|
|
64
|
+
const bag = schema._zod.bag;
|
|
65
|
+
if (bag.minimum !== void 0) narrowMin(agg, "minimum", bag.minimum);
|
|
66
|
+
if (bag.exclusiveMinimum !== void 0) narrowMin(agg, "exclusiveMinimum", bag.exclusiveMinimum);
|
|
67
|
+
if (bag.maximum !== void 0) narrowMax(agg, "maximum", bag.maximum);
|
|
68
|
+
if (bag.exclusiveMaximum !== void 0) narrowMax(agg, "exclusiveMaximum", bag.exclusiveMaximum);
|
|
69
|
+
if (bag.multipleOf !== void 0) addDivisor(agg, bag.multipleOf);
|
|
70
|
+
if (bag.format !== void 0) {
|
|
71
|
+
agg.format ?? (agg.format = bag.format);
|
|
72
|
+
if (bag.format.includes("int")) agg.isInt = true;
|
|
73
|
+
}
|
|
74
|
+
if (bag.mime) intersectMime(agg, bag.mime);
|
|
75
|
+
for (const pattern of bag.patterns ?? []) addPattern(agg, pattern);
|
|
76
|
+
return agg;
|
|
77
|
+
}
|
|
78
|
+
const formatMap = {
|
|
79
|
+
guid: "uuid",
|
|
80
|
+
url: "uri",
|
|
81
|
+
datetime: "date-time",
|
|
82
|
+
json_string: "json-string",
|
|
83
|
+
regex: ""
|
|
84
|
+
};
|
|
85
|
+
const exactPatterns = /* @__PURE__ */ new Map([[base64Charset, base64], [base64urlCharset, base64url]]);
|
|
86
|
+
const exactPattern = (p) => exactPatterns.get(p) ?? p;
|
|
87
|
+
const stringProcessor = (schema, ctx, _json, _params) => {
|
|
88
|
+
const json = _json;
|
|
89
|
+
json.type = "string";
|
|
90
|
+
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
|
|
91
|
+
if (typeof minimum === "number") json.minLength = minimum;
|
|
92
|
+
if (typeof maximum === "number") json.maxLength = maximum;
|
|
93
|
+
if (format) {
|
|
94
|
+
json.format = formatMap[format] ?? format;
|
|
95
|
+
if (json.format === "") delete json.format;
|
|
96
|
+
if (format === "time" || laxFormat) delete json.format;
|
|
97
|
+
}
|
|
98
|
+
if (contentEncoding) json.contentEncoding = contentEncoding;
|
|
99
|
+
if (patterns && patterns.size > 0) {
|
|
100
|
+
const patternList = [...patterns].map(exactPattern);
|
|
101
|
+
if (patternList.length === 1) json.pattern = patternList[0].source;
|
|
102
|
+
else if (patternList.length > 1) json.allOf = [...patternList.map((regex) => ({
|
|
103
|
+
...ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0" ? { type: "string" } : {},
|
|
104
|
+
pattern: regex.source
|
|
105
|
+
}))];
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const numberProcessor = (schema, ctx, _json, params) => {
|
|
109
|
+
const json = _json;
|
|
110
|
+
const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks(schema);
|
|
111
|
+
json.type = isInt ? "integer" : "number";
|
|
112
|
+
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
|
|
113
|
+
const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
|
|
114
|
+
const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
|
|
115
|
+
if (exMin) {
|
|
116
|
+
if (legacy) {
|
|
117
|
+
json.minimum = exclusiveMinimum;
|
|
118
|
+
json.exclusiveMinimum = true;
|
|
119
|
+
} else json.exclusiveMinimum = exclusiveMinimum;
|
|
120
|
+
} else if (typeof minimum === "number") json.minimum = minimum;
|
|
121
|
+
if (exMax) {
|
|
122
|
+
if (legacy) {
|
|
123
|
+
json.maximum = exclusiveMaximum;
|
|
124
|
+
json.exclusiveMaximum = true;
|
|
125
|
+
} else json.exclusiveMaximum = exclusiveMaximum;
|
|
126
|
+
} else if (typeof maximum === "number") json.maximum = maximum;
|
|
127
|
+
if (multipleOf) {
|
|
128
|
+
const divisors = /* @__PURE__ */ new Set();
|
|
129
|
+
for (const divisor of multipleOf) if (Number.isFinite(divisor) && divisor !== 0) divisors.add(Math.abs(divisor));
|
|
130
|
+
else handleUnrepresentable(schema, ctx, json, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
|
|
131
|
+
const [first, ...rest] = divisors;
|
|
132
|
+
if (first !== void 0) json.multipleOf = first;
|
|
133
|
+
if (rest.length) json.allOf = [...json.allOf ?? [], ...rest.map((m) => ({ multipleOf: m }))];
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const booleanProcessor = (_schema, _ctx, json, _params) => {
|
|
137
|
+
json.type = "boolean";
|
|
138
|
+
};
|
|
139
|
+
const neverProcessor = (_schema, _ctx, json, _params) => {
|
|
140
|
+
json.not = {};
|
|
141
|
+
};
|
|
142
|
+
const unknownProcessor = (_schema, _ctx, _json, _params) => {};
|
|
143
|
+
const enumProcessor = (schema, _ctx, json, _params) => {
|
|
144
|
+
const def = schema._zod.def;
|
|
145
|
+
const values = getEnumValues(def.entries);
|
|
146
|
+
if (values.length === 0) {
|
|
147
|
+
json.not = {};
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (values.every((v) => typeof v === "number")) json.type = "number";
|
|
151
|
+
if (values.every((v) => typeof v === "string")) json.type = "string";
|
|
152
|
+
json.enum = values;
|
|
153
|
+
};
|
|
154
|
+
const customProcessor = (schema, ctx, json, params) => {
|
|
155
|
+
handleUnrepresentable(schema, ctx, json, params, "Custom types cannot be represented in JSON Schema");
|
|
156
|
+
};
|
|
157
|
+
const transformProcessor = (schema, ctx, json, params) => {
|
|
158
|
+
handleUnrepresentable(schema, ctx, json, params, "Transforms cannot be represented in JSON Schema");
|
|
159
|
+
};
|
|
160
|
+
const arrayProcessor = (schema, ctx, _json, params) => {
|
|
161
|
+
const json = _json;
|
|
162
|
+
const def = schema._zod.def;
|
|
163
|
+
const { minimum, maximum } = aggregateChecks(schema);
|
|
164
|
+
if (typeof minimum === "number") json.minItems = minimum;
|
|
165
|
+
if (typeof maximum === "number") json.maxItems = maximum;
|
|
166
|
+
json.type = "array";
|
|
167
|
+
json.items = processSchema(def.element, ctx, {
|
|
168
|
+
...params,
|
|
169
|
+
path: [...params.path, "items"]
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
function inputOptin(schema) {
|
|
173
|
+
const def = schema._zod.def;
|
|
174
|
+
if (def.type === "pipe" && def.in._zod.traits.has("$ZodTransform")) return inputOptin(def.out);
|
|
175
|
+
if (def.type === "catch") return inputOptin(def.innerType);
|
|
176
|
+
return schema._zod.optin;
|
|
177
|
+
}
|
|
178
|
+
const objectProcessor = (schema, ctx, _json, params) => {
|
|
179
|
+
const json = _json;
|
|
180
|
+
const def = schema._zod.def;
|
|
181
|
+
const shape = def.shape;
|
|
182
|
+
if (Object.getOwnPropertySymbols(shape).length && handleUnrepresentable(schema, ctx, json, params, "Symbol keys cannot be represented in JSON Schema")) return;
|
|
183
|
+
json.type = "object";
|
|
184
|
+
json.properties = {};
|
|
185
|
+
for (const key in shape) assignProp(json.properties, key, processSchema(shape[key], ctx, {
|
|
186
|
+
...params,
|
|
187
|
+
path: [
|
|
188
|
+
...params.path,
|
|
189
|
+
"properties",
|
|
190
|
+
key
|
|
191
|
+
]
|
|
192
|
+
}));
|
|
193
|
+
const requiredKeys = [];
|
|
194
|
+
for (const key of Object.keys(shape)) {
|
|
195
|
+
const field = def.shape[key];
|
|
196
|
+
if (ctx.io === "input" ? inputOptin(field) === void 0 : field._zod.optout === void 0) requiredKeys.push(key);
|
|
197
|
+
}
|
|
198
|
+
if (requiredKeys.length > 0) json.required = requiredKeys;
|
|
199
|
+
if (def.catchall?._zod.def.type === "never") json.additionalProperties = false;
|
|
200
|
+
else if (!def.catchall) {
|
|
201
|
+
if (ctx.io === "output") json.additionalProperties = false;
|
|
202
|
+
} else if (def.catchall) json.additionalProperties = processSchema(def.catchall, ctx, {
|
|
203
|
+
...params,
|
|
204
|
+
path: [...params.path, "additionalProperties"]
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
const unionProcessor = (schema, ctx, json, params) => {
|
|
208
|
+
const def = schema._zod.def;
|
|
209
|
+
const isExclusive = def.inclusive === false;
|
|
210
|
+
const options = def.options.map((x, i) => processSchema(x, ctx, {
|
|
211
|
+
...params,
|
|
212
|
+
path: [
|
|
213
|
+
...params.path,
|
|
214
|
+
isExclusive ? "oneOf" : "anyOf",
|
|
215
|
+
i
|
|
216
|
+
]
|
|
217
|
+
}));
|
|
218
|
+
if (isExclusive) json.oneOf = options;
|
|
219
|
+
else json.anyOf = options;
|
|
220
|
+
};
|
|
221
|
+
const intersectionProcessor = (schema, ctx, json, params) => {
|
|
222
|
+
const def = schema._zod.def;
|
|
223
|
+
const a = processSchema(def.left, ctx, {
|
|
224
|
+
...params,
|
|
225
|
+
path: [
|
|
226
|
+
...params.path,
|
|
227
|
+
"allOf",
|
|
228
|
+
0
|
|
229
|
+
]
|
|
230
|
+
});
|
|
231
|
+
const b = processSchema(def.right, ctx, {
|
|
232
|
+
...params,
|
|
233
|
+
path: [
|
|
234
|
+
...params.path,
|
|
235
|
+
"allOf",
|
|
236
|
+
1
|
|
237
|
+
]
|
|
238
|
+
});
|
|
239
|
+
const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1;
|
|
240
|
+
const allOf = [...isSimpleIntersection(a) ? a.allOf : [a], ...isSimpleIntersection(b) ? b.allOf : [b]];
|
|
241
|
+
json.allOf = allOf;
|
|
242
|
+
ctx.intersections.push(allOf);
|
|
243
|
+
};
|
|
244
|
+
/** JSON object keys are always strings, so a numeric record key schema is re-expressed over the
|
|
245
|
+
* numeric-string form the record parser matches. Deferred to `finalize`, after the flatten: a key
|
|
246
|
+
* behind a wrapper only carries its own `type` before then, and a union key only has its branches.
|
|
247
|
+
*
|
|
248
|
+
* A numeric bound cannot apply to a property name, so `minimum` and its siblings are dropped rather
|
|
249
|
+
* than carried over: keeping them beside `type: "string"` reproduces the match-nothing schema this
|
|
250
|
+
* exists to fix. A key that carries one therefore emits wider than the record parses — `z.record(z.number().min(5), V)`
|
|
251
|
+
* accepts `"3"` — which is the deliberate trade, since throwing on it would reject an ordinary schema
|
|
252
|
+
* outright. */
|
|
253
|
+
function stringifyKeyNames(bySchema, json, visited) {
|
|
254
|
+
if (json.$ref) {
|
|
255
|
+
if (visited.has(json)) return json;
|
|
256
|
+
visited.add(json);
|
|
257
|
+
const def = bySchema.get(json)?.def;
|
|
258
|
+
if (!def) return json;
|
|
259
|
+
const inlined = stringifyKeyNames(bySchema, def, visited);
|
|
260
|
+
return inlined === def ? json : inlined;
|
|
261
|
+
}
|
|
262
|
+
for (const keyword of ["anyOf", "oneOf"]) {
|
|
263
|
+
const branches = json[keyword];
|
|
264
|
+
if (!Array.isArray(branches)) continue;
|
|
265
|
+
const mapped = branches.map((branch) => stringifyKeyNames(bySchema, branch, visited));
|
|
266
|
+
if (mapped.some((branch, i) => branch !== branches[i])) json = {
|
|
267
|
+
...json,
|
|
268
|
+
[keyword]: mapped
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
const types = Array.isArray(json.type) ? json.type : [json.type];
|
|
272
|
+
const numericType = !types.includes("string") && types.some((t) => t === "number" || t === "integer");
|
|
273
|
+
const values = json.enum ?? (json.const !== void 0 ? [json.const] : void 0);
|
|
274
|
+
if (!numericType && !values?.some((v) => typeof v === "number")) return json;
|
|
275
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json;
|
|
276
|
+
if (rest.enum) rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
|
|
277
|
+
else if (typeof rest.const === "number") rest.const = String(rest.const);
|
|
278
|
+
if (!numericType) return rest;
|
|
279
|
+
rest.type = "string";
|
|
280
|
+
if (!values) rest.pattern = (types.includes("number") ? number : integer).source;
|
|
281
|
+
return rest;
|
|
282
|
+
}
|
|
283
|
+
/** Every record of one conversion, so the carriers are found in a single pass rather than once per record. */
|
|
284
|
+
const pendingRecords = /* @__PURE__ */ new WeakMap();
|
|
285
|
+
function rewriteKeyNames(ctx) {
|
|
286
|
+
const bySchema = /* @__PURE__ */ new Map();
|
|
287
|
+
for (const entry of ctx.seen.values()) if (entry.def && !bySchema.has(entry.schema)) bySchema.set(entry.schema, entry);
|
|
288
|
+
const rewrites = /* @__PURE__ */ new Map();
|
|
289
|
+
for (const record of pendingRecords.get(ctx) ?? []) {
|
|
290
|
+
const seen = ctx.seen.get(record);
|
|
291
|
+
const names = (seen?.def ?? seen?.schema)?.propertyNames;
|
|
292
|
+
if (!names || names === true || rewrites.has(names)) continue;
|
|
293
|
+
const rewritten = stringifyKeyNames(bySchema, names, /* @__PURE__ */ new Set());
|
|
294
|
+
if (rewritten !== names) rewrites.set(names, rewritten);
|
|
295
|
+
}
|
|
296
|
+
if (!rewrites.size) return;
|
|
297
|
+
for (const entry of ctx.seen.values()) for (const carrier of [entry.schema, entry.def]) {
|
|
298
|
+
const rewritten = carrier && rewrites.get(carrier.propertyNames);
|
|
299
|
+
if (rewritten) carrier.propertyNames = rewritten;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const recordProcessor = (schema, ctx, _json, params) => {
|
|
303
|
+
const json = _json;
|
|
304
|
+
const def = schema._zod.def;
|
|
305
|
+
json.type = "object";
|
|
306
|
+
const keyType = def.keyType;
|
|
307
|
+
const patterns = aggregateChecks(keyType).patterns;
|
|
308
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
309
|
+
const valueSchema = processSchema(def.valueType, ctx, {
|
|
310
|
+
...params,
|
|
311
|
+
path: [
|
|
312
|
+
...params.path,
|
|
313
|
+
"patternProperties",
|
|
314
|
+
"*"
|
|
315
|
+
]
|
|
316
|
+
});
|
|
317
|
+
json.patternProperties = {};
|
|
318
|
+
for (const pattern of patterns) assignProp(json.patternProperties, exactPattern(pattern).source, valueSchema);
|
|
319
|
+
} else {
|
|
320
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
321
|
+
json.propertyNames = processSchema(def.keyType, ctx, {
|
|
322
|
+
...params,
|
|
323
|
+
path: [...params.path, "propertyNames"]
|
|
324
|
+
});
|
|
325
|
+
let pending = pendingRecords.get(ctx);
|
|
326
|
+
if (!pending) {
|
|
327
|
+
pending = [];
|
|
328
|
+
pendingRecords.set(ctx, pending);
|
|
329
|
+
ctx.deferred.push(() => rewriteKeyNames(ctx));
|
|
330
|
+
}
|
|
331
|
+
pending.push(schema);
|
|
332
|
+
}
|
|
333
|
+
json.additionalProperties = processSchema(def.valueType, ctx, {
|
|
334
|
+
...params,
|
|
335
|
+
path: [...params.path, "additionalProperties"]
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
const keyValues = keyType._zod.values;
|
|
339
|
+
const omittableOnInput = ctx.io === "input" && inputOptin(def.valueType) !== void 0;
|
|
340
|
+
if (keyValues && !def.partial && !omittableOnInput) {
|
|
341
|
+
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
342
|
+
if (validKeyValues.length > 0) json.required = validKeyValues.map(String);
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
const nullableProcessor = (schema, ctx, json, params) => {
|
|
346
|
+
const def = schema._zod.def;
|
|
347
|
+
const inner = processSchema(def.innerType, ctx, params);
|
|
348
|
+
const seen = ctx.seen.get(schema);
|
|
349
|
+
if (ctx.target === "openapi-3.0") {
|
|
350
|
+
seen.ref = def.innerType;
|
|
351
|
+
json.nullable = true;
|
|
352
|
+
} else json.anyOf = [inner, { type: "null" }];
|
|
353
|
+
};
|
|
354
|
+
const nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
355
|
+
const def = schema._zod.def;
|
|
356
|
+
processSchema(def.innerType, ctx, params);
|
|
357
|
+
const seen = ctx.seen.get(schema);
|
|
358
|
+
seen.ref = def.innerType;
|
|
359
|
+
};
|
|
360
|
+
/** Round-trips a default value through JSON so the emitted schema is guaranteed to be valid JSON.
|
|
361
|
+
* A BigInt has no reliable encoding, so it goes through `unrepresentable` like any other
|
|
362
|
+
* unrepresentable value. Returns a sentinel when the caller must not write a default of its own. */
|
|
363
|
+
const UNREPRESENTABLE_DEFAULT = Symbol();
|
|
364
|
+
function serializeDefaultValue(value, schema, ctx, json, params) {
|
|
365
|
+
let unrepresentable = false;
|
|
366
|
+
const serialized = JSON.stringify(value, (_, val) => {
|
|
367
|
+
if (typeof val !== "bigint") return val;
|
|
368
|
+
unrepresentable = true;
|
|
369
|
+
return null;
|
|
370
|
+
});
|
|
371
|
+
if (!unrepresentable) return JSON.parse(serialized);
|
|
372
|
+
handleUnrepresentable(schema, ctx, json, params, "BigInt defaults cannot be represented in JSON Schema");
|
|
373
|
+
return UNREPRESENTABLE_DEFAULT;
|
|
374
|
+
}
|
|
375
|
+
const defaultProcessor = (schema, ctx, json, params) => {
|
|
376
|
+
const def = schema._zod.def;
|
|
377
|
+
processSchema(def.innerType, ctx, params);
|
|
378
|
+
const seen = ctx.seen.get(schema);
|
|
379
|
+
seen.ref = def.innerType;
|
|
380
|
+
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json, params);
|
|
381
|
+
if (value !== UNREPRESENTABLE_DEFAULT) json.default = value;
|
|
382
|
+
};
|
|
383
|
+
const prefaultProcessor = (schema, ctx, json, params) => {
|
|
384
|
+
const def = schema._zod.def;
|
|
385
|
+
processSchema(def.innerType, ctx, params);
|
|
386
|
+
const seen = ctx.seen.get(schema);
|
|
387
|
+
seen.ref = def.innerType;
|
|
388
|
+
if (ctx.io !== "input") return;
|
|
389
|
+
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json, params);
|
|
390
|
+
if (value !== UNREPRESENTABLE_DEFAULT) json._prefault = value;
|
|
391
|
+
};
|
|
392
|
+
const catchProcessor = (schema, ctx, json, params) => {
|
|
393
|
+
const def = schema._zod.def;
|
|
394
|
+
processSchema(def.innerType, ctx, params);
|
|
395
|
+
const seen = ctx.seen.get(schema);
|
|
396
|
+
seen.ref = def.innerType;
|
|
397
|
+
let catchValue;
|
|
398
|
+
try {
|
|
399
|
+
catchValue = def.catchValue(void 0);
|
|
400
|
+
} catch {
|
|
401
|
+
handleUnrepresentable(schema, ctx, json, params, "Dynamic catch values are not supported in JSON Schema");
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
json.default = catchValue;
|
|
405
|
+
};
|
|
406
|
+
const pipeProcessor = (schema, ctx, _json, params) => {
|
|
407
|
+
const def = schema._zod.def;
|
|
408
|
+
const inIsTransform = def.in._zod.traits.has("$ZodTransform");
|
|
409
|
+
const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
|
|
410
|
+
processSchema(innerType, ctx, params);
|
|
411
|
+
const seen = ctx.seen.get(schema);
|
|
412
|
+
seen.ref = innerType;
|
|
413
|
+
};
|
|
414
|
+
const readonlyProcessor = (schema, ctx, json, params) => {
|
|
415
|
+
const def = schema._zod.def;
|
|
416
|
+
processSchema(def.innerType, ctx, params);
|
|
417
|
+
const seen = ctx.seen.get(schema);
|
|
418
|
+
seen.ref = def.innerType;
|
|
419
|
+
json.readOnly = true;
|
|
420
|
+
};
|
|
421
|
+
const optionalProcessor = (schema, ctx, _json, params) => {
|
|
422
|
+
const def = schema._zod.def;
|
|
423
|
+
processSchema(def.innerType, ctx, params);
|
|
424
|
+
const seen = ctx.seen.get(schema);
|
|
425
|
+
seen.ref = def.innerType;
|
|
426
|
+
};
|
|
427
|
+
//#endregion
|
|
428
|
+
export { aggregateChecks, arrayProcessor, booleanProcessor, catchProcessor, customProcessor, defaultProcessor, enumProcessor, intersectionProcessor, neverProcessor, nonoptionalProcessor, nullableProcessor, numberProcessor, objectProcessor, optionalProcessor, pipeProcessor, prefaultProcessor, readonlyProcessor, recordProcessor, stringProcessor, transformProcessor, unionProcessor, unknownProcessor };
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { rawShape } from "./util.js";
|
|
2
|
+
//#region node_modules/zod/v4/core/memoizer.js
|
|
3
|
+
var $ZodCyclicError = class extends Error {
|
|
4
|
+
constructor() {
|
|
5
|
+
super(`Cannot parse a reference cycle that closes through a transform`);
|
|
6
|
+
this.name = "ZodCyclicError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
/** Keyed off the context object every schema in one parse call already shares. */
|
|
10
|
+
const STATE = "~memo";
|
|
11
|
+
const NO_ISSUES = [];
|
|
12
|
+
function isRef(value) {
|
|
13
|
+
return value !== null && typeof value === "object";
|
|
14
|
+
}
|
|
15
|
+
function cloneIssues(issues) {
|
|
16
|
+
return issues.map((iss) => iss.path ? {
|
|
17
|
+
...iss,
|
|
18
|
+
path: iss.path.slice()
|
|
19
|
+
} : { ...iss });
|
|
20
|
+
}
|
|
21
|
+
const recursive = /*@__PURE__*/ new WeakMap();
|
|
22
|
+
/** What the walk established, in order of certainty: ordered so the strongest answer among children wins. */
|
|
23
|
+
const NONE = 0;
|
|
24
|
+
const ASSUMED = 1;
|
|
25
|
+
const PROVEN = 2;
|
|
26
|
+
/** Whether this schema's subtree contains a cycle, so one parse can re-enter it. */
|
|
27
|
+
function isRecursive(inst, stack, resolve) {
|
|
28
|
+
const cached = recursive.get(inst);
|
|
29
|
+
if (cached !== void 0) return cached ? PROVEN : NONE;
|
|
30
|
+
if (stack.has(inst)) return PROVEN;
|
|
31
|
+
stack.add(inst);
|
|
32
|
+
let result = NONE;
|
|
33
|
+
const check = (child) => {
|
|
34
|
+
if (result !== PROVEN && child?._zod) {
|
|
35
|
+
const answer = isRecursive(child, stack, resolve);
|
|
36
|
+
if (answer > result) result = answer;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const shape = (sh, spread) => {
|
|
40
|
+
let answer = NONE;
|
|
41
|
+
for (const key of Reflect.ownKeys(sh)) {
|
|
42
|
+
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
43
|
+
if (spread && !desc.enumerable) continue;
|
|
44
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;
|
|
45
|
+
if (child > answer) answer = child;
|
|
46
|
+
}
|
|
47
|
+
return answer;
|
|
48
|
+
};
|
|
49
|
+
const merge = (answer) => {
|
|
50
|
+
if (answer > result) result = answer;
|
|
51
|
+
};
|
|
52
|
+
const def = inst._zod.def;
|
|
53
|
+
switch (def.type) {
|
|
54
|
+
case "object": {
|
|
55
|
+
const raw = rawShape(def);
|
|
56
|
+
merge(raw ? shape(raw, true) : ASSUMED);
|
|
57
|
+
check(def.catchall);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
case "array":
|
|
61
|
+
check(def.element);
|
|
62
|
+
break;
|
|
63
|
+
case "tuple":
|
|
64
|
+
for (const el of def.items) check(el);
|
|
65
|
+
check(def.rest);
|
|
66
|
+
break;
|
|
67
|
+
case "record":
|
|
68
|
+
case "map":
|
|
69
|
+
check(def.keyType);
|
|
70
|
+
check(def.valueType);
|
|
71
|
+
break;
|
|
72
|
+
case "set":
|
|
73
|
+
check(def.valueType);
|
|
74
|
+
break;
|
|
75
|
+
case "union":
|
|
76
|
+
for (const el of def.options) check(el);
|
|
77
|
+
break;
|
|
78
|
+
case "intersection":
|
|
79
|
+
check(def.left);
|
|
80
|
+
check(def.right);
|
|
81
|
+
break;
|
|
82
|
+
case "optional":
|
|
83
|
+
case "nullable":
|
|
84
|
+
case "default":
|
|
85
|
+
case "prefault":
|
|
86
|
+
case "catch":
|
|
87
|
+
case "readonly":
|
|
88
|
+
case "nonoptional":
|
|
89
|
+
case "promise":
|
|
90
|
+
case "success":
|
|
91
|
+
check(def.innerType);
|
|
92
|
+
break;
|
|
93
|
+
case "pipe":
|
|
94
|
+
check(def.in);
|
|
95
|
+
check(def.out);
|
|
96
|
+
break;
|
|
97
|
+
case "function":
|
|
98
|
+
check(def.input);
|
|
99
|
+
check(def.output);
|
|
100
|
+
break;
|
|
101
|
+
case "lazy": {
|
|
102
|
+
const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : void 0);
|
|
103
|
+
merge(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
case "template_literal":
|
|
107
|
+
case "string":
|
|
108
|
+
case "number":
|
|
109
|
+
case "int":
|
|
110
|
+
case "boolean":
|
|
111
|
+
case "bigint":
|
|
112
|
+
case "symbol":
|
|
113
|
+
case "undefined":
|
|
114
|
+
case "null":
|
|
115
|
+
case "void":
|
|
116
|
+
case "never":
|
|
117
|
+
case "any":
|
|
118
|
+
case "unknown":
|
|
119
|
+
case "date":
|
|
120
|
+
case "nan":
|
|
121
|
+
case "enum":
|
|
122
|
+
case "literal":
|
|
123
|
+
case "file":
|
|
124
|
+
case "transform":
|
|
125
|
+
case "custom": break;
|
|
126
|
+
default: for (const key in def) {
|
|
127
|
+
const desc = Object.getOwnPropertyDescriptor(def, key);
|
|
128
|
+
if (!desc || desc.get) continue;
|
|
129
|
+
const value = desc.value;
|
|
130
|
+
if (!value || typeof value !== "object") continue;
|
|
131
|
+
if (value._zod) check(value);
|
|
132
|
+
else if (Array.isArray(value)) for (const el of value) check(el);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
stack.delete(inst);
|
|
136
|
+
return settle(inst, result);
|
|
137
|
+
}
|
|
138
|
+
/** An assumed answer must not outlive the resolution that settles it, so only a certain one is cached. */
|
|
139
|
+
function settle(inst, answer) {
|
|
140
|
+
if (answer !== ASSUMED) recursive.set(inst, answer === PROVEN);
|
|
141
|
+
return answer;
|
|
142
|
+
}
|
|
143
|
+
function bucketFor(state, inst) {
|
|
144
|
+
let bucket = state.buckets.get(inst);
|
|
145
|
+
if (!bucket) {
|
|
146
|
+
bucket = /* @__PURE__ */ new WeakMap();
|
|
147
|
+
state.buckets.set(inst, bucket);
|
|
148
|
+
}
|
|
149
|
+
return bucket;
|
|
150
|
+
}
|
|
151
|
+
let handoff;
|
|
152
|
+
const open = [];
|
|
153
|
+
const memo = {
|
|
154
|
+
alloc(_inst, payload, empty) {
|
|
155
|
+
const bucket = handoff;
|
|
156
|
+
if (!bucket) return empty;
|
|
157
|
+
handoff = void 0;
|
|
158
|
+
const entry = {
|
|
159
|
+
value: empty,
|
|
160
|
+
issues: null
|
|
161
|
+
};
|
|
162
|
+
bucket.set(payload.value, entry);
|
|
163
|
+
open.push(entry);
|
|
164
|
+
return empty;
|
|
165
|
+
},
|
|
166
|
+
guard(inst) {
|
|
167
|
+
var _a;
|
|
168
|
+
(_a = inst._zod).deferred ?? (_a.deferred = []);
|
|
169
|
+
inst._zod.deferred.push(() => {
|
|
170
|
+
const base = inst._zod.parse;
|
|
171
|
+
const wrapped = (payload, ctx) => {
|
|
172
|
+
if (ctx.direction !== "backward" && isBackEdge(ctx, payload.value)) throw new $ZodCyclicError();
|
|
173
|
+
return base(payload, ctx);
|
|
174
|
+
};
|
|
175
|
+
inst._zod.parse = wrapped;
|
|
176
|
+
if (inst._zod.run === base) inst._zod.run = wrapped;
|
|
177
|
+
});
|
|
178
|
+
},
|
|
179
|
+
attach(inst) {
|
|
180
|
+
var _a;
|
|
181
|
+
let isRecursiveInst;
|
|
182
|
+
let rechecked = false;
|
|
183
|
+
let lastCtx;
|
|
184
|
+
let lastBucket;
|
|
185
|
+
(_a = inst._zod).deferred ?? (_a.deferred = []);
|
|
186
|
+
inst._zod.deferred.push(() => {
|
|
187
|
+
const base = inst._zod.parse;
|
|
188
|
+
const wrapped = (payload, ctx) => {
|
|
189
|
+
if (isRecursiveInst === void 0) {
|
|
190
|
+
const walked = isRecursive(inst, /* @__PURE__ */ new Set(), false);
|
|
191
|
+
if (walked === NONE) {
|
|
192
|
+
inst._zod.parse = base;
|
|
193
|
+
if (inst._zod.run === wrapped) inst._zod.run = base;
|
|
194
|
+
return base(payload, ctx);
|
|
195
|
+
}
|
|
196
|
+
if (walked === PROVEN || rechecked) isRecursiveInst = true;
|
|
197
|
+
else rechecked = true;
|
|
198
|
+
}
|
|
199
|
+
const input = payload.value;
|
|
200
|
+
if (!isRef(input)) return base(payload, ctx);
|
|
201
|
+
let state = ctx[STATE];
|
|
202
|
+
if (!state) {
|
|
203
|
+
state = {
|
|
204
|
+
buckets: /* @__PURE__ */ new WeakMap(),
|
|
205
|
+
backEdges: void 0
|
|
206
|
+
};
|
|
207
|
+
ctx[STATE] = state;
|
|
208
|
+
}
|
|
209
|
+
let bucket;
|
|
210
|
+
if (lastCtx === ctx) bucket = lastBucket;
|
|
211
|
+
else {
|
|
212
|
+
bucket = bucketFor(state, inst);
|
|
213
|
+
lastCtx = ctx;
|
|
214
|
+
lastBucket = bucket;
|
|
215
|
+
}
|
|
216
|
+
const hit = bucket.get(input);
|
|
217
|
+
if (hit) {
|
|
218
|
+
payload.value = hit.value;
|
|
219
|
+
if (hit.issues) {
|
|
220
|
+
if (hit.issues.length) payload.issues.push(...cloneIssues(hit.issues));
|
|
221
|
+
} else {
|
|
222
|
+
payload.memo = true;
|
|
223
|
+
state.backEdges ?? (state.backEdges = /* @__PURE__ */ new WeakSet());
|
|
224
|
+
state.backEdges.add(hit.value);
|
|
225
|
+
}
|
|
226
|
+
return payload;
|
|
227
|
+
}
|
|
228
|
+
handoff = bucket;
|
|
229
|
+
const depth = open.length;
|
|
230
|
+
const result = base(payload, ctx);
|
|
231
|
+
handoff = void 0;
|
|
232
|
+
const entry = open.length > depth ? open.pop() : void 0;
|
|
233
|
+
if (result instanceof Promise) return result.then((r) => {
|
|
234
|
+
if (entry) entry.issues = r.issues.length ? cloneIssues(r.issues) : NO_ISSUES;
|
|
235
|
+
return r;
|
|
236
|
+
});
|
|
237
|
+
if (entry) entry.issues = result.issues.length ? cloneIssues(result.issues) : NO_ISSUES;
|
|
238
|
+
return result;
|
|
239
|
+
};
|
|
240
|
+
inst._zod.parse = wrapped;
|
|
241
|
+
if (inst._zod.run === base) inst._zod.run = wrapped;
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
/** The memoizer that gives containers cycle support. `zod` installs it by default; `zod/mini` opts in with `config({ memoizer: memoizer() })`. */
|
|
246
|
+
function memoizer() {
|
|
247
|
+
return memo;
|
|
248
|
+
}
|
|
249
|
+
/** Whether this value is a node a back-edge resolved to before it finished. */
|
|
250
|
+
function isBackEdge(ctx, value) {
|
|
251
|
+
const backEdges = ctx[STATE]?.backEdges;
|
|
252
|
+
return backEdges !== void 0 && isRef(value) && backEdges.has(value);
|
|
253
|
+
}
|
|
254
|
+
//#endregion
|
|
255
|
+
export { $ZodCyclicError, isBackEdge, memoizer };
|