@emeryld/rrroutes-contract 2.7.12 → 2.8.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/README.md +5 -5
- package/dist/index.cjs +9 -1364
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +8 -1337
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -10
- package/bin/rrroutes-export-finalized-leaves.mjs +0 -14
- package/dist/export/defaultViewerTemplate.d.ts +0 -1
- package/dist/export/exportFinalizedLeaves.cli.d.ts +0 -14
- package/dist/export/exportFinalizedLeaves.d.ts +0 -62
- package/dist/export/extractLeafSourceByAst.d.ts +0 -38
- package/dist/export/flattenSchema.d.ts +0 -12
- package/dist/export/index.d.ts +0 -7
- package/dist/export/schemaIntrospection.d.ts +0 -47
- package/dist/export/serializeLeafContract.d.ts +0 -31
- package/tools/finalized-leaves-viewer.html +0 -1551
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,50 +15,26 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/index.ts
|
|
31
21
|
var index_exports = {};
|
|
32
22
|
__export(index_exports, {
|
|
33
|
-
DEFAULT_VIEWER_TEMPLATE: () => DEFAULT_VIEWER_TEMPLATE,
|
|
34
23
|
buildCacheKey: () => buildCacheKey,
|
|
35
24
|
buildLowProfileLeaf: () => buildLowProfileLeaf,
|
|
36
|
-
clearSchemaIntrospectionHandlers: () => clearSchemaIntrospectionHandlers,
|
|
37
25
|
collectNestedFieldSuggestions: () => collectNestedFieldSuggestions,
|
|
38
26
|
compilePath: () => compilePath,
|
|
39
|
-
createSchemaIntrospector: () => createSchemaIntrospector,
|
|
40
27
|
defineSocketEvents: () => defineSocketEvents,
|
|
41
|
-
exportFinalizedLeaves: () => exportFinalizedLeaves,
|
|
42
|
-
extractLeafSourceByAst: () => extractLeafSourceByAst,
|
|
43
28
|
finalize: () => finalize,
|
|
44
|
-
flattenLeafSchemas: () => flattenLeafSchemas,
|
|
45
|
-
flattenSerializableSchema: () => flattenSerializableSchema,
|
|
46
29
|
getZodShape: () => getZodShape,
|
|
47
|
-
introspectSchema: () => introspectSchema,
|
|
48
30
|
keyOf: () => keyOf,
|
|
49
|
-
loadFinalizedLeavesInput: () => loadFinalizedLeavesInput,
|
|
50
31
|
lowProfileParse: () => lowProfileParse,
|
|
51
32
|
lowProfileSafeParse: () => lowProfileSafeParse,
|
|
52
33
|
mergeArrays: () => mergeArrays,
|
|
53
34
|
mergeSchemas: () => mergeSchemas,
|
|
54
|
-
parseFinalizedLeavesCliArgs: () => parseFinalizedLeavesCliArgs,
|
|
55
|
-
registerSchemaIntrospectionHandler: () => registerSchemaIntrospectionHandler,
|
|
56
35
|
resource: () => resource,
|
|
57
36
|
routeSchemaParse: () => routeSchemaParse,
|
|
58
|
-
|
|
59
|
-
serializableSchemaKinds: () => serializableSchemaKinds,
|
|
60
|
-
serializeLeafContract: () => serializeLeafContract,
|
|
61
|
-
serializeLeavesContract: () => serializeLeavesContract,
|
|
62
|
-
staticBase: () => staticBase,
|
|
63
|
-
writeFinalizedLeavesExport: () => writeFinalizedLeavesExport
|
|
37
|
+
staticBase: () => staticBase
|
|
64
38
|
});
|
|
65
39
|
module.exports = __toCommonJS(index_exports);
|
|
66
40
|
|
|
@@ -108,9 +82,9 @@ function collectNestedFieldSuggestions(shape, prefix = []) {
|
|
|
108
82
|
}
|
|
109
83
|
return suggestions;
|
|
110
84
|
}
|
|
111
|
-
function compilePath(
|
|
112
|
-
if (!params) return
|
|
113
|
-
const withParams =
|
|
85
|
+
function compilePath(path, params) {
|
|
86
|
+
if (!params) return path;
|
|
87
|
+
const withParams = path.replace(/:([A-Za-z0-9_]+)/g, (_, k) => {
|
|
114
88
|
const v = params[k];
|
|
115
89
|
if (v === void 0 || v === null) throw new Error(`Missing param :${k}`);
|
|
116
90
|
return String(v);
|
|
@@ -185,8 +159,8 @@ function buildLowProfileLeaf(leaf) {
|
|
|
185
159
|
}
|
|
186
160
|
};
|
|
187
161
|
}
|
|
188
|
-
var keyOf = (method,
|
|
189
|
-
const key = `${method.toUpperCase()} ${
|
|
162
|
+
var keyOf = (method, path, encodeSafe) => {
|
|
163
|
+
const key = `${method.toUpperCase()} ${path}`;
|
|
190
164
|
return encodeSafe ? encodeURIComponent(key) : key;
|
|
191
165
|
};
|
|
192
166
|
|
|
@@ -362,8 +336,8 @@ function joinPaths(parent, child) {
|
|
|
362
336
|
if (!trimmedChild) return trimmedParent;
|
|
363
337
|
return `${trimmedParent}/${trimmedChild}`;
|
|
364
338
|
}
|
|
365
|
-
function assertDynamicLayerUniqueness(
|
|
366
|
-
const segments =
|
|
339
|
+
function assertDynamicLayerUniqueness(path, dynamicLayerMap) {
|
|
340
|
+
const segments = path.split("/").filter(Boolean);
|
|
367
341
|
if (segments.length === 0) return;
|
|
368
342
|
for (let i = 0; i < segments.length; i++) {
|
|
369
343
|
const segment = segments[i];
|
|
@@ -401,1351 +375,22 @@ function finalize(leaves) {
|
|
|
401
375
|
function defineSocketEvents(config, events) {
|
|
402
376
|
return { config, events };
|
|
403
377
|
}
|
|
404
|
-
|
|
405
|
-
// src/export/schemaIntrospection.ts
|
|
406
|
-
var z3 = __toESM(require("zod"), 1);
|
|
407
|
-
var serializableSchemaKinds = [
|
|
408
|
-
"object",
|
|
409
|
-
"string",
|
|
410
|
-
"number",
|
|
411
|
-
"boolean",
|
|
412
|
-
"bigint",
|
|
413
|
-
"date",
|
|
414
|
-
"array",
|
|
415
|
-
"enum",
|
|
416
|
-
"literal",
|
|
417
|
-
"union",
|
|
418
|
-
"record",
|
|
419
|
-
"tuple",
|
|
420
|
-
"unknown",
|
|
421
|
-
"any"
|
|
422
|
-
];
|
|
423
|
-
var globalHandlers = {};
|
|
424
|
-
function registerSchemaIntrospectionHandler(kind, handler) {
|
|
425
|
-
globalHandlers[kind] = handler;
|
|
426
|
-
}
|
|
427
|
-
function clearSchemaIntrospectionHandlers() {
|
|
428
|
-
for (const key of Object.keys(globalHandlers)) {
|
|
429
|
-
delete globalHandlers[key];
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
function getDef(schema) {
|
|
433
|
-
if (!schema || typeof schema !== "object") return void 0;
|
|
434
|
-
const anySchema = schema;
|
|
435
|
-
return anySchema._zod?.def ?? anySchema._def;
|
|
436
|
-
}
|
|
437
|
-
function getDescription(schema) {
|
|
438
|
-
const anyZ = z3;
|
|
439
|
-
const registry = anyZ.globalRegistry?.get ? anyZ.globalRegistry.get(schema) : void 0;
|
|
440
|
-
if (registry && typeof registry.description === "string") {
|
|
441
|
-
return registry.description;
|
|
442
|
-
}
|
|
443
|
-
const def = getDef(schema);
|
|
444
|
-
if (def && typeof def.description === "string") {
|
|
445
|
-
return def.description;
|
|
446
|
-
}
|
|
447
|
-
return void 0;
|
|
448
|
-
}
|
|
449
|
-
function unwrap(schema) {
|
|
450
|
-
let current = schema;
|
|
451
|
-
let optional = false;
|
|
452
|
-
let nullable = false;
|
|
453
|
-
const ZodEffectsCtor = z3.ZodEffects;
|
|
454
|
-
while (true) {
|
|
455
|
-
if (ZodEffectsCtor && current instanceof ZodEffectsCtor) {
|
|
456
|
-
const def = getDef(current) || {};
|
|
457
|
-
const sourceType = typeof current.sourceType === "function" ? current.sourceType() : def.schema;
|
|
458
|
-
if (!sourceType) break;
|
|
459
|
-
current = sourceType;
|
|
460
|
-
continue;
|
|
461
|
-
}
|
|
462
|
-
if (current instanceof z3.ZodOptional) {
|
|
463
|
-
optional = true;
|
|
464
|
-
const def = getDef(current);
|
|
465
|
-
current = def && def.innerType || current;
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
if (current instanceof z3.ZodNullable) {
|
|
469
|
-
nullable = true;
|
|
470
|
-
const def = getDef(current);
|
|
471
|
-
current = def && def.innerType || current;
|
|
472
|
-
continue;
|
|
473
|
-
}
|
|
474
|
-
if (current instanceof z3.ZodDefault) {
|
|
475
|
-
const def = getDef(current);
|
|
476
|
-
current = def && def.innerType || current;
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
break;
|
|
480
|
-
}
|
|
481
|
-
return { base: current, optional, nullable };
|
|
482
|
-
}
|
|
483
|
-
function mergeProps(a, b) {
|
|
484
|
-
if (!a && !b) return void 0;
|
|
485
|
-
return { ...a ?? {}, ...b ?? {} };
|
|
486
|
-
}
|
|
487
|
-
function inferKind(schema) {
|
|
488
|
-
if (schema instanceof z3.ZodString) return "string";
|
|
489
|
-
if (schema instanceof z3.ZodNumber) return "number";
|
|
490
|
-
if (schema instanceof z3.ZodBoolean) return "boolean";
|
|
491
|
-
if (schema instanceof z3.ZodBigInt) return "bigint";
|
|
492
|
-
if (schema instanceof z3.ZodDate) return "date";
|
|
493
|
-
if (schema instanceof z3.ZodArray) return "array";
|
|
494
|
-
if (schema instanceof z3.ZodObject) return "object";
|
|
495
|
-
if (schema instanceof z3.ZodUnion) return "union";
|
|
496
|
-
if (schema instanceof z3.ZodLiteral) return "literal";
|
|
497
|
-
if (schema instanceof z3.ZodEnum) return "enum";
|
|
498
|
-
if (schema instanceof z3.ZodRecord) return "record";
|
|
499
|
-
if (schema instanceof z3.ZodTuple) return "tuple";
|
|
500
|
-
if (schema instanceof z3.ZodUnknown) return "unknown";
|
|
501
|
-
if (schema instanceof z3.ZodAny) return "any";
|
|
502
|
-
return "unknown";
|
|
503
|
-
}
|
|
504
|
-
var defaultHandlers = {
|
|
505
|
-
intersection({ base, def, node }, ctx) {
|
|
506
|
-
const left = def?.left;
|
|
507
|
-
const right = def?.right;
|
|
508
|
-
const leftNode = left ? ctx.introspect(left) : void 0;
|
|
509
|
-
const rightNode = right ? ctx.introspect(right) : void 0;
|
|
510
|
-
const leftIsObj = leftNode?.kind === "object" && !!leftNode.properties;
|
|
511
|
-
const rightIsObj = rightNode?.kind === "object" && !!rightNode.properties;
|
|
512
|
-
if (leftIsObj && rightIsObj) {
|
|
513
|
-
node.kind = "object";
|
|
514
|
-
node.description = node.description ?? leftNode.description ?? rightNode.description;
|
|
515
|
-
node.properties = mergeProps(leftNode.properties, rightNode.properties);
|
|
516
|
-
return node;
|
|
517
|
-
}
|
|
518
|
-
if (leftNode && rightNode) {
|
|
519
|
-
node.properties = {
|
|
520
|
-
left: leftNode,
|
|
521
|
-
right: rightNode
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
return node;
|
|
525
|
-
},
|
|
526
|
-
object({ base, def, node }, ctx) {
|
|
527
|
-
const rawShape = base.shape ?? (def && typeof def.shape === "function" ? def.shape() : def?.shape);
|
|
528
|
-
const shape = typeof rawShape === "function" ? rawShape() : rawShape ?? {};
|
|
529
|
-
const props = {};
|
|
530
|
-
for (const key of Object.keys(shape)) {
|
|
531
|
-
const child = shape[key];
|
|
532
|
-
const childNode = ctx.introspect(child);
|
|
533
|
-
if (childNode) props[key] = childNode;
|
|
534
|
-
}
|
|
535
|
-
node.properties = props;
|
|
536
|
-
return node;
|
|
537
|
-
},
|
|
538
|
-
array({ def, node }, ctx) {
|
|
539
|
-
const inner = def && def.element || def && def.type || void 0;
|
|
540
|
-
if (inner) {
|
|
541
|
-
node.element = ctx.introspect(inner);
|
|
542
|
-
}
|
|
543
|
-
return node;
|
|
544
|
-
},
|
|
545
|
-
union({ def, node }, ctx) {
|
|
546
|
-
const options = def && def.options || [];
|
|
547
|
-
node.union = options.map((opt) => ctx.introspect(opt)).filter(Boolean);
|
|
548
|
-
return node;
|
|
549
|
-
},
|
|
550
|
-
literal({ def, node }) {
|
|
551
|
-
if (def) {
|
|
552
|
-
if (Array.isArray(def.values)) {
|
|
553
|
-
node.literal = def.values.length === 1 ? def.values[0] : def.values.slice();
|
|
554
|
-
} else {
|
|
555
|
-
node.literal = def.value;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
return node;
|
|
559
|
-
},
|
|
560
|
-
enum({ def, node }) {
|
|
561
|
-
if (def) {
|
|
562
|
-
if (Array.isArray(def.values)) {
|
|
563
|
-
node.enumValues = def.values.slice();
|
|
564
|
-
} else if (def.entries && typeof def.entries === "object") {
|
|
565
|
-
node.enumValues = Object.values(def.entries).map((v) => String(v));
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
return node;
|
|
569
|
-
}
|
|
570
|
-
};
|
|
571
|
-
function createSchemaIntrospector(options = {}) {
|
|
572
|
-
const handlers = {
|
|
573
|
-
...defaultHandlers,
|
|
574
|
-
...globalHandlers,
|
|
575
|
-
...options.handlers ?? {}
|
|
576
|
-
};
|
|
577
|
-
const introspect = (schema) => {
|
|
578
|
-
if (!schema) return void 0;
|
|
579
|
-
const unwrapped = unwrap(schema);
|
|
580
|
-
const base = unwrapped.base;
|
|
581
|
-
const def = getDef(base);
|
|
582
|
-
const kind = base instanceof z3.ZodIntersection ? "intersection" : inferKind(base);
|
|
583
|
-
const node = {
|
|
584
|
-
kind: kind === "intersection" ? "unknown" : kind,
|
|
585
|
-
optional: unwrapped.optional || void 0,
|
|
586
|
-
nullable: unwrapped.nullable || void 0,
|
|
587
|
-
description: getDescription(base)
|
|
588
|
-
};
|
|
589
|
-
const handler = handlers[kind];
|
|
590
|
-
if (!handler) return node;
|
|
591
|
-
return handler(
|
|
592
|
-
{
|
|
593
|
-
schema,
|
|
594
|
-
base,
|
|
595
|
-
def,
|
|
596
|
-
kind,
|
|
597
|
-
optional: unwrapped.optional,
|
|
598
|
-
nullable: unwrapped.nullable,
|
|
599
|
-
node
|
|
600
|
-
},
|
|
601
|
-
{
|
|
602
|
-
zod: z3,
|
|
603
|
-
introspect,
|
|
604
|
-
getDef,
|
|
605
|
-
unwrap,
|
|
606
|
-
getDescription
|
|
607
|
-
}
|
|
608
|
-
);
|
|
609
|
-
};
|
|
610
|
-
return introspect;
|
|
611
|
-
}
|
|
612
|
-
function introspectSchema(schema, options = {}) {
|
|
613
|
-
const introspect = createSchemaIntrospector(options);
|
|
614
|
-
return introspect(schema);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
// src/export/serializeLeafContract.ts
|
|
618
|
-
function serializeContractSchema(schema, options) {
|
|
619
|
-
return schema ? introspectSchema(routeSchemaParse(schema), options) : void 0;
|
|
620
|
-
}
|
|
621
|
-
function serializeBodyFiles(cfg) {
|
|
622
|
-
if (!Array.isArray(cfg.bodyFiles) || cfg.bodyFiles.length === 0) {
|
|
623
|
-
return void 0;
|
|
624
|
-
}
|
|
625
|
-
return cfg.bodyFiles.map(({ name, maxCount }) => ({ name, maxCount }));
|
|
626
|
-
}
|
|
627
|
-
function serializeLeafContract(leaf, options = {}) {
|
|
628
|
-
const cfg = leaf.cfg;
|
|
629
|
-
return {
|
|
630
|
-
key: `${leaf.method.toUpperCase()} ${leaf.path}`,
|
|
631
|
-
method: leaf.method,
|
|
632
|
-
path: leaf.path,
|
|
633
|
-
cfg: {
|
|
634
|
-
description: cfg.description,
|
|
635
|
-
summary: cfg.summary,
|
|
636
|
-
docsGroup: cfg.docsGroup,
|
|
637
|
-
tags: Array.isArray(cfg.tags) ? cfg.tags.slice() : void 0,
|
|
638
|
-
deprecated: cfg.deprecated,
|
|
639
|
-
stability: cfg.stability,
|
|
640
|
-
docsHidden: cfg.docsHidden,
|
|
641
|
-
docsMeta: cfg.docsMeta,
|
|
642
|
-
feed: cfg.feed,
|
|
643
|
-
bodyFiles: serializeBodyFiles(cfg),
|
|
644
|
-
schemas: {
|
|
645
|
-
body: serializeContractSchema(cfg.bodySchema, options),
|
|
646
|
-
query: serializeContractSchema(cfg.querySchema, options),
|
|
647
|
-
params: serializeContractSchema(cfg.paramsSchema, options),
|
|
648
|
-
output: serializeContractSchema(cfg.outputSchema, options),
|
|
649
|
-
outputMeta: serializeContractSchema(cfg.outputMetaSchema, options),
|
|
650
|
-
queryExtension: serializeContractSchema(cfg.queryExtensionSchema, options)
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
function serializeLeavesContract(leaves, options = {}) {
|
|
656
|
-
return leaves.map((leaf) => serializeLeafContract(leaf, options));
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// src/export/flattenSchema.ts
|
|
660
|
-
function formatLiteralType(literal) {
|
|
661
|
-
if (typeof literal === "string") return literal;
|
|
662
|
-
if (typeof literal === "number" || typeof literal === "boolean" || typeof literal === "bigint") {
|
|
663
|
-
return String(literal);
|
|
664
|
-
}
|
|
665
|
-
if (literal === null) return "null";
|
|
666
|
-
if (Array.isArray(literal)) {
|
|
667
|
-
return literal.map((item) => formatLiteralType(item)).join("|");
|
|
668
|
-
}
|
|
669
|
-
if (typeof literal === "object") {
|
|
670
|
-
try {
|
|
671
|
-
return JSON.stringify(literal);
|
|
672
|
-
} catch {
|
|
673
|
-
return "object";
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
return "unknown";
|
|
677
|
-
}
|
|
678
|
-
function normalizeType(schema) {
|
|
679
|
-
switch (schema.kind) {
|
|
680
|
-
case "string":
|
|
681
|
-
case "number":
|
|
682
|
-
case "date":
|
|
683
|
-
case "boolean":
|
|
684
|
-
case "object":
|
|
685
|
-
case "array":
|
|
686
|
-
return schema.kind;
|
|
687
|
-
case "enum": {
|
|
688
|
-
if (Array.isArray(schema.enumValues) && schema.enumValues.length > 0) {
|
|
689
|
-
return schema.enumValues.join("|");
|
|
690
|
-
}
|
|
691
|
-
return "unknown";
|
|
692
|
-
}
|
|
693
|
-
case "literal": {
|
|
694
|
-
return formatLiteralType(schema.literal);
|
|
695
|
-
}
|
|
696
|
-
default:
|
|
697
|
-
return "unknown";
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
function isNonEmptyPath(path4) {
|
|
701
|
-
return typeof path4 === "string" && path4.length > 0;
|
|
702
|
-
}
|
|
703
|
-
function setNode(out, path4, schema, inherited) {
|
|
704
|
-
if (!isNonEmptyPath(path4)) return;
|
|
705
|
-
out[path4] = {
|
|
706
|
-
type: normalizeType(schema),
|
|
707
|
-
nullable: inherited.nullable || Boolean(schema.nullable),
|
|
708
|
-
optional: inherited.optional || Boolean(schema.optional),
|
|
709
|
-
literal: schema.kind === "literal" ? schema.literal : void 0
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
function flattenInto(out, schema, path4, inherited) {
|
|
713
|
-
if (!schema || !isNonEmptyPath(path4)) return;
|
|
714
|
-
const nextInherited = {
|
|
715
|
-
optional: inherited.optional || Boolean(schema.optional),
|
|
716
|
-
nullable: inherited.nullable || Boolean(schema.nullable)
|
|
717
|
-
};
|
|
718
|
-
if (schema.kind === "union" && Array.isArray(schema.union) && schema.union.length > 0) {
|
|
719
|
-
schema.union.forEach((option, index) => {
|
|
720
|
-
const optionPath = `${path4}-${index + 1}`;
|
|
721
|
-
flattenInto(out, option, optionPath, inherited);
|
|
722
|
-
});
|
|
723
|
-
return;
|
|
724
|
-
}
|
|
725
|
-
setNode(out, path4, schema, inherited);
|
|
726
|
-
if (schema.kind === "object" && schema.properties) {
|
|
727
|
-
for (const [key, child] of Object.entries(schema.properties)) {
|
|
728
|
-
const childPath = `${path4}.${key}`;
|
|
729
|
-
flattenInto(out, child, childPath, nextInherited);
|
|
730
|
-
}
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
if (schema.kind === "array" && schema.element) {
|
|
734
|
-
flattenInto(out, schema.element, `${path4}[]`, nextInherited);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
function flattenSerializableSchema(schema, path4) {
|
|
738
|
-
const out = {};
|
|
739
|
-
flattenInto(out, schema, path4, { optional: false, nullable: false });
|
|
740
|
-
return out;
|
|
741
|
-
}
|
|
742
|
-
function isSerializedLeaf(value) {
|
|
743
|
-
if (!value || typeof value !== "object") return false;
|
|
744
|
-
const item = value;
|
|
745
|
-
return typeof item.key === "string" && !!item.cfg && typeof item.cfg === "object";
|
|
746
|
-
}
|
|
747
|
-
function flattenLeafSchemas(leaf) {
|
|
748
|
-
const serialized = isSerializedLeaf(leaf) ? leaf : serializeLeafContract(leaf);
|
|
749
|
-
const out = {};
|
|
750
|
-
const sections = serialized.cfg.schemas;
|
|
751
|
-
Object.assign(out, flattenSerializableSchema(sections.params, "params"));
|
|
752
|
-
Object.assign(out, flattenSerializableSchema(sections.query, "query"));
|
|
753
|
-
Object.assign(out, flattenSerializableSchema(sections.body, "body"));
|
|
754
|
-
Object.assign(out, flattenSerializableSchema(sections.output, "output"));
|
|
755
|
-
return out;
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
// src/export/exportFinalizedLeaves.ts
|
|
759
|
-
var import_promises = __toESM(require("fs/promises"), 1);
|
|
760
|
-
var import_node_path2 = __toESM(require("path"), 1);
|
|
761
|
-
var import_node_child_process = require("child_process");
|
|
762
|
-
|
|
763
|
-
// src/export/defaultViewerTemplate.ts
|
|
764
|
-
var DEFAULT_VIEWER_TEMPLATE = `<!doctype html>
|
|
765
|
-
<html lang="en">
|
|
766
|
-
<head>
|
|
767
|
-
<meta charset="UTF-8" />
|
|
768
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
769
|
-
<title>Finalized Leaves Viewer</title>
|
|
770
|
-
<style>
|
|
771
|
-
:root {
|
|
772
|
-
--bg: #212121;
|
|
773
|
-
--surface: #2a2a2a;
|
|
774
|
-
--border: #4a4a4a;
|
|
775
|
-
--text: #fffafa;
|
|
776
|
-
--muted: #c8c2c2;
|
|
777
|
-
--accent: #a764d3;
|
|
778
|
-
}
|
|
779
|
-
body {
|
|
780
|
-
margin: 0;
|
|
781
|
-
font-family: 'Iosevka Web', 'SFMono-Regular', Menlo, Consolas, monospace;
|
|
782
|
-
color: var(--text);
|
|
783
|
-
background: var(--bg);
|
|
784
|
-
}
|
|
785
|
-
.wrap { max-width: 1100px; margin: 0 auto; padding: 20px; }
|
|
786
|
-
.card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px; }
|
|
787
|
-
.meta { color: var(--muted); font-size: 12px; }
|
|
788
|
-
#results { margin-top: 12px; display: grid; gap: 8px; }
|
|
789
|
-
details { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; }
|
|
790
|
-
summary { cursor: pointer; font-weight: 700; color: var(--accent); }
|
|
791
|
-
pre { margin: 10px 0 0; overflow: auto; border: 1px solid var(--border); border-radius: 8px; padding: 10px; background: #303030; color: var(--text); }
|
|
792
|
-
</style>
|
|
793
|
-
</head>
|
|
794
|
-
<body>
|
|
795
|
-
<div class="wrap">
|
|
796
|
-
<h1>Finalized Leaves Viewer (Baked)</h1>
|
|
797
|
-
<div class="card">
|
|
798
|
-
<div id="status" class="meta">Waiting for baked payload...</div>
|
|
799
|
-
</div>
|
|
800
|
-
<div id="results"></div>
|
|
801
|
-
</div>
|
|
802
|
-
|
|
803
|
-
<!--__FINALIZED_LEAVES_BAKED_PAYLOAD__-->
|
|
804
|
-
|
|
805
|
-
<script>
|
|
806
|
-
const statusEl = document.getElementById('status')
|
|
807
|
-
const resultsEl = document.getElementById('results')
|
|
808
|
-
const payload = window.__FINALIZED_LEAVES_PAYLOAD
|
|
809
|
-
|
|
810
|
-
if (!payload || !Array.isArray(payload.leaves)) {
|
|
811
|
-
statusEl.textContent = 'No baked payload found in this HTML file.'
|
|
812
|
-
} else {
|
|
813
|
-
statusEl.textContent = 'Loaded baked payload with ' + payload.leaves.length + ' routes.'
|
|
814
|
-
|
|
815
|
-
const toHref = (source) => {
|
|
816
|
-
if (!source || !source.file) return null
|
|
817
|
-
const normalizedPath = String(source.file).replace(/\\\\/g, '/')
|
|
818
|
-
const platform =
|
|
819
|
-
(navigator.userAgentData && navigator.userAgentData.platform) ||
|
|
820
|
-
navigator.platform ||
|
|
821
|
-
''
|
|
822
|
-
const isWindows = /win/i.test(platform)
|
|
823
|
-
const vscodePath = isWindows
|
|
824
|
-
? normalizedPath.replace(/^\\/+/, '')
|
|
825
|
-
: normalizedPath.startsWith('/')
|
|
826
|
-
? normalizedPath
|
|
827
|
-
: '/' + normalizedPath
|
|
828
|
-
const line = Number.isFinite(source.line) ? source.line : 1
|
|
829
|
-
const column = Number.isFinite(source.column) ? source.column : 1
|
|
830
|
-
return 'vscode://file/' + encodeURI(vscodePath) + ':' + line + ':' + column
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
const sourceDisplay = (source) => {
|
|
834
|
-
return ''
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
payload.leaves.forEach((leaf) => {
|
|
838
|
-
const details = document.createElement('details')
|
|
839
|
-
const summary = document.createElement('summary')
|
|
840
|
-
summary.textContent = String(leaf.method || '').toUpperCase() + ' ' + (leaf.path || '')
|
|
841
|
-
|
|
842
|
-
const pre = document.createElement('pre')
|
|
843
|
-
pre.textContent = JSON.stringify(leaf, null, 2)
|
|
844
|
-
|
|
845
|
-
const source = payload.sourceByLeaf && payload.sourceByLeaf[leaf.key]
|
|
846
|
-
let sourceWrap = null
|
|
847
|
-
if (source) {
|
|
848
|
-
sourceWrap = document.createElement('div')
|
|
849
|
-
sourceWrap.className = 'meta'
|
|
850
|
-
|
|
851
|
-
const definitionHref = toHref(source.definition)
|
|
852
|
-
if (definitionHref) {
|
|
853
|
-
const label = document.createElement('div')
|
|
854
|
-
const link = document.createElement('a')
|
|
855
|
-
link.href = definitionHref
|
|
856
|
-
link.target = '_blank'
|
|
857
|
-
link.rel = 'noopener noreferrer'
|
|
858
|
-
link.textContent = 'definition'
|
|
859
|
-
label.appendChild(link)
|
|
860
|
-
sourceWrap.appendChild(label)
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
if (source.schemas && typeof source.schemas === 'object') {
|
|
864
|
-
Object.entries(source.schemas).forEach(([name, schema]) => {
|
|
865
|
-
if (!schema) return
|
|
866
|
-
const href = toHref(schema)
|
|
867
|
-
const row = document.createElement('div')
|
|
868
|
-
if (href) {
|
|
869
|
-
const link = document.createElement('a')
|
|
870
|
-
link.href = href
|
|
871
|
-
link.target = '_blank'
|
|
872
|
-
link.rel = 'noopener noreferrer'
|
|
873
|
-
link.textContent =
|
|
874
|
-
name + ': ' + (schema.sourceName || schema.tag || '<anonymous>')
|
|
875
|
-
row.appendChild(link)
|
|
876
|
-
} else {
|
|
877
|
-
row.textContent = name + ': ' + (schema.sourceName || schema.tag || '<anonymous>')
|
|
878
|
-
}
|
|
879
|
-
sourceWrap.appendChild(row)
|
|
880
|
-
})
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
details.appendChild(summary)
|
|
886
|
-
if (sourceWrap) details.appendChild(sourceWrap)
|
|
887
|
-
details.appendChild(pre)
|
|
888
|
-
resultsEl.appendChild(details)
|
|
889
|
-
})
|
|
890
|
-
}
|
|
891
|
-
</script>
|
|
892
|
-
</body>
|
|
893
|
-
</html>
|
|
894
|
-
`;
|
|
895
|
-
|
|
896
|
-
// src/export/extractLeafSourceByAst.ts
|
|
897
|
-
var import_node_path = __toESM(require("path"), 1);
|
|
898
|
-
var import_typescript = __toESM(require("typescript"), 1);
|
|
899
|
-
var SCHEMA_KEYS = [
|
|
900
|
-
"bodySchema",
|
|
901
|
-
"querySchema",
|
|
902
|
-
"paramsSchema",
|
|
903
|
-
"outputSchema",
|
|
904
|
-
"outputMetaSchema",
|
|
905
|
-
"queryExtensionSchema"
|
|
906
|
-
];
|
|
907
|
-
var HTTP_METHODS = /* @__PURE__ */ new Set(["get", "post", "put", "patch", "delete"]);
|
|
908
|
-
var MAX_RECURSION_DEPTH = 120;
|
|
909
|
-
function toLocation(node) {
|
|
910
|
-
const sourceFile = node.getSourceFile();
|
|
911
|
-
const { line, character } = sourceFile.getLineAndCharacterOfPosition(
|
|
912
|
-
node.getStart(sourceFile)
|
|
913
|
-
);
|
|
914
|
-
return {
|
|
915
|
-
file: import_node_path.default.resolve(sourceFile.fileName),
|
|
916
|
-
line: line + 1,
|
|
917
|
-
column: character + 1
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
function markFile(ctx, sourceFile) {
|
|
921
|
-
if (!sourceFile) return;
|
|
922
|
-
ctx.visitedFilePaths.add(import_node_path.default.resolve(sourceFile.fileName));
|
|
923
|
-
}
|
|
924
|
-
function trimPreview(text, max = 80) {
|
|
925
|
-
const normalized = text.replace(/\s+/g, " ").trim();
|
|
926
|
-
return normalized.length > max ? `${normalized.slice(0, max)}...` : normalized;
|
|
927
|
-
}
|
|
928
|
-
function unwrapExpression(expression) {
|
|
929
|
-
let current = expression;
|
|
930
|
-
while (true) {
|
|
931
|
-
if (import_typescript.default.isParenthesizedExpression(current) || import_typescript.default.isAsExpression(current) || import_typescript.default.isTypeAssertionExpression(current) || import_typescript.default.isNonNullExpression(current) || import_typescript.default.isSatisfiesExpression(current)) {
|
|
932
|
-
current = current.expression;
|
|
933
|
-
continue;
|
|
934
|
-
}
|
|
935
|
-
break;
|
|
936
|
-
}
|
|
937
|
-
return current;
|
|
938
|
-
}
|
|
939
|
-
function getTextName(name) {
|
|
940
|
-
if (import_typescript.default.isIdentifier(name) || import_typescript.default.isStringLiteral(name) || import_typescript.default.isNumericLiteral(name)) {
|
|
941
|
-
return name.text;
|
|
942
|
-
}
|
|
943
|
-
return void 0;
|
|
944
|
-
}
|
|
945
|
-
function joinPaths2(parent, child) {
|
|
946
|
-
if (!parent) return child;
|
|
947
|
-
if (!child) return parent;
|
|
948
|
-
const trimmedParent = parent.endsWith("/") ? parent.replace(/\/+$/, "") : parent;
|
|
949
|
-
const trimmedChild = child.startsWith("/") ? child.replace(/^\/+/, "") : child;
|
|
950
|
-
if (!trimmedChild) return trimmedParent;
|
|
951
|
-
return `${trimmedParent}/${trimmedChild}`;
|
|
952
|
-
}
|
|
953
|
-
function buildLeafKey(method, leafPath) {
|
|
954
|
-
return `${method.toUpperCase()} ${leafPath}`;
|
|
955
|
-
}
|
|
956
|
-
function normalizeResourceBase(raw) {
|
|
957
|
-
if (raw === "") return "";
|
|
958
|
-
if (raw.startsWith("/") || raw.startsWith(":") || raw.startsWith("*")) {
|
|
959
|
-
return raw;
|
|
960
|
-
}
|
|
961
|
-
return `/${raw}`;
|
|
962
|
-
}
|
|
963
|
-
function getModuleSymbol(checker, sourceFile) {
|
|
964
|
-
return checker.getSymbolAtLocation(sourceFile);
|
|
965
|
-
}
|
|
966
|
-
function getAliasedSymbolIfNeeded(checker, symbol) {
|
|
967
|
-
if ((symbol.flags & import_typescript.default.SymbolFlags.Alias) !== 0) {
|
|
968
|
-
try {
|
|
969
|
-
return checker.getAliasedSymbol(symbol);
|
|
970
|
-
} catch {
|
|
971
|
-
return symbol;
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
return symbol;
|
|
975
|
-
}
|
|
976
|
-
function findSourceFile(program, filePath) {
|
|
977
|
-
const wanted = import_node_path.default.resolve(filePath);
|
|
978
|
-
const normalizedWanted = import_node_path.default.normalize(wanted);
|
|
979
|
-
return program.getSourceFiles().find((file) => import_node_path.default.normalize(import_node_path.default.resolve(file.fileName)) === normalizedWanted);
|
|
980
|
-
}
|
|
981
|
-
function declarationToExpression(declaration) {
|
|
982
|
-
if (!declaration) return void 0;
|
|
983
|
-
if (import_typescript.default.isVariableDeclaration(declaration)) {
|
|
984
|
-
return declaration.initializer;
|
|
985
|
-
}
|
|
986
|
-
if (import_typescript.default.isExportAssignment(declaration)) {
|
|
987
|
-
return declaration.expression;
|
|
988
|
-
}
|
|
989
|
-
if (import_typescript.default.isPropertyAssignment(declaration)) {
|
|
990
|
-
return declaration.initializer;
|
|
991
|
-
}
|
|
992
|
-
if (import_typescript.default.isShorthandPropertyAssignment(declaration)) {
|
|
993
|
-
return declaration.name;
|
|
994
|
-
}
|
|
995
|
-
if (import_typescript.default.isBindingElement(declaration)) {
|
|
996
|
-
return declaration.initializer;
|
|
997
|
-
}
|
|
998
|
-
if (import_typescript.default.isEnumMember(declaration)) {
|
|
999
|
-
return declaration.initializer;
|
|
1000
|
-
}
|
|
1001
|
-
return void 0;
|
|
1002
|
-
}
|
|
1003
|
-
function symbolKey(symbol) {
|
|
1004
|
-
const decl = symbol.declarations?.[0];
|
|
1005
|
-
if (!decl) return `${symbol.getName()}#${symbol.flags}`;
|
|
1006
|
-
const file = import_node_path.default.resolve(decl.getSourceFile().fileName);
|
|
1007
|
-
return `${file}:${decl.getStart()}:${symbol.getName()}`;
|
|
1008
|
-
}
|
|
1009
|
-
function resolveSymbolFromNode(node, ctx) {
|
|
1010
|
-
const symbol = ctx.checker.getSymbolAtLocation(node);
|
|
1011
|
-
if (!symbol) {
|
|
1012
|
-
ctx.unresolvedReferences += 1;
|
|
1013
|
-
return void 0;
|
|
1014
|
-
}
|
|
1015
|
-
const target = getAliasedSymbolIfNeeded(ctx.checker, symbol);
|
|
1016
|
-
const key = symbolKey(target);
|
|
1017
|
-
ctx.visitedSymbolKeys.add(key);
|
|
1018
|
-
return target;
|
|
1019
|
-
}
|
|
1020
|
-
function getExpressionFromSymbol(symbol, ctx, depth) {
|
|
1021
|
-
const key = symbolKey(symbol);
|
|
1022
|
-
if (ctx.activeSymbols.has(key)) return void 0;
|
|
1023
|
-
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
1024
|
-
ctx.activeSymbols.add(key);
|
|
1025
|
-
try {
|
|
1026
|
-
const declaration = symbol.declarations?.[0];
|
|
1027
|
-
markFile(ctx, declaration?.getSourceFile());
|
|
1028
|
-
const direct = declarationToExpression(declaration);
|
|
1029
|
-
if (direct) return direct;
|
|
1030
|
-
if (declaration && import_typescript.default.isImportSpecifier(declaration)) {
|
|
1031
|
-
const target = getAliasedSymbolIfNeeded(ctx.checker, symbol);
|
|
1032
|
-
if (target !== symbol) {
|
|
1033
|
-
return getExpressionFromSymbol(target, ctx, depth + 1);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
return void 0;
|
|
1037
|
-
} finally {
|
|
1038
|
-
ctx.activeSymbols.delete(key);
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
function resolveIdentifierExpression(identifier, ctx, depth) {
|
|
1042
|
-
const symbol = resolveSymbolFromNode(identifier, ctx);
|
|
1043
|
-
if (!symbol) return void 0;
|
|
1044
|
-
return getExpressionFromSymbol(symbol, ctx, depth);
|
|
1045
|
-
}
|
|
1046
|
-
function resolvePropertyExpression(expression, ctx, depth) {
|
|
1047
|
-
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
1048
|
-
if (import_typescript.default.isPropertyAccessExpression(expression)) {
|
|
1049
|
-
const symbol = resolveSymbolFromNode(expression.name, ctx);
|
|
1050
|
-
if (symbol) {
|
|
1051
|
-
const fromSymbol = getExpressionFromSymbol(symbol, ctx, depth + 1);
|
|
1052
|
-
if (fromSymbol) return fromSymbol;
|
|
1053
|
-
}
|
|
1054
|
-
} else if (expression.argumentExpression) {
|
|
1055
|
-
const symbol = resolveSymbolFromNode(expression.argumentExpression, ctx);
|
|
1056
|
-
if (symbol) {
|
|
1057
|
-
const fromSymbol = getExpressionFromSymbol(symbol, ctx, depth + 1);
|
|
1058
|
-
if (fromSymbol) return fromSymbol;
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
const ownerExpr = evaluateExpressionReference(expression.expression, ctx, depth + 1);
|
|
1062
|
-
const owner = ownerExpr ? maybeObjectLiteral(ownerExpr, ctx, depth + 1) : void 0;
|
|
1063
|
-
if (!owner) return void 0;
|
|
1064
|
-
const propName = import_typescript.default.isPropertyAccessExpression(expression) ? expression.name.text : expression.argumentExpression && import_typescript.default.isStringLiteralLike(expression.argumentExpression) ? expression.argumentExpression.text : void 0;
|
|
1065
|
-
if (!propName) return void 0;
|
|
1066
|
-
for (const property of owner.properties) {
|
|
1067
|
-
if (import_typescript.default.isPropertyAssignment(property) && getTextName(property.name) === propName) {
|
|
1068
|
-
return property.initializer;
|
|
1069
|
-
}
|
|
1070
|
-
if (import_typescript.default.isShorthandPropertyAssignment(property) && property.name.text === propName) {
|
|
1071
|
-
return property.name;
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
return void 0;
|
|
1075
|
-
}
|
|
1076
|
-
function evaluateExpressionReference(expression, ctx, depth) {
|
|
1077
|
-
const resolved = unwrapExpression(expression);
|
|
1078
|
-
markFile(ctx, resolved.getSourceFile());
|
|
1079
|
-
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
1080
|
-
if (import_typescript.default.isIdentifier(resolved)) {
|
|
1081
|
-
return resolveIdentifierExpression(resolved, ctx, depth + 1);
|
|
1082
|
-
}
|
|
1083
|
-
if (import_typescript.default.isPropertyAccessExpression(resolved) || import_typescript.default.isElementAccessExpression(resolved)) {
|
|
1084
|
-
return resolvePropertyExpression(resolved, ctx, depth + 1);
|
|
1085
|
-
}
|
|
1086
|
-
return void 0;
|
|
1087
|
-
}
|
|
1088
|
-
function resolveExportExpression(sourceFile, exportName, checker) {
|
|
1089
|
-
const moduleSymbol = getModuleSymbol(checker, sourceFile);
|
|
1090
|
-
if (!moduleSymbol) return void 0;
|
|
1091
|
-
const exports2 = checker.getExportsOfModule(moduleSymbol);
|
|
1092
|
-
const explicit = exports2.find((entry) => entry.getName() === exportName);
|
|
1093
|
-
if (explicit) {
|
|
1094
|
-
const declaration = getAliasedSymbolIfNeeded(checker, explicit).declarations?.[0];
|
|
1095
|
-
return declarationToExpression(declaration);
|
|
1096
|
-
}
|
|
1097
|
-
const defaultExport = exports2.find((entry) => entry.getName() === "default");
|
|
1098
|
-
if (!defaultExport) return void 0;
|
|
1099
|
-
const defaultDecl = getAliasedSymbolIfNeeded(checker, defaultExport).declarations?.[0];
|
|
1100
|
-
const defaultExpr = declarationToExpression(defaultDecl);
|
|
1101
|
-
if (!defaultExpr) return void 0;
|
|
1102
|
-
const resolved = unwrapExpression(defaultExpr);
|
|
1103
|
-
if (!import_typescript.default.isObjectLiteralExpression(resolved)) return void 0;
|
|
1104
|
-
for (const property of resolved.properties) {
|
|
1105
|
-
if (!import_typescript.default.isPropertyAssignment(property)) continue;
|
|
1106
|
-
const propertyName = getTextName(property.name);
|
|
1107
|
-
if (propertyName !== exportName) continue;
|
|
1108
|
-
return property.initializer;
|
|
1109
|
-
}
|
|
1110
|
-
return void 0;
|
|
1111
|
-
}
|
|
1112
|
-
function maybeObjectLiteral(expression, ctx, depth = 0) {
|
|
1113
|
-
if (!expression || depth > MAX_RECURSION_DEPTH) return void 0;
|
|
1114
|
-
const resolved = unwrapExpression(expression);
|
|
1115
|
-
markFile(ctx, resolved.getSourceFile());
|
|
1116
|
-
if (import_typescript.default.isObjectLiteralExpression(resolved)) return resolved;
|
|
1117
|
-
const referenced = evaluateExpressionReference(resolved, ctx, depth + 1);
|
|
1118
|
-
if (!referenced) return void 0;
|
|
1119
|
-
return maybeObjectLiteral(referenced, ctx, depth + 1);
|
|
1120
|
-
}
|
|
1121
|
-
function collectSchemaExpressionsFromObject(objectLiteral, ctx, depth) {
|
|
1122
|
-
const schemas = {};
|
|
1123
|
-
for (const property of objectLiteral.properties) {
|
|
1124
|
-
if (import_typescript.default.isSpreadAssignment(property)) {
|
|
1125
|
-
const spreadObject = maybeObjectLiteral(property.expression, ctx, depth + 1);
|
|
1126
|
-
if (!spreadObject) continue;
|
|
1127
|
-
Object.assign(
|
|
1128
|
-
schemas,
|
|
1129
|
-
collectSchemaExpressionsFromObject(spreadObject, ctx, depth + 1)
|
|
1130
|
-
);
|
|
1131
|
-
continue;
|
|
1132
|
-
}
|
|
1133
|
-
if (import_typescript.default.isPropertyAssignment(property)) {
|
|
1134
|
-
const key = getTextName(property.name);
|
|
1135
|
-
if (!key || !SCHEMA_KEYS.includes(key)) continue;
|
|
1136
|
-
schemas[key] = property.initializer;
|
|
1137
|
-
continue;
|
|
1138
|
-
}
|
|
1139
|
-
if (import_typescript.default.isShorthandPropertyAssignment(property)) {
|
|
1140
|
-
const key = property.name.text;
|
|
1141
|
-
if (!SCHEMA_KEYS.includes(key)) continue;
|
|
1142
|
-
schemas[key] = property.name;
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
return schemas;
|
|
1146
|
-
}
|
|
1147
|
-
function extractSchemaExpressions(cfgExpression, ctx, depth) {
|
|
1148
|
-
const objectLiteral = maybeObjectLiteral(cfgExpression, ctx, depth);
|
|
1149
|
-
if (!objectLiteral) return {};
|
|
1150
|
-
return collectSchemaExpressionsFromObject(objectLiteral, ctx, depth);
|
|
1151
|
-
}
|
|
1152
|
-
function getNearestVariableName(node) {
|
|
1153
|
-
let current = node;
|
|
1154
|
-
while (current) {
|
|
1155
|
-
if (import_typescript.default.isVariableDeclaration(current) && import_typescript.default.isIdentifier(current.name)) {
|
|
1156
|
-
return current.name.text;
|
|
1157
|
-
}
|
|
1158
|
-
current = current.parent;
|
|
1159
|
-
}
|
|
1160
|
-
return void 0;
|
|
1161
|
-
}
|
|
1162
|
-
function isAllAccess(expression) {
|
|
1163
|
-
if (import_typescript.default.isPropertyAccessExpression(expression)) {
|
|
1164
|
-
return expression.name.text === "all";
|
|
1165
|
-
}
|
|
1166
|
-
return Boolean(
|
|
1167
|
-
expression.argumentExpression && import_typescript.default.isStringLiteralLike(expression.argumentExpression) && expression.argumentExpression.text === "all"
|
|
1168
|
-
);
|
|
1169
|
-
}
|
|
1170
|
-
function evaluateBranchExpression(expression, ctx, depth) {
|
|
1171
|
-
const resolved = unwrapExpression(expression);
|
|
1172
|
-
markFile(ctx, resolved.getSourceFile());
|
|
1173
|
-
if (depth > MAX_RECURSION_DEPTH) return void 0;
|
|
1174
|
-
if (import_typescript.default.isIdentifier(resolved)) {
|
|
1175
|
-
const valueExpr = resolveIdentifierExpression(resolved, ctx, depth + 1);
|
|
1176
|
-
if (!valueExpr) return void 0;
|
|
1177
|
-
return evaluateBranchExpression(valueExpr, ctx, depth + 1);
|
|
1178
|
-
}
|
|
1179
|
-
if (!import_typescript.default.isCallExpression(resolved)) return void 0;
|
|
1180
|
-
const call = resolved;
|
|
1181
|
-
if (import_typescript.default.isIdentifier(call.expression) && call.expression.text === "resource") {
|
|
1182
|
-
const firstArg = call.arguments[0];
|
|
1183
|
-
if (!firstArg || !import_typescript.default.isStringLiteralLike(firstArg)) {
|
|
1184
|
-
ctx.unsupportedShapeSeen = true;
|
|
1185
|
-
return void 0;
|
|
1186
|
-
}
|
|
1187
|
-
return { base: normalizeResourceBase(firstArg.text), leaves: [] };
|
|
1188
|
-
}
|
|
1189
|
-
if (!import_typescript.default.isPropertyAccessExpression(call.expression)) {
|
|
1190
|
-
ctx.unsupportedShapeSeen = true;
|
|
1191
|
-
return void 0;
|
|
1192
|
-
}
|
|
1193
|
-
const owner = call.expression.expression;
|
|
1194
|
-
const method = call.expression.name.text;
|
|
1195
|
-
const branch = evaluateBranchExpression(owner, ctx, depth + 1);
|
|
1196
|
-
if (!branch) return void 0;
|
|
1197
|
-
if (method === "with") return branch;
|
|
1198
|
-
if (HTTP_METHODS.has(method)) {
|
|
1199
|
-
const cfgExpression = call.arguments[0];
|
|
1200
|
-
const schemas = extractSchemaExpressions(cfgExpression, ctx, depth + 1);
|
|
1201
|
-
const nextLeaf = {
|
|
1202
|
-
method,
|
|
1203
|
-
path: branch.base,
|
|
1204
|
-
definitionNode: call.expression.name,
|
|
1205
|
-
schemas
|
|
1206
|
-
};
|
|
1207
|
-
return {
|
|
1208
|
-
...branch,
|
|
1209
|
-
leaves: [...branch.leaves, nextLeaf]
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
if (method === "sub") {
|
|
1213
|
-
const mountedLeaves = call.arguments.flatMap(
|
|
1214
|
-
(arg) => evaluateLeavesFromExpression(arg, ctx, depth + 1)
|
|
1215
|
-
);
|
|
1216
|
-
const prefixed = mountedLeaves.map((leaf) => ({
|
|
1217
|
-
...leaf,
|
|
1218
|
-
path: joinPaths2(branch.base, leaf.path)
|
|
1219
|
-
}));
|
|
1220
|
-
return {
|
|
1221
|
-
...branch,
|
|
1222
|
-
leaves: [...branch.leaves, ...prefixed]
|
|
1223
|
-
};
|
|
1224
|
-
}
|
|
1225
|
-
ctx.unsupportedShapeSeen = true;
|
|
1226
|
-
return void 0;
|
|
1227
|
-
}
|
|
1228
|
-
function expressionKey(expression) {
|
|
1229
|
-
const source = expression.getSourceFile();
|
|
1230
|
-
return `${import_node_path.default.resolve(source.fileName)}:${expression.getStart(source)}:${expression.getEnd()}:${expression.kind}`;
|
|
1231
|
-
}
|
|
1232
|
-
function evaluateLeavesFromExpression(expression, ctx, depth = 0) {
|
|
1233
|
-
const resolved = unwrapExpression(expression);
|
|
1234
|
-
markFile(ctx, resolved.getSourceFile());
|
|
1235
|
-
const key = expressionKey(resolved);
|
|
1236
|
-
if (ctx.activeExpressionKeys.has(key)) return [];
|
|
1237
|
-
if (depth > MAX_RECURSION_DEPTH) return [];
|
|
1238
|
-
ctx.activeExpressionKeys.add(key);
|
|
1239
|
-
try {
|
|
1240
|
-
if (import_typescript.default.isIdentifier(resolved)) {
|
|
1241
|
-
const valueExpr = resolveIdentifierExpression(resolved, ctx, depth + 1);
|
|
1242
|
-
if (!valueExpr) return [];
|
|
1243
|
-
return evaluateLeavesFromExpression(valueExpr, ctx, depth + 1);
|
|
1244
|
-
}
|
|
1245
|
-
if (import_typescript.default.isPropertyAccessExpression(resolved) || import_typescript.default.isElementAccessExpression(resolved)) {
|
|
1246
|
-
if (isAllAccess(resolved)) {
|
|
1247
|
-
return evaluateLeavesFromExpression(resolved.expression, ctx, depth + 1);
|
|
1248
|
-
}
|
|
1249
|
-
const refExpr = resolvePropertyExpression(resolved, ctx, depth + 1);
|
|
1250
|
-
if (refExpr) {
|
|
1251
|
-
return evaluateLeavesFromExpression(refExpr, ctx, depth + 1);
|
|
1252
|
-
}
|
|
1253
|
-
return [];
|
|
1254
|
-
}
|
|
1255
|
-
if (import_typescript.default.isArrayLiteralExpression(resolved)) {
|
|
1256
|
-
const leaves = [];
|
|
1257
|
-
for (const element of resolved.elements) {
|
|
1258
|
-
if (import_typescript.default.isSpreadElement(element)) {
|
|
1259
|
-
leaves.push(...evaluateLeavesFromExpression(element.expression, ctx, depth + 1));
|
|
1260
|
-
continue;
|
|
1261
|
-
}
|
|
1262
|
-
leaves.push(...evaluateLeavesFromExpression(element, ctx, depth + 1));
|
|
1263
|
-
}
|
|
1264
|
-
return leaves;
|
|
1265
|
-
}
|
|
1266
|
-
if (import_typescript.default.isCallExpression(resolved)) {
|
|
1267
|
-
if (import_typescript.default.isIdentifier(resolved.expression)) {
|
|
1268
|
-
const callName = resolved.expression.text;
|
|
1269
|
-
if (callName === "finalize") {
|
|
1270
|
-
const arg = resolved.arguments[0];
|
|
1271
|
-
if (!arg) return [];
|
|
1272
|
-
return evaluateLeavesFromExpression(arg, ctx, depth + 1);
|
|
1273
|
-
}
|
|
1274
|
-
if (callName === "mergeArrays") {
|
|
1275
|
-
return resolved.arguments.flatMap(
|
|
1276
|
-
(arg) => evaluateLeavesFromExpression(arg, ctx, depth + 1)
|
|
1277
|
-
);
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
if (import_typescript.default.isPropertyAccessExpression(resolved.expression)) {
|
|
1281
|
-
const prop = resolved.expression.name.text;
|
|
1282
|
-
if (prop === "done") {
|
|
1283
|
-
const branch2 = evaluateBranchExpression(
|
|
1284
|
-
resolved.expression.expression,
|
|
1285
|
-
ctx,
|
|
1286
|
-
depth + 1
|
|
1287
|
-
);
|
|
1288
|
-
return branch2?.leaves ?? [];
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
const refExpr = evaluateExpressionReference(resolved, ctx, depth + 1);
|
|
1292
|
-
if (refExpr) return evaluateLeavesFromExpression(refExpr, ctx, depth + 1);
|
|
1293
|
-
ctx.unsupportedShapeSeen = true;
|
|
1294
|
-
return [];
|
|
1295
|
-
}
|
|
1296
|
-
const branch = evaluateBranchExpression(resolved, ctx, depth + 1);
|
|
1297
|
-
if (branch) return branch.leaves;
|
|
1298
|
-
ctx.unsupportedShapeSeen = true;
|
|
1299
|
-
return [];
|
|
1300
|
-
} finally {
|
|
1301
|
-
ctx.activeExpressionKeys.delete(key);
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
function resolveSchemaMetadata(expression, ctx) {
|
|
1305
|
-
const resolved = unwrapExpression(expression);
|
|
1306
|
-
if (import_typescript.default.isIdentifier(resolved)) {
|
|
1307
|
-
const symbol = resolveSymbolFromNode(resolved, ctx);
|
|
1308
|
-
const declaration = symbol?.declarations?.[0];
|
|
1309
|
-
const locationNode = declaration ? import_typescript.default.isVariableDeclaration(declaration) ? declaration.name : declaration : resolved;
|
|
1310
|
-
const sourceName = declaration && import_typescript.default.isVariableDeclaration(declaration) && import_typescript.default.isIdentifier(declaration.name) ? declaration.name.text : resolved.text;
|
|
1311
|
-
return {
|
|
1312
|
-
...toLocation(locationNode),
|
|
1313
|
-
sourceName,
|
|
1314
|
-
tag: declaration ? void 0 : "<anonymous>"
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1317
|
-
if (import_typescript.default.isPropertyAccessExpression(resolved) || import_typescript.default.isElementAccessExpression(resolved)) {
|
|
1318
|
-
return {
|
|
1319
|
-
...toLocation(resolved),
|
|
1320
|
-
sourceName: trimPreview(resolved.getText()),
|
|
1321
|
-
tag: "<expression>"
|
|
1322
|
-
};
|
|
1323
|
-
}
|
|
1324
|
-
return {
|
|
1325
|
-
...toLocation(resolved),
|
|
1326
|
-
sourceName: trimPreview(resolved.getText()),
|
|
1327
|
-
tag: "<inline>"
|
|
1328
|
-
};
|
|
1329
|
-
}
|
|
1330
|
-
function parseTsConfig(cwd, tsconfigPath) {
|
|
1331
|
-
const resolvedTsconfig = tsconfigPath ? import_node_path.default.resolve(cwd, tsconfigPath) : import_typescript.default.findConfigFile(cwd, import_typescript.default.sys.fileExists, "tsconfig.json");
|
|
1332
|
-
if (!resolvedTsconfig) {
|
|
1333
|
-
return void 0;
|
|
1334
|
-
}
|
|
1335
|
-
const read = import_typescript.default.readConfigFile(resolvedTsconfig, import_typescript.default.sys.readFile);
|
|
1336
|
-
if (read.error) {
|
|
1337
|
-
throw new Error(import_typescript.default.flattenDiagnosticMessageText(read.error.messageText, "\n"));
|
|
1338
|
-
}
|
|
1339
|
-
const parsed = import_typescript.default.parseJsonConfigFileContent(
|
|
1340
|
-
read.config,
|
|
1341
|
-
import_typescript.default.sys,
|
|
1342
|
-
import_node_path.default.dirname(resolvedTsconfig),
|
|
1343
|
-
void 0,
|
|
1344
|
-
resolvedTsconfig
|
|
1345
|
-
);
|
|
1346
|
-
const nonEmptyInputErrors = parsed.errors.filter((entry) => entry.code !== 18003);
|
|
1347
|
-
if (nonEmptyInputErrors.length > 0) {
|
|
1348
|
-
throw new Error(
|
|
1349
|
-
nonEmptyInputErrors.map((entry) => import_typescript.default.flattenDiagnosticMessageText(entry.messageText, "\n")).join("\n")
|
|
1350
|
-
);
|
|
1351
|
-
}
|
|
1352
|
-
return { resolvedTsconfig, parsed };
|
|
1353
|
-
}
|
|
1354
|
-
function createProgramWithFallback(parsed, moduleFileAbs) {
|
|
1355
|
-
const base = import_typescript.default.createProgram({
|
|
1356
|
-
rootNames: parsed.fileNames,
|
|
1357
|
-
options: parsed.options
|
|
1358
|
-
});
|
|
1359
|
-
if (findSourceFile(base, moduleFileAbs)) {
|
|
1360
|
-
return base;
|
|
1361
|
-
}
|
|
1362
|
-
const rootNames = Array.from(/* @__PURE__ */ new Set([...parsed.fileNames, moduleFileAbs]));
|
|
1363
|
-
return import_typescript.default.createProgram({ rootNames, options: parsed.options });
|
|
1364
|
-
}
|
|
1365
|
-
function extractLeafSourceByAst({
|
|
1366
|
-
modulePath,
|
|
1367
|
-
exportName,
|
|
1368
|
-
tsconfigPath,
|
|
1369
|
-
cwd = process.cwd()
|
|
1370
|
-
}) {
|
|
1371
|
-
const parsedConfig = parseTsConfig(cwd, tsconfigPath);
|
|
1372
|
-
if (!parsedConfig) {
|
|
1373
|
-
return {
|
|
1374
|
-
sourceByLeaf: {},
|
|
1375
|
-
reason: "module_not_in_program",
|
|
1376
|
-
stats: { visitedSymbols: 0, visitedFiles: 0, unresolvedReferences: 0 }
|
|
1377
|
-
};
|
|
1378
|
-
}
|
|
1379
|
-
const moduleAbs = import_node_path.default.resolve(cwd, modulePath);
|
|
1380
|
-
const program = createProgramWithFallback(parsedConfig.parsed, moduleAbs);
|
|
1381
|
-
const checker = program.getTypeChecker();
|
|
1382
|
-
const moduleFile = findSourceFile(program, moduleAbs);
|
|
1383
|
-
if (!moduleFile) {
|
|
1384
|
-
return {
|
|
1385
|
-
sourceByLeaf: {},
|
|
1386
|
-
tsconfigPath: parsedConfig.resolvedTsconfig,
|
|
1387
|
-
reason: "module_not_in_program",
|
|
1388
|
-
stats: { visitedSymbols: 0, visitedFiles: 0, unresolvedReferences: 0 }
|
|
1389
|
-
};
|
|
1390
|
-
}
|
|
1391
|
-
const exportedExpression = resolveExportExpression(moduleFile, exportName, checker);
|
|
1392
|
-
if (!exportedExpression) {
|
|
1393
|
-
return {
|
|
1394
|
-
sourceByLeaf: {},
|
|
1395
|
-
tsconfigPath: parsedConfig.resolvedTsconfig,
|
|
1396
|
-
reason: "export_not_found",
|
|
1397
|
-
stats: { visitedSymbols: 0, visitedFiles: 1, unresolvedReferences: 0 }
|
|
1398
|
-
};
|
|
1399
|
-
}
|
|
1400
|
-
const ctx = {
|
|
1401
|
-
checker,
|
|
1402
|
-
activeExpressionKeys: /* @__PURE__ */ new Set(),
|
|
1403
|
-
activeSymbols: /* @__PURE__ */ new Set(),
|
|
1404
|
-
visitedSymbolKeys: /* @__PURE__ */ new Set(),
|
|
1405
|
-
visitedFilePaths: /* @__PURE__ */ new Set([import_node_path.default.resolve(moduleFile.fileName)]),
|
|
1406
|
-
unresolvedReferences: 0,
|
|
1407
|
-
unsupportedShapeSeen: false
|
|
1408
|
-
};
|
|
1409
|
-
const evaluatedLeaves = evaluateLeavesFromExpression(exportedExpression, ctx, 0);
|
|
1410
|
-
const sourceByLeaf = {};
|
|
1411
|
-
for (const leaf of evaluatedLeaves) {
|
|
1412
|
-
const key = buildLeafKey(leaf.method, leaf.path);
|
|
1413
|
-
const definition = {
|
|
1414
|
-
...toLocation(leaf.definitionNode),
|
|
1415
|
-
symbolName: getNearestVariableName(leaf.definitionNode)
|
|
1416
|
-
};
|
|
1417
|
-
ctx.visitedFilePaths.add(definition.file);
|
|
1418
|
-
const schemas = {};
|
|
1419
|
-
for (const schemaKey of SCHEMA_KEYS) {
|
|
1420
|
-
const schemaExpression = leaf.schemas[schemaKey];
|
|
1421
|
-
if (!schemaExpression) continue;
|
|
1422
|
-
const schemaMeta = resolveSchemaMetadata(schemaExpression, ctx);
|
|
1423
|
-
ctx.visitedFilePaths.add(schemaMeta.file);
|
|
1424
|
-
schemas[schemaKey] = schemaMeta;
|
|
1425
|
-
}
|
|
1426
|
-
sourceByLeaf[key] = { definition, schemas };
|
|
1427
|
-
}
|
|
1428
|
-
const reason = Object.keys(sourceByLeaf).length > 0 ? void 0 : ctx.unsupportedShapeSeen ? "unsupported_expression_shape" : "resolved_zero_leaves";
|
|
1429
|
-
return {
|
|
1430
|
-
sourceByLeaf,
|
|
1431
|
-
tsconfigPath: parsedConfig.resolvedTsconfig,
|
|
1432
|
-
reason,
|
|
1433
|
-
stats: {
|
|
1434
|
-
visitedSymbols: ctx.visitedSymbolKeys.size,
|
|
1435
|
-
visitedFiles: ctx.visitedFilePaths.size,
|
|
1436
|
-
unresolvedReferences: ctx.unresolvedReferences
|
|
1437
|
-
}
|
|
1438
|
-
};
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
// src/export/exportFinalizedLeaves.ts
|
|
1442
|
-
function isRegistry(value) {
|
|
1443
|
-
return typeof value === "object" && value !== null && "all" in value && "byKey" in value;
|
|
1444
|
-
}
|
|
1445
|
-
function getLeaves(input) {
|
|
1446
|
-
return isRegistry(input) ? input.all : input;
|
|
1447
|
-
}
|
|
1448
|
-
function buildMeta(sourceExtraction) {
|
|
1449
|
-
return {
|
|
1450
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1451
|
-
description: "Finalized RRRoutes leaves export with serialized schemas and flattened schema paths for downstream processing.",
|
|
1452
|
-
sourceExtraction,
|
|
1453
|
-
fieldCatalog: {
|
|
1454
|
-
leaf: ["key", "method", "path", "cfg"],
|
|
1455
|
-
cfg: [
|
|
1456
|
-
"description?",
|
|
1457
|
-
"summary?",
|
|
1458
|
-
"docsGroup?",
|
|
1459
|
-
"tags?",
|
|
1460
|
-
"deprecated?",
|
|
1461
|
-
"stability?",
|
|
1462
|
-
"docsHidden?",
|
|
1463
|
-
"docsMeta?",
|
|
1464
|
-
"feed?",
|
|
1465
|
-
"bodyFiles?",
|
|
1466
|
-
"schemas"
|
|
1467
|
-
],
|
|
1468
|
-
schemaNode: [
|
|
1469
|
-
"kind",
|
|
1470
|
-
"optional?",
|
|
1471
|
-
"nullable?",
|
|
1472
|
-
"description?",
|
|
1473
|
-
"properties?",
|
|
1474
|
-
"element?",
|
|
1475
|
-
"union?",
|
|
1476
|
-
"literal?",
|
|
1477
|
-
"enumValues?"
|
|
1478
|
-
],
|
|
1479
|
-
flatSchemaEntry: ["type", "nullable", "optional", "literal?"]
|
|
1480
|
-
},
|
|
1481
|
-
flattening: {
|
|
1482
|
-
notation: "dot+[]",
|
|
1483
|
-
unionBranchSuffix: "-N",
|
|
1484
|
-
sections: ["params", "query", "body", "output"]
|
|
1485
|
-
}
|
|
1486
|
-
};
|
|
1487
|
-
}
|
|
1488
|
-
var BAKED_PAYLOAD_MARKER = "<!--__FINALIZED_LEAVES_BAKED_PAYLOAD__-->";
|
|
1489
|
-
function escapePayloadForInlineScript(payload) {
|
|
1490
|
-
return JSON.stringify(payload).replace(/<\//g, "<\\/").replace(/<!--/g, "<\\!--");
|
|
1491
|
-
}
|
|
1492
|
-
function injectPayloadIntoViewerHtml(htmlTemplate, payload) {
|
|
1493
|
-
const payloadScript = `${BAKED_PAYLOAD_MARKER}
|
|
1494
|
-
<script id="finalized-leaves-baked-payload">window.__FINALIZED_LEAVES_PAYLOAD = ${escapePayloadForInlineScript(
|
|
1495
|
-
payload
|
|
1496
|
-
)};</script>`;
|
|
1497
|
-
if (htmlTemplate.includes(BAKED_PAYLOAD_MARKER)) {
|
|
1498
|
-
return htmlTemplate.replace(BAKED_PAYLOAD_MARKER, payloadScript);
|
|
1499
|
-
}
|
|
1500
|
-
if (htmlTemplate.includes("</body>")) {
|
|
1501
|
-
return htmlTemplate.replace("</body>", `${payloadScript}
|
|
1502
|
-
</body>`);
|
|
1503
|
-
}
|
|
1504
|
-
return `${payloadScript}
|
|
1505
|
-
${htmlTemplate}`;
|
|
1506
|
-
}
|
|
1507
|
-
async function resolveViewerTemplatePath(viewerTemplateFile) {
|
|
1508
|
-
if (viewerTemplateFile) {
|
|
1509
|
-
const resolved = import_node_path2.default.resolve(viewerTemplateFile);
|
|
1510
|
-
await import_promises.default.access(resolved);
|
|
1511
|
-
return resolved;
|
|
1512
|
-
}
|
|
1513
|
-
const candidates = [
|
|
1514
|
-
import_node_path2.default.resolve(
|
|
1515
|
-
process.cwd(),
|
|
1516
|
-
"node_modules/@emeryld/rrroutes-contract/tools/finalized-leaves-viewer.html"
|
|
1517
|
-
),
|
|
1518
|
-
import_node_path2.default.resolve(
|
|
1519
|
-
process.cwd(),
|
|
1520
|
-
"tools/finalized-leaves-viewer.html"
|
|
1521
|
-
),
|
|
1522
|
-
import_node_path2.default.resolve(
|
|
1523
|
-
process.cwd(),
|
|
1524
|
-
"packages/contract/tools/finalized-leaves-viewer.html"
|
|
1525
|
-
)
|
|
1526
|
-
];
|
|
1527
|
-
for (const candidate of candidates) {
|
|
1528
|
-
try {
|
|
1529
|
-
await import_promises.default.access(candidate);
|
|
1530
|
-
return candidate;
|
|
1531
|
-
} catch {
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
return void 0;
|
|
1535
|
-
}
|
|
1536
|
-
async function writeJsonExport(payload, outFile) {
|
|
1537
|
-
const resolved = import_node_path2.default.resolve(outFile);
|
|
1538
|
-
await import_promises.default.mkdir(import_node_path2.default.dirname(resolved), { recursive: true });
|
|
1539
|
-
await import_promises.default.writeFile(resolved, `${JSON.stringify(payload, null, 2)}
|
|
1540
|
-
`, "utf8");
|
|
1541
|
-
return resolved;
|
|
1542
|
-
}
|
|
1543
|
-
async function writeBakedHtmlExport(payload, htmlFile, viewerTemplateFile) {
|
|
1544
|
-
const templatePath = await resolveViewerTemplatePath(viewerTemplateFile);
|
|
1545
|
-
const template = templatePath ? await import_promises.default.readFile(templatePath, "utf8") : DEFAULT_VIEWER_TEMPLATE;
|
|
1546
|
-
const baked = injectPayloadIntoViewerHtml(template, payload);
|
|
1547
|
-
const resolved = import_node_path2.default.resolve(htmlFile);
|
|
1548
|
-
await import_promises.default.mkdir(import_node_path2.default.dirname(resolved), { recursive: true });
|
|
1549
|
-
await import_promises.default.writeFile(resolved, baked, "utf8");
|
|
1550
|
-
return resolved;
|
|
1551
|
-
}
|
|
1552
|
-
async function openHtmlInBrowser(filePath) {
|
|
1553
|
-
const resolved = import_node_path2.default.resolve(filePath);
|
|
1554
|
-
const platform = process.platform;
|
|
1555
|
-
if (platform === "darwin") {
|
|
1556
|
-
(0, import_node_child_process.spawn)("open", [resolved], { detached: true, stdio: "ignore" }).unref();
|
|
1557
|
-
return;
|
|
1558
|
-
}
|
|
1559
|
-
if (platform === "win32") {
|
|
1560
|
-
(0, import_node_child_process.spawn)("cmd", ["/c", "start", "", resolved], {
|
|
1561
|
-
detached: true,
|
|
1562
|
-
stdio: "ignore"
|
|
1563
|
-
}).unref();
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
|
-
(0, import_node_child_process.spawn)("xdg-open", [resolved], { detached: true, stdio: "ignore" }).unref();
|
|
1567
|
-
}
|
|
1568
|
-
async function writeFinalizedLeavesExport(payload, outFileOrOptions) {
|
|
1569
|
-
const options = typeof outFileOrOptions === "string" ? { outFile: outFileOrOptions } : outFileOrOptions;
|
|
1570
|
-
const written = {};
|
|
1571
|
-
if (options.outFile) {
|
|
1572
|
-
written.outFile = await writeJsonExport(payload, options.outFile);
|
|
1573
|
-
}
|
|
1574
|
-
if (options.htmlFile) {
|
|
1575
|
-
written.htmlFile = await writeBakedHtmlExport(
|
|
1576
|
-
payload,
|
|
1577
|
-
options.htmlFile,
|
|
1578
|
-
options.viewerTemplateFile
|
|
1579
|
-
);
|
|
1580
|
-
}
|
|
1581
|
-
if (options.openOnFinish) {
|
|
1582
|
-
if (!written.htmlFile) {
|
|
1583
|
-
throw new Error(
|
|
1584
|
-
"openOnFinish requires htmlFile. Provide htmlFile to open the baked viewer."
|
|
1585
|
-
);
|
|
1586
|
-
}
|
|
1587
|
-
await openHtmlInBrowser(written.htmlFile);
|
|
1588
|
-
}
|
|
1589
|
-
return written;
|
|
1590
|
-
}
|
|
1591
|
-
async function exportFinalizedLeaves(input, options = {}) {
|
|
1592
|
-
const leaves = getLeaves(input);
|
|
1593
|
-
const serializedLeaves = serializeLeavesContract(leaves, options);
|
|
1594
|
-
const schemaFlatByLeaf = Object.fromEntries(
|
|
1595
|
-
serializedLeaves.map((leaf) => [leaf.key, flattenLeafSchemas(leaf)])
|
|
1596
|
-
);
|
|
1597
|
-
const sourceByLeaf = {};
|
|
1598
|
-
let sourceExtraction;
|
|
1599
|
-
if (options.includeSource) {
|
|
1600
|
-
const modulePath = options.sourceModulePath;
|
|
1601
|
-
const exportName = options.sourceExportName ?? "leaves";
|
|
1602
|
-
if (modulePath) {
|
|
1603
|
-
const extracted = extractLeafSourceByAst({
|
|
1604
|
-
modulePath,
|
|
1605
|
-
exportName,
|
|
1606
|
-
tsconfigPath: options.tsconfigPath
|
|
1607
|
-
});
|
|
1608
|
-
const allowedLeafKeys = new Set(serializedLeaves.map((leaf) => leaf.key));
|
|
1609
|
-
for (const [key, source] of Object.entries(extracted.sourceByLeaf)) {
|
|
1610
|
-
if (allowedLeafKeys.has(key)) {
|
|
1611
|
-
sourceByLeaf[key] = source;
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
sourceExtraction = {
|
|
1615
|
-
mode: "ast",
|
|
1616
|
-
enabled: true,
|
|
1617
|
-
modulePath: import_node_path2.default.resolve(modulePath),
|
|
1618
|
-
exportName,
|
|
1619
|
-
tsconfigPath: extracted.tsconfigPath,
|
|
1620
|
-
resolvedLeafCount: Object.keys(sourceByLeaf).length,
|
|
1621
|
-
reason: extracted.reason,
|
|
1622
|
-
stats: extracted.stats
|
|
1623
|
-
};
|
|
1624
|
-
} else {
|
|
1625
|
-
sourceExtraction = {
|
|
1626
|
-
mode: "ast",
|
|
1627
|
-
enabled: false,
|
|
1628
|
-
exportName,
|
|
1629
|
-
tsconfigPath: options.tsconfigPath ? import_node_path2.default.resolve(options.tsconfigPath) : void 0,
|
|
1630
|
-
resolvedLeafCount: 0,
|
|
1631
|
-
reason: "resolved_zero_leaves",
|
|
1632
|
-
stats: {
|
|
1633
|
-
visitedSymbols: 0,
|
|
1634
|
-
visitedFiles: 0,
|
|
1635
|
-
unresolvedReferences: 0
|
|
1636
|
-
}
|
|
1637
|
-
};
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
|
-
const payload = {
|
|
1641
|
-
_meta: buildMeta(sourceExtraction),
|
|
1642
|
-
leaves: serializedLeaves,
|
|
1643
|
-
schemaFlatByLeaf,
|
|
1644
|
-
sourceByLeaf: options.includeSource && Object.keys(sourceByLeaf).length > 0 ? sourceByLeaf : void 0
|
|
1645
|
-
};
|
|
1646
|
-
if (options.outFile || options.htmlFile) {
|
|
1647
|
-
await writeFinalizedLeavesExport(payload, {
|
|
1648
|
-
outFile: options.outFile,
|
|
1649
|
-
htmlFile: options.htmlFile,
|
|
1650
|
-
viewerTemplateFile: options.viewerTemplateFile,
|
|
1651
|
-
openOnFinish: options.openOnFinish
|
|
1652
|
-
});
|
|
1653
|
-
}
|
|
1654
|
-
return payload;
|
|
1655
|
-
}
|
|
1656
|
-
|
|
1657
|
-
// src/export/exportFinalizedLeaves.cli.ts
|
|
1658
|
-
var import_node_path3 = __toESM(require("path"), 1);
|
|
1659
|
-
var import_node_url = require("url");
|
|
1660
|
-
function parseFinalizedLeavesCliArgs(argv) {
|
|
1661
|
-
const args = /* @__PURE__ */ new Map();
|
|
1662
|
-
let withSource = false;
|
|
1663
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
1664
|
-
const key = argv[i];
|
|
1665
|
-
if (key === "--") continue;
|
|
1666
|
-
if (!key.startsWith("--")) continue;
|
|
1667
|
-
if (key === "--with-source") {
|
|
1668
|
-
withSource = true;
|
|
1669
|
-
continue;
|
|
1670
|
-
}
|
|
1671
|
-
const value = argv[i + 1];
|
|
1672
|
-
if (!value || value.startsWith("--")) {
|
|
1673
|
-
throw new Error(`Missing value for ${key}`);
|
|
1674
|
-
}
|
|
1675
|
-
args.set(key, value);
|
|
1676
|
-
i += 1;
|
|
1677
|
-
}
|
|
1678
|
-
const modulePath = args.get("--module");
|
|
1679
|
-
if (!modulePath) {
|
|
1680
|
-
throw new Error("Missing required --module argument");
|
|
1681
|
-
}
|
|
1682
|
-
return {
|
|
1683
|
-
modulePath,
|
|
1684
|
-
exportName: args.get("--export") ?? "leaves",
|
|
1685
|
-
outFile: args.get("--out") ?? "finalized-leaves.export.json",
|
|
1686
|
-
withSource,
|
|
1687
|
-
tsconfigPath: args.get("--tsconfig") ?? void 0
|
|
1688
|
-
};
|
|
1689
|
-
}
|
|
1690
|
-
async function loadFinalizedLeavesInput({
|
|
1691
|
-
modulePath,
|
|
1692
|
-
exportName
|
|
1693
|
-
}) {
|
|
1694
|
-
const resolvedModule = import_node_path3.default.resolve(process.cwd(), modulePath);
|
|
1695
|
-
const mod = await import((0, import_node_url.pathToFileURL)(resolvedModule).href);
|
|
1696
|
-
const value = mod[exportName] ?? (mod.default && mod.default[exportName]);
|
|
1697
|
-
if (!value) {
|
|
1698
|
-
throw new Error(`Export "${exportName}" not found in module: ${resolvedModule}`);
|
|
1699
|
-
}
|
|
1700
|
-
return value;
|
|
1701
|
-
}
|
|
1702
|
-
async function runExportFinalizedLeavesCli(argv) {
|
|
1703
|
-
const args = parseFinalizedLeavesCliArgs(argv);
|
|
1704
|
-
const input = await loadFinalizedLeavesInput(args);
|
|
1705
|
-
const payload = await exportFinalizedLeaves(input, {
|
|
1706
|
-
outFile: args.outFile,
|
|
1707
|
-
includeSource: args.withSource,
|
|
1708
|
-
tsconfigPath: args.tsconfigPath,
|
|
1709
|
-
sourceModulePath: args.modulePath,
|
|
1710
|
-
sourceExportName: args.exportName
|
|
1711
|
-
});
|
|
1712
|
-
return {
|
|
1713
|
-
payload,
|
|
1714
|
-
outFile: import_node_path3.default.resolve(args.outFile)
|
|
1715
|
-
};
|
|
1716
|
-
}
|
|
1717
378
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1718
379
|
0 && (module.exports = {
|
|
1719
|
-
DEFAULT_VIEWER_TEMPLATE,
|
|
1720
380
|
buildCacheKey,
|
|
1721
381
|
buildLowProfileLeaf,
|
|
1722
|
-
clearSchemaIntrospectionHandlers,
|
|
1723
382
|
collectNestedFieldSuggestions,
|
|
1724
383
|
compilePath,
|
|
1725
|
-
createSchemaIntrospector,
|
|
1726
384
|
defineSocketEvents,
|
|
1727
|
-
exportFinalizedLeaves,
|
|
1728
|
-
extractLeafSourceByAst,
|
|
1729
385
|
finalize,
|
|
1730
|
-
flattenLeafSchemas,
|
|
1731
|
-
flattenSerializableSchema,
|
|
1732
386
|
getZodShape,
|
|
1733
|
-
introspectSchema,
|
|
1734
387
|
keyOf,
|
|
1735
|
-
loadFinalizedLeavesInput,
|
|
1736
388
|
lowProfileParse,
|
|
1737
389
|
lowProfileSafeParse,
|
|
1738
390
|
mergeArrays,
|
|
1739
391
|
mergeSchemas,
|
|
1740
|
-
parseFinalizedLeavesCliArgs,
|
|
1741
|
-
registerSchemaIntrospectionHandler,
|
|
1742
392
|
resource,
|
|
1743
393
|
routeSchemaParse,
|
|
1744
|
-
|
|
1745
|
-
serializableSchemaKinds,
|
|
1746
|
-
serializeLeafContract,
|
|
1747
|
-
serializeLeavesContract,
|
|
1748
|
-
staticBase,
|
|
1749
|
-
writeFinalizedLeavesExport
|
|
394
|
+
staticBase
|
|
1750
395
|
});
|
|
1751
396
|
//# sourceMappingURL=index.cjs.map
|