@doccov/sdk 0.24.0 → 0.24.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.
@@ -3,250 +3,6 @@ import {
3
3
  REPORT_VERSION
4
4
  } from "./chunk-esptwrfq.js";
5
5
 
6
- // src/extract/schema/standard-schema.ts
7
- import { spawn } from "node:child_process";
8
- import * as fs from "node:fs";
9
- import * as path from "node:path";
10
- function isStandardJSONSchema(obj) {
11
- if (typeof obj !== "object" || obj === null)
12
- return false;
13
- const std = obj["~standard"];
14
- if (typeof std !== "object" || std === null)
15
- return false;
16
- const stdObj = std;
17
- if (typeof stdObj.version !== "number")
18
- return false;
19
- if (typeof stdObj.vendor !== "string")
20
- return false;
21
- const jsonSchema = stdObj.jsonSchema;
22
- if (typeof jsonSchema !== "object" || jsonSchema === null)
23
- return false;
24
- const jsObj = jsonSchema;
25
- return typeof jsObj.output === "function";
26
- }
27
- var WORKER_SCRIPT = `
28
- const path = require('path');
29
- const { pathToFileURL } = require('url');
30
-
31
- // TypeBox detection: schemas have Symbol.for('TypeBox.Kind') and are JSON Schema
32
- const TYPEBOX_KIND = Symbol.for('TypeBox.Kind');
33
-
34
- function isTypeBoxSchema(obj) {
35
- if (!obj || typeof obj !== 'object') return false;
36
- // TypeBox schemas always have Kind symbol (Union, Object, String, etc.)
37
- // Also check for common JSON Schema props to avoid false positives
38
- if (!obj[TYPEBOX_KIND]) return false;
39
- return typeof obj.type === 'string' || 'anyOf' in obj || 'oneOf' in obj || 'allOf' in obj;
40
- }
41
-
42
- function sanitizeTypeBoxSchema(schema) {
43
- // JSON.stringify removes symbol keys, keeping only JSON Schema props
44
- return JSON.parse(JSON.stringify(schema));
45
- }
46
-
47
- async function extract() {
48
- // With node -e, argv is: [node, arg1, arg2, ...]
49
- // (the -e script is NOT in argv)
50
- const [modulePath, target] = process.argv.slice(1);
51
-
52
- try {
53
- // Import the module using dynamic import (works with ESM and CJS)
54
- const absPath = path.resolve(modulePath);
55
- const mod = await import(pathToFileURL(absPath).href);
56
- const results = [];
57
-
58
- // Build exports map - handle both ESM and CJS (where exports are in mod.default)
59
- const exports = {};
60
- for (const [name, value] of Object.entries(mod)) {
61
- if (name === 'default' && typeof value === 'object' && value !== null) {
62
- // CJS module: spread default exports
63
- Object.assign(exports, value);
64
- } else if (name !== 'default') {
65
- exports[name] = value;
66
- }
67
- }
68
-
69
- // Check each export
70
- for (const [name, value] of Object.entries(exports)) {
71
- if (name.startsWith('_')) continue;
72
- if (typeof value !== 'object' || value === null) continue;
73
-
74
- // Priority 1: Standard Schema (Zod 4.2+, ArkType, etc.)
75
- const std = value['~standard'];
76
- if (std && typeof std === 'object' && typeof std.version === 'number' && typeof std.vendor === 'string' && std.jsonSchema && typeof std.jsonSchema.output === 'function') {
77
- try {
78
- const outputSchema = std.jsonSchema.output(target);
79
- const inputSchema = std.jsonSchema.input ? std.jsonSchema.input(target) : undefined;
80
- results.push({
81
- exportName: name,
82
- vendor: std.vendor,
83
- outputSchema,
84
- inputSchema
85
- });
86
- } catch (e) {
87
- // Skip schemas that fail to extract
88
- }
89
- continue;
90
- }
91
-
92
- // Priority 2: TypeBox (schema IS JSON Schema)
93
- if (isTypeBoxSchema(value)) {
94
- try {
95
- results.push({
96
- exportName: name,
97
- vendor: 'typebox',
98
- outputSchema: sanitizeTypeBoxSchema(value)
99
- });
100
- } catch (e) {
101
- // Skip schemas that fail to extract
102
- }
103
- continue;
104
- }
105
- }
106
-
107
- console.log(JSON.stringify({ success: true, results }));
108
- } catch (e) {
109
- console.log(JSON.stringify({ success: false, error: e.message }));
110
- }
111
- }
112
-
113
- extract();
114
- `;
115
- function resolveCompiledPath(tsPath, baseDir) {
116
- const relativePath = path.relative(baseDir, tsPath);
117
- const withoutExt = relativePath.replace(/\.tsx?$/, "");
118
- const candidates = [
119
- path.join(baseDir, `${withoutExt}.js`),
120
- path.join(baseDir, "dist", `${withoutExt.replace(/^src\//, "")}.js`),
121
- path.join(baseDir, "build", `${withoutExt.replace(/^src\//, "")}.js`),
122
- path.join(baseDir, "lib", `${withoutExt.replace(/^src\//, "")}.js`)
123
- ];
124
- for (const candidate of candidates) {
125
- if (fs.existsSync(candidate)) {
126
- return candidate;
127
- }
128
- }
129
- return null;
130
- }
131
- async function extractStandardSchemas(compiledJsPath, options = {}) {
132
- const { timeout = 1e4, target = "draft-2020-12" } = options;
133
- const result = {
134
- schemas: new Map,
135
- errors: []
136
- };
137
- if (!fs.existsSync(compiledJsPath)) {
138
- result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
139
- return result;
140
- }
141
- return new Promise((resolve) => {
142
- const child = spawn("node", ["-e", WORKER_SCRIPT, compiledJsPath, target], {
143
- timeout,
144
- stdio: ["ignore", "pipe", "pipe"]
145
- });
146
- let stdout = "";
147
- let stderr = "";
148
- child.stdout.on("data", (data) => {
149
- stdout += data.toString();
150
- });
151
- child.stderr.on("data", (data) => {
152
- stderr += data.toString();
153
- });
154
- child.on("close", (code) => {
155
- if (code !== 0) {
156
- result.errors.push(`Extraction process failed: ${stderr || `exit code ${code}`}`);
157
- resolve(result);
158
- return;
159
- }
160
- try {
161
- const parsed = JSON.parse(stdout);
162
- if (!parsed.success) {
163
- result.errors.push(`Extraction failed: ${parsed.error}`);
164
- resolve(result);
165
- return;
166
- }
167
- for (const item of parsed.results) {
168
- result.schemas.set(item.exportName, {
169
- exportName: item.exportName,
170
- vendor: item.vendor,
171
- outputSchema: item.outputSchema,
172
- inputSchema: item.inputSchema
173
- });
174
- }
175
- } catch (e) {
176
- result.errors.push(`Failed to parse extraction output: ${e}`);
177
- }
178
- resolve(result);
179
- });
180
- child.on("error", (err) => {
181
- result.errors.push(`Subprocess error: ${err.message}`);
182
- resolve(result);
183
- });
184
- });
185
- }
186
- async function extractStandardSchemasFromProject(entryFile, baseDir, options = {}) {
187
- const compiledPath = resolveCompiledPath(entryFile, baseDir);
188
- if (!compiledPath) {
189
- return {
190
- schemas: new Map,
191
- errors: [`Could not find compiled JS for ${entryFile}. Build the project first.`]
192
- };
193
- }
194
- return extractStandardSchemas(compiledPath, options);
195
- }
196
-
197
- // src/analysis/schema-detection.ts
198
- async function detectRuntimeSchemas(context) {
199
- const { baseDir, entryFile } = context;
200
- const compiledPath = resolveCompiledPath(entryFile, baseDir);
201
- if (!compiledPath) {
202
- return {
203
- schemas: new Map,
204
- errors: [],
205
- noCompiledJsWarning: true
206
- };
207
- }
208
- const extraction = await extractStandardSchemasFromProject(entryFile, baseDir);
209
- const schemas = new Map;
210
- for (const [name, result] of extraction.schemas) {
211
- schemas.set(name, {
212
- schema: result.outputSchema,
213
- vendor: result.vendor
214
- });
215
- }
216
- return {
217
- schemas,
218
- errors: extraction.errors
219
- };
220
- }
221
-
222
- // src/analysis/drift/types.ts
223
- var DRIFT_CATEGORIES = {
224
- "param-mismatch": "structural",
225
- "param-type-mismatch": "structural",
226
- "return-type-mismatch": "structural",
227
- "optionality-mismatch": "structural",
228
- "generic-constraint-mismatch": "structural",
229
- "property-type-drift": "structural",
230
- "async-mismatch": "structural",
231
- "deprecated-mismatch": "semantic",
232
- "visibility-mismatch": "semantic",
233
- "broken-link": "semantic",
234
- "example-drift": "example",
235
- "example-syntax-error": "example",
236
- "example-runtime-error": "example",
237
- "example-assertion-failed": "example"
238
- };
239
- var DRIFT_CATEGORY_LABELS = {
240
- structural: "Signature mismatches",
241
- semantic: "Metadata issues",
242
- example: "Example problems"
243
- };
244
- var DRIFT_CATEGORY_DESCRIPTIONS = {
245
- structural: "JSDoc types or parameters don't match the actual code signature",
246
- semantic: "Deprecation, visibility, or reference issues",
247
- example: "@example code has errors or doesn't work correctly"
248
- };
249
-
250
6
  // src/fix/deterministic-fixes.ts
