@emeryld/rrroutes-export 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/bin/rrroutes-export-finalized-leaves.mjs +14 -0
- package/dist/defaultViewerTemplate.d.ts +1 -0
- package/dist/exportFinalizedLeaves.cli.d.ts +14 -0
- package/dist/exportFinalizedLeaves.d.ts +61 -0
- package/dist/extractLeafSourceByAst.d.ts +38 -0
- package/dist/flattenSchema.d.ts +12 -0
- package/dist/index.cjs +1386 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +1336 -0
- package/dist/index.mjs.map +1 -0
- package/dist/schemaIntrospection.d.ts +47 -0
- package/dist/serializeLeafContract.d.ts +31 -0
- package/package.json +46 -0
- package/tools/finalized-leaves-viewer.html +1550 -0
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @emeryld/rrroutes-export
|
|
2
|
+
|
|
3
|
+
Export helpers and CLI for RRRoutes finalized leaves.
|
|
4
|
+
|
|
5
|
+
- Runtime API: `exportFinalizedLeaves`, `writeFinalizedLeavesExport`
|
|
6
|
+
- CLI: `rrroutes-export-finalized-leaves`
|
|
7
|
+
- Schema utilities: `serializeLeafContract`, `flattenLeafSchemas`, `introspectSchema`
|
|
8
|
+
|
|
9
|
+
Depends on `@emeryld/rrroutes-contract` for contract types and schema parsing.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { runExportFinalizedLeavesCli } from '../dist/index.mjs'
|
|
4
|
+
|
|
5
|
+
runExportFinalizedLeavesCli(process.argv.slice(2))
|
|
6
|
+
.then(({ payload, outFile }) => {
|
|
7
|
+
process.stdout.write(`Exported ${payload.leaves.length} finalized leaves to ${outFile}\n`)
|
|
8
|
+
})
|
|
9
|
+
.catch((error) => {
|
|
10
|
+
process.stderr.write(
|
|
11
|
+
`${error instanceof Error ? error.message : String(error)}\n`,
|
|
12
|
+
)
|
|
13
|
+
process.exitCode = 1
|
|
14
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_VIEWER_TEMPLATE = "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Finalized Leaves Viewer</title>\n <style>\n :root {\n --bg: #212121;\n --surface: #2a2a2a;\n --border: #4a4a4a;\n --text: #fffafa;\n --muted: #c8c2c2;\n --accent: #a764d3;\n --schema-accent: #fbbd23;\n }\n body {\n margin: 0;\n font-family: 'Iosevka Web', 'SFMono-Regular', Menlo, Consolas, monospace;\n color: var(--text);\n background: var(--bg);\n }\n a { color: var(--schema-accent); }\n .wrap { max-width: 1100px; margin: 0 auto; padding: 20px; }\n .card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px; }\n .meta { color: var(--muted); font-size: 12px; }\n #results { margin-top: 12px; display: grid; gap: 8px; }\n details { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; }\n summary { cursor: pointer; font-weight: 700; color: var(--accent); }\n pre { margin: 10px 0 0; overflow: auto; border: 1px solid var(--border); border-radius: 8px; padding: 10px; background: #303030; color: var(--text); }\n </style>\n </head>\n <body>\n <div class=\"wrap\">\n <h1>Finalized Leaves Viewer (Baked)</h1>\n <div class=\"card\">\n <div id=\"status\" class=\"meta\">Waiting for baked payload...</div>\n </div>\n <div id=\"results\"></div>\n </div>\n\n <!--__FINALIZED_LEAVES_BAKED_PAYLOAD__-->\n\n <script>\n const statusEl = document.getElementById('status')\n const resultsEl = document.getElementById('results')\n const payload = window.__FINALIZED_LEAVES_PAYLOAD\n\n if (!payload || !Array.isArray(payload.leaves)) {\n statusEl.textContent = 'No baked payload found in this HTML file.'\n } else {\n statusEl.textContent = 'Loaded baked payload with ' + payload.leaves.length + ' routes.'\n\n const toHref = (source) => {\n if (!source || !source.file) return null\n const normalizedPath = String(source.file).replace(/\\\\/g, '/')\n const platform =\n (navigator.userAgentData && navigator.userAgentData.platform) ||\n navigator.platform ||\n ''\n const isWindows = /win/i.test(platform)\n const vscodePath = isWindows\n ? normalizedPath.replace(/^\\/+/, '')\n : normalizedPath.startsWith('/')\n ? normalizedPath\n : '/' + normalizedPath\n const line = Number.isFinite(source.line) ? source.line : 1\n const column = Number.isFinite(source.column) ? source.column : 1\n return 'vscode://file/' + encodeURI(vscodePath) + ':' + line + ':' + column\n }\n\n const sourceDisplay = (source) => {\n return ''\n }\n\n payload.leaves.forEach((leaf) => {\n const details = document.createElement('details')\n const summary = document.createElement('summary')\n summary.textContent = String(leaf.method || '').toUpperCase() + ' ' + (leaf.path || '')\n\n const pre = document.createElement('pre')\n pre.textContent = JSON.stringify(leaf, null, 2)\n\n const source = payload.sourceByLeaf && payload.sourceByLeaf[leaf.key]\n let sourceWrap = null\n if (source) {\n sourceWrap = document.createElement('div')\n sourceWrap.className = 'meta'\n\n const definitionHref = toHref(source.definition)\n if (definitionHref) {\n const label = document.createElement('div')\n const link = document.createElement('a')\n link.href = definitionHref\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.textContent = 'definition'\n label.appendChild(link)\n sourceWrap.appendChild(label)\n }\n\n if (source.schemas && typeof source.schemas === 'object') {\n Object.entries(source.schemas).forEach(([name, schema]) => {\n if (!schema) return\n const href = toHref(schema)\n const row = document.createElement('div')\n if (href) {\n const link = document.createElement('a')\n link.href = href\n link.target = '_blank'\n link.rel = 'noopener noreferrer'\n link.textContent =\n name + ': ' + (schema.sourceName || schema.tag || '<anonymous>')\n row.appendChild(link)\n } else {\n row.textContent = name + ': ' + (schema.sourceName || schema.tag || '<anonymous>')\n }\n sourceWrap.appendChild(row)\n })\n }\n\n }\n\n details.appendChild(summary)\n if (sourceWrap) details.appendChild(sourceWrap)\n details.appendChild(pre)\n resultsEl.appendChild(details)\n })\n }\n </script>\n </body>\n</html>\n";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ExportFinalizedLeavesInput } from './exportFinalizedLeaves';
|
|
2
|
+
export type FinalizedLeavesCliArgs = {
|
|
3
|
+
modulePath: string;
|
|
4
|
+
exportName: string;
|
|
5
|
+
outFile: string;
|
|
6
|
+
withSource: boolean;
|
|
7
|
+
tsconfigPath?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function parseFinalizedLeavesCliArgs(argv: string[]): FinalizedLeavesCliArgs;
|
|
10
|
+
export declare function loadFinalizedLeavesInput({ modulePath, exportName, }: FinalizedLeavesCliArgs): Promise<ExportFinalizedLeavesInput>;
|
|
11
|
+
export declare function runExportFinalizedLeavesCli(argv: string[]): Promise<{
|
|
12
|
+
payload: import("./exportFinalizedLeaves").FinalizedLeavesExport;
|
|
13
|
+
outFile: string;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { AnyLeafLowProfile, FinalizedRegistry } from '@emeryld/rrroutes-contract';
|
|
2
|
+
import { type FlatSchemaMap } from './flattenSchema';
|
|
3
|
+
import { type SerializeLeafContractOptions, type SerializedLeafContract } from './serializeLeafContract';
|
|
4
|
+
import { type LeafSourceByKey, type SourceExtractionReason } from './extractLeafSourceByAst';
|
|
5
|
+
export type ExportFinalizedLeavesInput = readonly AnyLeafLowProfile[] | FinalizedRegistry<readonly AnyLeafLowProfile[]>;
|
|
6
|
+
export type ExportFinalizedLeavesMeta = {
|
|
7
|
+
generatedAt: string;
|
|
8
|
+
description: string;
|
|
9
|
+
sourceExtraction?: {
|
|
10
|
+
mode: 'ast';
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
modulePath?: string;
|
|
13
|
+
exportName?: string;
|
|
14
|
+
tsconfigPath?: string;
|
|
15
|
+
resolvedLeafCount: number;
|
|
16
|
+
reason?: SourceExtractionReason;
|
|
17
|
+
stats?: {
|
|
18
|
+
visitedSymbols: number;
|
|
19
|
+
visitedFiles: number;
|
|
20
|
+
unresolvedReferences: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
fieldCatalog: {
|
|
24
|
+
leaf: string[];
|
|
25
|
+
cfg: string[];
|
|
26
|
+
schemaNode: string[];
|
|
27
|
+
flatSchemaEntry: string[];
|
|
28
|
+
};
|
|
29
|
+
flattening: {
|
|
30
|
+
notation: 'dot+[]';
|
|
31
|
+
unionBranchSuffix: '-N';
|
|
32
|
+
sections: readonly ['params', 'query', 'body', 'output'];
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export type FinalizedLeavesExport = {
|
|
36
|
+
_meta: ExportFinalizedLeavesMeta;
|
|
37
|
+
leaves: SerializedLeafContract[];
|
|
38
|
+
schemaFlatByLeaf: Record<string, FlatSchemaMap>;
|
|
39
|
+
sourceByLeaf?: LeafSourceByKey;
|
|
40
|
+
};
|
|
41
|
+
export type ExportFinalizedLeavesOptions = SerializeLeafContractOptions & {
|
|
42
|
+
outFile?: string;
|
|
43
|
+
htmlFile?: string;
|
|
44
|
+
viewerTemplateFile?: string;
|
|
45
|
+
openOnFinish?: boolean;
|
|
46
|
+
includeSource?: boolean;
|
|
47
|
+
tsconfigPath?: string;
|
|
48
|
+
sourceModulePath?: string;
|
|
49
|
+
sourceExportName?: string;
|
|
50
|
+
};
|
|
51
|
+
export type WriteFinalizedLeavesExportOptions = {
|
|
52
|
+
outFile?: string;
|
|
53
|
+
htmlFile?: string;
|
|
54
|
+
viewerTemplateFile?: string;
|
|
55
|
+
openOnFinish?: boolean;
|
|
56
|
+
};
|
|
57
|
+
export declare function writeFinalizedLeavesExport(payload: FinalizedLeavesExport, outFileOrOptions: string | WriteFinalizedLeavesExportOptions): Promise<{
|
|
58
|
+
outFile?: string;
|
|
59
|
+
htmlFile?: string;
|
|
60
|
+
}>;
|
|
61
|
+
export declare function exportFinalizedLeaves(input: ExportFinalizedLeavesInput, options?: ExportFinalizedLeavesOptions): Promise<FinalizedLeavesExport>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
declare const SCHEMA_KEYS: readonly ["bodySchema", "querySchema", "paramsSchema", "outputSchema", "outputMetaSchema", "queryExtensionSchema"];
|
|
2
|
+
export type SourceExtractionReason = 'module_not_in_program' | 'export_not_found' | 'unsupported_expression_shape' | 'resolved_zero_leaves';
|
|
3
|
+
type SchemaKey = (typeof SCHEMA_KEYS)[number];
|
|
4
|
+
export type LeafSourceLocation = {
|
|
5
|
+
file: string;
|
|
6
|
+
line: number;
|
|
7
|
+
column: number;
|
|
8
|
+
};
|
|
9
|
+
export type SchemaSourceMetadata = LeafSourceLocation & {
|
|
10
|
+
sourceName?: string;
|
|
11
|
+
tag?: '<inline>' | '<anonymous>' | '<expression>';
|
|
12
|
+
};
|
|
13
|
+
export type LeafSourceMetadata = {
|
|
14
|
+
definition: LeafSourceLocation & {
|
|
15
|
+
symbolName?: string;
|
|
16
|
+
};
|
|
17
|
+
schemas: Partial<Record<SchemaKey, SchemaSourceMetadata>>;
|
|
18
|
+
};
|
|
19
|
+
export type LeafSourceByKey = Record<string, LeafSourceMetadata>;
|
|
20
|
+
export type ExtractLeafSourceByAstOptions = {
|
|
21
|
+
modulePath: string;
|
|
22
|
+
exportName: string;
|
|
23
|
+
tsconfigPath?: string;
|
|
24
|
+
cwd?: string;
|
|
25
|
+
};
|
|
26
|
+
export type ExtractLeafSourceByAstStats = {
|
|
27
|
+
visitedSymbols: number;
|
|
28
|
+
visitedFiles: number;
|
|
29
|
+
unresolvedReferences: number;
|
|
30
|
+
};
|
|
31
|
+
export type ExtractLeafSourceByAstResult = {
|
|
32
|
+
sourceByLeaf: LeafSourceByKey;
|
|
33
|
+
tsconfigPath?: string;
|
|
34
|
+
reason?: SourceExtractionReason;
|
|
35
|
+
stats: ExtractLeafSourceByAstStats;
|
|
36
|
+
};
|
|
37
|
+
export declare function extractLeafSourceByAst({ modulePath, exportName, tsconfigPath, cwd, }: ExtractLeafSourceByAstOptions): ExtractLeafSourceByAstResult;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AnyLeafLowProfile } from '@emeryld/rrroutes-contract';
|
|
2
|
+
import { type SerializedLeafContract } from './serializeLeafContract';
|
|
3
|
+
import type { SerializableSchema } from './schemaIntrospection';
|
|
4
|
+
export type FlatSchemaEntry = {
|
|
5
|
+
type: string;
|
|
6
|
+
nullable: boolean;
|
|
7
|
+
optional: boolean;
|
|
8
|
+
literal?: unknown;
|
|
9
|
+
};
|
|
10
|
+
export type FlatSchemaMap = Record<string, FlatSchemaEntry>;
|
|
11
|
+
export declare function flattenSerializableSchema(schema: SerializableSchema | undefined, path: string): FlatSchemaMap;
|
|
12
|
+
export declare function flattenLeafSchemas(leaf: AnyLeafLowProfile | SerializedLeafContract): FlatSchemaMap;
|