@demokit-ai/schema 0.0.1 → 0.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/dist/index.cjs +150 -120
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +150 -116
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
-
|
|
7
|
-
var SwaggerParser__default = /*#__PURE__*/_interopDefault(SwaggerParser);
|
|
3
|
+
var openapiParser = require('@scalar/openapi-parser');
|
|
8
4
|
|
|
9
5
|
// src/parser.ts
|
|
10
6
|
|
|
@@ -157,47 +153,52 @@ function getModelDependencyOrder(models, relationships) {
|
|
|
157
153
|
|
|
158
154
|
// src/parser.ts
|
|
159
155
|
async function parseOpenAPIFromPath(pathOrUrl, options = {}) {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
api = await SwaggerParser__default.default.dereference(pathOrUrl);
|
|
164
|
-
} else {
|
|
165
|
-
api = await SwaggerParser__default.default.parse(pathOrUrl);
|
|
156
|
+
const response = await fetch(pathOrUrl);
|
|
157
|
+
if (!response.ok) {
|
|
158
|
+
throw new Error(`Failed to fetch OpenAPI spec from ${pathOrUrl}: ${response.statusText}`);
|
|
166
159
|
}
|
|
167
|
-
|
|
160
|
+
const content = await response.text();
|
|
161
|
+
return parseOpenAPIFromString(content, options);
|
|
168
162
|
}
|
|
169
163
|
async function parseOpenAPIFromString(spec, options = {}) {
|
|
170
|
-
const { dereference = true } = options;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const api2 = await SwaggerParser__default.default.parse(spec);
|
|
176
|
-
if (dereference) {
|
|
177
|
-
return parseOpenAPIDocument(
|
|
178
|
-
await SwaggerParser__default.default.dereference(api2),
|
|
179
|
-
options
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
return parseOpenAPIDocument(api2, options);
|
|
164
|
+
const { dereference: shouldDereference = true } = options;
|
|
165
|
+
const validationResult = await openapiParser.validate(spec);
|
|
166
|
+
if (!validationResult.valid) {
|
|
167
|
+
const errorMessages = validationResult.errors?.map((e) => e.message).join(", ") || "Unknown validation error";
|
|
168
|
+
throw new Error(`Invalid OpenAPI specification: ${errorMessages}`);
|
|
183
169
|
}
|
|
184
|
-
let
|
|
185
|
-
if (
|
|
186
|
-
|
|
170
|
+
let schema;
|
|
171
|
+
if (shouldDereference) {
|
|
172
|
+
const derefResult = await openapiParser.dereference(spec);
|
|
173
|
+
if (derefResult.errors && derefResult.errors.length > 0) {
|
|
174
|
+
const errorMessages = derefResult.errors.map((e) => e.message).join(", ");
|
|
175
|
+
throw new Error(`Failed to dereference OpenAPI spec: ${errorMessages}`);
|
|
176
|
+
}
|
|
177
|
+
schema = derefResult.schema;
|
|
187
178
|
} else {
|
|
188
|
-
|
|
179
|
+
schema = validationResult.specification;
|
|
189
180
|
}
|
|
190
|
-
return parseOpenAPIDocument(
|
|
181
|
+
return parseOpenAPIDocument(schema, options);
|
|
191
182
|
}
|
|
192
183
|
async function parseOpenAPIFromObject(spec, options = {}) {
|
|
193
|
-
const { dereference = true } = options;
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
|
|
184
|
+
const { dereference: shouldDereference = true } = options;
|
|
185
|
+
const validationResult = await openapiParser.validate(spec);
|
|
186
|
+
if (!validationResult.valid) {
|
|
187
|
+
const errorMessages = validationResult.errors?.map((e) => e.message).join(", ") || "Unknown validation error";
|
|
188
|
+
throw new Error(`Invalid OpenAPI specification: ${errorMessages}`);
|
|
189
|
+
}
|
|
190
|
+
let schema;
|
|
191
|
+
if (shouldDereference) {
|
|
192
|
+
const derefResult = await openapiParser.dereference(spec);
|
|
193
|
+
if (derefResult.errors && derefResult.errors.length > 0) {
|
|
194
|
+
const errorMessages = derefResult.errors.map((e) => e.message).join(", ");
|
|
195
|
+
throw new Error(`Failed to dereference OpenAPI spec: ${errorMessages}`);
|
|
196
|
+
}
|
|
197
|
+
schema = derefResult.schema;
|
|
197
198
|
} else {
|
|
198
|
-
|
|
199
|
+
schema = validationResult.specification;
|
|
199
200
|
}
|
|
200
|
-
return parseOpenAPIDocument(
|
|
201
|
+
return parseOpenAPIDocument(schema, options);
|
|
201
202
|
}
|
|
202
203
|
function parseOpenAPIDocument(doc, options = {}) {
|
|
203
204
|
const { detectRelationships: shouldDetect = true } = options;
|
|
@@ -213,24 +214,27 @@ function parseOpenAPIDocument(doc, options = {}) {
|
|
|
213
214
|
};
|
|
214
215
|
}
|
|
215
216
|
function parseInfo(doc) {
|
|
217
|
+
const docInfo = doc.info || {};
|
|
216
218
|
const info = {
|
|
217
|
-
title:
|
|
218
|
-
version:
|
|
219
|
-
description:
|
|
219
|
+
title: docInfo.title ?? "Untitled API",
|
|
220
|
+
version: docInfo.version ?? "1.0.0",
|
|
221
|
+
description: docInfo.description
|
|
220
222
|
};
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
const servers = doc.servers;
|
|
224
|
+
if (servers && servers.length > 0 && servers[0]) {
|
|
225
|
+
info.baseUrl = servers[0].url;
|
|
223
226
|
}
|
|
224
227
|
return info;
|
|
225
228
|
}
|
|
226
229
|
function parseModels(doc) {
|
|
227
230
|
const models = {};
|
|
228
|
-
const
|
|
231
|
+
const components = doc.components;
|
|
232
|
+
const schemas = components?.schemas;
|
|
229
233
|
if (!schemas) {
|
|
230
234
|
return models;
|
|
231
235
|
}
|
|
232
236
|
for (const [name, schema] of Object.entries(schemas)) {
|
|
233
|
-
if ("$ref" in schema) {
|
|
237
|
+
if (schema && typeof schema === "object" && "$ref" in schema) {
|
|
234
238
|
continue;
|
|
235
239
|
}
|
|
236
240
|
models[name] = parseSchemaToModel(name, schema);
|
|
@@ -238,17 +242,21 @@ function parseModels(doc) {
|
|
|
238
242
|
return models;
|
|
239
243
|
}
|
|
240
244
|
function parseSchemaToModel(name, schema) {
|
|
245
|
+
if (!schema || typeof schema !== "object") {
|
|
246
|
+
return { name, type: "object" };
|
|
247
|
+
}
|
|
248
|
+
const s = schema;
|
|
241
249
|
const model = {
|
|
242
250
|
name,
|
|
243
|
-
type: schemaTypeToModelType(
|
|
244
|
-
description:
|
|
251
|
+
type: schemaTypeToModelType(s.type),
|
|
252
|
+
description: s.description
|
|
245
253
|
};
|
|
246
|
-
if (
|
|
254
|
+
if (s.type === "object" || s.properties) {
|
|
247
255
|
model.type = "object";
|
|
248
256
|
model.properties = {};
|
|
249
|
-
model.required =
|
|
250
|
-
if (
|
|
251
|
-
for (const [propName, propSchema] of Object.entries(
|
|
257
|
+
model.required = s.required || [];
|
|
258
|
+
if (s.properties && typeof s.properties === "object") {
|
|
259
|
+
for (const [propName, propSchema] of Object.entries(s.properties)) {
|
|
252
260
|
model.properties[propName] = parseProperty(
|
|
253
261
|
propName,
|
|
254
262
|
propSchema,
|
|
@@ -256,39 +264,41 @@ function parseSchemaToModel(name, schema) {
|
|
|
256
264
|
);
|
|
257
265
|
}
|
|
258
266
|
}
|
|
259
|
-
if (
|
|
260
|
-
if (typeof
|
|
261
|
-
model.additionalProperties =
|
|
262
|
-
} else if (
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
267
|
+
if (s.additionalProperties !== void 0) {
|
|
268
|
+
if (typeof s.additionalProperties === "boolean") {
|
|
269
|
+
model.additionalProperties = s.additionalProperties;
|
|
270
|
+
} else if (s.additionalProperties && typeof s.additionalProperties === "object") {
|
|
271
|
+
if ("$ref" in s.additionalProperties) {
|
|
272
|
+
model.additionalProperties = {
|
|
273
|
+
$ref: s.additionalProperties.$ref
|
|
274
|
+
};
|
|
275
|
+
} else {
|
|
276
|
+
model.additionalProperties = parseSchemaToModel(
|
|
277
|
+
`${name}AdditionalProps`,
|
|
278
|
+
s.additionalProperties
|
|
279
|
+
);
|
|
280
|
+
}
|
|
271
281
|
}
|
|
272
282
|
}
|
|
273
283
|
}
|
|
274
|
-
if (
|
|
284
|
+
if (s.type === "array" && s.items) {
|
|
275
285
|
model.type = "array";
|
|
276
|
-
if ("$ref" in
|
|
277
|
-
model.items = { $ref:
|
|
286
|
+
if (typeof s.items === "object" && "$ref" in s.items) {
|
|
287
|
+
model.items = { $ref: s.items.$ref };
|
|
278
288
|
} else {
|
|
279
|
-
model.items = parseSchemaToModel(`${name}Item`,
|
|
289
|
+
model.items = parseSchemaToModel(`${name}Item`, s.items);
|
|
280
290
|
}
|
|
281
291
|
}
|
|
282
|
-
if (
|
|
283
|
-
model.enum =
|
|
292
|
+
if (s.enum) {
|
|
293
|
+
model.enum = s.enum;
|
|
284
294
|
}
|
|
285
|
-
if (
|
|
286
|
-
model.example =
|
|
295
|
+
if (s.example !== void 0) {
|
|
296
|
+
model.example = s.example;
|
|
287
297
|
}
|
|
288
298
|
return model;
|
|
289
299
|
}
|
|
290
300
|
function parseProperty(name, schema, required) {
|
|
291
|
-
if ("$ref" in schema) {
|
|
301
|
+
if (schema && typeof schema === "object" && "$ref" in schema) {
|
|
292
302
|
return {
|
|
293
303
|
name,
|
|
294
304
|
type: "object",
|
|
@@ -296,31 +306,32 @@ function parseProperty(name, schema, required) {
|
|
|
296
306
|
$ref: schema.$ref
|
|
297
307
|
};
|
|
298
308
|
}
|
|
309
|
+
const s = schema;
|
|
299
310
|
const prop = {
|
|
300
311
|
name,
|
|
301
|
-
type: schemaTypeToPropertyType(
|
|
312
|
+
type: schemaTypeToPropertyType(s.type),
|
|
302
313
|
required,
|
|
303
|
-
nullable:
|
|
304
|
-
description:
|
|
305
|
-
format:
|
|
306
|
-
enum:
|
|
307
|
-
example:
|
|
308
|
-
default:
|
|
309
|
-
minimum:
|
|
310
|
-
maximum:
|
|
311
|
-
minLength:
|
|
312
|
-
maxLength:
|
|
313
|
-
pattern:
|
|
314
|
+
nullable: s.nullable,
|
|
315
|
+
description: s.description,
|
|
316
|
+
format: s.format,
|
|
317
|
+
enum: s.enum,
|
|
318
|
+
example: s.example,
|
|
319
|
+
default: s.default,
|
|
320
|
+
minimum: s.minimum,
|
|
321
|
+
maximum: s.maximum,
|
|
322
|
+
minLength: s.minLength,
|
|
323
|
+
maxLength: s.maxLength,
|
|
324
|
+
pattern: s.pattern
|
|
314
325
|
};
|
|
315
|
-
if (
|
|
326
|
+
if (s.type === "array" && s.items) {
|
|
316
327
|
prop.type = "array";
|
|
317
|
-
if ("$ref" in
|
|
318
|
-
prop.items = { $ref:
|
|
328
|
+
if (typeof s.items === "object" && "$ref" in s.items) {
|
|
329
|
+
prop.items = { $ref: s.items.$ref };
|
|
319
330
|
} else {
|
|
320
|
-
prop.items = parseSchemaToModel(`${name}Item`,
|
|
331
|
+
prop.items = parseSchemaToModel(`${name}Item`, s.items);
|
|
321
332
|
}
|
|
322
333
|
}
|
|
323
|
-
const xRelationship =
|
|
334
|
+
const xRelationship = s["x-demokit-relationship"];
|
|
324
335
|
if (xRelationship && typeof xRelationship === "object") {
|
|
325
336
|
prop["x-demokit-relationship"] = xRelationship;
|
|
326
337
|
}
|
|
@@ -328,28 +339,32 @@ function parseProperty(name, schema, required) {
|
|
|
328
339
|
}
|
|
329
340
|
function parseEndpoints(doc) {
|
|
330
341
|
const endpoints = [];
|
|
331
|
-
|
|
342
|
+
const paths = doc.paths;
|
|
343
|
+
if (!paths) {
|
|
332
344
|
return endpoints;
|
|
333
345
|
}
|
|
334
346
|
const methods = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
335
|
-
for (const [path, pathItem] of Object.entries(
|
|
336
|
-
if (!pathItem) continue;
|
|
347
|
+
for (const [path, pathItem] of Object.entries(paths)) {
|
|
348
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
337
349
|
for (const method of methods) {
|
|
338
350
|
const operation = pathItem[method.toLowerCase()];
|
|
339
|
-
if (!operation) continue;
|
|
351
|
+
if (!operation || typeof operation !== "object") continue;
|
|
340
352
|
endpoints.push(parseEndpoint(method, path, operation, pathItem));
|
|
341
353
|
}
|
|
342
354
|
}
|
|
343
355
|
return endpoints;
|
|
344
356
|
}
|
|
345
357
|
function parseEndpoint(method, path, operation, pathItem) {
|
|
346
|
-
const allParams = [...pathItem.parameters || [], ...operation.parameters || []];
|
|
347
358
|
const pathParams = [];
|
|
348
359
|
const queryParams = [];
|
|
360
|
+
const allParams = [
|
|
361
|
+
...pathItem.parameters || [],
|
|
362
|
+
...operation.parameters || []
|
|
363
|
+
];
|
|
349
364
|
for (const param of allParams) {
|
|
365
|
+
if (!param || typeof param !== "object") continue;
|
|
350
366
|
if ("$ref" in param) continue;
|
|
351
|
-
const
|
|
352
|
-
const parsed = parseParameter(paramObj);
|
|
367
|
+
const parsed = parseParameter(param);
|
|
353
368
|
if (parsed.in === "path") {
|
|
354
369
|
pathParams.push(parsed);
|
|
355
370
|
} else if (parsed.in === "query") {
|
|
@@ -357,12 +372,15 @@ function parseEndpoint(method, path, operation, pathItem) {
|
|
|
357
372
|
}
|
|
358
373
|
}
|
|
359
374
|
let requestBody;
|
|
360
|
-
|
|
361
|
-
|
|
375
|
+
const opRequestBody = operation.requestBody;
|
|
376
|
+
if (opRequestBody && typeof opRequestBody === "object" && !("$ref" in opRequestBody)) {
|
|
377
|
+
requestBody = parseRequestBody(opRequestBody);
|
|
362
378
|
}
|
|
363
379
|
const responses = {};
|
|
364
|
-
|
|
365
|
-
|
|
380
|
+
const opResponses = operation.responses;
|
|
381
|
+
if (opResponses && typeof opResponses === "object") {
|
|
382
|
+
for (const [statusCode, response] of Object.entries(opResponses)) {
|
|
383
|
+
if (!response || typeof response !== "object") continue;
|
|
366
384
|
if ("$ref" in response) continue;
|
|
367
385
|
responses[statusCode] = parseResponse(statusCode, response);
|
|
368
386
|
}
|
|
@@ -381,52 +399,64 @@ function parseEndpoint(method, path, operation, pathItem) {
|
|
|
381
399
|
};
|
|
382
400
|
}
|
|
383
401
|
function parseParameter(param) {
|
|
384
|
-
const
|
|
402
|
+
const p = param;
|
|
403
|
+
const schema = p.schema;
|
|
385
404
|
return {
|
|
386
|
-
name:
|
|
387
|
-
in:
|
|
388
|
-
required:
|
|
405
|
+
name: p.name,
|
|
406
|
+
in: p.in,
|
|
407
|
+
required: p.required ?? false,
|
|
389
408
|
type: schema ? schemaTypeToPropertyType(schema.type) : "string",
|
|
390
409
|
format: schema?.format,
|
|
391
|
-
description:
|
|
392
|
-
example:
|
|
410
|
+
description: p.description,
|
|
411
|
+
example: p.example ?? schema?.example
|
|
393
412
|
};
|
|
394
413
|
}
|
|
395
414
|
function parseRequestBody(body) {
|
|
396
|
-
const
|
|
397
|
-
const
|
|
415
|
+
const b = body;
|
|
416
|
+
const content = b.content;
|
|
417
|
+
const contentType = Object.keys(content || {})[0] || "application/json";
|
|
418
|
+
const mediaType = content?.[contentType];
|
|
398
419
|
let schema = { name: "Unknown", type: "object" };
|
|
399
|
-
if (mediaType
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
420
|
+
if (mediaType) {
|
|
421
|
+
const m = mediaType;
|
|
422
|
+
const mediaSchema = m.schema;
|
|
423
|
+
if (mediaSchema && typeof mediaSchema === "object") {
|
|
424
|
+
if ("$ref" in mediaSchema) {
|
|
425
|
+
schema = { $ref: mediaSchema.$ref };
|
|
426
|
+
} else {
|
|
427
|
+
schema = parseSchemaToModel("RequestBody", mediaSchema);
|
|
428
|
+
}
|
|
404
429
|
}
|
|
405
430
|
}
|
|
406
431
|
return {
|
|
407
432
|
contentType,
|
|
408
433
|
schema,
|
|
409
|
-
required:
|
|
410
|
-
description:
|
|
434
|
+
required: b.required ?? false,
|
|
435
|
+
description: b.description
|
|
411
436
|
};
|
|
412
437
|
}
|
|
413
438
|
function parseResponse(statusCode, response) {
|
|
439
|
+
const r = response;
|
|
414
440
|
const responseDef = {
|
|
415
441
|
statusCode,
|
|
416
|
-
description:
|
|
442
|
+
description: r.description
|
|
417
443
|
};
|
|
418
|
-
|
|
444
|
+
const content = r.content;
|
|
445
|
+
if (content) {
|
|
419
446
|
responseDef.content = {};
|
|
420
|
-
for (const [contentType, mediaType] of Object.entries(
|
|
421
|
-
if (mediaType
|
|
422
|
-
|
|
447
|
+
for (const [contentType, mediaType] of Object.entries(content)) {
|
|
448
|
+
if (!mediaType || typeof mediaType !== "object") continue;
|
|
449
|
+
const m = mediaType;
|
|
450
|
+
const schema = m.schema;
|
|
451
|
+
if (schema && typeof schema === "object") {
|
|
452
|
+
if ("$ref" in schema) {
|
|
423
453
|
responseDef.content[contentType] = {
|
|
424
|
-
$ref:
|
|
454
|
+
$ref: schema.$ref
|
|
425
455
|
};
|
|
426
456
|
} else {
|
|
427
457
|
responseDef.content[contentType] = parseSchemaToModel(
|
|
428
458
|
`Response${statusCode}`,
|
|
429
|
-
|
|
459
|
+
schema
|
|
430
460
|
);
|
|
431
461
|
}
|
|
432
462
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/relationships.ts","../src/parser.ts"],"names":["SwaggerParser","api"],"mappings":";;;;;;;;;;;AA2cO,SAAS,YAAY,KAAA,EAAoC;AAC9D,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,MAAA,IAAU,KAAA,IACV,OAAQ,KAAA,CAAoB,IAAA,KAAS,QAAA;AAEzC;AAMO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA,IAAK,GAAA;AACpC;;;ACpcA,IAAM,iBAAA,GAAoB;AAAA;AAAA,EAExB,EAAE,OAAA,EAAS,UAAA,EAAY,WAAA,EAAa,IAAA,EAAK;AAAA,EACzC,EAAE,OAAA,EAAS,WAAA,EAAa,WAAA,EAAa,IAAA,EAAK;AAAA,EAC1C,EAAE,OAAA,EAAS,UAAA,EAAY,WAAA,EAAa,IAAA,EAAK;AAAA;AAAA,EAGzC,EAAE,OAAA,EAAS,YAAA,EAAc,WAAA,EAAa,MAAA,EAAO;AAAA,EAC7C,EAAE,OAAA,EAAS,YAAA,EAAc,WAAA,EAAa,MAAA,EAAO;AAAA,EAC7C,EAAE,OAAA,EAAS,aAAA,EAAe,WAAA,EAAa,MAAA;AACzC,CAAA;AAMA,SAAS,kBAAkB,MAAA,EAAwB;AACjD,EAAA,OAAO,MAAA,CAAO,OAAO,CAAC,CAAA,CAAE,aAAY,GAAI,MAAA,CAAO,MAAM,CAAC,CAAA;AACxD;AAKO,SAAS,4BAAA,CACd,UACA,eAAA,EAC2B;AAC3B,EAAA,MAAM,YAAY,QAAA,CAAS,IAAA;AAE3B,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,WAAA,EAAY,IAAK,iBAAA,EAAmB;AACxD,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,OAAO,CAAA;AACrC,IAAA,IAAI,KAAA,IAAS,KAAA,CAAM,CAAC,CAAA,EAAG;AACrB,MAAA,MAAM,MAAA,GAAS,MAAM,CAAC,CAAA;AACtB,MAAA,MAAM,SAAA,GAAY,kBAAkB,MAAM,CAAA;AAG1C,MAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,QAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,WAAA,EAAY;AAAA,MAChD;AAGA,MAAA,MAAM,cAAc,SAAA,GAAY,GAAA;AAChC,MAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA,EAAG;AACpC,QAAA,OAAO,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,WAAA,EAAY;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,gCACd,QAAA,EAC2B;AAC3B,EAAA,MAAM,SAAA,GAAY,SAAS,wBAAwB,CAAA;AACnD,EAAA,IAAI,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC9C,IAAA,OAAO;AAAA,MACL,OAAO,SAAA,CAAU,KAAA;AAAA,MACjB,KAAA,EAAO,UAAU,KAAA,IAAS;AAAA,KAC5B;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,yBAAA,CACd,UACA,eAAA,EAC2B;AAC3B,EAAA,IAAI,SAAS,IAAA,EAAM;AACjB,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,QAAA,CAAS,IAAI,CAAA;AAC9C,IAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,MAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,IAAA,EAAK;AAAA,IACzC;AAAA,EACF;AAGA,EAAA,IAAI,QAAA,CAAS,KAAA,IAAS,WAAA,CAAY,QAAA,CAAS,KAAK,CAAA,EAAG;AACjD,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACpD,IAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,MAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,IAAA,EAAK;AAAA,IACzC;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,yBAAA,CACP,UACA,UAAA,EACkB;AAElB,EAAA,IAAI,QAAA,CAAS,SAAS,OAAA,EAAS;AAG7B,IAAA,OAAO,aAAA;AAAA,EACT;AAGA,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,oBACd,MAAA,EACgB;AAChB,EAAA,MAAM,gBAAgC,EAAC;AACvC,EAAA,MAAM,kBAAkB,IAAI,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAEnD,EAAA,KAAA,MAAW,CAAC,SAAA,EAAW,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACvD,IAAA,IAAI,CAAC,MAAM,UAAA,EAAY;AAEvB,IAAA,KAAA,MAAW,CAAC,UAAU,QAAQ,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAA,EAAG;AACnE,MAAA,IAAI,MAAA,GAAoC,IAAA;AACxC,MAAA,IAAI,eAAA,GAA+C,UAAA;AAGnD,MAAA,MAAA,GAAS,gCAAgC,QAAQ,CAAA;AACjD,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,eAAA,GAAkB,qBAAA;AAAA,MACpB;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,yBAAA,CAA0B,UAAU,eAAe,CAAA;AAC5D,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,eAAA,GAAkB,cAAA;AAAA,QACpB;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,4BAAA,CAA6B,UAAU,eAAe,CAAA;AAC/D,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,eAAA,GAAkB,mBAAA;AAAA,QACpB;AAAA,MACF;AAEA,MAAA,IAAI,MAAA,EAAQ;AAEV,QAAA,IAAI,OAAO,KAAA,KAAU,SAAA,IAAa,OAAO,KAAA,KAAU,IAAA,IAAQ,aAAa,IAAA,EAAM;AAC5E,UAAA;AAAA,QACF;AAGA,QAAA,QAAA,CAAS,cAAA,GAAiB,MAAA;AAE1B,QAAA,aAAA,CAAc,IAAA,CAAK;AAAA,UACjB,IAAA,EAAM,EAAE,KAAA,EAAO,SAAA,EAAW,OAAO,QAAA,EAAS;AAAA,UAC1C,EAAA,EAAI,MAAA;AAAA,UACJ,IAAA,EAAM,yBAAA,CAA0B,QAAe,CAAA;AAAA,UAC/C,QAAA,EAAU,SAAS,QAAA,IAAY,KAAA;AAAA,UAC/B,UAAA,EAAY;AAAA,SACb,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,wBAAA,CACd,WACA,aAAA,EAIA;AACA,EAAA,OAAO;AAAA,IACL,UAAU,aAAA,CAAc,MAAA,CAAO,OAAK,CAAA,CAAE,IAAA,CAAK,UAAU,SAAS,CAAA;AAAA,IAC9D,UAAU,aAAA,CAAc,MAAA,CAAO,OAAK,CAAA,CAAE,EAAA,CAAG,UAAU,SAAS;AAAA,GAC9D;AACF;AAKO,SAAS,iBAAA,CACd,WACA,aAAA,EACS;AACT,EAAA,OAAO,cAAc,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,CAAG,UAAU,SAAS,CAAA;AACzD;AAMO,SAAS,uBAAA,CACd,QACA,aAAA,EACU;AACV,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AACrC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,SAAS,KAAA,CAAM,IAAA,EAAc,IAAA,mBAAoB,IAAI,KAAI,EAAG;AAC1D,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACvB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAElB,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AAGb,IAAA,MAAM,IAAA,GAAO,cACV,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,IAAA,CAAK,KAAA,KAAU,IAAI,CAAA,CACjC,GAAA,CAAI,OAAK,CAAA,CAAE,EAAA,CAAG,KAAK,CAAA,CACnB,MAAA,CAAO,SAAO,UAAA,CAAW,QAAA,CAAS,GAAG,CAAC,CAAA;AAEzC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,KAAA,CAAM,GAAA,EAAK,IAAI,GAAA,CAAI,IAAI,CAAC,CAAA;AAAA,IAC1B;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACtB,MAAA,OAAA,CAAQ,IAAI,IAAI,CAAA;AAChB,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,KAAA,CAAM,IAAI,CAAA;AAAA,EACZ;AAEA,EAAA,OAAO,KAAA;AACT;;;AC3MA,eAAsB,oBAAA,CACpB,SAAA,EACA,OAAA,GAAwB,EAAC,EACD;AACxB,EAAA,MAAM,EAAE,WAAA,GAAc,IAAA,EAAK,GAAI,OAAA;AAE/B,EAAA,IAAI,GAAA;AAEJ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,GAAA,GAAM,MAAMA,8BAAA,CAAc,WAAA,CAAY,SAAS,CAAA;AAAA,EACjD,CAAA,MAAO;AACL,IAAA,GAAA,GAAM,MAAMA,8BAAA,CAAc,KAAA,CAAM,SAAS,CAAA;AAAA,EAC3C;AAEA,EAAA,OAAO,oBAAA,CAAqB,KAAwB,OAAO,CAAA;AAC7D;AAKA,eAAsB,sBAAA,CACpB,IAAA,EACA,OAAA,GAAwB,EAAC,EACD;AACxB,EAAA,MAAM,EAAE,WAAA,GAAc,IAAA,EAAK,GAAI,OAAA;AAG/B,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AAEN,IAAA,MAAMC,IAAAA,GAAM,MAAMD,8BAAA,CAAc,KAAA,CAAM,IAAyB,CAAA;AAC/D,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,OAAO,oBAAA;AAAA,QACJ,MAAMA,8BAAA,CAAc,WAAA,CAAYC,IAAG,CAAA;AAAA,QACpC;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,oBAAA,CAAqBA,MAAwB,OAAO,CAAA;AAAA,EAC7D;AAEA,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,GAAA,GAAM,MAAMD,8BAAA,CAAc,WAAA,CAAY,MAA0B,CAAA;AAAA,EAClE,CAAA,MAAO;AACL,IAAA,GAAA,GAAM,MAAMA,8BAAA,CAAc,QAAA,CAAS,MAA0B,CAAA;AAAA,EAC/D;AAEA,EAAA,OAAO,oBAAA,CAAqB,KAAwB,OAAO,CAAA;AAC7D;AAKA,eAAsB,sBAAA,CACpB,IAAA,EACA,OAAA,GAAwB,EAAC,EACD;AACxB,EAAA,MAAM,EAAE,WAAA,GAAc,IAAA,EAAK,GAAI,OAAA;AAE/B,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,GAAA,GAAM,MAAMA,8BAAA,CAAc,WAAA,CAAY,IAAwB,CAAA;AAAA,EAChE,CAAA,MAAO;AACL,IAAA,GAAA,GAAM,MAAMA,8BAAA,CAAc,QAAA,CAAS,IAAwB,CAAA;AAAA,EAC7D;AAEA,EAAA,OAAO,oBAAA,CAAqB,KAAwB,OAAO,CAAA;AAC7D;AAKA,SAAS,oBAAA,CACP,GAAA,EACA,OAAA,GAAwB,EAAC,EACV;AACf,EAAA,MAAM,EAAE,mBAAA,EAAqB,YAAA,GAAe,IAAA,EAAK,GAAI,OAAA;AAGrD,EAAA,MAAM,IAAA,GAAO,UAAU,GAAG,CAAA;AAG1B,EAAA,MAAM,MAAA,GAAS,YAAY,GAAG,CAAA;AAG9B,EAAA,MAAM,SAAA,GAAY,eAAe,GAAG,CAAA;AAGpC,EAAA,MAAM,aAAA,GAAgB,YAAA,GAAe,mBAAA,CAAoB,MAAM,IAAI,EAAC;AAEpE,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAKA,SAAS,UAAU,GAAA,EAAkC;AACnD,EAAA,MAAM,IAAA,GAAmB;AAAA,IACvB,KAAA,EAAO,GAAA,CAAI,IAAA,EAAM,KAAA,IAAS,cAAA;AAAA,IAC1B,OAAA,EAAS,GAAA,CAAI,IAAA,EAAM,OAAA,IAAW,OAAA;AAAA,IAC9B,WAAA,EAAa,IAAI,IAAA,EAAM;AAAA,GACzB;AAGA,EAAA,IAAI,GAAA,CAAI,WAAW,GAAA,CAAI,OAAA,CAAQ,SAAS,CAAA,IAAK,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AAC3D,IAAA,IAAA,CAAK,OAAA,GAAU,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,CAAE,GAAA;AAAA,EAChC;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,YAAY,GAAA,EAAiD;AACpE,EAAA,MAAM,SAAoC,EAAC;AAE3C,EAAA,MAAM,OAAA,GAAU,IAAI,UAAA,EAAY,OAAA;AAChC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAEpD,IAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,kBAAA,CAAmB,IAAA,EAAM,MAAsB,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,MAAA;AACT;AAKA,SAAS,kBAAA,CAAmB,MAAc,MAAA,EAAiC;AACzE,EAAA,MAAM,KAAA,GAAmB;AAAA,IACvB,IAAA;AAAA,IACA,IAAA,EAAM,qBAAA,CAAsB,MAAA,CAAO,IAAI,CAAA;AAAA,IACvC,aAAa,MAAA,CAAO;AAAA,GACtB;AAGA,EAAA,IAAI,MAAA,CAAO,IAAA,KAAS,QAAA,IAAY,MAAA,CAAO,UAAA,EAAY;AACjD,IAAA,KAAA,CAAM,IAAA,GAAO,QAAA;AACb,IAAA,KAAA,CAAM,aAAa,EAAC;AACpB,IAAA,KAAA,CAAM,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,EAAC;AAErC,IAAA,IAAI,OAAO,UAAA,EAAY;AACrB,MAAA,KAAA,MAAW,CAAC,UAAU,UAAU,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA,EAAG;AACtE,QAAA,KAAA,CAAM,UAAA,CAAW,QAAQ,CAAA,GAAI,aAAA;AAAA,UAC3B,QAAA;AAAA,UACA,UAAA;AAAA,UACA,KAAA,CAAM,QAAA,CAAS,QAAA,CAAS,QAAQ;AAAA,SAClC;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,CAAO,yBAAyB,MAAA,EAAW;AAC7C,MAAA,IAAI,OAAO,MAAA,CAAO,oBAAA,KAAyB,SAAA,EAAW;AACpD,QAAA,KAAA,CAAM,uBAAuB,MAAA,CAAO,oBAAA;AAAA,MACtC,CAAA,MAAA,IAAW,MAAA,IAAU,MAAA,CAAO,oBAAA,EAAsB;AAChD,QAAA,KAAA,CAAM,oBAAA,GAAuB;AAAA,UAC3B,IAAA,EAAO,OAAO,oBAAA,CAAyC;AAAA,SACzD;AAAA,MACF,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,oBAAA,GAAuB,kBAAA;AAAA,UAC3B,GAAG,IAAI,CAAA,eAAA,CAAA;AAAA,UACP,MAAA,CAAO;AAAA,SACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,MAAA,CAAO,IAAA,KAAS,OAAA,IAAW,MAAA,CAAO,KAAA,EAAO;AAC3C,IAAA,KAAA,CAAM,IAAA,GAAO,OAAA;AACb,IAAA,IAAI,MAAA,IAAU,OAAO,KAAA,EAAO;AAC1B,MAAA,KAAA,CAAM,KAAA,GAAQ,EAAE,IAAA,EAAO,MAAA,CAAO,MAA0B,IAAA,EAAK;AAAA,IAC/D,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,QAAQ,kBAAA,CAAmB,CAAA,EAAG,IAAI,CAAA,IAAA,CAAA,EAAQ,OAAO,KAAqB,CAAA;AAAA,IAC9E;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,KAAA,CAAM,OAAO,MAAA,CAAO,IAAA;AAAA,EACtB;AAGA,EAAA,IAAI,MAAA,CAAO,YAAY,MAAA,EAAW;AAChC,IAAA,KAAA,CAAM,UAAU,MAAA,CAAO,OAAA;AAAA,EACzB;AAEA,EAAA,OAAO,KAAA;AACT;AAKA,SAAS,aAAA,CACP,IAAA,EACA,MAAA,EACA,QAAA,EACa;AAEb,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,IAAA,EAAM,QAAA;AAAA,MACN,QAAA;AAAA,MACA,MAAM,MAAA,CAAO;AAAA,KACf;AAAA,EACF;AAEA,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,IAAA;AAAA,IACA,IAAA,EAAM,wBAAA,CAAyB,MAAA,CAAO,IAAI,CAAA;AAAA,IAC1C,QAAA;AAAA,IACA,UAAW,MAAA,CAAmC,QAAA;AAAA,IAC9C,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,SAAS,MAAA,CAAO;AAAA,GAClB;AAGA,EAAA,IAAI,MAAA,CAAO,IAAA,KAAS,OAAA,IAAW,MAAA,CAAO,KAAA,EAAO;AAC3C,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA;AACZ,IAAA,IAAI,MAAA,IAAU,OAAO,KAAA,EAAO;AAC1B,MAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,IAAA,EAAO,MAAA,CAAO,MAA0B,IAAA,EAAK;AAAA,IAC9D,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,QAAQ,kBAAA,CAAmB,CAAA,EAAG,IAAI,CAAA,IAAA,CAAA,EAAQ,OAAO,KAAqB,CAAA;AAAA,IAC7E;AAAA,EACF;AAGA,EAAA,MAAM,aAAA,GAAiB,OAAmC,wBAAwB,CAAA;AAClF,EAAA,IAAI,aAAA,IAAiB,OAAO,aAAA,KAAkB,QAAA,EAAU;AACtD,IAAA,IAAA,CAAK,wBAAwB,CAAA,GAAI,aAAA;AAAA,EACnC;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,eAAe,GAAA,EAAkC;AACxD,EAAA,MAAM,YAAwB,EAAC;AAE/B,EAAA,IAAI,CAAC,IAAI,KAAA,EAAO;AACd,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAwB,CAAC,KAAA,EAAO,MAAA,EAAQ,OAAO,OAAA,EAAS,QAAA,EAAU,QAAQ,SAAS,CAAA;AAEzF,EAAA,KAAA,MAAW,CAAC,MAAM,QAAQ,CAAA,IAAK,OAAO,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACxD,IAAA,IAAI,CAAC,QAAA,EAAU;AAEf,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,SAAA,GAAY,QAAA,CAAS,MAAA,CAAO,WAAA,EAAsC,CAAA;AAKxE,MAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,MAAA,SAAA,CAAU,KAAK,aAAA,CAAc,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAW,QAAQ,CAAC,CAAA;AAAA,IACjE;AAAA,EACF;AAEA,EAAA,OAAO,SAAA;AACT;AAKA,SAAS,aAAA,CACP,MAAA,EACA,IAAA,EACA,SAAA,EACA,QAAA,EACU;AAEV,EAAA,MAAM,SAAA,GAAY,CAAC,GAAI,QAAA,CAAS,UAAA,IAAc,EAAC,EAAI,GAAI,SAAA,CAAU,UAAA,IAAc,EAAG,CAAA;AAElF,EAAA,MAAM,aAA6B,EAAC;AACpC,EAAA,MAAM,cAA8B,EAAC;AAErC,EAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC7B,IAAA,IAAI,UAAU,KAAA,EAAO;AACrB,IAAA,MAAM,QAAA,GAAW,KAAA;AACjB,IAAA,MAAM,MAAA,GAAS,eAAe,QAAQ,CAAA;AAEtC,IAAA,IAAI,MAAA,CAAO,OAAO,MAAA,EAAQ;AACxB,MAAA,UAAA,CAAW,KAAK,MAAM,CAAA;AAAA,IACxB,CAAA,MAAA,IAAW,MAAA,CAAO,EAAA,KAAO,OAAA,EAAS;AAChC,MAAA,WAAA,CAAY,KAAK,MAAM,CAAA;AAAA,IACzB;AAAA,EACF;AAGA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,SAAA,CAAU,WAAA,IAAe,EAAE,MAAA,IAAU,UAAU,WAAA,CAAA,EAAc;AAC/D,IAAA,WAAA,GAAc,gBAAA,CAAiB,UAAU,WAAgC,CAAA;AAAA,EAC3E;AAGA,EAAA,MAAM,YAAyC,EAAC;AAChD,EAAA,IAAI,UAAU,SAAA,EAAW;AACvB,IAAA,KAAA,MAAW,CAAC,YAAY,QAAQ,CAAA,IAAK,OAAO,OAAA,CAAQ,SAAA,CAAU,SAAS,CAAA,EAAG;AACxE,MAAA,IAAI,UAAU,QAAA,EAAU;AACxB,MAAA,SAAA,CAAU,UAAU,CAAA,GAAI,aAAA,CAAc,UAAA,EAAY,QAA0B,CAAA;AAAA,IAC9E;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,IAAA;AAAA,IACA,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,SAAS,SAAA,CAAU,OAAA;AAAA,IACnB,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,UAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA,EAAM,SAAA,CAAU,IAAA,IAAQ;AAAC,GAC3B;AACF;AAKA,SAAS,eAAe,KAAA,EAAsC;AAC5D,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AAErB,EAAA,OAAO;AAAA,IACL,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,IAAI,KAAA,CAAM,EAAA;AAAA,IACV,QAAA,EAAU,MAAM,QAAA,IAAY,KAAA;AAAA,IAC5B,IAAA,EAAM,MAAA,GAAS,wBAAA,CAAyB,MAAA,CAAO,IAAI,CAAA,GAAI,QAAA;AAAA,IACvD,QAAQ,MAAA,EAAQ,MAAA;AAAA,IAChB,aAAa,KAAA,CAAM,WAAA;AAAA,IACnB,OAAA,EAAS,KAAA,CAAM,OAAA,IAAW,MAAA,EAAQ;AAAA,GACpC;AACF;AAKA,SAAS,iBAAiB,IAAA,EAAsC;AAC9D,EAAA,MAAM,WAAA,GAAc,OAAO,IAAA,CAAK,IAAA,CAAK,WAAW,EAAE,CAAA,CAAE,CAAC,CAAA,IAAK,kBAAA;AAC1D,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,GAAU,WAAW,CAAA;AAE5C,EAAA,IAAI,MAAA,GAAgC,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,QAAA,EAAS;AAEtE,EAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,IAAA,IAAI,MAAA,IAAU,UAAU,MAAA,EAAQ;AAC9B,MAAA,MAAA,GAAS,EAAE,IAAA,EAAO,SAAA,CAAU,MAAA,CAA2B,IAAA,EAAK;AAAA,IAC9D,CAAA,MAAO;AACL,MAAA,MAAA,GAAS,kBAAA,CAAmB,aAAA,EAAe,SAAA,CAAU,MAAsB,CAAA;AAAA,IAC7E;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAU,KAAK,QAAA,IAAY,KAAA;AAAA,IAC3B,aAAa,IAAA,CAAK;AAAA,GACpB;AACF;AAKA,SAAS,aAAA,CAAc,YAAoB,QAAA,EAAuC;AAChF,EAAA,MAAM,WAAA,GAA2B;AAAA,IAC/B,UAAA;AAAA,IACA,aAAa,QAAA,CAAS;AAAA,GACxB;AAEA,EAAA,IAAI,SAAS,OAAA,EAAS;AACpB,IAAA,WAAA,CAAY,UAAU,EAAC;AAEvB,IAAA,KAAA,MAAW,CAAC,aAAa,SAAS,CAAA,IAAK,OAAO,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA,EAAG;AACvE,MAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,QAAA,IAAI,MAAA,IAAU,UAAU,MAAA,EAAQ;AAC9B,UAAA,WAAA,CAAY,OAAA,CAAQ,WAAW,CAAA,GAAI;AAAA,YACjC,IAAA,EAAO,UAAU,MAAA,CAA2B;AAAA,WAC9C;AAAA,QACF,CAAA,MAAO;AACL,UAAA,WAAA,CAAY,OAAA,CAAQ,WAAW,CAAA,GAAI,kBAAA;AAAA,YACjC,WAAW,UAAU,CAAA,CAAA;AAAA,YACrB,SAAA,CAAU;AAAA,WACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,WAAA;AACT;AAKA,SAAS,sBACP,IAAA,EACW;AACX,EAAA,IAAI,CAAC,MAAM,OAAO,QAAA;AAClB,EAAA,IAAI,MAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,KAAK,CAAC,CAAA;AACtC,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,yBACP,IAAA,EACc;AACd,EAAA,IAAI,CAAC,MAAM,OAAO,QAAA;AAClB,EAAA,IAAI,MAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,KAAK,CAAC,CAAA;AACtC,EAAA,OAAO,IAAA;AACT","file":"index.cjs","sourcesContent":["/**\n * Core types for DemoKit schema representation\n *\n * These types represent a parsed API schema with relationship detection,\n * independent of the source format (OpenAPI, GraphQL, etc.)\n */\n\n/**\n * The main schema representation for DemoKit\n * Contains all information needed for fixture generation\n */\nexport interface DemokitSchema {\n /**\n * Metadata about the API\n */\n info: SchemaInfo\n\n /**\n * All API endpoints discovered from the spec\n */\n endpoints: Endpoint[]\n\n /**\n * All data models (schemas) from the spec\n */\n models: Record<string, DataModel>\n\n /**\n * Detected relationships between models\n */\n relationships: Relationship[]\n}\n\n/**\n * API metadata\n */\nexport interface SchemaInfo {\n /**\n * API title from the spec\n */\n title: string\n\n /**\n * API version\n */\n version: string\n\n /**\n * Optional description\n */\n description?: string\n\n /**\n * Base URL for the API (if specified)\n */\n baseUrl?: string\n}\n\n/**\n * An API endpoint\n */\nexport interface Endpoint {\n /**\n * HTTP method (GET, POST, PUT, PATCH, DELETE)\n */\n method: HttpMethod\n\n /**\n * URL path with parameter placeholders\n * @example \"/users/{id}\" or \"/orders/{orderId}/items\"\n */\n path: string\n\n /**\n * Operation ID from OpenAPI (if available)\n */\n operationId?: string\n\n /**\n * Human-readable summary\n */\n summary?: string\n\n /**\n * Detailed description\n */\n description?: string\n\n /**\n * Path parameters\n */\n pathParams: ParameterDef[]\n\n /**\n * Query parameters\n */\n queryParams: ParameterDef[]\n\n /**\n * Request body schema (for POST/PUT/PATCH)\n */\n requestBody?: RequestBody\n\n /**\n * Response schemas by status code\n */\n responses: Record<string, ResponseDef>\n\n /**\n * Tags for grouping endpoints\n */\n tags: string[]\n}\n\n/**\n * HTTP methods supported\n */\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\n/**\n * A request or response body definition\n */\nexport interface RequestBody {\n /**\n * Content type (usually application/json)\n */\n contentType: string\n\n /**\n * Reference to the model name, or inline schema\n */\n schema: SchemaRef | DataModel\n\n /**\n * Whether the body is required\n */\n required: boolean\n\n /**\n * Description of the body\n */\n description?: string\n}\n\n/**\n * A response definition\n */\nexport interface ResponseDef {\n /**\n * HTTP status code\n */\n statusCode: string\n\n /**\n * Description of the response\n */\n description?: string\n\n /**\n * Content type to schema mapping\n */\n content?: Record<string, SchemaRef | DataModel>\n}\n\n/**\n * A parameter definition (path or query)\n */\nexport interface ParameterDef {\n /**\n * Parameter name\n */\n name: string\n\n /**\n * Where the parameter is located\n */\n in: 'path' | 'query' | 'header' | 'cookie'\n\n /**\n * Whether the parameter is required\n */\n required: boolean\n\n /**\n * Parameter type\n */\n type: PropertyType\n\n /**\n * Optional format hint\n */\n format?: string\n\n /**\n * Description\n */\n description?: string\n\n /**\n * Example value\n */\n example?: unknown\n}\n\n/**\n * Reference to another schema/model\n */\nexport interface SchemaRef {\n /**\n * The referenced model name\n */\n $ref: string\n}\n\n/**\n * A data model representing an object schema\n */\nexport interface DataModel {\n /**\n * Model name (from the schema component name)\n */\n name: string\n\n /**\n * The type of this model\n */\n type: ModelType\n\n /**\n * Description from the spec\n */\n description?: string\n\n /**\n * Properties for object types\n */\n properties?: Record<string, PropertyDef>\n\n /**\n * Required property names\n */\n required?: string[]\n\n /**\n * For array types, the item schema\n */\n items?: SchemaRef | DataModel\n\n /**\n * Enum values for enum types\n */\n enum?: unknown[]\n\n /**\n * Example value from the spec\n */\n example?: unknown\n\n /**\n * Additional properties schema (for dictionaries)\n */\n additionalProperties?: boolean | SchemaRef | DataModel\n}\n\n/**\n * Model types\n */\nexport type ModelType = 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'\n\n/**\n * A property definition within a model\n */\nexport interface PropertyDef {\n /**\n * Property name\n */\n name: string\n\n /**\n * Property type\n */\n type: PropertyType\n\n /**\n * Format hint (uuid, email, date-time, etc.)\n */\n format?: string\n\n /**\n * Description\n */\n description?: string\n\n /**\n * Whether this property is required\n */\n required?: boolean\n\n /**\n * Whether this property is nullable\n */\n nullable?: boolean\n\n /**\n * Enum values for string enums\n */\n enum?: unknown[]\n\n /**\n * For array types, the item schema\n */\n items?: SchemaRef | DataModel\n\n /**\n * Reference to another model (for $ref properties)\n */\n $ref?: string\n\n /**\n * Example value\n */\n example?: unknown\n\n /**\n * Default value\n */\n default?: unknown\n\n /**\n * Minimum value (for numbers)\n */\n minimum?: number\n\n /**\n * Maximum value (for numbers)\n */\n maximum?: number\n\n /**\n * Min length (for strings)\n */\n minLength?: number\n\n /**\n * Max length (for strings)\n */\n maxLength?: number\n\n /**\n * Pattern (regex for strings)\n */\n pattern?: string\n\n /**\n * Detected relationship to another model\n * Set by relationship detection, not directly from spec\n */\n relationshipTo?: RelationshipTarget\n\n /**\n * Custom extension for explicit relationship hints\n * @example \"x-demokit-relationship\": { \"model\": \"User\", \"field\": \"id\" }\n */\n 'x-demokit-relationship'?: RelationshipTarget\n}\n\n/**\n * Property types\n */\nexport type PropertyType =\n | 'string'\n | 'number'\n | 'integer'\n | 'boolean'\n | 'array'\n | 'object'\n | 'null'\n\n/**\n * A detected relationship between two models\n */\nexport interface Relationship {\n /**\n * The source side of the relationship\n */\n from: RelationshipSide\n\n /**\n * The target side of the relationship\n */\n to: RelationshipSide\n\n /**\n * Type of relationship\n */\n type: RelationshipType\n\n /**\n * Whether the relationship is required (not nullable)\n */\n required: boolean\n\n /**\n * How this relationship was detected\n */\n detectedBy: RelationshipDetectionMethod\n}\n\n/**\n * One side of a relationship\n */\nexport interface RelationshipSide {\n /**\n * Model name\n */\n model: string\n\n /**\n * Field name\n */\n field: string\n}\n\n/**\n * Target for a relationship from a property\n */\nexport interface RelationshipTarget {\n /**\n * Target model name\n */\n model: string\n\n /**\n * Target field (usually \"id\")\n */\n field: string\n}\n\n/**\n * Types of relationships between models\n */\nexport type RelationshipType =\n | 'one-to-one'\n | 'one-to-many'\n | 'many-to-one'\n | 'many-to-many'\n\n/**\n * How a relationship was detected\n */\nexport type RelationshipDetectionMethod =\n | 'explicit-ref' // OpenAPI $ref\n | 'naming-convention' // userId -> User.id pattern\n | 'x-demokit-extension' // x-demokit-relationship extension\n | 'inferred' // AI or heuristic inference\n\n/**\n * Helper type to check if something is a schema reference\n */\nexport function isSchemaRef(value: unknown): value is SchemaRef {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$ref' in value &&\n typeof (value as SchemaRef).$ref === 'string'\n )\n}\n\n/**\n * Extract the model name from a $ref string\n * @example \"#/components/schemas/User\" -> \"User\"\n */\nexport function extractRefName(ref: string): string {\n const parts = ref.split('/')\n return parts[parts.length - 1] ?? ref\n}\n","/**\n * Relationship detection for DemoKit schemas\n *\n * Detects relationships between models using:\n * 1. Explicit $ref references in OpenAPI\n * 2. Naming conventions (userId -> User.id)\n * 3. x-demokit-relationship extension\n */\n\nimport type {\n DataModel,\n PropertyDef,\n Relationship,\n RelationshipTarget,\n RelationshipDetectionMethod,\n RelationshipType,\n} from './types'\nimport { isSchemaRef, extractRefName } from './types'\n\n/**\n * Common ID field naming patterns\n * Maps suffix patterns to implied relationships\n */\nconst ID_FIELD_PATTERNS = [\n // Standard patterns: userId -> User, customerId -> Customer\n { pattern: /^(.+)Id$/, targetField: 'id' },\n { pattern: /^(.+)_id$/, targetField: 'id' },\n { pattern: /^(.+)ID$/, targetField: 'id' },\n\n // UUID patterns: userUuid -> User, customerUUID -> Customer\n { pattern: /^(.+)Uuid$/, targetField: 'uuid' },\n { pattern: /^(.+)UUID$/, targetField: 'uuid' },\n { pattern: /^(.+)_uuid$/, targetField: 'uuid' },\n]\n\n/**\n * Convert a field name prefix to a model name\n * @example \"user\" -> \"User\", \"orderItem\" -> \"OrderItem\"\n */\nfunction prefixToModelName(prefix: string): string {\n return prefix.charAt(0).toUpperCase() + prefix.slice(1)\n}\n\n/**\n * Check if a property looks like a foreign key based on naming conventions\n */\nexport function detectRelationshipFromNaming(\n property: PropertyDef,\n availableModels: Set<string>\n): RelationshipTarget | null {\n const fieldName = property.name\n\n for (const { pattern, targetField } of ID_FIELD_PATTERNS) {\n const match = fieldName.match(pattern)\n if (match && match[1]) {\n const prefix = match[1]\n const modelName = prefixToModelName(prefix)\n\n // Check if this model exists in the schema\n if (availableModels.has(modelName)) {\n return { model: modelName, field: targetField }\n }\n\n // Also check for plural forms\n const pluralModel = modelName + 's'\n if (availableModels.has(pluralModel)) {\n return { model: pluralModel, field: targetField }\n }\n }\n }\n\n return null\n}\n\n/**\n * Check if a property has an explicit x-demokit-relationship extension\n */\nexport function detectRelationshipFromExtension(\n property: PropertyDef\n): RelationshipTarget | null {\n const extension = property['x-demokit-relationship']\n if (extension && typeof extension === 'object') {\n return {\n model: extension.model,\n field: extension.field || 'id',\n }\n }\n return null\n}\n\n/**\n * Check if a property is a $ref to another model\n */\nexport function detectRelationshipFromRef(\n property: PropertyDef,\n availableModels: Set<string>\n): RelationshipTarget | null {\n if (property.$ref) {\n const modelName = extractRefName(property.$ref)\n if (availableModels.has(modelName)) {\n return { model: modelName, field: 'id' }\n }\n }\n\n // Check if items is a $ref (for arrays of references)\n if (property.items && isSchemaRef(property.items)) {\n const modelName = extractRefName(property.items.$ref)\n if (availableModels.has(modelName)) {\n return { model: modelName, field: 'id' }\n }\n }\n\n return null\n}\n\n/**\n * Detect the relationship type based on property and target\n */\nfunction determineRelationshipType(\n property: PropertyDef,\n _fromModel: DataModel\n): RelationshipType {\n // If the property is an array, it's one-to-many or many-to-many\n if (property.type === 'array') {\n // For simplicity, treat array references as one-to-many\n // (the \"one\" side has the array of references)\n return 'one-to-many'\n }\n\n // Single reference is many-to-one (many records can reference one target)\n return 'many-to-one'\n}\n\n/**\n * Detect all relationships in a set of models\n */\nexport function detectRelationships(\n models: Record<string, DataModel>\n): Relationship[] {\n const relationships: Relationship[] = []\n const availableModels = new Set(Object.keys(models))\n\n for (const [modelName, model] of Object.entries(models)) {\n if (!model.properties) continue\n\n for (const [propName, property] of Object.entries(model.properties)) {\n let target: RelationshipTarget | null = null\n let detectionMethod: RelationshipDetectionMethod = 'inferred'\n\n // Priority 1: Explicit x-demokit-relationship extension\n target = detectRelationshipFromExtension(property)\n if (target) {\n detectionMethod = 'x-demokit-extension'\n }\n\n // Priority 2: $ref references\n if (!target) {\n target = detectRelationshipFromRef(property, availableModels)\n if (target) {\n detectionMethod = 'explicit-ref'\n }\n }\n\n // Priority 3: Naming conventions\n if (!target) {\n target = detectRelationshipFromNaming(property, availableModels)\n if (target) {\n detectionMethod = 'naming-convention'\n }\n }\n\n if (target) {\n // Don't create self-referential relationships for simple IDs\n if (target.model === modelName && target.field === 'id' && propName === 'id') {\n continue\n }\n\n // Add the detected relationship info to the property\n property.relationshipTo = target\n\n relationships.push({\n from: { model: modelName, field: propName },\n to: target,\n type: determineRelationshipType(property, model),\n required: property.required ?? false,\n detectedBy: detectionMethod,\n })\n }\n }\n }\n\n return relationships\n}\n\n/**\n * Find all relationships for a specific model\n */\nexport function getRelationshipsForModel(\n modelName: string,\n relationships: Relationship[]\n): {\n outgoing: Relationship[]\n incoming: Relationship[]\n} {\n return {\n outgoing: relationships.filter(r => r.from.model === modelName),\n incoming: relationships.filter(r => r.to.model === modelName),\n }\n}\n\n/**\n * Check if a model is referenced by other models\n */\nexport function isModelReferenced(\n modelName: string,\n relationships: Relationship[]\n): boolean {\n return relationships.some(r => r.to.model === modelName)\n}\n\n/**\n * Get the dependency order for models based on relationships\n * Returns models in order such that dependencies come before dependents\n */\nexport function getModelDependencyOrder(\n models: Record<string, DataModel>,\n relationships: Relationship[]\n): string[] {\n const modelNames = Object.keys(models)\n const visited = new Set<string>()\n const order: string[] = []\n\n function visit(name: string, path: Set<string> = new Set()) {\n if (visited.has(name)) return\n if (path.has(name)) {\n // Circular dependency - skip to break the cycle\n return\n }\n\n path.add(name)\n\n // Visit all models that this model depends on first\n const deps = relationships\n .filter(r => r.from.model === name)\n .map(r => r.to.model)\n .filter(dep => modelNames.includes(dep))\n\n for (const dep of deps) {\n visit(dep, new Set(path))\n }\n\n if (!visited.has(name)) {\n visited.add(name)\n order.push(name)\n }\n }\n\n for (const name of modelNames) {\n visit(name)\n }\n\n return order\n}\n","/**\n * OpenAPI 3.x parser for DemoKit\n *\n * Parses OpenAPI specs into DemoKit's internal schema representation\n * with automatic relationship detection.\n */\n\nimport SwaggerParser from '@apidevtools/swagger-parser'\nimport type { OpenAPI, OpenAPIV3, OpenAPIV3_1 } from 'openapi-types'\nimport type {\n DemokitSchema,\n SchemaInfo,\n Endpoint,\n DataModel,\n PropertyDef,\n HttpMethod,\n ParameterDef,\n RequestBody,\n ResponseDef,\n PropertyType,\n ModelType,\n} from './types'\n// extractRefName is used in relationships.ts, re-exported from index.ts\nimport { detectRelationships } from './relationships'\n\ntype OpenAPIDocument = OpenAPIV3.Document | OpenAPIV3_1.Document\ntype SchemaObject = OpenAPIV3.SchemaObject | OpenAPIV3_1.SchemaObject\ntype ReferenceObject = OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject\ntype ParameterObject = OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject\ntype RequestBodyObject = OpenAPIV3.RequestBodyObject | OpenAPIV3_1.RequestBodyObject\ntype ResponseObject = OpenAPIV3.ResponseObject | OpenAPIV3_1.ResponseObject\ntype MediaTypeObject = OpenAPIV3.MediaTypeObject | OpenAPIV3_1.MediaTypeObject\n\n/**\n * Options for parsing OpenAPI specs\n */\nexport interface ParseOptions {\n /**\n * Whether to dereference all $ref pointers\n * @default true\n */\n dereference?: boolean\n\n /**\n * Whether to detect relationships automatically\n * @default true\n */\n detectRelationships?: boolean\n\n /**\n * Whether to include response schemas in models\n * @default true\n */\n includeResponses?: boolean\n}\n\n/**\n * Parse an OpenAPI spec from a file path or URL\n */\nexport async function parseOpenAPIFromPath(\n pathOrUrl: string,\n options: ParseOptions = {}\n): Promise<DemokitSchema> {\n const { dereference = true } = options\n\n let api: OpenAPI.Document\n\n if (dereference) {\n api = await SwaggerParser.dereference(pathOrUrl)\n } else {\n api = await SwaggerParser.parse(pathOrUrl)\n }\n\n return parseOpenAPIDocument(api as OpenAPIDocument, options)\n}\n\n/**\n * Parse an OpenAPI spec from a string (JSON or YAML)\n */\nexport async function parseOpenAPIFromString(\n spec: string,\n options: ParseOptions = {}\n): Promise<DemokitSchema> {\n const { dereference = true } = options\n\n // Parse the string as JSON or YAML\n let parsed: unknown\n try {\n parsed = JSON.parse(spec)\n } catch {\n // If JSON parse fails, try YAML via SwaggerParser\n const api = await SwaggerParser.parse(spec as unknown as string)\n if (dereference) {\n return parseOpenAPIDocument(\n (await SwaggerParser.dereference(api)) as OpenAPIDocument,\n options\n )\n }\n return parseOpenAPIDocument(api as OpenAPIDocument, options)\n }\n\n let api: OpenAPI.Document\n if (dereference) {\n api = await SwaggerParser.dereference(parsed as OpenAPI.Document)\n } else {\n api = await SwaggerParser.validate(parsed as OpenAPI.Document)\n }\n\n return parseOpenAPIDocument(api as OpenAPIDocument, options)\n}\n\n/**\n * Parse an OpenAPI spec from an already-parsed object\n */\nexport async function parseOpenAPIFromObject(\n spec: Record<string, unknown>,\n options: ParseOptions = {}\n): Promise<DemokitSchema> {\n const { dereference = true } = options\n\n let api: OpenAPI.Document\n if (dereference) {\n api = await SwaggerParser.dereference(spec as OpenAPI.Document)\n } else {\n api = await SwaggerParser.validate(spec as OpenAPI.Document)\n }\n\n return parseOpenAPIDocument(api as OpenAPIDocument, options)\n}\n\n/**\n * Parse an OpenAPI document into DemokitSchema\n */\nfunction parseOpenAPIDocument(\n doc: OpenAPIDocument,\n options: ParseOptions = {}\n): DemokitSchema {\n const { detectRelationships: shouldDetect = true } = options\n\n // Parse info\n const info = parseInfo(doc)\n\n // Parse models from components/schemas\n const models = parseModels(doc)\n\n // Parse endpoints from paths\n const endpoints = parseEndpoints(doc)\n\n // Detect relationships\n const relationships = shouldDetect ? detectRelationships(models) : []\n\n return {\n info,\n endpoints,\n models,\n relationships,\n }\n}\n\n/**\n * Parse API info from the document\n */\nfunction parseInfo(doc: OpenAPIDocument): SchemaInfo {\n const info: SchemaInfo = {\n title: doc.info?.title ?? 'Untitled API',\n version: doc.info?.version ?? '1.0.0',\n description: doc.info?.description,\n }\n\n // Try to extract base URL from servers\n if (doc.servers && doc.servers.length > 0 && doc.servers[0]) {\n info.baseUrl = doc.servers[0].url\n }\n\n return info\n}\n\n/**\n * Parse all models from components/schemas\n */\nfunction parseModels(doc: OpenAPIDocument): Record<string, DataModel> {\n const models: Record<string, DataModel> = {}\n\n const schemas = doc.components?.schemas\n if (!schemas) {\n return models\n }\n\n for (const [name, schema] of Object.entries(schemas)) {\n // Skip reference objects (shouldn't happen after dereference)\n if ('$ref' in schema) {\n continue\n }\n\n models[name] = parseSchemaToModel(name, schema as SchemaObject)\n }\n\n return models\n}\n\n/**\n * Parse a schema object into a DataModel\n */\nfunction parseSchemaToModel(name: string, schema: SchemaObject): DataModel {\n const model: DataModel = {\n name,\n type: schemaTypeToModelType(schema.type),\n description: schema.description,\n }\n\n // Parse properties for object types\n if (schema.type === 'object' || schema.properties) {\n model.type = 'object'\n model.properties = {}\n model.required = schema.required || []\n\n if (schema.properties) {\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n model.properties[propName] = parseProperty(\n propName,\n propSchema as SchemaObject | ReferenceObject,\n model.required.includes(propName)\n )\n }\n }\n\n if (schema.additionalProperties !== undefined) {\n if (typeof schema.additionalProperties === 'boolean') {\n model.additionalProperties = schema.additionalProperties\n } else if ('$ref' in schema.additionalProperties) {\n model.additionalProperties = {\n $ref: (schema.additionalProperties as ReferenceObject).$ref,\n }\n } else {\n model.additionalProperties = parseSchemaToModel(\n `${name}AdditionalProps`,\n schema.additionalProperties as SchemaObject\n )\n }\n }\n }\n\n // Parse array items\n if (schema.type === 'array' && schema.items) {\n model.type = 'array'\n if ('$ref' in schema.items) {\n model.items = { $ref: (schema.items as ReferenceObject).$ref }\n } else {\n model.items = parseSchemaToModel(`${name}Item`, schema.items as SchemaObject)\n }\n }\n\n // Parse enum values\n if (schema.enum) {\n model.enum = schema.enum\n }\n\n // Parse example\n if (schema.example !== undefined) {\n model.example = schema.example\n }\n\n return model\n}\n\n/**\n * Parse a property schema into a PropertyDef\n */\nfunction parseProperty(\n name: string,\n schema: SchemaObject | ReferenceObject,\n required: boolean\n): PropertyDef {\n // Handle $ref\n if ('$ref' in schema) {\n return {\n name,\n type: 'object',\n required,\n $ref: schema.$ref,\n }\n }\n\n const prop: PropertyDef = {\n name,\n type: schemaTypeToPropertyType(schema.type),\n required,\n nullable: (schema as Record<string, unknown>).nullable as boolean | undefined,\n description: schema.description,\n format: schema.format,\n enum: schema.enum,\n example: schema.example,\n default: schema.default,\n minimum: schema.minimum,\n maximum: schema.maximum,\n minLength: schema.minLength,\n maxLength: schema.maxLength,\n pattern: schema.pattern,\n }\n\n // Parse array items\n if (schema.type === 'array' && schema.items) {\n prop.type = 'array'\n if ('$ref' in schema.items) {\n prop.items = { $ref: (schema.items as ReferenceObject).$ref }\n } else {\n prop.items = parseSchemaToModel(`${name}Item`, schema.items as SchemaObject)\n }\n }\n\n // Check for x-demokit-relationship extension\n const xRelationship = (schema as Record<string, unknown>)['x-demokit-relationship']\n if (xRelationship && typeof xRelationship === 'object') {\n prop['x-demokit-relationship'] = xRelationship as { model: string; field: string }\n }\n\n return prop\n}\n\n/**\n * Parse all endpoints from paths\n */\nfunction parseEndpoints(doc: OpenAPIDocument): Endpoint[] {\n const endpoints: Endpoint[] = []\n\n if (!doc.paths) {\n return endpoints\n }\n\n const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']\n\n for (const [path, pathItem] of Object.entries(doc.paths)) {\n if (!pathItem) continue\n\n for (const method of methods) {\n const operation = pathItem[method.toLowerCase() as keyof typeof pathItem] as\n | OpenAPIV3.OperationObject\n | OpenAPIV3_1.OperationObject\n | undefined\n\n if (!operation) continue\n\n endpoints.push(parseEndpoint(method, path, operation, pathItem))\n }\n }\n\n return endpoints\n}\n\n/**\n * Parse a single endpoint\n */\nfunction parseEndpoint(\n method: HttpMethod,\n path: string,\n operation: OpenAPIV3.OperationObject | OpenAPIV3_1.OperationObject,\n pathItem: OpenAPIV3.PathItemObject | OpenAPIV3_1.PathItemObject\n): Endpoint {\n // Combine path-level and operation-level parameters\n const allParams = [...(pathItem.parameters || []), ...(operation.parameters || [])]\n\n const pathParams: ParameterDef[] = []\n const queryParams: ParameterDef[] = []\n\n for (const param of allParams) {\n if ('$ref' in param) continue // Skip refs\n const paramObj = param as ParameterObject\n const parsed = parseParameter(paramObj)\n\n if (parsed.in === 'path') {\n pathParams.push(parsed)\n } else if (parsed.in === 'query') {\n queryParams.push(parsed)\n }\n }\n\n // Parse request body\n let requestBody: RequestBody | undefined\n if (operation.requestBody && !('$ref' in operation.requestBody)) {\n requestBody = parseRequestBody(operation.requestBody as RequestBodyObject)\n }\n\n // Parse responses\n const responses: Record<string, ResponseDef> = {}\n if (operation.responses) {\n for (const [statusCode, response] of Object.entries(operation.responses)) {\n if ('$ref' in response) continue\n responses[statusCode] = parseResponse(statusCode, response as ResponseObject)\n }\n }\n\n return {\n method,\n path,\n operationId: operation.operationId,\n summary: operation.summary,\n description: operation.description,\n pathParams,\n queryParams,\n requestBody,\n responses,\n tags: operation.tags || [],\n }\n}\n\n/**\n * Parse a parameter object\n */\nfunction parseParameter(param: ParameterObject): ParameterDef {\n const schema = param.schema as SchemaObject | undefined\n\n return {\n name: param.name,\n in: param.in as 'path' | 'query' | 'header' | 'cookie',\n required: param.required ?? false,\n type: schema ? schemaTypeToPropertyType(schema.type) : 'string',\n format: schema?.format,\n description: param.description,\n example: param.example ?? schema?.example,\n }\n}\n\n/**\n * Parse a request body object\n */\nfunction parseRequestBody(body: RequestBodyObject): RequestBody {\n const contentType = Object.keys(body.content || {})[0] || 'application/json'\n const mediaType = body.content?.[contentType] as MediaTypeObject | undefined\n\n let schema: RequestBody['schema'] = { name: 'Unknown', type: 'object' }\n\n if (mediaType?.schema) {\n if ('$ref' in mediaType.schema) {\n schema = { $ref: (mediaType.schema as ReferenceObject).$ref }\n } else {\n schema = parseSchemaToModel('RequestBody', mediaType.schema as SchemaObject)\n }\n }\n\n return {\n contentType,\n schema,\n required: body.required ?? false,\n description: body.description,\n }\n}\n\n/**\n * Parse a response object\n */\nfunction parseResponse(statusCode: string, response: ResponseObject): ResponseDef {\n const responseDef: ResponseDef = {\n statusCode,\n description: response.description,\n }\n\n if (response.content) {\n responseDef.content = {}\n\n for (const [contentType, mediaType] of Object.entries(response.content)) {\n if (mediaType.schema) {\n if ('$ref' in mediaType.schema) {\n responseDef.content[contentType] = {\n $ref: (mediaType.schema as ReferenceObject).$ref,\n }\n } else {\n responseDef.content[contentType] = parseSchemaToModel(\n `Response${statusCode}`,\n mediaType.schema as SchemaObject\n )\n }\n }\n }\n }\n\n return responseDef\n}\n\n/**\n * Convert OpenAPI schema type to ModelType\n */\nfunction schemaTypeToModelType(\n type: string | string[] | undefined\n): ModelType {\n if (!type) return 'object'\n if (Array.isArray(type)) return type[0] as ModelType\n return type as ModelType\n}\n\n/**\n * Convert OpenAPI schema type to PropertyType\n */\nfunction schemaTypeToPropertyType(\n type: string | string[] | undefined\n): PropertyType {\n if (!type) return 'object'\n if (Array.isArray(type)) return type[0] as PropertyType\n return type as PropertyType\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/relationships.ts","../src/parser.ts"],"names":["validate","dereference"],"mappings":";;;;;;;AA2cO,SAAS,YAAY,KAAA,EAAoC;AAC9D,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,MAAA,IAAU,KAAA,IACV,OAAQ,KAAA,CAAoB,IAAA,KAAS,QAAA;AAEzC;AAMO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA,IAAK,GAAA;AACpC;;;ACpcA,IAAM,iBAAA,GAAoB;AAAA;AAAA,EAExB,EAAE,OAAA,EAAS,UAAA,EAAY,WAAA,EAAa,IAAA,EAAK;AAAA,EACzC,EAAE,OAAA,EAAS,WAAA,EAAa,WAAA,EAAa,IAAA,EAAK;AAAA,EAC1C,EAAE,OAAA,EAAS,UAAA,EAAY,WAAA,EAAa,IAAA,EAAK;AAAA;AAAA,EAGzC,EAAE,OAAA,EAAS,YAAA,EAAc,WAAA,EAAa,MAAA,EAAO;AAAA,EAC7C,EAAE,OAAA,EAAS,YAAA,EAAc,WAAA,EAAa,MAAA,EAAO;AAAA,EAC7C,EAAE,OAAA,EAAS,aAAA,EAAe,WAAA,EAAa,MAAA;AACzC,CAAA;AAMA,SAAS,kBAAkB,MAAA,EAAwB;AACjD,EAAA,OAAO,MAAA,CAAO,OAAO,CAAC,CAAA,CAAE,aAAY,GAAI,MAAA,CAAO,MAAM,CAAC,CAAA;AACxD;AAKO,SAAS,4BAAA,CACd,UACA,eAAA,EAC2B;AAC3B,EAAA,MAAM,YAAY,QAAA,CAAS,IAAA;AAE3B,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,WAAA,EAAY,IAAK,iBAAA,EAAmB;AACxD,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,KAAA,CAAM,OAAO,CAAA;AACrC,IAAA,IAAI,KAAA,IAAS,KAAA,CAAM,CAAC,CAAA,EAAG;AACrB,MAAA,MAAM,MAAA,GAAS,MAAM,CAAC,CAAA;AACtB,MAAA,MAAM,SAAA,GAAY,kBAAkB,MAAM,CAAA;AAG1C,MAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,QAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,WAAA,EAAY;AAAA,MAChD;AAGA,MAAA,MAAM,cAAc,SAAA,GAAY,GAAA;AAChC,MAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA,EAAG;AACpC,QAAA,OAAO,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,WAAA,EAAY;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,gCACd,QAAA,EAC2B;AAC3B,EAAA,MAAM,SAAA,GAAY,SAAS,wBAAwB,CAAA;AACnD,EAAA,IAAI,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC9C,IAAA,OAAO;AAAA,MACL,OAAO,SAAA,CAAU,KAAA;AAAA,MACjB,KAAA,EAAO,UAAU,KAAA,IAAS;AAAA,KAC5B;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,yBAAA,CACd,UACA,eAAA,EAC2B;AAC3B,EAAA,IAAI,SAAS,IAAA,EAAM;AACjB,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,QAAA,CAAS,IAAI,CAAA;AAC9C,IAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,MAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,IAAA,EAAK;AAAA,IACzC;AAAA,EACF;AAGA,EAAA,IAAI,QAAA,CAAS,KAAA,IAAS,WAAA,CAAY,QAAA,CAAS,KAAK,CAAA,EAAG;AACjD,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACpD,IAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,MAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,IAAA,EAAK;AAAA,IACzC;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,yBAAA,CACP,UACA,UAAA,EACkB;AAElB,EAAA,IAAI,QAAA,CAAS,SAAS,OAAA,EAAS;AAG7B,IAAA,OAAO,aAAA;AAAA,EACT;AAGA,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,oBACd,MAAA,EACgB;AAChB,EAAA,MAAM,gBAAgC,EAAC;AACvC,EAAA,MAAM,kBAAkB,IAAI,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAEnD,EAAA,KAAA,MAAW,CAAC,SAAA,EAAW,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACvD,IAAA,IAAI,CAAC,MAAM,UAAA,EAAY;AAEvB,IAAA,KAAA,MAAW,CAAC,UAAU,QAAQ,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,UAAU,CAAA,EAAG;AACnE,MAAA,IAAI,MAAA,GAAoC,IAAA;AACxC,MAAA,IAAI,eAAA,GAA+C,UAAA;AAGnD,MAAA,MAAA,GAAS,gCAAgC,QAAQ,CAAA;AACjD,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,eAAA,GAAkB,qBAAA;AAAA,MACpB;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,yBAAA,CAA0B,UAAU,eAAe,CAAA;AAC5D,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,eAAA,GAAkB,cAAA;AAAA,QACpB;AAAA,MACF;AAGA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,4BAAA,CAA6B,UAAU,eAAe,CAAA;AAC/D,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,eAAA,GAAkB,mBAAA;AAAA,QACpB;AAAA,MACF;AAEA,MAAA,IAAI,MAAA,EAAQ;AAEV,QAAA,IAAI,OAAO,KAAA,KAAU,SAAA,IAAa,OAAO,KAAA,KAAU,IAAA,IAAQ,aAAa,IAAA,EAAM;AAC5E,UAAA;AAAA,QACF;AAGA,QAAA,QAAA,CAAS,cAAA,GAAiB,MAAA;AAE1B,QAAA,aAAA,CAAc,IAAA,CAAK;AAAA,UACjB,IAAA,EAAM,EAAE,KAAA,EAAO,SAAA,EAAW,OAAO,QAAA,EAAS;AAAA,UAC1C,EAAA,EAAI,MAAA;AAAA,UACJ,IAAA,EAAM,yBAAA,CAA0B,QAAe,CAAA;AAAA,UAC/C,QAAA,EAAU,SAAS,QAAA,IAAY,KAAA;AAAA,UAC/B,UAAA,EAAY;AAAA,SACb,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,wBAAA,CACd,WACA,aAAA,EAIA;AACA,EAAA,OAAO;AAAA,IACL,UAAU,aAAA,CAAc,MAAA,CAAO,OAAK,CAAA,CAAE,IAAA,CAAK,UAAU,SAAS,CAAA;AAAA,IAC9D,UAAU,aAAA,CAAc,MAAA,CAAO,OAAK,CAAA,CAAE,EAAA,CAAG,UAAU,SAAS;AAAA,GAC9D;AACF;AAKO,SAAS,iBAAA,CACd,WACA,aAAA,EACS;AACT,EAAA,OAAO,cAAc,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,CAAG,UAAU,SAAS,CAAA;AACzD;AAMO,SAAS,uBAAA,CACd,QACA,aAAA,EACU;AACV,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AACrC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,SAAS,KAAA,CAAM,IAAA,EAAc,IAAA,mBAAoB,IAAI,KAAI,EAAG;AAC1D,IAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACvB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAElB,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AAGb,IAAA,MAAM,IAAA,GAAO,cACV,MAAA,CAAO,CAAA,CAAA,KAAK,EAAE,IAAA,CAAK,KAAA,KAAU,IAAI,CAAA,CACjC,GAAA,CAAI,OAAK,CAAA,CAAE,EAAA,CAAG,KAAK,CAAA,CACnB,MAAA,CAAO,SAAO,UAAA,CAAW,QAAA,CAAS,GAAG,CAAC,CAAA;AAEzC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,KAAA,CAAM,GAAA,EAAK,IAAI,GAAA,CAAI,IAAI,CAAC,CAAA;AAAA,IAC1B;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACtB,MAAA,OAAA,CAAQ,IAAI,IAAI,CAAA;AAChB,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAAA,EACF;AAEA,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,KAAA,CAAM,IAAI,CAAA;AAAA,EACZ;AAEA,EAAA,OAAO,KAAA;AACT;;;ACzMA,eAAsB,oBAAA,CACpB,SAAA,EACA,OAAA,GAAwB,EAAC,EACD;AAExB,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,SAAS,CAAA;AACtC,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,SAAS,CAAA,EAAA,EAAK,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,EAC1F;AAEA,EAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,IAAA,EAAK;AACpC,EAAA,OAAO,sBAAA,CAAuB,SAAS,OAAO,CAAA;AAChD;AAKA,eAAsB,sBAAA,CACpB,IAAA,EACA,OAAA,GAAwB,EAAC,EACD;AACxB,EAAA,MAAM,EAAE,WAAA,EAAa,iBAAA,GAAoB,IAAA,EAAK,GAAI,OAAA;AAGlD,EAAA,MAAM,gBAAA,GAAmB,MAAMA,sBAAA,CAAS,IAAI,CAAA;AAC5C,EAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,IAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,MAAA,EAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,IAAK,0BAAA;AACjF,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,aAAa,CAAA,CAAE,CAAA;AAAA,EACnE;AAGA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,iBAAA,EAAmB;AACrB,IAAA,MAAM,WAAA,GAAc,MAAMC,yBAAA,CAAY,IAAI,CAAA;AAC1C,IAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,MAAA,MAAM,aAAA,GAAgB,YAAY,MAAA,CAAO,GAAA,CAAI,OAAK,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACtE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,aAAa,CAAA,CAAE,CAAA;AAAA,IACxE;AACA,IAAA,MAAA,GAAS,WAAA,CAAY,MAAA;AAAA,EACvB,CAAA,MAAO;AAEL,IAAA,MAAA,GAAS,gBAAA,CAAiB,aAAA;AAAA,EAC5B;AAEA,EAAA,OAAO,oBAAA,CAAqB,QAAQ,OAAO,CAAA;AAC7C;AAKA,eAAsB,sBAAA,CACpB,IAAA,EACA,OAAA,GAAwB,EAAC,EACD;AACxB,EAAA,MAAM,EAAE,WAAA,EAAa,iBAAA,GAAoB,IAAA,EAAK,GAAI,OAAA;AAGlD,EAAA,MAAM,gBAAA,GAAmB,MAAMD,sBAAA,CAAS,IAAI,CAAA;AAC5C,EAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,IAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,MAAA,EAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,IAAK,0BAAA;AACjF,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,aAAa,CAAA,CAAE,CAAA;AAAA,EACnE;AAGA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,iBAAA,EAAmB;AACrB,IAAA,MAAM,WAAA,GAAc,MAAMC,yBAAA,CAAY,IAAI,CAAA;AAC1C,IAAA,IAAI,WAAA,CAAY,MAAA,IAAU,WAAA,CAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AACvD,MAAA,MAAM,aAAA,GAAgB,YAAY,MAAA,CAAO,GAAA,CAAI,OAAK,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACtE,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oCAAA,EAAuC,aAAa,CAAA,CAAE,CAAA;AAAA,IACxE;AACA,IAAA,MAAA,GAAS,WAAA,CAAY,MAAA;AAAA,EACvB,CAAA,MAAO;AACL,IAAA,MAAA,GAAS,gBAAA,CAAiB,aAAA;AAAA,EAC5B;AAEA,EAAA,OAAO,oBAAA,CAAqB,QAAQ,OAAO,CAAA;AAC7C;AAKA,SAAS,oBAAA,CACP,GAAA,EACA,OAAA,GAAwB,EAAC,EACV;AACf,EAAA,MAAM,EAAE,mBAAA,EAAqB,YAAA,GAAe,IAAA,EAAK,GAAI,OAAA;AAGrD,EAAA,MAAM,IAAA,GAAO,UAAU,GAAG,CAAA;AAG1B,EAAA,MAAM,MAAA,GAAS,YAAY,GAAG,CAAA;AAG9B,EAAA,MAAM,SAAA,GAAY,eAAe,GAAG,CAAA;AAGpC,EAAA,MAAM,aAAA,GAAgB,YAAA,GAAe,mBAAA,CAAoB,MAAM,IAAI,EAAC;AAEpE,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF;AAKA,SAAS,UAAU,GAAA,EAAkC;AACnD,EAAA,MAAM,OAAA,GAAW,GAAA,CAAY,IAAA,IAAQ,EAAC;AACtC,EAAA,MAAM,IAAA,GAAmB;AAAA,IACvB,KAAA,EAAO,QAAQ,KAAA,IAAS,cAAA;AAAA,IACxB,OAAA,EAAS,QAAQ,OAAA,IAAW,OAAA;AAAA,IAC5B,aAAa,OAAA,CAAQ;AAAA,GACvB;AAGA,EAAA,MAAM,UAAW,GAAA,CAAY,OAAA;AAC7B,EAAA,IAAI,WAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,IAAK,OAAA,CAAQ,CAAC,CAAA,EAAG;AAC/C,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA,CAAQ,CAAC,CAAA,CAAE,GAAA;AAAA,EAC5B;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,YAAY,GAAA,EAAiD;AACpE,EAAA,MAAM,SAAoC,EAAC;AAE3C,EAAA,MAAM,aAAc,GAAA,CAAY,UAAA;AAChC,EAAA,MAAM,UAAU,UAAA,EAAY,OAAA;AAC5B,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAEpD,IAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,IAAY,UAAU,MAAA,EAAQ;AAC5D,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,kBAAA,CAAmB,IAAA,EAAM,MAAsB,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,MAAA;AACT;AAKA,SAAS,kBAAA,CAAmB,MAAc,MAAA,EAAiC;AACzE,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AACzC,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAS;AAAA,EAChC;AAEA,EAAA,MAAM,CAAA,GAAI,MAAA;AACV,EAAA,MAAM,KAAA,GAAmB;AAAA,IACvB,IAAA;AAAA,IACA,IAAA,EAAM,qBAAA,CAAsB,CAAA,CAAE,IAAqC,CAAA;AAAA,IACnE,aAAa,CAAA,CAAE;AAAA,GACjB;AAGA,EAAA,IAAI,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,UAAA,EAAY;AACvC,IAAA,KAAA,CAAM,IAAA,GAAO,QAAA;AACb,IAAA,KAAA,CAAM,aAAa,EAAC;AACpB,IAAA,KAAA,CAAM,QAAA,GAAY,CAAA,CAAE,QAAA,IAAyB,EAAC;AAE9C,IAAA,IAAI,CAAA,CAAE,UAAA,IAAc,OAAO,CAAA,CAAE,eAAe,QAAA,EAAU;AACpD,MAAA,KAAA,MAAW,CAAC,UAAU,UAAU,CAAA,IAAK,OAAO,OAAA,CAAQ,CAAA,CAAE,UAAU,CAAA,EAAG;AACjE,QAAA,KAAA,CAAM,UAAA,CAAW,QAAQ,CAAA,GAAI,aAAA;AAAA,UAC3B,QAAA;AAAA,UACA,UAAA;AAAA,UACA,KAAA,CAAM,QAAA,CAAS,QAAA,CAAS,QAAQ;AAAA,SAClC;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAA,CAAE,yBAAyB,MAAA,EAAW;AACxC,MAAA,IAAI,OAAO,CAAA,CAAE,oBAAA,KAAyB,SAAA,EAAW;AAC/C,QAAA,KAAA,CAAM,uBAAuB,CAAA,CAAE,oBAAA;AAAA,MACjC,WAAW,CAAA,CAAE,oBAAA,IAAwB,OAAO,CAAA,CAAE,yBAAyB,QAAA,EAAU;AAC/E,QAAA,IAAI,MAAA,IAAU,EAAE,oBAAA,EAAsB;AACpC,UAAA,KAAA,CAAM,oBAAA,GAAuB;AAAA,YAC3B,IAAA,EAAO,EAAE,oBAAA,CAAyC;AAAA,WACpD;AAAA,QACF,CAAA,MAAO;AACL,UAAA,KAAA,CAAM,oBAAA,GAAuB,kBAAA;AAAA,YAC3B,GAAG,IAAI,CAAA,eAAA,CAAA;AAAA,YACP,CAAA,CAAE;AAAA,WACJ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,CAAA,CAAE,IAAA,KAAS,OAAA,IAAW,CAAA,CAAE,KAAA,EAAO;AACjC,IAAA,KAAA,CAAM,IAAA,GAAO,OAAA;AACb,IAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,IAAY,MAAA,IAAU,EAAE,KAAA,EAAO;AACpD,MAAA,KAAA,CAAM,KAAA,GAAQ,EAAE,IAAA,EAAO,CAAA,CAAE,MAA0B,IAAA,EAAK;AAAA,IAC1D,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,QAAQ,kBAAA,CAAmB,CAAA,EAAG,IAAI,CAAA,IAAA,CAAA,EAAQ,EAAE,KAAqB,CAAA;AAAA,IACzE;AAAA,EACF;AAGA,EAAA,IAAI,EAAE,IAAA,EAAM;AACV,IAAA,KAAA,CAAM,OAAO,CAAA,CAAE,IAAA;AAAA,EACjB;AAGA,EAAA,IAAI,CAAA,CAAE,YAAY,MAAA,EAAW;AAC3B,IAAA,KAAA,CAAM,UAAU,CAAA,CAAE,OAAA;AAAA,EACpB;AAEA,EAAA,OAAO,KAAA;AACT;AAKA,SAAS,aAAA,CACP,IAAA,EACA,MAAA,EACA,QAAA,EACa;AAEb,EAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,IAAY,UAAU,MAAA,EAAQ;AAC5D,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,IAAA,EAAM,QAAA;AAAA,MACN,QAAA;AAAA,MACA,MAAM,MAAA,CAAO;AAAA,KACf;AAAA,EACF;AAEA,EAAA,MAAM,CAAA,GAAI,MAAA;AAEV,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,IAAA;AAAA,IACA,IAAA,EAAM,wBAAA,CAAyB,CAAA,CAAE,IAAqC,CAAA;AAAA,IACtE,QAAA;AAAA,IACA,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,aAAa,CAAA,CAAE,WAAA;AAAA,IACf,QAAQ,CAAA,CAAE,MAAA;AAAA,IACV,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,SAAS,CAAA,CAAE;AAAA,GACb;AAGA,EAAA,IAAI,CAAA,CAAE,IAAA,KAAS,OAAA,IAAW,CAAA,CAAE,KAAA,EAAO;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO,OAAA;AACZ,IAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,IAAY,MAAA,IAAU,EAAE,KAAA,EAAO;AACpD,MAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,IAAA,EAAO,CAAA,CAAE,MAA0B,IAAA,EAAK;AAAA,IACzD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,QAAQ,kBAAA,CAAmB,CAAA,EAAG,IAAI,CAAA,IAAA,CAAA,EAAQ,EAAE,KAAqB,CAAA;AAAA,IACxE;AAAA,EACF;AAGA,EAAA,MAAM,aAAA,GAAgB,EAAE,wBAAwB,CAAA;AAChD,EAAA,IAAI,aAAA,IAAiB,OAAO,aAAA,KAAkB,QAAA,EAAU;AACtD,IAAA,IAAA,CAAK,wBAAwB,CAAA,GAAI,aAAA;AAAA,EACnC;AAEA,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,eAAe,GAAA,EAAkC;AACxD,EAAA,MAAM,YAAwB,EAAC;AAE/B,EAAA,MAAM,QAAS,GAAA,CAAY,KAAA;AAC3B,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAwB,CAAC,KAAA,EAAO,MAAA,EAAQ,OAAO,OAAA,EAAS,QAAA,EAAU,QAAQ,SAAS,CAAA;AAEzF,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACpD,IAAA,IAAI,CAAC,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,EAAU;AAE/C,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,SAAA,GAAa,QAAA,CAAqC,MAAA,CAAO,WAAA,EAAa,CAAA;AAE5E,MAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAEjD,MAAA,SAAA,CAAU,KAAK,aAAA,CAAc,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAsC,QAAmC,CAAC,CAAA;AAAA,IACvH;AAAA,EACF;AAEA,EAAA,OAAO,SAAA;AACT;AAKA,SAAS,aAAA,CACP,MAAA,EACA,IAAA,EACA,SAAA,EACA,QAAA,EACU;AAEV,EAAA,MAAM,aAA6B,EAAC;AACpC,EAAA,MAAM,cAA8B,EAAC;AAErC,EAAA,MAAM,SAAA,GAAY;AAAA,IAChB,GAAK,QAAA,CAAS,UAAA,IAA4B,EAAC;AAAA,IAC3C,GAAK,SAAA,CAAU,UAAA,IAA4B;AAAC,GAC9C;AAEA,EAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC7B,IAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACzC,IAAA,IAAI,UAAU,KAAA,EAAO;AAErB,IAAA,MAAM,MAAA,GAAS,eAAe,KAAwB,CAAA;AAEtD,IAAA,IAAI,MAAA,CAAO,OAAO,MAAA,EAAQ;AACxB,MAAA,UAAA,CAAW,KAAK,MAAM,CAAA;AAAA,IACxB,CAAA,MAAA,IAAW,MAAA,CAAO,EAAA,KAAO,OAAA,EAAS;AAChC,MAAA,WAAA,CAAY,KAAK,MAAM,CAAA;AAAA,IACzB;AAAA,EACF;AAGA,EAAA,IAAI,WAAA;AACJ,EAAA,MAAM,gBAAgB,SAAA,CAAU,WAAA;AAChC,EAAA,IAAI,iBAAiB,OAAO,aAAA,KAAkB,QAAA,IAAY,EAAE,UAAU,aAAA,CAAA,EAAgB;AACpF,IAAA,WAAA,GAAc,iBAAiB,aAAkC,CAAA;AAAA,EACnE;AAGA,EAAA,MAAM,YAAyC,EAAC;AAChD,EAAA,MAAM,cAAc,SAAA,CAAU,SAAA;AAC9B,EAAA,IAAI,WAAA,IAAe,OAAO,WAAA,KAAgB,QAAA,EAAU;AAClD,IAAA,KAAA,MAAW,CAAC,UAAA,EAAY,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAA,EAAG;AAChE,MAAA,IAAI,CAAC,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,EAAU;AAC/C,MAAA,IAAI,UAAU,QAAA,EAAU;AACxB,MAAA,SAAA,CAAU,UAAU,CAAA,GAAI,aAAA,CAAc,UAAA,EAAY,QAA0B,CAAA;AAAA,IAC9E;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,IAAA;AAAA,IACA,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,SAAS,SAAA,CAAU,OAAA;AAAA,IACnB,aAAa,SAAA,CAAU,WAAA;AAAA,IACvB,UAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA,EAAO,SAAA,CAAU,IAAA,IAAqB;AAAC,GACzC;AACF;AAKA,SAAS,eAAe,KAAA,EAAsC;AAC5D,EAAA,MAAM,CAAA,GAAI,KAAA;AACV,EAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AAEjB,EAAA,OAAO;AAAA,IACL,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,IAAI,CAAA,CAAE,EAAA;AAAA,IACN,QAAA,EAAW,EAAE,QAAA,IAAwB,KAAA;AAAA,IACrC,IAAA,EAAM,MAAA,GAAS,wBAAA,CAAyB,MAAA,CAAO,IAAqC,CAAA,GAAI,QAAA;AAAA,IACxF,QAAQ,MAAA,EAAQ,MAAA;AAAA,IAChB,aAAa,CAAA,CAAE,WAAA;AAAA,IACf,OAAA,EAAS,CAAA,CAAE,OAAA,IAAW,MAAA,EAAQ;AAAA,GAChC;AACF;AAKA,SAAS,iBAAiB,IAAA,EAAsC;AAC9D,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,MAAM,UAAU,CAAA,CAAE,OAAA;AAClB,EAAA,MAAM,WAAA,GAAc,OAAO,IAAA,CAAK,OAAA,IAAW,EAAE,CAAA,CAAE,CAAC,CAAA,IAAK,kBAAA;AACrD,EAAA,MAAM,SAAA,GAAY,UAAU,WAAW,CAAA;AAEvC,EAAA,IAAI,MAAA,GAAgC,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,QAAA,EAAS;AAEtE,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,MAAM,CAAA,GAAI,SAAA;AACV,IAAA,MAAM,cAAc,CAAA,CAAE,MAAA;AACtB,IAAA,IAAI,WAAA,IAAe,OAAO,WAAA,KAAgB,QAAA,EAAU;AAClD,MAAA,IAAI,UAAU,WAAA,EAAa;AACzB,QAAA,MAAA,GAAS,EAAE,IAAA,EAAO,WAAA,CAAgC,IAAA,EAAK;AAAA,MACzD,CAAA,MAAO;AACL,QAAA,MAAA,GAAS,kBAAA,CAAmB,eAAe,WAA2B,CAAA;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA,EAAW,EAAE,QAAA,IAAwB,KAAA;AAAA,IACrC,aAAa,CAAA,CAAE;AAAA,GACjB;AACF;AAKA,SAAS,aAAA,CAAc,YAAoB,QAAA,EAAuC;AAChF,EAAA,MAAM,CAAA,GAAI,QAAA;AACV,EAAA,MAAM,WAAA,GAA2B;AAAA,IAC/B,UAAA;AAAA,IACA,aAAa,CAAA,CAAE;AAAA,GACjB;AAEA,EAAA,MAAM,UAAU,CAAA,CAAE,OAAA;AAClB,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,WAAA,CAAY,UAAU,EAAC;AAEvB,IAAA,KAAA,MAAW,CAAC,WAAA,EAAa,SAAS,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC9D,MAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAEjD,MAAA,MAAM,CAAA,GAAI,SAAA;AACV,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AACxC,QAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,UAAA,WAAA,CAAY,OAAA,CAAQ,WAAW,CAAA,GAAI;AAAA,YACjC,MAAO,MAAA,CAA2B;AAAA,WACpC;AAAA,QACF,CAAA,MAAO;AACL,UAAA,WAAA,CAAY,OAAA,CAAQ,WAAW,CAAA,GAAI,kBAAA;AAAA,YACjC,WAAW,UAAU,CAAA,CAAA;AAAA,YACrB;AAAA,WACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,WAAA;AACT;AAKA,SAAS,sBACP,IAAA,EACW;AACX,EAAA,IAAI,CAAC,MAAM,OAAO,QAAA;AAClB,EAAA,IAAI,MAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,KAAK,CAAC,CAAA;AACtC,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,yBACP,IAAA,EACc;AACd,EAAA,IAAI,CAAC,MAAM,OAAO,QAAA;AAClB,EAAA,IAAI,MAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,KAAK,CAAC,CAAA;AACtC,EAAA,OAAO,IAAA;AACT","file":"index.cjs","sourcesContent":["/**\n * Core types for DemoKit schema representation\n *\n * These types represent a parsed API schema with relationship detection,\n * independent of the source format (OpenAPI, GraphQL, etc.)\n */\n\n/**\n * The main schema representation for DemoKit\n * Contains all information needed for fixture generation\n */\nexport interface DemokitSchema {\n /**\n * Metadata about the API\n */\n info: SchemaInfo\n\n /**\n * All API endpoints discovered from the spec\n */\n endpoints: Endpoint[]\n\n /**\n * All data models (schemas) from the spec\n */\n models: Record<string, DataModel>\n\n /**\n * Detected relationships between models\n */\n relationships: Relationship[]\n}\n\n/**\n * API metadata\n */\nexport interface SchemaInfo {\n /**\n * API title from the spec\n */\n title: string\n\n /**\n * API version\n */\n version: string\n\n /**\n * Optional description\n */\n description?: string\n\n /**\n * Base URL for the API (if specified)\n */\n baseUrl?: string\n}\n\n/**\n * An API endpoint\n */\nexport interface Endpoint {\n /**\n * HTTP method (GET, POST, PUT, PATCH, DELETE)\n */\n method: HttpMethod\n\n /**\n * URL path with parameter placeholders\n * @example \"/users/{id}\" or \"/orders/{orderId}/items\"\n */\n path: string\n\n /**\n * Operation ID from OpenAPI (if available)\n */\n operationId?: string\n\n /**\n * Human-readable summary\n */\n summary?: string\n\n /**\n * Detailed description\n */\n description?: string\n\n /**\n * Path parameters\n */\n pathParams: ParameterDef[]\n\n /**\n * Query parameters\n */\n queryParams: ParameterDef[]\n\n /**\n * Request body schema (for POST/PUT/PATCH)\n */\n requestBody?: RequestBody\n\n /**\n * Response schemas by status code\n */\n responses: Record<string, ResponseDef>\n\n /**\n * Tags for grouping endpoints\n */\n tags: string[]\n}\n\n/**\n * HTTP methods supported\n */\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\n/**\n * A request or response body definition\n */\nexport interface RequestBody {\n /**\n * Content type (usually application/json)\n */\n contentType: string\n\n /**\n * Reference to the model name, or inline schema\n */\n schema: SchemaRef | DataModel\n\n /**\n * Whether the body is required\n */\n required: boolean\n\n /**\n * Description of the body\n */\n description?: string\n}\n\n/**\n * A response definition\n */\nexport interface ResponseDef {\n /**\n * HTTP status code\n */\n statusCode: string\n\n /**\n * Description of the response\n */\n description?: string\n\n /**\n * Content type to schema mapping\n */\n content?: Record<string, SchemaRef | DataModel>\n}\n\n/**\n * A parameter definition (path or query)\n */\nexport interface ParameterDef {\n /**\n * Parameter name\n */\n name: string\n\n /**\n * Where the parameter is located\n */\n in: 'path' | 'query' | 'header' | 'cookie'\n\n /**\n * Whether the parameter is required\n */\n required: boolean\n\n /**\n * Parameter type\n */\n type: PropertyType\n\n /**\n * Optional format hint\n */\n format?: string\n\n /**\n * Description\n */\n description?: string\n\n /**\n * Example value\n */\n example?: unknown\n}\n\n/**\n * Reference to another schema/model\n */\nexport interface SchemaRef {\n /**\n * The referenced model name\n */\n $ref: string\n}\n\n/**\n * A data model representing an object schema\n */\nexport interface DataModel {\n /**\n * Model name (from the schema component name)\n */\n name: string\n\n /**\n * The type of this model\n */\n type: ModelType\n\n /**\n * Description from the spec\n */\n description?: string\n\n /**\n * Properties for object types\n */\n properties?: Record<string, PropertyDef>\n\n /**\n * Required property names\n */\n required?: string[]\n\n /**\n * For array types, the item schema\n */\n items?: SchemaRef | DataModel\n\n /**\n * Enum values for enum types\n */\n enum?: unknown[]\n\n /**\n * Example value from the spec\n */\n example?: unknown\n\n /**\n * Additional properties schema (for dictionaries)\n */\n additionalProperties?: boolean | SchemaRef | DataModel\n}\n\n/**\n * Model types\n */\nexport type ModelType = 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'\n\n/**\n * A property definition within a model\n */\nexport interface PropertyDef {\n /**\n * Property name\n */\n name: string\n\n /**\n * Property type\n */\n type: PropertyType\n\n /**\n * Format hint (uuid, email, date-time, etc.)\n */\n format?: string\n\n /**\n * Description\n */\n description?: string\n\n /**\n * Whether this property is required\n */\n required?: boolean\n\n /**\n * Whether this property is nullable\n */\n nullable?: boolean\n\n /**\n * Enum values for string enums\n */\n enum?: unknown[]\n\n /**\n * For array types, the item schema\n */\n items?: SchemaRef | DataModel\n\n /**\n * Reference to another model (for $ref properties)\n */\n $ref?: string\n\n /**\n * Example value\n */\n example?: unknown\n\n /**\n * Default value\n */\n default?: unknown\n\n /**\n * Minimum value (for numbers)\n */\n minimum?: number\n\n /**\n * Maximum value (for numbers)\n */\n maximum?: number\n\n /**\n * Min length (for strings)\n */\n minLength?: number\n\n /**\n * Max length (for strings)\n */\n maxLength?: number\n\n /**\n * Pattern (regex for strings)\n */\n pattern?: string\n\n /**\n * Detected relationship to another model\n * Set by relationship detection, not directly from spec\n */\n relationshipTo?: RelationshipTarget\n\n /**\n * Custom extension for explicit relationship hints\n * @example \"x-demokit-relationship\": { \"model\": \"User\", \"field\": \"id\" }\n */\n 'x-demokit-relationship'?: RelationshipTarget\n}\n\n/**\n * Property types\n */\nexport type PropertyType =\n | 'string'\n | 'number'\n | 'integer'\n | 'boolean'\n | 'array'\n | 'object'\n | 'null'\n\n/**\n * A detected relationship between two models\n */\nexport interface Relationship {\n /**\n * The source side of the relationship\n */\n from: RelationshipSide\n\n /**\n * The target side of the relationship\n */\n to: RelationshipSide\n\n /**\n * Type of relationship\n */\n type: RelationshipType\n\n /**\n * Whether the relationship is required (not nullable)\n */\n required: boolean\n\n /**\n * How this relationship was detected\n */\n detectedBy: RelationshipDetectionMethod\n}\n\n/**\n * One side of a relationship\n */\nexport interface RelationshipSide {\n /**\n * Model name\n */\n model: string\n\n /**\n * Field name\n */\n field: string\n}\n\n/**\n * Target for a relationship from a property\n */\nexport interface RelationshipTarget {\n /**\n * Target model name\n */\n model: string\n\n /**\n * Target field (usually \"id\")\n */\n field: string\n}\n\n/**\n * Types of relationships between models\n */\nexport type RelationshipType =\n | 'one-to-one'\n | 'one-to-many'\n | 'many-to-one'\n | 'many-to-many'\n\n/**\n * How a relationship was detected\n */\nexport type RelationshipDetectionMethod =\n | 'explicit-ref' // OpenAPI $ref\n | 'naming-convention' // userId -> User.id pattern\n | 'x-demokit-extension' // x-demokit-relationship extension\n | 'inferred' // AI or heuristic inference\n\n/**\n * Helper type to check if something is a schema reference\n */\nexport function isSchemaRef(value: unknown): value is SchemaRef {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$ref' in value &&\n typeof (value as SchemaRef).$ref === 'string'\n )\n}\n\n/**\n * Extract the model name from a $ref string\n * @example \"#/components/schemas/User\" -> \"User\"\n */\nexport function extractRefName(ref: string): string {\n const parts = ref.split('/')\n return parts[parts.length - 1] ?? ref\n}\n","/**\n * Relationship detection for DemoKit schemas\n *\n * Detects relationships between models using:\n * 1. Explicit $ref references in OpenAPI\n * 2. Naming conventions (userId -> User.id)\n * 3. x-demokit-relationship extension\n */\n\nimport type {\n DataModel,\n PropertyDef,\n Relationship,\n RelationshipTarget,\n RelationshipDetectionMethod,\n RelationshipType,\n} from './types'\nimport { isSchemaRef, extractRefName } from './types'\n\n/**\n * Common ID field naming patterns\n * Maps suffix patterns to implied relationships\n */\nconst ID_FIELD_PATTERNS = [\n // Standard patterns: userId -> User, customerId -> Customer\n { pattern: /^(.+)Id$/, targetField: 'id' },\n { pattern: /^(.+)_id$/, targetField: 'id' },\n { pattern: /^(.+)ID$/, targetField: 'id' },\n\n // UUID patterns: userUuid -> User, customerUUID -> Customer\n { pattern: /^(.+)Uuid$/, targetField: 'uuid' },\n { pattern: /^(.+)UUID$/, targetField: 'uuid' },\n { pattern: /^(.+)_uuid$/, targetField: 'uuid' },\n]\n\n/**\n * Convert a field name prefix to a model name\n * @example \"user\" -> \"User\", \"orderItem\" -> \"OrderItem\"\n */\nfunction prefixToModelName(prefix: string): string {\n return prefix.charAt(0).toUpperCase() + prefix.slice(1)\n}\n\n/**\n * Check if a property looks like a foreign key based on naming conventions\n */\nexport function detectRelationshipFromNaming(\n property: PropertyDef,\n availableModels: Set<string>\n): RelationshipTarget | null {\n const fieldName = property.name\n\n for (const { pattern, targetField } of ID_FIELD_PATTERNS) {\n const match = fieldName.match(pattern)\n if (match && match[1]) {\n const prefix = match[1]\n const modelName = prefixToModelName(prefix)\n\n // Check if this model exists in the schema\n if (availableModels.has(modelName)) {\n return { model: modelName, field: targetField }\n }\n\n // Also check for plural forms\n const pluralModel = modelName + 's'\n if (availableModels.has(pluralModel)) {\n return { model: pluralModel, field: targetField }\n }\n }\n }\n\n return null\n}\n\n/**\n * Check if a property has an explicit x-demokit-relationship extension\n */\nexport function detectRelationshipFromExtension(\n property: PropertyDef\n): RelationshipTarget | null {\n const extension = property['x-demokit-relationship']\n if (extension && typeof extension === 'object') {\n return {\n model: extension.model,\n field: extension.field || 'id',\n }\n }\n return null\n}\n\n/**\n * Check if a property is a $ref to another model\n */\nexport function detectRelationshipFromRef(\n property: PropertyDef,\n availableModels: Set<string>\n): RelationshipTarget | null {\n if (property.$ref) {\n const modelName = extractRefName(property.$ref)\n if (availableModels.has(modelName)) {\n return { model: modelName, field: 'id' }\n }\n }\n\n // Check if items is a $ref (for arrays of references)\n if (property.items && isSchemaRef(property.items)) {\n const modelName = extractRefName(property.items.$ref)\n if (availableModels.has(modelName)) {\n return { model: modelName, field: 'id' }\n }\n }\n\n return null\n}\n\n/**\n * Detect the relationship type based on property and target\n */\nfunction determineRelationshipType(\n property: PropertyDef,\n _fromModel: DataModel\n): RelationshipType {\n // If the property is an array, it's one-to-many or many-to-many\n if (property.type === 'array') {\n // For simplicity, treat array references as one-to-many\n // (the \"one\" side has the array of references)\n return 'one-to-many'\n }\n\n // Single reference is many-to-one (many records can reference one target)\n return 'many-to-one'\n}\n\n/**\n * Detect all relationships in a set of models\n */\nexport function detectRelationships(\n models: Record<string, DataModel>\n): Relationship[] {\n const relationships: Relationship[] = []\n const availableModels = new Set(Object.keys(models))\n\n for (const [modelName, model] of Object.entries(models)) {\n if (!model.properties) continue\n\n for (const [propName, property] of Object.entries(model.properties)) {\n let target: RelationshipTarget | null = null\n let detectionMethod: RelationshipDetectionMethod = 'inferred'\n\n // Priority 1: Explicit x-demokit-relationship extension\n target = detectRelationshipFromExtension(property)\n if (target) {\n detectionMethod = 'x-demokit-extension'\n }\n\n // Priority 2: $ref references\n if (!target) {\n target = detectRelationshipFromRef(property, availableModels)\n if (target) {\n detectionMethod = 'explicit-ref'\n }\n }\n\n // Priority 3: Naming conventions\n if (!target) {\n target = detectRelationshipFromNaming(property, availableModels)\n if (target) {\n detectionMethod = 'naming-convention'\n }\n }\n\n if (target) {\n // Don't create self-referential relationships for simple IDs\n if (target.model === modelName && target.field === 'id' && propName === 'id') {\n continue\n }\n\n // Add the detected relationship info to the property\n property.relationshipTo = target\n\n relationships.push({\n from: { model: modelName, field: propName },\n to: target,\n type: determineRelationshipType(property, model),\n required: property.required ?? false,\n detectedBy: detectionMethod,\n })\n }\n }\n }\n\n return relationships\n}\n\n/**\n * Find all relationships for a specific model\n */\nexport function getRelationshipsForModel(\n modelName: string,\n relationships: Relationship[]\n): {\n outgoing: Relationship[]\n incoming: Relationship[]\n} {\n return {\n outgoing: relationships.filter(r => r.from.model === modelName),\n incoming: relationships.filter(r => r.to.model === modelName),\n }\n}\n\n/**\n * Check if a model is referenced by other models\n */\nexport function isModelReferenced(\n modelName: string,\n relationships: Relationship[]\n): boolean {\n return relationships.some(r => r.to.model === modelName)\n}\n\n/**\n * Get the dependency order for models based on relationships\n * Returns models in order such that dependencies come before dependents\n */\nexport function getModelDependencyOrder(\n models: Record<string, DataModel>,\n relationships: Relationship[]\n): string[] {\n const modelNames = Object.keys(models)\n const visited = new Set<string>()\n const order: string[] = []\n\n function visit(name: string, path: Set<string> = new Set()) {\n if (visited.has(name)) return\n if (path.has(name)) {\n // Circular dependency - skip to break the cycle\n return\n }\n\n path.add(name)\n\n // Visit all models that this model depends on first\n const deps = relationships\n .filter(r => r.from.model === name)\n .map(r => r.to.model)\n .filter(dep => modelNames.includes(dep))\n\n for (const dep of deps) {\n visit(dep, new Set(path))\n }\n\n if (!visited.has(name)) {\n visited.add(name)\n order.push(name)\n }\n }\n\n for (const name of modelNames) {\n visit(name)\n }\n\n return order\n}\n","/**\n * OpenAPI 3.x parser for DemoKit\n *\n * Parses OpenAPI specs into DemoKit's internal schema representation\n * with automatic relationship detection.\n *\n * Uses @scalar/openapi-parser - a modern, webpack-compatible parser.\n */\n\nimport { dereference, validate } from '@scalar/openapi-parser'\nimport type { OpenAPI, OpenAPIV3_1 } from '@scalar/openapi-types'\nimport type {\n DemokitSchema,\n SchemaInfo,\n Endpoint,\n DataModel,\n PropertyDef,\n HttpMethod,\n ParameterDef,\n RequestBody,\n ResponseDef,\n PropertyType,\n ModelType,\n} from './types'\nimport { detectRelationships } from './relationships'\n\n// Type aliases for OpenAPI 3.x structures\ntype OpenAPIDocument = OpenAPI.Document\ntype SchemaObject = OpenAPIV3_1.SchemaObject\ntype ReferenceObject = OpenAPIV3_1.ReferenceObject\ntype ParameterObject = OpenAPIV3_1.ParameterObject\ntype RequestBodyObject = OpenAPIV3_1.RequestBodyObject\ntype ResponseObject = OpenAPIV3_1.ResponseObject\ntype MediaTypeObject = OpenAPIV3_1.MediaTypeObject\n\n/**\n * Options for parsing OpenAPI specs\n */\nexport interface ParseOptions {\n /**\n * Whether to dereference all $ref pointers\n * @default true\n */\n dereference?: boolean\n\n /**\n * Whether to detect relationships automatically\n * @default true\n */\n detectRelationships?: boolean\n\n /**\n * Whether to include response schemas in models\n * @default true\n */\n includeResponses?: boolean\n}\n\n/**\n * Parse an OpenAPI spec from a file path or URL\n */\nexport async function parseOpenAPIFromPath(\n pathOrUrl: string,\n options: ParseOptions = {}\n): Promise<DemokitSchema> {\n // Fetch the content\n const response = await fetch(pathOrUrl)\n if (!response.ok) {\n throw new Error(`Failed to fetch OpenAPI spec from ${pathOrUrl}: ${response.statusText}`)\n }\n\n const content = await response.text()\n return parseOpenAPIFromString(content, options)\n}\n\n/**\n * Parse an OpenAPI spec from a string (JSON or YAML)\n */\nexport async function parseOpenAPIFromString(\n spec: string,\n options: ParseOptions = {}\n): Promise<DemokitSchema> {\n const { dereference: shouldDereference = true } = options\n\n // First validate the spec\n const validationResult = await validate(spec)\n if (!validationResult.valid) {\n const errorMessages = validationResult.errors?.map(e => e.message).join(', ') || 'Unknown validation error'\n throw new Error(`Invalid OpenAPI specification: ${errorMessages}`)\n }\n\n // Get the dereferenced schema if requested\n let schema: OpenAPIDocument\n if (shouldDereference) {\n const derefResult = await dereference(spec)\n if (derefResult.errors && derefResult.errors.length > 0) {\n const errorMessages = derefResult.errors.map(e => e.message).join(', ')\n throw new Error(`Failed to dereference OpenAPI spec: ${errorMessages}`)\n }\n schema = derefResult.schema as OpenAPIDocument\n } else {\n // Parse without dereferencing - just use the validated result\n schema = validationResult.specification as OpenAPIDocument\n }\n\n return parseOpenAPIDocument(schema, options)\n}\n\n/**\n * Parse an OpenAPI spec from an already-parsed object\n */\nexport async function parseOpenAPIFromObject(\n spec: Record<string, unknown>,\n options: ParseOptions = {}\n): Promise<DemokitSchema> {\n const { dereference: shouldDereference = true } = options\n\n // Validate the object\n const validationResult = await validate(spec)\n if (!validationResult.valid) {\n const errorMessages = validationResult.errors?.map(e => e.message).join(', ') || 'Unknown validation error'\n throw new Error(`Invalid OpenAPI specification: ${errorMessages}`)\n }\n\n // Get the dereferenced schema if requested\n let schema: OpenAPIDocument\n if (shouldDereference) {\n const derefResult = await dereference(spec)\n if (derefResult.errors && derefResult.errors.length > 0) {\n const errorMessages = derefResult.errors.map(e => e.message).join(', ')\n throw new Error(`Failed to dereference OpenAPI spec: ${errorMessages}`)\n }\n schema = derefResult.schema as OpenAPIDocument\n } else {\n schema = validationResult.specification as OpenAPIDocument\n }\n\n return parseOpenAPIDocument(schema, options)\n}\n\n/**\n * Parse an OpenAPI document into DemokitSchema\n */\nfunction parseOpenAPIDocument(\n doc: OpenAPIDocument,\n options: ParseOptions = {}\n): DemokitSchema {\n const { detectRelationships: shouldDetect = true } = options\n\n // Parse info\n const info = parseInfo(doc)\n\n // Parse models from components/schemas\n const models = parseModels(doc)\n\n // Parse endpoints from paths\n const endpoints = parseEndpoints(doc)\n\n // Detect relationships\n const relationships = shouldDetect ? detectRelationships(models) : []\n\n return {\n info,\n endpoints,\n models,\n relationships,\n }\n}\n\n/**\n * Parse API info from the document\n */\nfunction parseInfo(doc: OpenAPIDocument): SchemaInfo {\n const docInfo = (doc as any).info || {}\n const info: SchemaInfo = {\n title: docInfo.title ?? 'Untitled API',\n version: docInfo.version ?? '1.0.0',\n description: docInfo.description,\n }\n\n // Try to extract base URL from servers\n const servers = (doc as any).servers\n if (servers && servers.length > 0 && servers[0]) {\n info.baseUrl = servers[0].url\n }\n\n return info\n}\n\n/**\n * Parse all models from components/schemas\n */\nfunction parseModels(doc: OpenAPIDocument): Record<string, DataModel> {\n const models: Record<string, DataModel> = {}\n\n const components = (doc as any).components\n const schemas = components?.schemas\n if (!schemas) {\n return models\n }\n\n for (const [name, schema] of Object.entries(schemas)) {\n // Skip reference objects (shouldn't happen after dereference)\n if (schema && typeof schema === 'object' && '$ref' in schema) {\n continue\n }\n\n models[name] = parseSchemaToModel(name, schema as SchemaObject)\n }\n\n return models\n}\n\n/**\n * Parse a schema object into a DataModel\n */\nfunction parseSchemaToModel(name: string, schema: SchemaObject): DataModel {\n if (!schema || typeof schema !== 'object') {\n return { name, type: 'object' }\n }\n\n const s = schema as Record<string, unknown>\n const model: DataModel = {\n name,\n type: schemaTypeToModelType(s.type as string | string[] | undefined),\n description: s.description as string | undefined,\n }\n\n // Parse properties for object types\n if (s.type === 'object' || s.properties) {\n model.type = 'object'\n model.properties = {}\n model.required = (s.required as string[]) || []\n\n if (s.properties && typeof s.properties === 'object') {\n for (const [propName, propSchema] of Object.entries(s.properties)) {\n model.properties[propName] = parseProperty(\n propName,\n propSchema as SchemaObject | ReferenceObject,\n model.required.includes(propName)\n )\n }\n }\n\n if (s.additionalProperties !== undefined) {\n if (typeof s.additionalProperties === 'boolean') {\n model.additionalProperties = s.additionalProperties\n } else if (s.additionalProperties && typeof s.additionalProperties === 'object') {\n if ('$ref' in s.additionalProperties) {\n model.additionalProperties = {\n $ref: (s.additionalProperties as ReferenceObject).$ref,\n }\n } else {\n model.additionalProperties = parseSchemaToModel(\n `${name}AdditionalProps`,\n s.additionalProperties as SchemaObject\n )\n }\n }\n }\n }\n\n // Parse array items\n if (s.type === 'array' && s.items) {\n model.type = 'array'\n if (typeof s.items === 'object' && '$ref' in s.items) {\n model.items = { $ref: (s.items as ReferenceObject).$ref }\n } else {\n model.items = parseSchemaToModel(`${name}Item`, s.items as SchemaObject)\n }\n }\n\n // Parse enum values\n if (s.enum) {\n model.enum = s.enum as unknown[]\n }\n\n // Parse example\n if (s.example !== undefined) {\n model.example = s.example\n }\n\n return model\n}\n\n/**\n * Parse a property schema into a PropertyDef\n */\nfunction parseProperty(\n name: string,\n schema: SchemaObject | ReferenceObject,\n required: boolean\n): PropertyDef {\n // Handle $ref\n if (schema && typeof schema === 'object' && '$ref' in schema) {\n return {\n name,\n type: 'object',\n required,\n $ref: schema.$ref,\n }\n }\n\n const s = schema as Record<string, unknown>\n\n const prop: PropertyDef = {\n name,\n type: schemaTypeToPropertyType(s.type as string | string[] | undefined),\n required,\n nullable: s.nullable as boolean | undefined,\n description: s.description as string | undefined,\n format: s.format as string | undefined,\n enum: s.enum as unknown[] | undefined,\n example: s.example,\n default: s.default,\n minimum: s.minimum as number | undefined,\n maximum: s.maximum as number | undefined,\n minLength: s.minLength as number | undefined,\n maxLength: s.maxLength as number | undefined,\n pattern: s.pattern as string | undefined,\n }\n\n // Parse array items\n if (s.type === 'array' && s.items) {\n prop.type = 'array'\n if (typeof s.items === 'object' && '$ref' in s.items) {\n prop.items = { $ref: (s.items as ReferenceObject).$ref }\n } else {\n prop.items = parseSchemaToModel(`${name}Item`, s.items as SchemaObject)\n }\n }\n\n // Check for x-demokit-relationship extension\n const xRelationship = s['x-demokit-relationship']\n if (xRelationship && typeof xRelationship === 'object') {\n prop['x-demokit-relationship'] = xRelationship as { model: string; field: string }\n }\n\n return prop\n}\n\n/**\n * Parse all endpoints from paths\n */\nfunction parseEndpoints(doc: OpenAPIDocument): Endpoint[] {\n const endpoints: Endpoint[] = []\n\n const paths = (doc as any).paths\n if (!paths) {\n return endpoints\n }\n\n const methods: HttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']\n\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!pathItem || typeof pathItem !== 'object') continue\n\n for (const method of methods) {\n const operation = (pathItem as Record<string, unknown>)[method.toLowerCase()]\n\n if (!operation || typeof operation !== 'object') continue\n\n endpoints.push(parseEndpoint(method, path, operation as Record<string, unknown>, pathItem as Record<string, unknown>))\n }\n }\n\n return endpoints\n}\n\n/**\n * Parse a single endpoint\n */\nfunction parseEndpoint(\n method: HttpMethod,\n path: string,\n operation: Record<string, unknown>,\n pathItem: Record<string, unknown>\n): Endpoint {\n // Combine path-level and operation-level parameters\n const pathParams: ParameterDef[] = []\n const queryParams: ParameterDef[] = []\n\n const allParams = [\n ...((pathItem.parameters as unknown[]) || []),\n ...((operation.parameters as unknown[]) || []),\n ]\n\n for (const param of allParams) {\n if (!param || typeof param !== 'object') continue\n if ('$ref' in param) continue // Skip refs\n\n const parsed = parseParameter(param as ParameterObject)\n\n if (parsed.in === 'path') {\n pathParams.push(parsed)\n } else if (parsed.in === 'query') {\n queryParams.push(parsed)\n }\n }\n\n // Parse request body\n let requestBody: RequestBody | undefined\n const opRequestBody = operation.requestBody\n if (opRequestBody && typeof opRequestBody === 'object' && !('$ref' in opRequestBody)) {\n requestBody = parseRequestBody(opRequestBody as RequestBodyObject)\n }\n\n // Parse responses\n const responses: Record<string, ResponseDef> = {}\n const opResponses = operation.responses\n if (opResponses && typeof opResponses === 'object') {\n for (const [statusCode, response] of Object.entries(opResponses)) {\n if (!response || typeof response !== 'object') continue\n if ('$ref' in response) continue\n responses[statusCode] = parseResponse(statusCode, response as ResponseObject)\n }\n }\n\n return {\n method,\n path,\n operationId: operation.operationId as string | undefined,\n summary: operation.summary as string | undefined,\n description: operation.description as string | undefined,\n pathParams,\n queryParams,\n requestBody,\n responses,\n tags: (operation.tags as string[]) || [],\n }\n}\n\n/**\n * Parse a parameter object\n */\nfunction parseParameter(param: ParameterObject): ParameterDef {\n const p = param as Record<string, unknown>\n const schema = p.schema as Record<string, unknown> | undefined\n\n return {\n name: p.name as string,\n in: p.in as 'path' | 'query' | 'header' | 'cookie',\n required: (p.required as boolean) ?? false,\n type: schema ? schemaTypeToPropertyType(schema.type as string | string[] | undefined) : 'string',\n format: schema?.format as string | undefined,\n description: p.description as string | undefined,\n example: p.example ?? schema?.example,\n }\n}\n\n/**\n * Parse a request body object\n */\nfunction parseRequestBody(body: RequestBodyObject): RequestBody {\n const b = body as Record<string, unknown>\n const content = b.content as Record<string, unknown> | undefined\n const contentType = Object.keys(content || {})[0] || 'application/json'\n const mediaType = content?.[contentType] as MediaTypeObject | undefined\n\n let schema: RequestBody['schema'] = { name: 'Unknown', type: 'object' }\n\n if (mediaType) {\n const m = mediaType as Record<string, unknown>\n const mediaSchema = m.schema\n if (mediaSchema && typeof mediaSchema === 'object') {\n if ('$ref' in mediaSchema) {\n schema = { $ref: (mediaSchema as ReferenceObject).$ref }\n } else {\n schema = parseSchemaToModel('RequestBody', mediaSchema as SchemaObject)\n }\n }\n }\n\n return {\n contentType,\n schema,\n required: (b.required as boolean) ?? false,\n description: b.description as string | undefined,\n }\n}\n\n/**\n * Parse a response object\n */\nfunction parseResponse(statusCode: string, response: ResponseObject): ResponseDef {\n const r = response as Record<string, unknown>\n const responseDef: ResponseDef = {\n statusCode,\n description: r.description as string | undefined,\n }\n\n const content = r.content as Record<string, unknown> | undefined\n if (content) {\n responseDef.content = {}\n\n for (const [contentType, mediaType] of Object.entries(content)) {\n if (!mediaType || typeof mediaType !== 'object') continue\n\n const m = mediaType as Record<string, unknown>\n const schema = m.schema\n if (schema && typeof schema === 'object') {\n if ('$ref' in schema) {\n responseDef.content[contentType] = {\n $ref: (schema as ReferenceObject).$ref,\n }\n } else {\n responseDef.content[contentType] = parseSchemaToModel(\n `Response${statusCode}`,\n schema as SchemaObject\n )\n }\n }\n }\n }\n\n return responseDef\n}\n\n/**\n * Convert OpenAPI schema type to ModelType\n */\nfunction schemaTypeToModelType(\n type: string | string[] | undefined\n): ModelType {\n if (!type) return 'object'\n if (Array.isArray(type)) return type[0] as ModelType\n return type as ModelType\n}\n\n/**\n * Convert OpenAPI schema type to PropertyType\n */\nfunction schemaTypeToPropertyType(\n type: string | string[] | undefined\n): PropertyType {\n if (!type) return 'object'\n if (Array.isArray(type)) return type[0] as PropertyType\n return type as PropertyType\n}\n"]}
|