251
7
  var FIXABLE_DRIFT_TYPES = new Set([
252
8
  "param-mismatch",
@@ -671,8 +427,8 @@ function categorizeDrifts(drifts) {
671
427
  }
672
428
 
673
429
  // src/fix/jsdoc-writer.ts
674
- import * as fs2 from "node:fs";
675
- import * as path2 from "node:path";
430
+ import * as fs from "node:fs";
431
+ import * as path from "node:path";
676
432
 
677
433
  // src/ts-module.ts
678
434
  import * as tsNamespace from "typescript";
@@ -1011,7 +767,7 @@ async function applyEdits(edits) {
1011
767
  }
1012
768
  for (const [filePath, fileEdits] of editsByFile) {
1013
769
  try {
1014
- const content = fs2.readFileSync(filePath, "utf-8");
770
+ const content = fs.readFileSync(filePath, "utf-8");
1015
771
  const lines = content.split(`
1016
772
  `);
1017
773
  const sortedEdits = [...fileEdits].sort((a, b) => b.startLine - a.startLine);
@@ -1025,7 +781,7 @@ async function applyEdits(edits) {
1025
781
  }
1026
782
  result.editsApplied++;
1027
783
  }
1028
- fs2.writeFileSync(filePath, lines.join(`
784
+ fs.writeFileSync(filePath, lines.join(`
1029
785
  `));
1030
786
  result.filesModified++;
1031
787
  } catch (error) {
@@ -1038,71 +794,21 @@ async function applyEdits(edits) {
1038
794
  return result;
1039
795
  }
1040
796
  function createSourceFile(filePath) {
1041
- const content = fs2.readFileSync(filePath, "utf-8");
1042
- return ts.createSourceFile(path2.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
797
+ const content = fs.readFileSync(filePath, "utf-8");
798
+ return ts.createSourceFile(path.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
1043
799
  }
1044
- // src/analysis/drift/categorize.ts
1045
- function categorizeDrift(drift) {
1046
- return {
1047
- ...drift,
1048
- category: DRIFT_CATEGORIES[drift.type],
1049
- fixable: isFixableDrift(drift)
1050
- };
1051
- }
1052
- function groupDriftsByCategory(drifts) {
1053
- const grouped = {
1054
- structural: [],
1055
- semantic: [],
1056
- example: []
1057
- };
1058
- for (const drift of drifts) {
1059
- const categorized = categorizeDrift(drift);
1060
- grouped[categorized.category].push(categorized);
1061
- }
1062
- return grouped;
1063
- }
1064
- function getDriftSummary(drifts) {
1065
- const grouped = groupDriftsByCategory(drifts);
1066
- return {
1067
- total: drifts.length,
1068
- byCategory: {
1069
- structural: grouped.structural.length,
1070
- semantic: grouped.semantic.length,
1071
- example: grouped.example.length
1072
- },
1073
- fixable: drifts.filter((d) => isFixableDrift(d)).length
1074
- };
1075
- }
1076
- function formatDriftSummaryLine(summary) {
1077
- if (summary.total === 0) {
1078
- return "No drift detected";
1079
- }
1080
- const parts = [];
1081
- if (summary.byCategory.structural > 0) {
1082
- parts.push(`${summary.byCategory.structural} structural`);
1083
- }
1084
- if (summary.byCategory.semantic > 0) {
1085
- parts.push(`${summary.byCategory.semantic} semantic`);
1086
- }
1087
- if (summary.byCategory.example > 0) {
1088
- parts.push(`${summary.byCategory.example} example`);
1089
- }
1090
- const fixableNote = summary.fixable > 0 ? ` (${summary.fixable} auto-fixable)` : "";
1091
- return `${summary.total} issues (${parts.join(", ")})${fixableNote}`;
1092
- }
1093
-
1094
- // src/analysis/drift/example-drift.ts
1095
- import ts2 from "typescript";
1096
-
1097
- // src/utils/builtin-detection.ts
1098
- function isBuiltInTypeName(name) {
1099
- if (name.length === 1 && /^[A-Z]$/.test(name)) {
1100
- return true;
1101
- }
1102
- if (name.startsWith("__")) {
1103
- return true;
1104
- }
1105
- return BUILTIN_TYPE_NAMES.has(name) || LIBRARY_INTERNAL_PATTERNS.some((re) => re.test(name));
800
+ // src/analysis/drift/example-drift.ts
801
+ import ts2 from "typescript";
802
+
803
+ // src/utils/builtin-detection.ts
804
+ function isBuiltInTypeName(name) {
805
+ if (name.length === 1 && /^[A-Z]$/.test(name)) {
806
+ return true;
807
+ }
808
+ if (name.startsWith("__")) {
809
+ return true;
810
+ }
811
+ return BUILTIN_TYPE_NAMES.has(name) || LIBRARY_INTERNAL_PATTERNS.some((re) => re.test(name));
1106
812
  }
1107
813
  function isBuiltInIdentifier(identifier) {
1108
814
  return BUILTIN_GLOBALS.has(identifier);
@@ -2310,6 +2016,84 @@ function computeExportDrift(entry, registry) {
2310
2016
  ];
2311
2017
  }
2312
2018
 
2019
+ // src/analysis/drift/types.ts
2020
+ var DRIFT_CATEGORIES = {
2021
+ "param-mismatch": "structural",
2022
+ "param-type-mismatch": "structural",
2023
+ "return-type-mismatch": "structural",
2024
+ "optionality-mismatch": "structural",
2025
+ "generic-constraint-mismatch": "structural",
2026
+ "property-type-drift": "structural",
2027
+ "async-mismatch": "structural",
2028
+ "deprecated-mismatch": "semantic",
2029
+ "visibility-mismatch": "semantic",
2030
+ "broken-link": "semantic",
2031
+ "example-drift": "example",
2032
+ "example-syntax-error": "example",
2033
+ "example-runtime-error": "example",
2034
+ "example-assertion-failed": "example"
2035
+ };
2036
+ var DRIFT_CATEGORY_LABELS = {
2037
+ structural: "Signature mismatches",
2038
+ semantic: "Metadata issues",
2039
+ example: "Example problems"
2040
+ };
2041
+ var DRIFT_CATEGORY_DESCRIPTIONS = {
2042
+ structural: "JSDoc types or parameters don't match the actual code signature",
2043
+ semantic: "Deprecation, visibility, or reference issues",
2044
+ example: "@example code has errors or doesn't work correctly"
2045
+ };
2046
+
2047
+ // src/analysis/drift/categorize.ts
2048
+ function categorizeDrift(drift) {
2049
+ return {
2050
+ ...drift,
2051
+ category: DRIFT_CATEGORIES[drift.type],
2052
+ fixable: isFixableDrift(drift)
2053
+ };
2054
+ }
2055
+ function groupDriftsByCategory(drifts) {
2056
+ const grouped = {
2057
+ structural: [],
2058
+ semantic: [],
2059
+ example: []
2060
+ };
2061
+ for (const drift of drifts) {
2062
+ const categorized = categorizeDrift(drift);
2063
+ grouped[categorized.category].push(categorized);
2064
+ }
2065
+ return grouped;
2066
+ }
2067
+ function getDriftSummary(drifts) {
2068
+ const grouped = groupDriftsByCategory(drifts);
2069
+ return {
2070
+ total: drifts.length,
2071
+ byCategory: {
2072
+ structural: grouped.structural.length,
2073
+ semantic: grouped.semantic.length,
2074
+ example: grouped.example.length
2075
+ },
2076
+ fixable: drifts.filter((d) => isFixableDrift(d)).length
2077
+ };
2078
+ }
2079
+ function formatDriftSummaryLine(summary) {
2080
+ if (summary.total === 0) {
2081
+ return "No drift detected";
2082
+ }
2083
+ const parts = [];
2084
+ if (summary.byCategory.structural > 0) {
2085
+ parts.push(`${summary.byCategory.structural} structural`);
2086
+ }
2087
+ if (summary.byCategory.semantic > 0) {
2088
+ parts.push(`${summary.byCategory.semantic} semantic`);
2089
+ }
2090
+ if (summary.byCategory.example > 0) {
2091
+ parts.push(`${summary.byCategory.example} example`);
2092
+ }
2093
+ const fixableNote = summary.fixable > 0 ? ` (${summary.fixable} auto-fixable)` : "";
2094
+ return `${summary.total} issues (${parts.join(", ")})${fixableNote}`;
2095
+ }
2096
+
2313
2097
  // src/analysis/drift/coverage.ts
2314
2098
  function calculateAggregateCoverage(spec) {
2315
2099
  const exports = spec.exports ?? [];
@@ -2416,8 +2200,8 @@ function enrichSpec(spec, options = {}) {
2416
2200
  }
2417
2201
 
2418
2202
  // src/analysis/report.ts
2419
- import * as fs3 from "node:fs";
2420
- import * as path3 from "node:path";
2203
+ import * as fs2 from "node:fs";
2204
+ import * as path2 from "node:path";
2421
2205
  function generateReport(spec) {
2422
2206
  const enriched = enrichSpec(spec);
2423
2207
  return generateReportFromEnriched(enriched);
@@ -2471,23 +2255,23 @@ function generateReportFromEnriched(enriched) {
2471
2255
  }
2472
2256
  function loadCachedReport(reportPath = DEFAULT_REPORT_PATH) {
2473
2257
  try {
2474
- const fullPath = path3.resolve(reportPath);
2475
- if (!fs3.existsSync(fullPath)) {
2258
+ const fullPath = path2.resolve(reportPath);
2259
+ if (!fs2.existsSync(fullPath)) {
2476
2260
  return null;
2477
2261
  }
2478
- const content = fs3.readFileSync(fullPath, "utf-8");
2262
+ const content = fs2.readFileSync(fullPath, "utf-8");
2479
2263
  return JSON.parse(content);
2480
2264
  } catch {
2481
2265
  return null;
2482
2266
  }
2483
2267
  }
2484
2268
  function saveReport(report, reportPath = DEFAULT_REPORT_PATH) {
2485
- const fullPath = path3.resolve(reportPath);
2486
- const dir = path3.dirname(fullPath);
2487
- if (!fs3.existsSync(dir)) {
2488
- fs3.mkdirSync(dir, { recursive: true });
2269
+ const fullPath = path2.resolve(reportPath);
2270
+ const dir = path2.dirname(fullPath);
2271
+ if (!fs2.existsSync(dir)) {
2272
+ fs2.mkdirSync(dir, { recursive: true });
2489
2273
  }
2490
- fs3.writeFileSync(fullPath, JSON.stringify(report, null, 2));
2274
+ fs2.writeFileSync(fullPath, JSON.stringify(report, null, 2));
2491
2275
  }
2492
2276
  function isCachedReportValid(reportPath = DEFAULT_REPORT_PATH, sourceFiles = []) {
2493
2277
  const report = loadCachedReport(reportPath);
@@ -2497,7 +2281,7 @@ function isCachedReportValid(reportPath = DEFAULT_REPORT_PATH, sourceFiles = [])
2497
2281
  const reportTime = new Date(report.generatedAt).getTime();
2498
2282
  for (const file of sourceFiles) {
2499
2283
  try {
2500
- const stat = fs3.statSync(file);
2284
+ const stat = fs2.statSync(file);
2501
2285
  if (stat.mtimeMs > reportTime) {
2502
2286
  return false;
2503
2287
  }
@@ -2684,6 +2468,222 @@ function renderApiSurface(spec) {
2684
2468
  `);
2685
2469
  }
2686
2470
 
2471
+ // src/extract/schema/standard-schema.ts
2472
+ import { spawn } from "node:child_process";
2473
+ import * as fs3 from "node:fs";
2474
+ import * as path3 from "node:path";
2475
+ function isStandardJSONSchema(obj) {
2476
+ if (typeof obj !== "object" || obj === null)
2477
+ return false;
2478
+ const std = obj["~standard"];
2479
+ if (typeof std !== "object" || std === null)
2480
+ return false;
2481
+ const stdObj = std;
2482
+ if (typeof stdObj.version !== "number")
2483
+ return false;
2484
+ if (typeof stdObj.vendor !== "string")
2485
+ return false;
2486
+ const jsonSchema = stdObj.jsonSchema;
2487
+ if (typeof jsonSchema !== "object" || jsonSchema === null)
2488
+ return false;
2489
+ const jsObj = jsonSchema;
2490
+ return typeof jsObj.output === "function";
2491
+ }
2492
+ var WORKER_SCRIPT = `
2493
+ const path = require('path');
2494
+ const { pathToFileURL } = require('url');
2495
+
2496
+ // TypeBox detection: schemas have Symbol.for('TypeBox.Kind') and are JSON Schema
2497
+ const TYPEBOX_KIND = Symbol.for('TypeBox.Kind');
2498
+
2499
+ function isTypeBoxSchema(obj) {
2500
+ if (!obj || typeof obj !== 'object') return false;
2501
+ // TypeBox schemas always have Kind symbol (Union, Object, String, etc.)
2502
+ // Also check for common JSON Schema props to avoid false positives
2503
+ if (!obj[TYPEBOX_KIND]) return false;
2504
+ return typeof obj.type === 'string' || 'anyOf' in obj || 'oneOf' in obj || 'allOf' in obj;
2505
+ }
2506
+
2507
+ function sanitizeTypeBoxSchema(schema) {
2508
+ // JSON.stringify removes symbol keys, keeping only JSON Schema props
2509
+ return JSON.parse(JSON.stringify(schema));
2510
+ }
2511
+
2512
+ async function extract() {
2513
+ // With node -e, argv is: [node, arg1, arg2, ...]
2514
+ // (the -e script is NOT in argv)
2515
+ const [modulePath, target] = process.argv.slice(1);
2516
+
2517
+ try {
2518
+ // Import the module using dynamic import (works with ESM and CJS)
2519
+ const absPath = path.resolve(modulePath);
2520
+ const mod = await import(pathToFileURL(absPath).href);
2521
+ const results = [];
2522
+
2523
+ // Build exports map - handle both ESM and CJS (where exports are in mod.default)
2524
+ const exports = {};
2525
+ for (const [name, value] of Object.entries(mod)) {
2526
+ if (name === 'default' && typeof value === 'object' && value !== null) {
2527
+ // CJS module: spread default exports
2528
+ Object.assign(exports, value);
2529
+ } else if (name !== 'default') {
2530
+ exports[name] = value;
2531
+ }
2532
+ }
2533
+
2534
+ // Check each export
2535
+ for (const [name, value] of Object.entries(exports)) {
2536
+ if (name.startsWith('_')) continue;
2537
+ if (typeof value !== 'object' || value === null) continue;
2538
+
2539
+ // Priority 1: Standard Schema (Zod 4.2+, ArkType, etc.)
2540
+ const std = value['~standard'];
2541
+ if (std && typeof std === 'object' && typeof std.version === 'number' && typeof std.vendor === 'string' && std.jsonSchema && typeof std.jsonSchema.output === 'function') {
2542
+ try {
2543
+ const outputSchema = std.jsonSchema.output(target);
2544
+ const inputSchema = std.jsonSchema.input ? std.jsonSchema.input(target) : undefined;
2545
+ results.push({
2546
+ exportName: name,
2547
+ vendor: std.vendor,
2548
+ outputSchema,
2549
+ inputSchema
2550
+ });
2551
+ } catch (e) {
2552
+ // Skip schemas that fail to extract
2553
+ }
2554
+ continue;
2555
+ }
2556
+
2557
+ // Priority 2: TypeBox (schema IS JSON Schema)
2558
+ if (isTypeBoxSchema(value)) {
2559
+ try {
2560
+ results.push({
2561
+ exportName: name,
2562
+ vendor: 'typebox',
2563
+ outputSchema: sanitizeTypeBoxSchema(value)
2564
+ });
2565
+ } catch (e) {
2566
+ // Skip schemas that fail to extract
2567
+ }
2568
+ continue;
2569
+ }
2570
+ }
2571
+
2572
+ console.log(JSON.stringify({ success: true, results }));
2573
+ } catch (e) {
2574
+ console.log(JSON.stringify({ success: false, error: e.message }));
2575
+ }
2576
+ }
2577
+
2578
+ extract();
2579
+ `;
2580
+ function resolveCompiledPath(tsPath, baseDir) {
2581
+ const relativePath = path3.relative(baseDir, tsPath);
2582
+ const withoutExt = relativePath.replace(/\.tsx?$/, "");
2583
+ const candidates = [
2584
+ path3.join(baseDir, `${withoutExt}.js`),
2585
+ path3.join(baseDir, "dist", `${withoutExt.replace(/^src\//, "")}.js`),
2586
+ path3.join(baseDir, "build", `${withoutExt.replace(/^src\//, "")}.js`),
2587
+ path3.join(baseDir, "lib", `${withoutExt.replace(/^src\//, "")}.js`)
2588
+ ];
2589
+ for (const candidate of candidates) {
2590
+ if (fs3.existsSync(candidate)) {
2591
+ return candidate;
2592
+ }
2593
+ }
2594
+ return null;
2595
+ }
2596
+ async function extractStandardSchemas(compiledJsPath, options = {}) {
2597
+ const { timeout = 1e4, target = "draft-2020-12" } = options;
2598
+ const result = {
2599
+ schemas: new Map,
2600
+ errors: []
2601
+ };
2602
+ if (!fs3.existsSync(compiledJsPath)) {
2603
+ result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
2604
+ return result;
2605
+ }
2606
+ return new Promise((resolve2) => {
2607
+ const child = spawn("node", ["-e", WORKER_SCRIPT, compiledJsPath, target], {
2608
+ timeout,
2609
+ stdio: ["ignore", "pipe", "pipe"]
2610
+ });
2611
+ let stdout = "";
2612
+ let stderr = "";
2613
+ child.stdout.on("data", (data) => {
2614
+ stdout += data.toString();
2615
+ });
2616
+ child.stderr.on("data", (data) => {
2617
+ stderr += data.toString();
2618
+ });
2619
+ child.on("close", (code) => {
2620
+ if (code !== 0) {
2621
+ result.errors.push(`Extraction process failed: ${stderr || `exit code ${code}`}`);
2622
+ resolve2(result);
2623
+ return;
2624
+ }
2625
+ try {
2626
+ const parsed = JSON.parse(stdout);
2627
+ if (!parsed.success) {
2628
+ result.errors.push(`Extraction failed: ${parsed.error}`);
2629
+ resolve2(result);
2630
+ return;
2631
+ }
2632
+ for (const item of parsed.results) {
2633
+ result.schemas.set(item.exportName, {
2634
+ exportName: item.exportName,
2635
+ vendor: item.vendor,
2636
+ outputSchema: item.outputSchema,
2637
+ inputSchema: item.inputSchema
2638
+ });
2639
+ }
2640
+ } catch (e) {
2641
+ result.errors.push(`Failed to parse extraction output: ${e}`);
2642
+ }
2643
+ resolve2(result);
2644
+ });
2645
+ child.on("error", (err) => {
2646
+ result.errors.push(`Subprocess error: ${err.message}`);
2647
+ resolve2(result);
2648
+ });
2649
+ });
2650
+ }
2651
+ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {}) {
2652
+ const compiledPath = resolveCompiledPath(entryFile, baseDir);
2653
+ if (!compiledPath) {
2654
+ return {
2655
+ schemas: new Map,
2656
+ errors: [`Could not find compiled JS for ${entryFile}. Build the project first.`]
2657
+ };
2658
+ }
2659
+ return extractStandardSchemas(compiledPath, options);
2660
+ }
2661
+
2662
+ // src/analysis/schema-detection.ts
2663
+ async function detectRuntimeSchemas(context) {
2664
+ const { baseDir, entryFile } = context;
2665
+ const compiledPath = resolveCompiledPath(entryFile, baseDir);
2666
+ if (!compiledPath) {
2667
+ return {
2668
+ schemas: new Map,
2669
+ errors: [],
2670
+ noCompiledJsWarning: true
2671
+ };
2672
+ }
2673
+ const extraction = await extractStandardSchemasFromProject(entryFile, baseDir);
2674
+ const schemas = new Map;
2675
+ for (const [name, result] of extraction.schemas) {
2676
+ schemas.set(name, {
2677
+ schema: result.outputSchema,
2678
+ vendor: result.vendor
2679
+ });
2680
+ }
2681
+ return {
2682
+ schemas,
2683
+ errors: extraction.errors
2684
+ };
2685
+ }
2686
+
2687
2687
  // src/analysis/history.ts
2688
2688
  import * as fs4 from "node:fs";
2689
2689
  import * as path4 from "node:path";
@@ -2911,4 +2911,4 @@ function getExtendedTrend(spec, cwd, options) {
2911
2911
  };
2912
2912
  }
2913
2913
 
2914
- export { ts, isBuiltInTypeName, isBuiltInIdentifier, isStandardJSONSchema, resolveCompiledPath, extractStandardSchemas, extractStandardSchemasFromProject, detectRuntimeSchemas, DRIFT_CATEGORIES, DRIFT_CATEGORY_LABELS, DRIFT_CATEGORY_DESCRIPTIONS, isFixableDrift, generateFix, generateFixesForExport, mergeFixes, categorizeDrifts, parseJSDocToPatch, applyPatchToJSDoc, serializeJSDoc, findJSDocLocation, applyEdits, createSourceFile, categorizeDrift, groupDriftsByCategory, getDriftSummary, formatDriftSummaryLine, detectExampleRuntimeErrors, parseAssertions, hasNonAssertionComments, detectExampleAssertionFailures, buildExportRegistry, computeDrift, computeExportDrift, calculateAggregateCoverage, ensureSpecCoverage, enrichSpec, generateReport, generateReportFromEnriched, loadCachedReport, saveReport, isCachedReportValid, renderApiSurface, HISTORY_DIR, RETENTION_DAYS, computeSnapshot, saveSnapshot, loadSnapshots, getTrend, renderSparkline, formatDelta, pruneHistory, pruneByTier, loadSnapshotsForDays, generateWeeklySummaries, getExtendedTrend };
2914
+ export { isFixableDrift, generateFix, generateFixesForExport, mergeFixes, categorizeDrifts, ts, parseJSDocToPatch, applyPatchToJSDoc, serializeJSDoc, findJSDocLocation, applyEdits, createSourceFile, isBuiltInTypeName, isBuiltInIdentifier, detectExampleRuntimeErrors, parseAssertions, hasNonAssertionComments, detectExampleAssertionFailures, buildExportRegistry, computeDrift, computeExportDrift, DRIFT_CATEGORIES, DRIFT_CATEGORY_LABELS, DRIFT_CATEGORY_DESCRIPTIONS, categorizeDrift, groupDriftsByCategory, getDriftSummary, formatDriftSummaryLine, calculateAggregateCoverage, ensureSpecCoverage, enrichSpec, generateReport, generateReportFromEnriched, loadCachedReport, saveReport, isCachedReportValid, renderApiSurface, isStandardJSONSchema, resolveCompiledPath, extractStandardSchemas, extractStandardSchemasFromProject, detectRuntimeSchemas, HISTORY_DIR, RETENTION_DAYS, computeSnapshot, saveSnapshot, loadSnapshots, getTrend, renderSparkline, formatDelta, pruneHistory, pruneByTier, loadSnapshotsForDays, generateWeeklySummaries, getExtendedTrend };