@doccov/sdk 0.18.0 → 0.20.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +397 -822
  2. package/dist/index.js +595 -1237
  3. package/package.json +6 -2
package/dist/index.js CHANGED
@@ -4,168 +4,378 @@ var __getProtoOf = Object.getPrototypeOf;
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __toESM = (mod2, isNodeMode, target) => {
8
- target = mod2 != null ? __create(__getProtoOf(mod2)) : {};
9
- const to = isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target;
10
- for (let key of __getOwnPropNames(mod2))
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
11
  if (!__hasOwnProp.call(to, key))
12
12
  __defProp(to, key, {
13
- get: () => mod2[key],
13
+ get: () => mod[key],
14
14
  enumerable: true
15
15
  });
16
16
  return to;
17
17
  };
18
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
- // src/analysis/schema-detection.ts
20
+ // src/extract/schema/standard-schema.ts
21
+ import { spawn } from "node:child_process";
21
22
  import * as fs from "node:fs";
22
-
23
- // src/extraction/standard-schema.ts
24
- function isStandardJSONSchema(value) {
25
- if (typeof value !== "object" || value === null) {
23
+ import * as path from "node:path";
24
+ function isStandardJSONSchema(obj) {
25
+ if (typeof obj !== "object" || obj === null)
26
26
  return false;
27
- }
28
- const obj = value;
29
- const standard = obj["~standard"];
30
- if (typeof standard !== "object" || standard === null) {
27
+ const std = obj["~standard"];
28
+ if (typeof std !== "object" || std === null)
31
29
  return false;
32
- }
33
- const stdObj = standard;
34
- if (typeof stdObj.version !== "number") {
30
+ const stdObj = std;
31
+ if (typeof stdObj.version !== "number")
32
+ return false;
33
+ if (typeof stdObj.vendor !== "string")
35
34
  return false;
36
- }
37
35
  const jsonSchema = stdObj.jsonSchema;
38
- if (typeof jsonSchema !== "object" || jsonSchema === null) {
36
+ if (typeof jsonSchema !== "object" || jsonSchema === null)
39
37
  return false;
38
+ const jsObj = jsonSchema;
39
+ return typeof jsObj.output === "function";
40
+ }
41
+ var WORKER_SCRIPT = `
42
+ const path = require('path');
43
+ const { pathToFileURL } = require('url');
44
+
45
+ async function extract() {
46
+ // With node -e, argv is: [node, arg1, arg2, ...]
47
+ // (the -e script is NOT in argv)
48
+ const [modulePath, target] = process.argv.slice(1);
49
+
50
+ try {
51
+ // Import the module using dynamic import (works with ESM and CJS)
52
+ const absPath = path.resolve(modulePath);
53
+ const mod = await import(pathToFileURL(absPath).href);
54
+ const results = [];
55
+
56
+ // Check each export
57
+ for (const [name, value] of Object.entries(mod)) {
58
+ if (name.startsWith('_')) continue;
59
+ if (typeof value !== 'object' || value === null) continue;
60
+
61
+ const std = value['~standard'];
62
+ if (!std || typeof std !== 'object') continue;
63
+ if (typeof std.version !== 'number') continue;
64
+ if (typeof std.vendor !== 'string') continue;
65
+ if (!std.jsonSchema || typeof std.jsonSchema.output !== 'function') continue;
66
+
67
+ try {
68
+ const outputSchema = std.jsonSchema.output(target);
69
+ const inputSchema = std.jsonSchema.input ? std.jsonSchema.input(target) : undefined;
70
+
71
+ results.push({
72
+ exportName: name,
73
+ vendor: std.vendor,
74
+ outputSchema,
75
+ inputSchema
76
+ });
77
+ } catch (e) {
78
+ // Skip schemas that fail to extract
79
+ }
80
+ }
81
+
82
+ console.log(JSON.stringify({ success: true, results }));
83
+ } catch (e) {
84
+ console.log(JSON.stringify({ success: false, error: e.message }));
85
+ }
86
+ }
87
+
88
+ extract();
89
+ `;
90
+ function resolveCompiledPath(tsPath, baseDir) {
91
+ const relativePath = path.relative(baseDir, tsPath);
92
+ const withoutExt = relativePath.replace(/\.tsx?$/, "");
93
+ const candidates = [
94
+ path.join(baseDir, `${withoutExt}.js`),
95
+ path.join(baseDir, "dist", `${withoutExt.replace(/^src\//, "")}.js`),
96
+ path.join(baseDir, "build", `${withoutExt.replace(/^src\//, "")}.js`),
97
+ path.join(baseDir, "lib", `${withoutExt.replace(/^src\//, "")}.js`)
98
+ ];
99
+ for (const candidate of candidates) {
100
+ if (fs.existsSync(candidate)) {
101
+ return candidate;
102
+ }
103
+ }
104
+ return null;
105
+ }
106
+ async function extractStandardSchemas(compiledJsPath, options = {}) {
107
+ const { timeout = 1e4, target = "draft-2020-12" } = options;
108
+ const result = {
109
+ schemas: new Map,
110
+ errors: []
111
+ };
112
+ if (!fs.existsSync(compiledJsPath)) {
113
+ result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
114
+ return result;
40
115
  }
41
- const jsonSchemaObj = jsonSchema;
42
- return typeof jsonSchemaObj.output === "function";
116
+ return new Promise((resolve) => {
117
+ const child = spawn("node", ["-e", WORKER_SCRIPT, compiledJsPath, target], {
118
+ timeout,
119
+ stdio: ["ignore", "pipe", "pipe"]
120
+ });
121
+ let stdout = "";
122
+ let stderr = "";
123
+ child.stdout.on("data", (data) => {
124
+ stdout += data.toString();
125
+ });
126
+ child.stderr.on("data", (data) => {
127
+ stderr += data.toString();
128
+ });
129
+ child.on("close", (code) => {
130
+ if (code !== 0) {
131
+ result.errors.push(`Extraction process failed: ${stderr || `exit code ${code}`}`);
132
+ resolve(result);
133
+ return;
134
+ }
135
+ try {
136
+ const parsed = JSON.parse(stdout);
137
+ if (!parsed.success) {
138
+ result.errors.push(`Extraction failed: ${parsed.error}`);
139
+ resolve(result);
140
+ return;
141
+ }
142
+ for (const item of parsed.results) {
143
+ result.schemas.set(item.exportName, {
144
+ exportName: item.exportName,
145
+ vendor: item.vendor,
146
+ outputSchema: item.outputSchema,
147
+ inputSchema: item.inputSchema
148
+ });
149
+ }
150
+ } catch (e) {
151
+ result.errors.push(`Failed to parse extraction output: ${e}`);
152
+ }
153
+ resolve(result);
154
+ });
155
+ child.on("error", (err) => {
156
+ result.errors.push(`Subprocess error: ${err.message}`);
157
+ resolve(result);
158
+ });
159
+ });
43
160
  }
44
- function extractViaStandardSchema(schema, options = {}) {
45
- const standard = schema["~standard"];
46
- const target = options.target ?? "draft-2020-12";
47
- const extractedSchema = standard.jsonSchema.output({ target });
161
+ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {}) {
162
+ const compiledPath = resolveCompiledPath(entryFile, baseDir);
163
+ if (!compiledPath) {
164
+ return {
165
+ schemas: new Map,
166
+ errors: [`Could not find compiled JS for ${entryFile}. Build the project first.`]
167
+ };
168
+ }
169
+ return extractStandardSchemas(compiledPath, options);
170
+ }
171
+
172
+ // src/analysis/schema-detection.ts
173
+ async function detectRuntimeSchemas(context) {
174
+ const { baseDir, entryFile } = context;
175
+ const compiledPath = resolveCompiledPath(entryFile, baseDir);
176
+ if (!compiledPath) {
177
+ return {
178
+ schemas: new Map,
179
+ errors: []
180
+ };
181
+ }
182
+ const extraction = await extractStandardSchemasFromProject(entryFile, baseDir);
183
+ const schemas = new Map;
184
+ for (const [name, result] of extraction.schemas) {
185
+ schemas.set(name, {
186
+ schema: result.outputSchema,
187
+ vendor: result.vendor
188
+ });
189
+ }
48
190
  return {
49
- schema: extractedSchema,
50
- vendor: standard.vendor,
51
- version: standard.version
191
+ schemas,
192
+ errors: extraction.errors
52
193
  };
53
194
  }
54
- function tryExtractStandardSchema(value, options = {}) {
55
- if (!isStandardJSONSchema(value)) {
56
- return null;
195
+ function clearSchemaCache() {}
196
+ // src/extract/schema/types.ts
197
+ function isTypeReference(type) {
198
+ return !!(type.flags & 524288 && type.objectFlags && type.objectFlags & 4);
199
+ }
200
+ function getNonNullableType(type) {
201
+ if (type.isUnion()) {
202
+ const nonNullable = type.types.filter((t) => !(t.flags & 32768) && !(t.flags & 65536));
203
+ if (nonNullable.length === 1) {
204
+ return nonNullable[0];
205
+ }
57
206
  }
58
- try {
59
- return extractViaStandardSchema(value, options);
60
- } catch {
207
+ return type;
208
+ }
209
+ // src/extract/schema/adapters/zod.ts
210
+ var ZOD_TYPE_PATTERN = /^Zod[A-Z]/;
211
+ var zodAdapter = {
212
+ id: "zod",
213
+ packages: ["zod"],
214
+ matches(type, checker) {
215
+ const typeName = checker.typeToString(type);
216
+ return ZOD_TYPE_PATTERN.test(typeName);
217
+ },
218
+ extractOutputType(type, checker) {
219
+ const outputSymbol = type.getProperty("_output");
220
+ if (outputSymbol) {
221
+ return checker.getTypeOfSymbol(outputSymbol);
222
+ }
223
+ const typeSymbol = type.getProperty("_type");
224
+ if (typeSymbol) {
225
+ return checker.getTypeOfSymbol(typeSymbol);
226
+ }
227
+ return null;
228
+ },
229
+ extractInputType(type, checker) {
230
+ const inputSymbol = type.getProperty("_input");
231
+ if (inputSymbol) {
232
+ return checker.getTypeOfSymbol(inputSymbol);
233
+ }
61
234
  return null;
62
235
  }
63
- }
64
- var KNOWN_VENDORS = {
65
- zod: { minVersion: "4.2.0", homepage: "https://zod.dev" },
66
- arktype: { minVersion: "2.0.0", homepage: "https://arktype.io" },
67
- valibot: { minVersion: "1.0.0", homepage: "https://valibot.dev" }
68
236
  };
69
- // src/analysis/schema-detection.ts
70
- var moduleCache = new Map;
71
- function getFileMtime(filePath) {
72
- try {
73
- return fs.statSync(filePath).mtimeMs;
74
- } catch {
75
- return 0;
237
+
238
+ // src/extract/schema/adapters/valibot.ts
239
+ var VALIBOT_TYPE_PATTERN = /Schema(<|$)/;
240
+ var valibotAdapter = {
241
+ id: "valibot",
242
+ packages: ["valibot"],
243
+ matches(type, checker) {
244
+ const typeName = checker.typeToString(type);
245
+ return VALIBOT_TYPE_PATTERN.test(typeName) && !typeName.includes("Zod");
246
+ },
247
+ extractOutputType(type, checker) {
248
+ const typesSymbol = type.getProperty("~types");
249
+ if (!typesSymbol) {
250
+ return null;
251
+ }
252
+ let typesType = checker.getTypeOfSymbol(typesSymbol);
253
+ typesType = getNonNullableType(typesType);
254
+ const outputSymbol = typesType.getProperty("output");
255
+ if (!outputSymbol) {
256
+ return null;
257
+ }
258
+ return checker.getTypeOfSymbol(outputSymbol);
259
+ },
260
+ extractInputType(type, checker) {
261
+ const typesSymbol = type.getProperty("~types");
262
+ if (!typesSymbol) {
263
+ return null;
264
+ }
265
+ let typesType = checker.getTypeOfSymbol(typesSymbol);
266
+ typesType = getNonNullableType(typesType);
267
+ const inputSymbol = typesType.getProperty("input");
268
+ if (!inputSymbol) {
269
+ return null;
270
+ }
271
+ return checker.getTypeOfSymbol(inputSymbol);
76
272
  }
77
- }
78
- async function loadModule(modulePath) {
79
- const currentMtime = getFileMtime(modulePath);
80
- const cached = moduleCache.get(modulePath);
81
- if (cached && cached.mtime === currentMtime && currentMtime > 0) {
82
- return cached.module;
273
+ };
274
+
275
+ // src/extract/schema/adapters/typebox.ts
276
+ var TYPEBOX_TYPE_PATTERN = /^T[A-Z]/;
277
+ var typeboxAdapter = {
278
+ id: "typebox",
279
+ packages: ["@sinclair/typebox"],
280
+ matches(type, checker) {
281
+ const typeName = checker.typeToString(type);
282
+ if (!TYPEBOX_TYPE_PATTERN.test(typeName)) {
283
+ return false;
284
+ }
285
+ const typeProperty = type.getProperty("type");
286
+ return typeProperty !== undefined;
287
+ },
288
+ extractOutputType(type, checker) {
289
+ const staticSymbol = type.getProperty("static");
290
+ if (staticSymbol) {
291
+ return checker.getTypeOfSymbol(staticSymbol);
292
+ }
293
+ return null;
83
294
  }
84
- try {
85
- const requireCache = eval("require").cache;
86
- if (requireCache && requireCache[modulePath]) {
87
- delete requireCache[modulePath];
295
+ };
296
+
297
+ // src/extract/schema/adapters/arktype.ts
298
+ var ARKTYPE_TYPE_PATTERN = /^Type</;
299
+ var arktypeAdapter = {
300
+ id: "arktype",
301
+ packages: ["arktype"],
302
+ matches(type, checker) {
303
+ const typeName = checker.typeToString(type);
304
+ return ARKTYPE_TYPE_PATTERN.test(typeName);
305
+ },
306
+ extractOutputType(type, checker) {
307
+ if (!isTypeReference(type)) {
308
+ return null;
88
309
  }
89
- } catch {}
90
- let mod;
91
- try {
92
- mod = eval("require")(modulePath);
93
- } catch (err) {
94
- const nodeErr = err;
95
- if (nodeErr.code === "ERR_REQUIRE_ESM") {
96
- const cacheBuster = currentMtime > 0 ? `?t=${currentMtime}` : "";
97
- mod = await import(`${modulePath}${cacheBuster}`);
98
- } else {
99
- throw err;
310
+ const args = checker.getTypeArguments(type);
311
+ if (args.length < 1) {
312
+ return null;
100
313
  }
314
+ return args[0];
315
+ },
316
+ extractInputType(type, checker) {
317
+ if (!isTypeReference(type)) {
318
+ return null;
319
+ }
320
+ const args = checker.getTypeArguments(type);
321
+ if (args.length < 2) {
322
+ return null;
323
+ }
324
+ return args[1];
325
+ }
326
+ };
327
+
328
+ // src/extract/schema/registry.ts
329
+ var adapters = [
330
+ zodAdapter,
331
+ arktypeAdapter,
332
+ typeboxAdapter,
333
+ valibotAdapter
334
+ ];
335
+ function findAdapter(type, checker) {
336
+ for (const adapter of adapters) {
337
+ if (adapter.matches(type, checker)) {
338
+ return adapter;
339
+ }
340
+ }
341
+ return null;
342
+ }
343
+ function isSchemaType(type, checker) {
344
+ return findAdapter(type, checker) !== null;
345
+ }
346
+ function extractSchemaOutputType(type, checker) {
347
+ const adapter = findAdapter(type, checker);
348
+ if (!adapter) {
349
+ return null;
101
350
  }
102
- moduleCache.set(modulePath, { module: mod, mtime: currentMtime });
103
- return mod;
351
+ return adapter.extractOutputType(type, checker);
104
352
  }
105
- async function detectRuntimeSchemas(context) {
353
+ function extractSchemaType(type, checker) {
354
+ const adapter = findAdapter(type, checker);
355
+ if (!adapter) {
356
+ return null;
357
+ }
358
+ const outputType = adapter.extractOutputType(type, checker);
359
+ if (!outputType) {
360
+ return null;
361
+ }
106
362
  const result = {
107
- schemas: new Map,
108
- errors: []
363
+ adapter,
364
+ outputType
109
365
  };
110
- try {
111
- const modulePath2 = resolveModulePath(context.entryFile, context.baseDir);
112
- if (!modulePath2) {
113
- result.errors.push("Could not resolve compiled module path");
114
- return result;
115
- }
116
- const mod2 = await loadModule(modulePath2);
117
- if (!mod2 || typeof mod2 !== "object") {
118
- result.errors.push("Module did not export an object");
119
- return result;
120
- }
121
- const exports = mod2;
122
- for (const [name, value] of Object.entries(exports)) {
123
- if (name.startsWith("_") || name === "default") {
124
- continue;
125
- }
126
- const schemaResult = tryExtractStandardSchema(value);
127
- if (schemaResult) {
128
- result.schemas.set(name, schemaResult);
129
- }
366
+ if (adapter.extractInputType) {
367
+ const inputType = adapter.extractInputType(type, checker);
368
+ if (inputType) {
369
+ result.inputType = inputType;
130
370
  }
131
- if ("default" in exports && exports.default && typeof exports.default === "object") {
132
- const defaultExports = exports.default;
133
- for (const [name, value] of Object.entries(defaultExports)) {
134
- if (name.startsWith("_"))
135
- continue;
136
- const schemaResult = tryExtractStandardSchema(value);
137
- if (schemaResult && !result.schemas.has(name)) {
138
- result.schemas.set(name, schemaResult);
139
- }
140
- }
141
- }
142
- } catch (err) {
143
- result.errors.push(`Runtime detection failed: ${err instanceof Error ? err.message : String(err)}`);
144
371
  }
145
372
  return result;
146
373
  }
147
- function resolveModulePath(entryFile, baseDir) {
148
- if (entryFile.endsWith(".js") || entryFile.endsWith(".mjs") || entryFile.endsWith(".cjs")) {
149
- return entryFile;
150
- }
151
- const tsFile = entryFile;
152
- const possiblePaths = [
153
- tsFile.replace(/\.tsx?$/, ".js"),
154
- tsFile.replace(/\.tsx?$/, ".mjs"),
155
- tsFile.replace(/\/src\//, "/dist/").replace(/\.tsx?$/, ".js"),
156
- tsFile.replace(/\/src\//, "/build/").replace(/\.tsx?$/, ".js"),
157
- tsFile.replace(/\/src\//, "/lib/").replace(/\.tsx?$/, ".js")
158
- ];
159
- for (const testPath of possiblePaths) {
160
- try {
161
- __require.resolve(testPath, { paths: [baseDir] });
162
- return testPath;
163
- } catch {}
164
- }
165
- return null;
374
+ function getRegisteredAdapters() {
375
+ return adapters;
166
376
  }
167
- function clearSchemaCache() {
168
- moduleCache.clear();
377
+ function getSupportedLibraries() {
378
+ return adapters.flatMap((a) => a.packages);
169
379
  }
170
380
  // src/analysis/docs-coverage.ts
171
381
  import {
@@ -597,7 +807,7 @@ function categorizeDrifts(drifts) {
597
807
  }
598
808
  // src/fix/jsdoc-writer.ts
599
809
  import * as fs2 from "node:fs";
600
- import * as path from "node:path";
810
+ import * as path2 from "node:path";
601
811
 
602
812
  // src/ts-module.ts
603
813
  import * as tsNamespace from "typescript";
@@ -964,7 +1174,7 @@ async function applyEdits(edits) {
964
1174
  }
965
1175
  function createSourceFile(filePath) {
966
1176
  const content = fs2.readFileSync(filePath, "utf-8");
967
- return ts.createSourceFile(path.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
1177
+ return ts.createSourceFile(path2.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
968
1178
  }
969
1179
  // src/utils/builtin-detection.ts
970
1180
  function isBuiltInTypeName(name) {
@@ -2162,480 +2372,6 @@ function ensureSpecCoverage(spec) {
2162
2372
  }
2163
2373
  };
2164
2374
  }
2165
- // src/quality/rules.ts
2166
- var BUILTIN_TYPES = new Set([
2167
- "string",
2168
- "number",
2169
- "boolean",
2170
- "object",
2171
- "any",
2172
- "unknown",
2173
- "void",
2174
- "never",
2175
- "null",
2176
- "undefined",
2177
- "symbol",
2178
- "bigint",
2179
- "Array",
2180
- "Promise",
2181
- "Map",
2182
- "Set",
2183
- "Record",
2184
- "Partial",
2185
- "Required",
2186
- "Readonly",
2187
- "Pick",
2188
- "Omit",
2189
- "Exclude",
2190
- "Extract",
2191
- "NonNullable",
2192
- "ReturnType",
2193
- "Parameters",
2194
- "InstanceType",
2195
- "ConstructorParameters",
2196
- "Awaited"
2197
- ]);
2198
- function extractTypeReferences(exp) {
2199
- const refs = new Set;
2200
- function collectFromSchema(schema) {
2201
- if (!schema)
2202
- return;
2203
- if (typeof schema === "string") {
2204
- if (!BUILTIN_TYPES.has(schema)) {
2205
- refs.add(schema);
2206
- }
2207
- return;
2208
- }
2209
- if (typeof schema === "object") {
2210
- const obj = schema;
2211
- if (typeof obj.$ref === "string") {
2212
- const ref = obj.$ref;
2213
- const name = ref.startsWith("#/types/") ? ref.slice("#/types/".length) : ref;
2214
- if (!BUILTIN_TYPES.has(name)) {
2215
- refs.add(name);
2216
- }
2217
- }
2218
- if (typeof obj.type === "string" && !BUILTIN_TYPES.has(obj.type)) {
2219
- refs.add(obj.type);
2220
- }
2221
- if (obj.items) {
2222
- collectFromSchema(obj.items);
2223
- }
2224
- if (obj.properties && typeof obj.properties === "object") {
2225
- for (const prop of Object.values(obj.properties)) {
2226
- collectFromSchema(prop);
2227
- }
2228
- }
2229
- if (Array.isArray(obj.anyOf)) {
2230
- for (const item of obj.anyOf) {
2231
- collectFromSchema(item);
2232
- }
2233
- }
2234
- if (Array.isArray(obj.oneOf)) {
2235
- for (const item of obj.oneOf) {
2236
- collectFromSchema(item);
2237
- }
2238
- }
2239
- if (Array.isArray(obj.allOf)) {
2240
- for (const item of obj.allOf) {
2241
- collectFromSchema(item);
2242
- }
2243
- }
2244
- if (obj.additionalProperties && typeof obj.additionalProperties === "object") {
2245
- collectFromSchema(obj.additionalProperties);
2246
- }
2247
- }
2248
- }
2249
- for (const sig of exp.signatures ?? []) {
2250
- for (const param of sig.parameters ?? []) {
2251
- collectFromSchema(param.schema);
2252
- }
2253
- if (sig.returns?.schema) {
2254
- collectFromSchema(sig.returns.schema);
2255
- }
2256
- }
2257
- for (const member of exp.members ?? []) {
2258
- collectFromSchema(member.schema);
2259
- for (const sig of member.signatures ?? []) {
2260
- for (const param of sig.parameters ?? []) {
2261
- collectFromSchema(param.schema);
2262
- }
2263
- if (sig.returns?.schema) {
2264
- collectFromSchema(sig.returns.schema);
2265
- }
2266
- }
2267
- }
2268
- collectFromSchema(exp.schema);
2269
- if (typeof exp.type === "string" && !BUILTIN_TYPES.has(exp.type)) {
2270
- refs.add(exp.type);
2271
- }
2272
- if (exp.extends && !BUILTIN_TYPES.has(exp.extends)) {
2273
- refs.add(exp.extends);
2274
- }
2275
- for (const impl of exp.implements ?? []) {
2276
- if (!BUILTIN_TYPES.has(impl)) {
2277
- refs.add(impl);
2278
- }
2279
- }
2280
- return refs;
2281
- }
2282
- var CORE_RULES = [
2283
- {
2284
- id: "has-description",
2285
- name: "Has Description",
2286
- description: "Export has a description comment",
2287
- affectsCoverage: true,
2288
- defaultSeverity: "warn",
2289
- check(ctx) {
2290
- return Boolean(ctx.export.description?.trim());
2291
- },
2292
- getViolation(ctx) {
2293
- return {
2294
- ruleId: "has-description",
2295
- severity: "warn",
2296
- message: `Export '${ctx.export.name}' is missing a description`,
2297
- fixable: false
2298
- };
2299
- }
2300
- },
2301
- {
2302
- id: "has-params",
2303
- name: "Has Parameters",
2304
- description: "All parameters are documented",
2305
- appliesTo: ["function"],
2306
- affectsCoverage: true,
2307
- defaultSeverity: "off",
2308
- check(ctx) {
2309
- const parameters = (ctx.export.signatures ?? []).flatMap((sig) => sig.parameters ?? []);
2310
- if (parameters.length === 0)
2311
- return true;
2312
- return parameters.every((p) => Boolean(p.description?.trim()));
2313
- },
2314
- getViolation(ctx) {
2315
- return {
2316
- ruleId: "has-params",
2317
- severity: "warn",
2318
- message: `Function '${ctx.export.name}' has undocumented parameters`,
2319
- fixable: true
2320
- };
2321
- }
2322
- },
2323
- {
2324
- id: "has-returns",
2325
- name: "Has Returns",
2326
- description: "Return value is documented",
2327
- appliesTo: ["function"],
2328
- affectsCoverage: true,
2329
- defaultSeverity: "off",
2330
- check(ctx) {
2331
- const signatures = ctx.export.signatures ?? [];
2332
- if (signatures.length === 0)
2333
- return true;
2334
- return signatures.every((sig) => {
2335
- const text = sig.returns?.description;
2336
- return Boolean(text?.trim());
2337
- });
2338
- },
2339
- getViolation(ctx) {
2340
- return {
2341
- ruleId: "has-returns",
2342
- severity: "warn",
2343
- message: `Function '${ctx.export.name}' has undocumented return value`,
2344
- fixable: true
2345
- };
2346
- }
2347
- },
2348
- {
2349
- id: "has-examples",
2350
- name: "Has Examples",
2351
- description: "Export has at least one @example",
2352
- appliesTo: ["function", "class"],
2353
- affectsCoverage: true,
2354
- defaultSeverity: "off",
2355
- check(ctx) {
2356
- return Boolean(ctx.export.examples?.length);
2357
- },
2358
- getViolation(ctx) {
2359
- return {
2360
- ruleId: "has-examples",
2361
- severity: "warn",
2362
- message: `Export '${ctx.export.name}' is missing an @example`,
2363
- fixable: false
2364
- };
2365
- }
2366
- }
2367
- ];
2368
- var TSDOC_RULES = [
2369
- {
2370
- id: "require-release-tag",
2371
- name: "Require Release Tag",
2372
- description: "All exports must have @public, @beta, @alpha, or @internal",
2373
- affectsCoverage: false,
2374
- defaultSeverity: "off",
2375
- check(ctx) {
2376
- const tags = ctx.export.tags ?? [];
2377
- return tags.some((t) => ["public", "beta", "alpha", "internal"].includes(t.name.toLowerCase()));
2378
- },
2379
- getViolation(ctx) {
2380
- return {
2381
- ruleId: "require-release-tag",
2382
- severity: "warn",
2383
- message: `Export '${ctx.export.name}' is missing a release tag (@public, @beta, @alpha, or @internal)`,
2384
- fixable: true
2385
- };
2386
- }
2387
- },
2388
- {
2389
- id: "internal-underscore",
2390
- name: "Internal Underscore Prefix",
2391
- description: "@internal exports should have underscore prefix",
2392
- affectsCoverage: false,
2393
- defaultSeverity: "off",
2394
- check(ctx) {
2395
- const tags = ctx.export.tags ?? [];
2396
- const isInternal = tags.some((t) => t.name.toLowerCase() === "internal");
2397
- if (!isInternal)
2398
- return true;
2399
- return ctx.export.name.startsWith("_");
2400
- },
2401
- getViolation(ctx) {
2402
- return {
2403
- ruleId: "internal-underscore",
2404
- severity: "warn",
2405
- message: `Internal export '${ctx.export.name}' should have underscore prefix (_${ctx.export.name})`,
2406
- fixable: false
2407
- };
2408
- }
2409
- },
2410
- {
2411
- id: "no-conflicting-tags",
2412
- name: "No Conflicting Tags",
2413
- description: "Cannot have both @internal and @public/@beta/@alpha",
2414
- affectsCoverage: false,
2415
- defaultSeverity: "warn",
2416
- check(ctx) {
2417
- const tags = ctx.export.tags ?? [];
2418
- const tagNames = tags.map((t) => t.name.toLowerCase());
2419
- const hasInternal = tagNames.includes("internal");
2420
- const hasPublicish = tagNames.some((n) => ["public", "beta", "alpha"].includes(n));
2421
- return !(hasInternal && hasPublicish);
2422
- },
2423
- getViolation(ctx) {
2424
- return {
2425
- ruleId: "no-conflicting-tags",
2426
- severity: "error",
2427
- message: `Export '${ctx.export.name}' has conflicting release tags (@internal with @public/@beta/@alpha)`,
2428
- fixable: false
2429
- };
2430
- }
2431
- },
2432
- {
2433
- id: "no-forgotten-export",
2434
- name: "No Forgotten Export",
2435
- description: "All referenced types must be exported",
2436
- affectsCoverage: false,
2437
- defaultSeverity: "off",
2438
- check(ctx) {
2439
- if (!ctx.exportRegistry)
2440
- return true;
2441
- const refs = extractTypeReferences(ctx.export);
2442
- for (const ref of refs) {
2443
- if (!ctx.exportRegistry.has(ref)) {
2444
- return false;
2445
- }
2446
- }
2447
- return true;
2448
- },
2449
- getViolation(ctx) {
2450
- const refs = extractTypeReferences(ctx.export);
2451
- const missing = ctx.exportRegistry ? [...refs].filter((r) => !ctx.exportRegistry.has(r)) : [];
2452
- return {
2453
- ruleId: "no-forgotten-export",
2454
- severity: "warn",
2455
- message: missing.length > 0 ? `Export '${ctx.export.name}' references unexported types: ${missing.join(", ")}` : `Export '${ctx.export.name}' references types that are not exported`,
2456
- fixable: false
2457
- };
2458
- }
2459
- }
2460
- ];
2461
- var STYLE_RULES = [
2462
- {
2463
- id: "no-empty-returns",
2464
- name: "No Empty Returns",
2465
- description: "@returns tag must have a description",
2466
- appliesTo: ["function"],
2467
- affectsCoverage: false,
2468
- defaultSeverity: "warn",
2469
- check(ctx) {
2470
- if (!ctx.rawJSDoc)
2471
- return true;
2472
- const returnsMatch = ctx.rawJSDoc.match(/@returns?\s*(?:\{[^}]*\})?\s*$/m);
2473
- if (returnsMatch)
2474
- return false;
2475
- const returnsTypeOnly = ctx.rawJSDoc.match(/@returns?\s+\{[^}]+\}\s*$/m);
2476
- if (returnsTypeOnly)
2477
- return false;
2478
- return true;
2479
- },
2480
- getViolation(ctx) {
2481
- return {
2482
- ruleId: "no-empty-returns",
2483
- severity: "warn",
2484
- message: `Export '${ctx.export.name}' has @returns without a description`,
2485
- fixable: false
2486
- };
2487
- }
2488
- },
2489
- {
2490
- id: "consistent-param-style",
2491
- name: "Consistent Param Style",
2492
- description: "@param tags use dash separator",
2493
- appliesTo: ["function"],
2494
- affectsCoverage: false,
2495
- defaultSeverity: "off",
2496
- check(ctx) {
2497
- if (!ctx.rawJSDoc)
2498
- return true;
2499
- const paramRegex = /@param\s+(?:\{[^}]+\}\s+)?(\S+)\s+([^@\n]+)/g;
2500
- const matches = ctx.rawJSDoc.matchAll(paramRegex);
2501
- for (const match of matches) {
2502
- const rest = match[2]?.trim();
2503
- if (rest && !rest.startsWith("-") && !rest.startsWith("–")) {
2504
- return false;
2505
- }
2506
- }
2507
- return true;
2508
- },
2509
- getViolation(ctx) {
2510
- return {
2511
- ruleId: "consistent-param-style",
2512
- severity: "warn",
2513
- message: `Export '${ctx.export.name}' has @param without dash separator`,
2514
- fixable: true
2515
- };
2516
- },
2517
- fix(ctx) {
2518
- if (!ctx.rawJSDoc)
2519
- return null;
2520
- const patch = parseJSDocToPatch(ctx.rawJSDoc);
2521
- if (!patch.params || patch.params.length === 0)
2522
- return null;
2523
- return patch;
2524
- }
2525
- }
2526
- ];
2527
- var BUILTIN_RULES = [...CORE_RULES, ...TSDOC_RULES, ...STYLE_RULES];
2528
- function getCoverageRules() {
2529
- return BUILTIN_RULES.filter((r) => r.affectsCoverage);
2530
- }
2531
- function getRulesForKind(kind) {
2532
- return BUILTIN_RULES.filter((r) => {
2533
- if (!r.appliesTo)
2534
- return true;
2535
- return r.appliesTo.includes(kind);
2536
- });
2537
- }
2538
- function getRule(id) {
2539
- return BUILTIN_RULES.find((r) => r.id === id);
2540
- }
2541
- function getDefaultConfig() {
2542
- const config = {};
2543
- for (const rule of BUILTIN_RULES) {
2544
- config[rule.id] = rule.defaultSeverity;
2545
- }
2546
- return config;
2547
- }
2548
-
2549
- // src/quality/engine.ts
2550
- function evaluateExportQuality(exp, rawJSDoc, config = { rules: {} }, exportRegistry) {
2551
- const kind = exp.kind ?? "variable";
2552
- const applicableRules = getRulesForKind(kind);
2553
- const defaults = getDefaultConfig();
2554
- const getSeverity = (ruleId, defaultSev) => config.rules[ruleId] ?? defaults[ruleId] ?? defaultSev;
2555
- const activeCoverageRules = applicableRules.filter((r) => {
2556
- if (!r.affectsCoverage)
2557
- return false;
2558
- const severity = getSeverity(r.id, r.defaultSeverity);
2559
- return severity !== "off";
2560
- });
2561
- const result = {
2562
- coverageScore: 0,
2563
- coverage: {
2564
- satisfied: [],
2565
- missing: [],
2566
- applicable: activeCoverageRules.map((r) => r.id)
2567
- },
2568
- violations: [],
2569
- summary: {
2570
- errorCount: 0,
2571
- warningCount: 0,
2572
- fixableCount: 0
2573
- }
2574
- };
2575
- const context = { export: exp, rawJSDoc, exportRegistry };
2576
- for (const rule of applicableRules) {
2577
- const passed = rule.check(context);
2578
- const severity = getSeverity(rule.id, rule.defaultSeverity);
2579
- if (rule.affectsCoverage && severity !== "off") {
2580
- if (passed) {
2581
- result.coverage.satisfied.push(rule.id);
2582
- } else {
2583
- result.coverage.missing.push(rule.id);
2584
- }
2585
- }
2586
- if (!passed && severity !== "off" && rule.getViolation) {
2587
- const violation = {
2588
- ...rule.getViolation(context),
2589
- severity: severity === "error" ? "error" : "warn"
2590
- };
2591
- result.violations.push(violation);
2592
- if (violation.severity === "error") {
2593
- result.summary.errorCount++;
2594
- } else {
2595
- result.summary.warningCount++;
2596
- }
2597
- if (violation.fixable) {
2598
- result.summary.fixableCount++;
2599
- }
2600
- }
2601
- }
2602
- const { satisfied, applicable } = result.coverage;
2603
- result.coverageScore = applicable.length === 0 ? 100 : Math.round(satisfied.length / applicable.length * 100);
2604
- return result;
2605
- }
2606
- function evaluateQuality(exports, config = { rules: {} }) {
2607
- const byExport = new Map;
2608
- let totalCoverage = 0;
2609
- let totalErrors = 0;
2610
- let totalWarnings = 0;
2611
- for (const { export: exp, rawJSDoc } of exports) {
2612
- const result = evaluateExportQuality(exp, rawJSDoc, config);
2613
- byExport.set(exp.id ?? exp.name, result);
2614
- totalCoverage += result.coverageScore;
2615
- totalErrors += result.summary.errorCount;
2616
- totalWarnings += result.summary.warningCount;
2617
- }
2618
- const count = exports.length;
2619
- return {
2620
- byExport,
2621
- overall: {
2622
- coverageScore: count === 0 ? 100 : Math.round(totalCoverage / count),
2623
- totalViolations: totalErrors + totalWarnings,
2624
- errorCount: totalErrors,
2625
- warningCount: totalWarnings
2626
- }
2627
- };
2628
- }
2629
- function mergeConfig(userConfig) {
2630
- const defaults = getDefaultConfig();
2631
- return {
2632
- rules: {
2633
- ...defaults,
2634
- ...userConfig.rules
2635
- }
2636
- };
2637
- }
2638
-
2639
2375
  // src/analysis/enrich.ts
2640
2376
  function collectAllMissing(exports) {
2641
2377
  const allMissing = new Set;
@@ -2657,38 +2393,33 @@ function collectAllDrift(exports) {
2657
2393
  }
2658
2394
  return allDrift;
2659
2395
  }
2660
- function collectAllViolations(exports) {
2661
- const allViolations = [];
2662
- for (const exp of exports) {
2663
- if (exp.docs?.violations) {
2664
- allViolations.push(...exp.docs.violations);
2665
- }
2396
+ function computeExportCoverage(exp) {
2397
+ const missing = [];
2398
+ if (!exp.description) {
2399
+ missing.push("has-description");
2400
+ return { score: 0, missing };
2666
2401
  }
2667
- return allViolations;
2402
+ return { score: 100, missing: [] };
2668
2403
  }
2669
2404
  function enrichSpec(spec, options = {}) {
2670
- const { driftByExport, qualityConfig = { rules: {} }, rawJSDocByExport } = options;
2405
+ const { driftByExport } = options;
2671
2406
  const exportRegistry = buildExportRegistry(spec);
2672
2407
  let totalCoverage = 0;
2673
2408
  const enrichedExports = spec.exports.map((exp) => {
2674
- const rawJSDoc = rawJSDocByExport?.get(exp.id);
2675
- const quality = evaluateExportQuality(exp, rawJSDoc, qualityConfig, exportRegistry);
2409
+ const coverage = computeExportCoverage(exp);
2676
2410
  const drift = computeExportDrift(exp, exportRegistry);
2677
2411
  const additionalDrift = driftByExport?.get(exp.id);
2678
2412
  const allDrift2 = additionalDrift ? [...drift, ...additionalDrift] : drift;
2679
- totalCoverage += quality.coverageScore;
2413
+ totalCoverage += coverage.score;
2680
2414
  const docs2 = {
2681
- coverageScore: quality.coverageScore
2415
+ coverageScore: coverage.score
2682
2416
  };
2683
- if (quality.coverage.missing.length > 0) {
2684
- docs2.missing = quality.coverage.missing;
2417
+ if (coverage.missing.length > 0) {
2418
+ docs2.missing = coverage.missing;
2685
2419
  }
2686
2420
  if (allDrift2.length > 0) {
2687
2421
  docs2.drift = allDrift2;
2688
2422
  }
2689
- if (quality.violations.length > 0) {
2690
- docs2.violations = quality.violations;
2691
- }
2692
2423
  return {
2693
2424
  ...exp,
2694
2425
  docs: docs2
@@ -2697,7 +2428,6 @@ function enrichSpec(spec, options = {}) {
2697
2428
  const count = enrichedExports.length;
2698
2429
  const allMissing = collectAllMissing(enrichedExports);
2699
2430
  const allDrift = collectAllDrift(enrichedExports);
2700
- const allViolations = collectAllViolations(enrichedExports);
2701
2431
  const docs = {
2702
2432
  coverageScore: count === 0 ? 100 : Math.round(totalCoverage / count)
2703
2433
  };
@@ -2707,9 +2437,6 @@ function enrichSpec(spec, options = {}) {
2707
2437
  if (allDrift.length > 0) {
2708
2438
  docs.drift = allDrift;
2709
2439
  }
2710
- if (allViolations.length > 0) {
2711
- docs.violations = allViolations;
2712
- }
2713
2440
  const driftSummary = allDrift.length > 0 ? getDriftSummary(allDrift) : undefined;
2714
2441
  return {
2715
2442
  ...spec,
@@ -2720,7 +2447,7 @@ function enrichSpec(spec, options = {}) {
2720
2447
  }
2721
2448
  // src/analysis/report.ts
2722
2449
  import * as fs3 from "node:fs";
2723
- import * as path2 from "node:path";
2450
+ import * as path3 from "node:path";
2724
2451
 
2725
2452
  // src/types/report.ts
2726
2453
  var REPORT_VERSION = "1.0.0";
@@ -2796,7 +2523,7 @@ function generateReportFromEnriched(enriched) {
2796
2523
  }
2797
2524
  function loadCachedReport(reportPath = DEFAULT_REPORT_PATH) {
2798
2525
  try {
2799
- const fullPath = path2.resolve(reportPath);
2526
+ const fullPath = path3.resolve(reportPath);
2800
2527
  if (!fs3.existsSync(fullPath)) {
2801
2528
  return null;
2802
2529
  }
@@ -2807,8 +2534,8 @@ function loadCachedReport(reportPath = DEFAULT_REPORT_PATH) {
2807
2534
  }
2808
2535
  }
2809
2536
  function saveReport(report, reportPath = DEFAULT_REPORT_PATH) {
2810
- const fullPath = path2.resolve(reportPath);
2811
- const dir = path2.dirname(fullPath);
2537
+ const fullPath = path3.resolve(reportPath);
2538
+ const dir = path3.dirname(fullPath);
2812
2539
  if (!fs3.existsSync(dir)) {
2813
2540
  fs3.mkdirSync(dir, { recursive: true });
2814
2541
  }
@@ -3010,7 +2737,7 @@ function renderApiSurface(spec) {
3010
2737
  }
3011
2738
  // src/analysis/history.ts
3012
2739
  import * as fs4 from "node:fs";
3013
- import * as path3 from "node:path";
2740
+ import * as path4 from "node:path";
3014
2741
  var HISTORY_DIR = ".doccov/history";
3015
2742
  var RETENTION_DAYS = {
3016
2743
  free: 7,
@@ -3048,16 +2775,16 @@ function computeSnapshot(spec, options) {
3048
2775
  };
3049
2776
  }
3050
2777
  function saveSnapshot(snapshot, cwd) {
3051
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2778
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3052
2779
  if (!fs4.existsSync(historyDir)) {
3053
2780
  fs4.mkdirSync(historyDir, { recursive: true });
3054
2781
  }
3055
2782
  const filename = getSnapshotFilename(new Date(snapshot.timestamp));
3056
- const filepath = path3.join(historyDir, filename);
2783
+ const filepath = path4.join(historyDir, filename);
3057
2784
  fs4.writeFileSync(filepath, JSON.stringify(snapshot, null, 2));
3058
2785
  }
3059
2786
  function loadSnapshots(cwd) {
3060
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2787
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3061
2788
  if (!fs4.existsSync(historyDir)) {
3062
2789
  return [];
3063
2790
  }
@@ -3065,7 +2792,7 @@ function loadSnapshots(cwd) {
3065
2792
  const snapshots = [];
3066
2793
  for (const file of files) {
3067
2794
  try {
3068
- const content = fs4.readFileSync(path3.join(historyDir, file), "utf-8");
2795
+ const content = fs4.readFileSync(path4.join(historyDir, file), "utf-8");
3069
2796
  snapshots.push(JSON.parse(content));
3070
2797
  } catch {}
3071
2798
  }
@@ -3105,7 +2832,7 @@ function formatDelta(delta) {
3105
2832
  return "→0%";
3106
2833
  }
3107
2834
  function pruneHistory(cwd, keepCount = 100) {
3108
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2835
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3109
2836
  if (!fs4.existsSync(historyDir)) {
3110
2837
  return 0;
3111
2838
  }
@@ -3113,7 +2840,7 @@ function pruneHistory(cwd, keepCount = 100) {
3113
2840
  const toDelete = files.slice(keepCount);
3114
2841
  for (const file of toDelete) {
3115
2842
  try {
3116
- fs4.unlinkSync(path3.join(historyDir, file));
2843
+ fs4.unlinkSync(path4.join(historyDir, file));
3117
2844
  } catch {}
3118
2845
  }
3119
2846
  return toDelete.length;
@@ -3122,7 +2849,7 @@ function pruneByTier(cwd, tier) {
3122
2849
  const retentionDays = RETENTION_DAYS[tier];
3123
2850
  const cutoffDate = new Date;
3124
2851
  cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
3125
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2852
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3126
2853
  if (!fs4.existsSync(historyDir)) {
3127
2854
  return 0;
3128
2855
  }
@@ -3130,7 +2857,7 @@ function pruneByTier(cwd, tier) {
3130
2857
  let deleted = 0;
3131
2858
  for (const file of files) {
3132
2859
  try {
3133
- const filepath = path3.join(historyDir, file);
2860
+ const filepath = path4.join(historyDir, file);
3134
2861
  const content = fs4.readFileSync(filepath, "utf-8");
3135
2862
  const snapshot = JSON.parse(content);
3136
2863
  const snapshotDate = new Date(snapshot.timestamp);
@@ -3237,7 +2964,7 @@ function getExtendedTrend(spec, cwd, options) {
3237
2964
  // src/cache/hash.ts
3238
2965
  import * as crypto from "node:crypto";
3239
2966
  import * as fs5 from "node:fs";
3240
- import * as path4 from "node:path";
2967
+ import * as path5 from "node:path";
3241
2968
  function hashFile(filePath) {
3242
2969
  try {
3243
2970
  const content = fs5.readFileSync(filePath);
@@ -3254,21 +2981,21 @@ function hashFiles(filePaths, cwd) {
3254
2981
  for (const filePath of filePaths) {
3255
2982
  const hash = hashFile(filePath);
3256
2983
  if (hash) {
3257
- const relativePath = path4.relative(cwd, filePath);
2984
+ const relativePath = path5.relative(cwd, filePath);
3258
2985
  hashes[relativePath] = hash;
3259
2986
  }
3260
2987
  }
3261
2988
  return hashes;
3262
2989
  }
3263
- function diffHashes(cached2, current) {
2990
+ function diffHashes(cached, current) {
3264
2991
  const changed = [];
3265
- for (const [file, hash] of Object.entries(cached2)) {
2992
+ for (const [file, hash] of Object.entries(cached)) {
3266
2993
  if (current[file] !== hash) {
3267
2994
  changed.push(file);
3268
2995
  }
3269
2996
  }
3270
2997
  for (const file of Object.keys(current)) {
3271
- if (!(file in cached2)) {
2998
+ if (!(file in cached)) {
3272
2999
  changed.push(file);
3273
3000
  }
3274
3001
  }
@@ -3276,12 +3003,12 @@ function diffHashes(cached2, current) {
3276
3003
  }
3277
3004
  // src/cache/spec-cache.ts
3278
3005
  import * as fs6 from "node:fs";
3279
- import * as path5 from "node:path";
3006
+ import * as path6 from "node:path";
3280
3007
  var CACHE_VERSION = "1.0.0";
3281
3008
  var SPEC_CACHE_FILE = ".doccov/spec.cache.json";
3282
3009
  function loadSpecCache(cwd) {
3283
3010
  try {
3284
- const cachePath = path5.resolve(cwd, SPEC_CACHE_FILE);
3011
+ const cachePath = path6.resolve(cwd, SPEC_CACHE_FILE);
3285
3012
  if (!fs6.existsSync(cachePath)) {
3286
3013
  return null;
3287
3014
  }
@@ -3297,7 +3024,7 @@ function saveSpecCache(spec, context) {
3297
3024
  cacheVersion: CACHE_VERSION,
3298
3025
  generatedAt: new Date().toISOString(),
3299
3026
  specVersion: spec.openpkg,
3300
- entryFile: path5.relative(cwd, entryFile),
3027
+ entryFile: path6.relative(cwd, entryFile),
3301
3028
  hashes: {
3302
3029
  tsconfig: tsconfigPath ? hashFile(tsconfigPath) : null,
3303
3030
  packageJson: hashFile(packageJsonPath) ?? "",
@@ -3306,8 +3033,8 @@ function saveSpecCache(spec, context) {
3306
3033
  config,
3307
3034
  spec
3308
3035
  };
3309
- const cachePath = path5.resolve(cwd, SPEC_CACHE_FILE);
3310
- const dir = path5.dirname(cachePath);
3036
+ const cachePath = path6.resolve(cwd, SPEC_CACHE_FILE);
3037
+ const dir = path6.dirname(cachePath);
3311
3038
  if (!fs6.existsSync(dir)) {
3312
3039
  fs6.mkdirSync(dir, { recursive: true });
3313
3040
  }
@@ -3318,7 +3045,7 @@ function validateSpecCache(cache, context) {
3318
3045
  if (cache.cacheVersion !== CACHE_VERSION) {
3319
3046
  return { valid: false, reason: "cache-version-mismatch" };
3320
3047
  }
3321
- const relativeEntry = path5.relative(cwd, entryFile);
3048
+ const relativeEntry = path6.relative(cwd, entryFile);
3322
3049
  if (cache.entryFile !== relativeEntry) {
3323
3050
  return { valid: false, reason: "entry-file-changed" };
3324
3051
  }
@@ -3341,7 +3068,7 @@ function validateSpecCache(cache, context) {
3341
3068
  return { valid: true };
3342
3069
  }
3343
3070
  function clearSpecCache(cwd) {
3344
- const cachePath = path5.resolve(cwd, SPEC_CACHE_FILE);
3071
+ const cachePath = path6.resolve(cwd, SPEC_CACHE_FILE);
3345
3072
  if (fs6.existsSync(cachePath)) {
3346
3073
  fs6.unlinkSync(cachePath);
3347
3074
  return true;
@@ -3349,325 +3076,26 @@ function clearSpecCache(cwd) {
3349
3076
  return false;
3350
3077
  }
3351
3078
  function getSpecCachePath(cwd) {
3352
- return path5.resolve(cwd, SPEC_CACHE_FILE);
3353
- }
3354
- // src/codeowners/index.ts
3355
- import * as fs7 from "node:fs";
3356
- import * as path6 from "node:path";
3357
- import { minimatch } from "minimatch";
3358
- var CODEOWNERS_LOCATIONS = [
3359
- "CODEOWNERS",
3360
- ".github/CODEOWNERS",
3361
- "docs/CODEOWNERS"
3362
- ];
3363
- function parseCodeOwners(content) {
3364
- const rules = [];
3365
- const lines = content.split(`
3366
- `);
3367
- for (let i = 0;i < lines.length; i++) {
3368
- const line = lines[i].trim();
3369
- if (!line || line.startsWith("#"))
3370
- continue;
3371
- const parts = line.split(/\s+/);
3372
- if (parts.length < 2)
3373
- continue;
3374
- const pattern = parts[0];
3375
- const owners = parts.slice(1).filter((o) => o.startsWith("@") || o.includes("@"));
3376
- if (owners.length > 0) {
3377
- rules.push({
3378
- line: i + 1,
3379
- pattern,
3380
- owners
3381
- });
3382
- }
3383
- }
3384
- return rules;
3385
- }
3386
- function loadCodeOwners(baseDir) {
3387
- for (const location of CODEOWNERS_LOCATIONS) {
3388
- const filePath = path6.join(baseDir, location);
3389
- if (fs7.existsSync(filePath)) {
3390
- const content = fs7.readFileSync(filePath, "utf-8");
3391
- return {
3392
- filePath,
3393
- rules: parseCodeOwners(content)
3394
- };
3395
- }
3396
- }
3397
- return null;
3398
- }
3399
- function findOwners(filePath, rules) {
3400
- const normalizedPath = filePath.replace(/^\.\//, "");
3401
- let matchingOwners = [];
3402
- for (const rule of rules) {
3403
- let pattern = rule.pattern;
3404
- if (pattern.endsWith("/")) {
3405
- pattern = pattern + "**";
3406
- }
3407
- if (pattern.startsWith("/")) {
3408
- pattern = pattern.slice(1);
3409
- } else if (!pattern.startsWith("*")) {
3410
- pattern = "**/" + pattern;
3411
- }
3412
- if (minimatch(normalizedPath, pattern, { matchBase: true, dot: true })) {
3413
- matchingOwners = rule.owners;
3414
- }
3415
- }
3416
- return matchingOwners;
3417
- }
3418
- function attributeOwners(exports, rules, baseDir) {
3419
- const ownershipMap = new Map;
3420
- for (const exp of exports) {
3421
- const filePath = exp.source?.file;
3422
- if (!filePath) {
3423
- ownershipMap.set(exp, []);
3424
- continue;
3425
- }
3426
- let relativePath = filePath;
3427
- if (path6.isAbsolute(filePath)) {
3428
- relativePath = path6.relative(baseDir, filePath);
3429
- }
3430
- const owners = findOwners(relativePath, rules);
3431
- ownershipMap.set(exp, owners);
3432
- }
3433
- return ownershipMap;
3434
- }
3435
- function analyzeOwnership(spec, codeowners, baseDir) {
3436
- const exports = spec.exports ?? [];
3437
- const ownershipMap = attributeOwners(exports, codeowners.rules, baseDir);
3438
- const byOwnerExports = new Map;
3439
- const unowned = [];
3440
- for (const [exp, owners] of ownershipMap) {
3441
- if (owners.length === 0) {
3442
- unowned.push(exp);
3443
- } else {
3444
- for (const owner of owners) {
3445
- const existing = byOwnerExports.get(owner) ?? [];
3446
- existing.push(exp);
3447
- byOwnerExports.set(owner, existing);
3448
- }
3449
- }
3450
- }
3451
- const byOwner = new Map;
3452
- for (const [owner, ownerExports] of byOwnerExports) {
3453
- const documented = ownerExports.filter((e) => e.description);
3454
- const withDrift = ownerExports.filter((e) => e.docs?.drift && e.docs.drift.length > 0);
3455
- const withExamples = ownerExports.filter((e) => e.examples && e.examples.length > 0);
3456
- const undocumented = ownerExports.filter((e) => !e.description);
3457
- const coverageScore = ownerExports.length === 0 ? 100 : Math.round(documented.length / ownerExports.length * 100);
3458
- const driftScore = ownerExports.length === 0 ? 0 : Math.round(withDrift.length / ownerExports.length * 100);
3459
- byOwner.set(owner, {
3460
- owner,
3461
- totalExports: ownerExports.length,
3462
- documentedExports: documented.length,
3463
- coverageScore,
3464
- exportsWithDrift: withDrift.length,
3465
- driftScore,
3466
- missingExamples: ownerExports.length - withExamples.length,
3467
- undocumentedExports: undocumented.map((e) => e.name)
3468
- });
3469
- }
3470
- return {
3471
- codeownersPath: codeowners.filePath,
3472
- byOwner,
3473
- unowned,
3474
- totalExports: exports.length
3475
- };
3476
- }
3477
- function analyzeSpecOwnership(spec, options) {
3478
- const codeowners = loadCodeOwners(options.baseDir);
3479
- if (!codeowners)
3480
- return null;
3481
- return analyzeOwnership(spec, codeowners, options.baseDir);
3482
- }
3483
- // src/contributors/index.ts
3484
- import { execSync } from "node:child_process";
3485
- import * as path7 from "node:path";
3486
- function parseBlameOutput(output) {
3487
- const results = [];
3488
- const lines = output.split(`
3489
- `);
3490
- let currentCommit = "";
3491
- let currentAuthor = "";
3492
- let currentEmail = "";
3493
- let currentTime = 0;
3494
- let lineNumber = 0;
3495
- for (const line of lines) {
3496
- if (line.match(/^[0-9a-f]{40}/)) {
3497
- const parts = line.split(" ");
3498
- currentCommit = parts[0];
3499
- lineNumber = parseInt(parts[2], 10);
3500
- } else if (line.startsWith("author ")) {
3501
- currentAuthor = line.slice(7);
3502
- } else if (line.startsWith("author-mail ")) {
3503
- currentEmail = line.slice(12).replace(/[<>]/g, "");
3504
- } else if (line.startsWith("author-time ")) {
3505
- currentTime = parseInt(line.slice(12), 10);
3506
- } else if (line.startsWith("\t")) {
3507
- results.push({
3508
- commit: currentCommit,
3509
- author: currentAuthor,
3510
- email: currentEmail,
3511
- line: lineNumber,
3512
- timestamp: currentTime
3513
- });
3514
- }
3515
- }
3516
- return results;
3517
- }
3518
- function getFileBlame(filePath, cwd) {
3519
- try {
3520
- const relativePath = path7.isAbsolute(filePath) ? path7.relative(cwd, filePath) : filePath;
3521
- const output = execSync(`git blame --porcelain "${relativePath}"`, {
3522
- cwd,
3523
- encoding: "utf-8",
3524
- maxBuffer: 10 * 1024 * 1024,
3525
- stdio: ["pipe", "pipe", "pipe"]
3526
- });
3527
- return parseBlameOutput(output);
3528
- } catch {
3529
- return null;
3530
- }
3531
- }
3532
- function getBlameForLines(filePath, startLine, endLine, cwd) {
3533
- try {
3534
- const relativePath = path7.isAbsolute(filePath) ? path7.relative(cwd, filePath) : filePath;
3535
- const output = execSync(`git blame --porcelain -L ${startLine},${endLine} "${relativePath}"`, {
3536
- cwd,
3537
- encoding: "utf-8",
3538
- maxBuffer: 10 * 1024 * 1024,
3539
- stdio: ["pipe", "pipe", "pipe"]
3540
- });
3541
- return parseBlameOutput(output);
3542
- } catch {
3543
- return null;
3544
- }
3545
- }
3546
- function findPrimaryAuthor(blameLines) {
3547
- if (blameLines.length === 0)
3548
- return null;
3549
- const authorCounts = new Map;
3550
- for (const line of blameLines) {
3551
- const key = line.email;
3552
- const existing = authorCounts.get(key);
3553
- if (existing) {
3554
- existing.count++;
3555
- if (line.timestamp > existing.info.timestamp) {
3556
- existing.info = line;
3557
- }
3558
- } else {
3559
- authorCounts.set(key, { count: 1, info: line });
3560
- }
3561
- }
3562
- let maxCount = 0;
3563
- let primaryAuthor = null;
3564
- for (const { count, info } of authorCounts.values()) {
3565
- if (count > maxCount) {
3566
- maxCount = count;
3567
- primaryAuthor = info;
3568
- }
3569
- }
3570
- return primaryAuthor;
3571
- }
3572
- function analyzeContributors(spec, baseDir) {
3573
- const exports = spec.exports ?? [];
3574
- const byContributor = new Map;
3575
- const unattributed = [];
3576
- let totalDocumented = 0;
3577
- const fileBlameCache = new Map;
3578
- for (const exp of exports) {
3579
- if (!exp.description)
3580
- continue;
3581
- const filePath = exp.source?.file;
3582
- const line = exp.source?.line;
3583
- if (!filePath || !line) {
3584
- unattributed.push(exp.name);
3585
- continue;
3586
- }
3587
- let fileBlame = fileBlameCache.get(filePath);
3588
- if (fileBlame === undefined) {
3589
- fileBlame = getFileBlame(filePath, baseDir);
3590
- fileBlameCache.set(filePath, fileBlame);
3591
- }
3592
- if (!fileBlame) {
3593
- unattributed.push(exp.name);
3594
- continue;
3595
- }
3596
- const jsDocStartLine = Math.max(1, line - 20);
3597
- const declarationLine = line;
3598
- const jsDocBlame = fileBlame.filter((b) => b.line >= jsDocStartLine && b.line < declarationLine);
3599
- const primaryAuthor = findPrimaryAuthor(jsDocBlame);
3600
- if (!primaryAuthor) {
3601
- const declBlame = fileBlame.find((b) => b.line === declarationLine);
3602
- if (declBlame) {
3603
- attributeToContributor(byContributor, declBlame, exp.name, 1);
3604
- totalDocumented++;
3605
- } else {
3606
- unattributed.push(exp.name);
3607
- }
3608
- continue;
3609
- }
3610
- const linesAuthored = jsDocBlame.filter((b) => b.email === primaryAuthor.email).length;
3611
- attributeToContributor(byContributor, primaryAuthor, exp.name, linesAuthored);
3612
- totalDocumented++;
3613
- }
3614
- return {
3615
- byContributor,
3616
- totalDocumented,
3617
- unattributed
3618
- };
3619
- }
3620
- function attributeToContributor(byContributor, blame, exportName, lines) {
3621
- const key = blame.email;
3622
- const existing = byContributor.get(key);
3623
- if (existing) {
3624
- existing.documentedExports++;
3625
- existing.exports.push(exportName);
3626
- existing.linesAuthored += lines;
3627
- const blameDate = new Date(blame.timestamp * 1000);
3628
- if (!existing.lastContribution || blameDate > existing.lastContribution) {
3629
- existing.lastContribution = blameDate;
3630
- }
3631
- } else {
3632
- byContributor.set(key, {
3633
- name: blame.author,
3634
- email: blame.email,
3635
- documentedExports: 1,
3636
- exports: [exportName],
3637
- linesAuthored: lines,
3638
- lastContribution: new Date(blame.timestamp * 1000)
3639
- });
3640
- }
3641
- }
3642
- function analyzeSpecContributors(spec, options) {
3643
- try {
3644
- execSync("git rev-parse --git-dir", {
3645
- cwd: options.baseDir,
3646
- stdio: ["pipe", "pipe", "pipe"]
3647
- });
3648
- } catch {
3649
- return null;
3650
- }
3651
- return analyzeContributors(spec, options.baseDir);
3079
+ return path6.resolve(cwd, SPEC_CACHE_FILE);
3652
3080
  }
3653
3081
  // src/config/types.ts
3654
3082
  function defineConfig(config) {
3655
3083
  return config;
3656
3084
  }
3657
3085
  // src/detect/utils.ts
3658
- async function safeParseJson(fs8, path8) {
3086
+ async function safeParseJson(fs7, path7) {
3659
3087
  try {
3660
- if (!await fs8.exists(path8))
3088
+ if (!await fs7.exists(path7))
3661
3089
  return null;
3662
- const content = await fs8.readFile(path8);
3090
+ const content = await fs7.readFile(path7);
3663
3091
  return JSON.parse(content);
3664
3092
  } catch {
3665
3093
  return null;
3666
3094
  }
3667
3095
  }
3668
- async function readPackageJson(fs8, dir) {
3669
- const path8 = dir === "." ? "package.json" : `${dir}/package.json`;
3670
- return safeParseJson(fs8, path8);
3096
+ async function readPackageJson(fs7, dir) {
3097
+ const path7 = dir === "." ? "package.json" : `${dir}/package.json`;
3098
+ return safeParseJson(fs7, path7);
3671
3099
  }
3672
3100
 
3673
3101
  // src/detect/build.ts
@@ -3697,8 +3125,8 @@ var BUILD_TOOL_PATTERNS = [
3697
3125
  "babel",
3698
3126
  "ncc build"
3699
3127
  ];
3700
- async function detectBuildInfo(fs8, packagePath = ".") {
3701
- const pkgJson = await readPackageJson(fs8, packagePath);
3128
+ async function detectBuildInfo(fs7, packagePath = ".") {
3129
+ const pkgJson = await readPackageJson(fs7, packagePath);
3702
3130
  const scripts = pkgJson?.scripts ?? {};
3703
3131
  const scriptNames = Object.keys(scripts);
3704
3132
  const buildScriptsByName = scriptNames.filter((name) => BUILD_SCRIPT_NAMES.has(name) || BUILD_SCRIPT_PREFIXES.some((prefix) => name.startsWith(prefix)));
@@ -3710,10 +3138,10 @@ async function detectBuildInfo(fs8, packagePath = ".") {
3710
3138
  });
3711
3139
  const buildScripts = [...new Set([...buildScriptsByName, ...buildScriptsByContent])];
3712
3140
  const tsconfigPath = packagePath === "." ? "tsconfig.json" : `${packagePath}/tsconfig.json`;
3713
- const hasTsConfig = await fs8.exists(tsconfigPath);
3141
+ const hasTsConfig = await fs7.exists(tsconfigPath);
3714
3142
  const hasTsDep = pkgJson?.devDependencies?.typescript !== undefined || pkgJson?.dependencies?.typescript !== undefined;
3715
3143
  const hasTypeScript = hasTsConfig || hasTsDep;
3716
- const wasm = await detectWasmProject(fs8, packagePath, pkgJson);
3144
+ const wasm = await detectWasmProject(fs7, packagePath, pkgJson);
3717
3145
  const napi = detectNapiProject(pkgJson);
3718
3146
  return {
3719
3147
  scripts: buildScripts,
@@ -3730,11 +3158,11 @@ var WASM_PACKAGES = new Set([
3730
3158
  "wasm-bindgen",
3731
3159
  "@aspect/aspect-cli"
3732
3160
  ]);
3733
- async function detectWasmProject(fs8, packagePath, pkgJson) {
3161
+ async function detectWasmProject(fs7, packagePath, pkgJson) {
3734
3162
  const pkgCargoPath = packagePath === "." ? "Cargo.toml" : `${packagePath}/Cargo.toml`;
3735
- if (await fs8.exists(pkgCargoPath))
3163
+ if (await fs7.exists(pkgCargoPath))
3736
3164
  return true;
3737
- if (packagePath !== "." && await fs8.exists("Cargo.toml"))
3165
+ if (packagePath !== "." && await fs7.exists("Cargo.toml"))
3738
3166
  return true;
3739
3167
  if (pkgJson) {
3740
3168
  const deps = Object.keys({
@@ -3775,15 +3203,15 @@ function getPrimaryBuildScript(buildInfo) {
3775
3203
  return buildInfo.scripts[0] ?? null;
3776
3204
  }
3777
3205
  // src/detect/entry-point.ts
3778
- async function detectEntryPoint(fs8, packagePath = ".") {
3779
- const pkgJson = await readPackageJson(fs8, packagePath);
3206
+ async function detectEntryPoint(fs7, packagePath = ".") {
3207
+ const pkgJson = await readPackageJson(fs7, packagePath);
3780
3208
  if (!pkgJson) {
3781
3209
  throw new Error("No package.json found - not a valid npm package");
3782
3210
  }
3783
- const tsConfig = await parseTsConfig(fs8, packagePath);
3211
+ const tsConfig = await parseTsConfig(fs7, packagePath);
3784
3212
  const typesField = pkgJson.types || pkgJson.typings;
3785
3213
  if (typesField && typeof typesField === "string") {
3786
- const resolved = await resolveToSource(fs8, packagePath, typesField, tsConfig);
3214
+ const resolved = await resolveToSource(fs7, packagePath, typesField, tsConfig);
3787
3215
  if (resolved) {
3788
3216
  return { ...resolved, source: "types" };
3789
3217
  }
@@ -3793,7 +3221,7 @@ async function detectEntryPoint(fs8, packagePath = ".") {
3793
3221
  if (dotExport && typeof dotExport === "object" && "types" in dotExport) {
3794
3222
  const typesPath = dotExport.types;
3795
3223
  if (typesPath && typeof typesPath === "string") {
3796
- const resolved = await resolveToSource(fs8, packagePath, typesPath, tsConfig);
3224
+ const resolved = await resolveToSource(fs7, packagePath, typesPath, tsConfig);
3797
3225
  if (resolved) {
3798
3226
  return { ...resolved, source: "exports" };
3799
3227
  }
@@ -3801,13 +3229,13 @@ async function detectEntryPoint(fs8, packagePath = ".") {
3801
3229
  }
3802
3230
  }
3803
3231
  if (pkgJson.main && typeof pkgJson.main === "string") {
3804
- const resolved = await resolveToSource(fs8, packagePath, pkgJson.main, tsConfig);
3232
+ const resolved = await resolveToSource(fs7, packagePath, pkgJson.main, tsConfig);
3805
3233
  if (resolved) {
3806
3234
  return { ...resolved, source: "main" };
3807
3235
  }
3808
3236
  }
3809
3237
  if (pkgJson.module && typeof pkgJson.module === "string") {
3810
- const resolved = await resolveToSource(fs8, packagePath, pkgJson.module, tsConfig);
3238
+ const resolved = await resolveToSource(fs7, packagePath, pkgJson.module, tsConfig);
3811
3239
  if (resolved) {
3812
3240
  return { ...resolved, source: "module" };
3813
3241
  }
@@ -3825,27 +3253,27 @@ async function detectEntryPoint(fs8, packagePath = ".") {
3825
3253
  ];
3826
3254
  for (const fallback of fallbacks) {
3827
3255
  const checkPath = packagePath === "." ? fallback : `${packagePath}/${fallback}`;
3828
- if (await fs8.exists(checkPath)) {
3256
+ if (await fs7.exists(checkPath)) {
3829
3257
  return { path: fallback, source: "fallback", isDeclarationOnly: false };
3830
3258
  }
3831
3259
  }
3832
3260
  throw new Error("Could not detect TypeScript entry point. No types field in package.json and no common entry paths found.");
3833
3261
  }
3834
- async function parseTsConfig(fs8, packagePath) {
3262
+ async function parseTsConfig(fs7, packagePath) {
3835
3263
  const tsconfigPath = packagePath === "." ? "tsconfig.json" : `${packagePath}/tsconfig.json`;
3836
- const tsconfig = await safeParseJson(fs8, tsconfigPath);
3264
+ const tsconfig = await safeParseJson(fs7, tsconfigPath);
3837
3265
  if (!tsconfig?.compilerOptions) {
3838
3266
  return null;
3839
3267
  }
3840
3268
  const { outDir, rootDir, baseUrl, paths } = tsconfig.compilerOptions;
3841
3269
  return { outDir, rootDir, baseUrl, paths };
3842
3270
  }
3843
- async function resolveToSource(fs8, basePath, filePath, tsConfig) {
3271
+ async function resolveToSource(fs7, basePath, filePath, tsConfig) {
3844
3272
  const normalized = filePath.replace(/^\.\//, "");
3845
3273
  const checkPath = (p) => basePath === "." ? p : `${basePath}/${p}`;
3846
3274
  const isSourceTs = normalized.endsWith(".ts") && !normalized.endsWith(".d.ts") || normalized.endsWith(".tsx");
3847
3275
  if (isSourceTs) {
3848
- if (await fs8.exists(checkPath(normalized))) {
3276
+ if (await fs7.exists(checkPath(normalized))) {
3849
3277
  return { path: normalized, isDeclarationOnly: false };
3850
3278
  }
3851
3279
  }
@@ -3887,19 +3315,19 @@ async function resolveToSource(fs8, basePath, filePath, tsConfig) {
3887
3315
  for (const candidate of candidates) {
3888
3316
  if (candidate.endsWith(".d.ts"))
3889
3317
  continue;
3890
- if (await fs8.exists(checkPath(candidate))) {
3318
+ if (await fs7.exists(checkPath(candidate))) {
3891
3319
  return { path: candidate, isDeclarationOnly: false };
3892
3320
  }
3893
3321
  }
3894
3322
  if (normalized.endsWith(".d.ts")) {
3895
- if (await fs8.exists(checkPath(normalized))) {
3323
+ if (await fs7.exists(checkPath(normalized))) {
3896
3324
  return { path: normalized, isDeclarationOnly: true };
3897
3325
  }
3898
3326
  }
3899
3327
  return null;
3900
3328
  }
3901
3329
  // src/detect/filesystem.ts
3902
- import * as fs8 from "node:fs";
3330
+ import * as fs7 from "node:fs";
3903
3331
  import * as nodePath from "node:path";
3904
3332
  import { Writable } from "node:stream";
3905
3333
 
@@ -3912,19 +3340,19 @@ class NodeFileSystem {
3912
3340
  return nodePath.join(this.basePath, relativePath);
3913
3341
  }
3914
3342
  async exists(relativePath) {
3915
- return fs8.existsSync(this.resolve(relativePath));
3343
+ return fs7.existsSync(this.resolve(relativePath));
3916
3344
  }
3917
3345
  async readFile(relativePath) {
3918
- return fs8.readFileSync(this.resolve(relativePath), "utf-8");
3346
+ return fs7.readFileSync(this.resolve(relativePath), "utf-8");
3919
3347
  }
3920
3348
  async readDir(relativePath) {
3921
- return fs8.readdirSync(this.resolve(relativePath));
3349
+ return fs7.readdirSync(this.resolve(relativePath));
3922
3350
  }
3923
3351
  async isDirectory(relativePath) {
3924
3352
  const fullPath = this.resolve(relativePath);
3925
- if (!fs8.existsSync(fullPath))
3353
+ if (!fs7.existsSync(fullPath))
3926
3354
  return false;
3927
- return fs8.statSync(fullPath).isDirectory();
3355
+ return fs7.statSync(fullPath).isDirectory();
3928
3356
  }
3929
3357
  }
3930
3358
  function createCaptureStream() {
@@ -3940,9 +3368,9 @@ function createCaptureStream() {
3940
3368
 
3941
3369
  class FileNotFoundError extends Error {
3942
3370
  path;
3943
- constructor(path8, message) {
3944
- super(message ?? `File not found: ${path8}`);
3945
- this.path = path8;
3371
+ constructor(path7, message) {
3372
+ super(message ?? `File not found: ${path7}`);
3373
+ this.path = path7;
3946
3374
  this.name = "FileNotFoundError";
3947
3375
  }
3948
3376
  }
@@ -3952,34 +3380,34 @@ class SandboxFileSystem {
3952
3380
  constructor(sandbox) {
3953
3381
  this.sandbox = sandbox;
3954
3382
  }
3955
- async exists(path8) {
3383
+ async exists(path7) {
3956
3384
  const result = await this.sandbox.runCommand({
3957
3385
  cmd: "test",
3958
- args: ["-e", path8]
3386
+ args: ["-e", path7]
3959
3387
  });
3960
3388
  return result.exitCode === 0;
3961
3389
  }
3962
- async readFile(path8) {
3963
- const exists = await this.exists(path8);
3390
+ async readFile(path7) {
3391
+ const exists = await this.exists(path7);
3964
3392
  if (!exists) {
3965
- throw new FileNotFoundError(path8);
3393
+ throw new FileNotFoundError(path7);
3966
3394
  }
3967
3395
  const capture = createCaptureStream();
3968
3396
  const result = await this.sandbox.runCommand({
3969
3397
  cmd: "cat",
3970
- args: [path8],
3398
+ args: [path7],
3971
3399
  stdout: capture.stream
3972
3400
  });
3973
3401
  if (result.exitCode !== 0) {
3974
- throw new FileNotFoundError(path8, `Failed to read file: ${path8}`);
3402
+ throw new FileNotFoundError(path7, `Failed to read file: ${path7}`);
3975
3403
  }
3976
3404
  return capture.getOutput();
3977
3405
  }
3978
- async readDir(path8) {
3406
+ async readDir(path7) {
3979
3407
  const capture = createCaptureStream();
3980
3408
  const result = await this.sandbox.runCommand({
3981
3409
  cmd: "ls",
3982
- args: ["-1", path8],
3410
+ args: ["-1", path7],
3983
3411
  stdout: capture.stream
3984
3412
  });
3985
3413
  if (result.exitCode !== 0) {
@@ -3988,20 +3416,20 @@ class SandboxFileSystem {
3988
3416
  return capture.getOutput().split(`
3989
3417
  `).filter(Boolean);
3990
3418
  }
3991
- async isDirectory(path8) {
3419
+ async isDirectory(path7) {
3992
3420
  const result = await this.sandbox.runCommand({
3993
3421
  cmd: "test",
3994
- args: ["-d", path8]
3422
+ args: ["-d", path7]
3995
3423
  });
3996
3424
  return result.exitCode === 0;
3997
3425
  }
3998
3426
  }
3999
3427
  // src/detect/monorepo.ts
4000
- async function detectMonorepo(fs9) {
4001
- const pkgJson = await readPackageJson(fs9, ".");
3428
+ async function detectMonorepo(fs8) {
3429
+ const pkgJson = await readPackageJson(fs8, ".");
4002
3430
  if (pkgJson?.workspaces) {
4003
3431
  const patterns = extractWorkspacePatterns(pkgJson.workspaces);
4004
- const packages = await resolveWorkspacePackages(fs9, patterns, pkgJson.name, pkgJson.private);
3432
+ const packages = await resolveWorkspacePackages(fs8, patterns, pkgJson.name, pkgJson.private);
4005
3433
  return {
4006
3434
  isMonorepo: packages.length > 0,
4007
3435
  type: "npm-workspaces",
@@ -4009,10 +3437,10 @@ async function detectMonorepo(fs9) {
4009
3437
  packages
4010
3438
  };
4011
3439
  }
4012
- if (await fs9.exists("pnpm-workspace.yaml")) {
4013
- const content = await fs9.readFile("pnpm-workspace.yaml");
3440
+ if (await fs8.exists("pnpm-workspace.yaml")) {
3441
+ const content = await fs8.readFile("pnpm-workspace.yaml");
4014
3442
  const patterns = parsePnpmWorkspace(content);
4015
- const packages = await resolveWorkspacePackages(fs9, patterns, pkgJson?.name, pkgJson?.private);
3443
+ const packages = await resolveWorkspacePackages(fs8, patterns, pkgJson?.name, pkgJson?.private);
4016
3444
  return {
4017
3445
  isMonorepo: packages.length > 0,
4018
3446
  type: "pnpm-workspaces",
@@ -4020,10 +3448,10 @@ async function detectMonorepo(fs9) {
4020
3448
  packages
4021
3449
  };
4022
3450
  }
4023
- if (await fs9.exists("lerna.json")) {
4024
- const lerna = await safeParseJson(fs9, "lerna.json");
3451
+ if (await fs8.exists("lerna.json")) {
3452
+ const lerna = await safeParseJson(fs8, "lerna.json");
4025
3453
  const patterns = lerna?.packages ?? ["packages/*"];
4026
- const packages = await resolveWorkspacePackages(fs9, patterns, pkgJson?.name, pkgJson?.private);
3454
+ const packages = await resolveWorkspacePackages(fs8, patterns, pkgJson?.name, pkgJson?.private);
4027
3455
  return {
4028
3456
  isMonorepo: packages.length > 0,
4029
3457
  type: "lerna",
@@ -4097,7 +3525,7 @@ function parsePnpmWorkspace(content) {
4097
3525
  }
4098
3526
  return patterns.length > 0 ? patterns : ["packages/*"];
4099
3527
  }
4100
- async function resolveWorkspacePackages(fs9, patterns, rootPackageName, rootIsPrivate) {
3528
+ async function resolveWorkspacePackages(fs8, patterns, rootPackageName, rootIsPrivate) {
4101
3529
  const packages = [];
4102
3530
  const seen = new Set;
4103
3531
  if (rootPackageName && !rootIsPrivate && rootPackageName !== "root") {
@@ -4119,18 +3547,18 @@ async function resolveWorkspacePackages(fs9, patterns, rootPackageName, rootIsPr
4119
3547
  }
4120
3548
  dirsToScan.add("packages");
4121
3549
  for (const dir of dirsToScan) {
4122
- if (!await fs9.exists(dir))
3550
+ if (!await fs8.exists(dir))
4123
3551
  continue;
4124
- if (!await fs9.isDirectory(dir))
3552
+ if (!await fs8.isDirectory(dir))
4125
3553
  continue;
4126
- const subdirs = await fs9.readDir(dir);
3554
+ const subdirs = await fs8.readDir(dir);
4127
3555
  for (const subdir of subdirs) {
4128
3556
  const pkgPath = `${dir}/${subdir}`;
4129
3557
  const pkgJsonPath = `${pkgPath}/package.json`;
4130
- if (!await fs9.exists(pkgJsonPath))
3558
+ if (!await fs8.exists(pkgJsonPath))
4131
3559
  continue;
4132
3560
  try {
4133
- const content = await fs9.readFile(pkgJsonPath);
3561
+ const content = await fs8.readFile(pkgJsonPath);
4134
3562
  const pkg = JSON.parse(content);
4135
3563
  if (pkg.name && !seen.has(pkg.name)) {
4136
3564
  seen.add(pkg.name);
@@ -4202,14 +3630,14 @@ var DEFAULT_PM = {
4202
3630
  installArgs: ["install", "--legacy-peer-deps"],
4203
3631
  runPrefix: ["npm", "run"]
4204
3632
  };
4205
- async function detectPackageManager(fs9) {
4206
- const pkgJson = await safeParseJson(fs9, "package.json");
3633
+ async function detectPackageManager(fs8) {
3634
+ const pkgJson = await safeParseJson(fs8, "package.json");
4207
3635
  if (pkgJson?.packageManager) {
4208
3636
  const pmName = parsePackageManagerField(pkgJson.packageManager);
4209
3637
  if (pmName && PM_CONFIGS[pmName]) {
4210
3638
  const config = PM_CONFIGS[pmName];
4211
3639
  for (const lockfile of config.lockfiles) {
4212
- if (await fs9.exists(lockfile)) {
3640
+ if (await fs8.exists(lockfile)) {
4213
3641
  return { ...config.info, lockfile };
4214
3642
  }
4215
3643
  }
@@ -4219,7 +3647,7 @@ async function detectPackageManager(fs9) {
4219
3647
  const foundLockfiles = [];
4220
3648
  for (const [pmName, config] of Object.entries(PM_CONFIGS)) {
4221
3649
  for (const lockfile of config.lockfiles) {
4222
- if (await fs9.exists(lockfile)) {
3650
+ if (await fs8.exists(lockfile)) {
4223
3651
  foundLockfiles.push({ lockfile, pm: pmName });
4224
3652
  }
4225
3653
  }
@@ -4251,10 +3679,10 @@ function getRunCommand(pm, script) {
4251
3679
  return [...pm.runPrefix, script];
4252
3680
  }
4253
3681
  // src/detect/index.ts
4254
- async function analyzeProject(fs9, options = {}) {
3682
+ async function analyzeProject(fs8, options = {}) {
4255
3683
  const [packageManager, monorepo] = await Promise.all([
4256
- detectPackageManager(fs9),
4257
- detectMonorepo(fs9)
3684
+ detectPackageManager(fs8),
3685
+ detectMonorepo(fs8)
4258
3686
  ]);
4259
3687
  let targetPath = ".";
4260
3688
  if (monorepo.isMonorepo) {
@@ -4271,8 +3699,8 @@ async function analyzeProject(fs9, options = {}) {
4271
3699
  targetPath = pkg.path;
4272
3700
  }
4273
3701
  const [entryPoint, build] = await Promise.all([
4274
- detectEntryPoint(fs9, targetPath),
4275
- detectBuildInfo(fs9, targetPath)
3702
+ detectEntryPoint(fs8, targetPath),
3703
+ detectBuildInfo(fs8, targetPath)
4276
3704
  ]);
4277
3705
  return { packageManager, monorepo, entryPoint, build };
4278
3706
  }
@@ -4316,17 +3744,17 @@ function shouldValidate(validations, check) {
4316
3744
  return validations.includes(check);
4317
3745
  }
4318
3746
  // src/typecheck/example-typechecker.ts
4319
- import * as fs9 from "node:fs";
4320
- import * as path8 from "node:path";
3747
+ import * as fs8 from "node:fs";
3748
+ import * as path7 from "node:path";
4321
3749
  import ts3 from "typescript";
4322
3750
  function stripCodeBlockMarkers(code) {
4323
3751
  return code.replace(/^```(?:ts|typescript|js|javascript)?\n?/i, "").replace(/\n?```$/i, "").trim();
4324
3752
  }
4325
3753
  function getPackageName(packagePath) {
4326
- const pkgJsonPath = path8.join(packagePath, "package.json");
4327
- if (fs9.existsSync(pkgJsonPath)) {
3754
+ const pkgJsonPath = path7.join(packagePath, "package.json");
3755
+ if (fs8.existsSync(pkgJsonPath)) {
4328
3756
  try {
4329
- const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
3757
+ const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
4330
3758
  return pkgJson.name;
4331
3759
  } catch {
4332
3760
  return;
@@ -4336,12 +3764,12 @@ function getPackageName(packagePath) {
4336
3764
  }
4337
3765
  function findTsConfig(packagePath) {
4338
3766
  let dir = packagePath;
4339
- while (dir !== path8.dirname(dir)) {
4340
- const tsConfigPath = path8.join(dir, "tsconfig.json");
4341
- if (fs9.existsSync(tsConfigPath)) {
3767
+ while (dir !== path7.dirname(dir)) {
3768
+ const tsConfigPath = path7.join(dir, "tsconfig.json");
3769
+ if (fs8.existsSync(tsConfigPath)) {
4342
3770
  return tsConfigPath;
4343
3771
  }
4344
- dir = path8.dirname(dir);
3772
+ dir = path7.dirname(dir);
4345
3773
  }
4346
3774
  return;
4347
3775
  }
@@ -4357,10 +3785,10 @@ function createVirtualSource(example, packageName, exportNames) {
4357
3785
  `);
4358
3786
  }
4359
3787
  function getCompilerOptions(tsconfigPath) {
4360
- if (tsconfigPath && fs9.existsSync(tsconfigPath)) {
3788
+ if (tsconfigPath && fs8.existsSync(tsconfigPath)) {
4361
3789
  const configFile = ts3.readConfigFile(tsconfigPath, ts3.sys.readFile);
4362
3790
  if (!configFile.error) {
4363
- const parsed = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys, path8.dirname(tsconfigPath));
3791
+ const parsed = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys, path7.dirname(tsconfigPath));
4364
3792
  return {
4365
3793
  ...parsed.options,
4366
3794
  noEmit: true,
@@ -4386,7 +3814,7 @@ function typecheckExample(example, packagePath, options = {}) {
4386
3814
  const tsconfigPath = options.tsconfig ?? findTsConfig(packagePath);
4387
3815
  const compilerOptions = getCompilerOptions(tsconfigPath);
4388
3816
  const virtualSource = createVirtualSource(cleanCode, packageName, exportNames);
4389
- const virtualFileName = path8.join(packagePath, "__doccov_example__.ts");
3817
+ const virtualFileName = path7.join(packagePath, "__doccov_example__.ts");
4390
3818
  const hasImport = packageName !== undefined && exportNames && exportNames.length > 0;
4391
3819
  const lineOffset = hasImport ? 2 : 0;
4392
3820
  const sourceFile = ts3.createSourceFile(virtualFileName, virtualSource, ts3.ScriptTarget.ES2022, true);
@@ -4457,25 +3885,25 @@ function typecheckExamples(examples, packagePath, options = {}) {
4457
3885
  }
4458
3886
 
4459
3887
  // src/utils/example-runner.ts
4460
- import { spawn } from "node:child_process";
4461
- import * as fs10 from "node:fs";
3888
+ import { spawn as spawn2 } from "node:child_process";
3889
+ import * as fs9 from "node:fs";
4462
3890
  import * as os from "node:os";
4463
- import * as path9 from "node:path";
3891
+ import * as path8 from "node:path";
4464
3892
  function stripCodeBlockMarkers2(code) {
4465
3893
  return code.replace(/^```(?:ts|typescript|js|javascript)?\n?/i, "").replace(/\n?```$/i, "").trim();
4466
3894
  }
4467
3895
  async function runExample(code, options = {}) {
4468
3896
  const { timeout = 5000, cwd = process.cwd() } = options;
4469
3897
  const cleanCode = stripCodeBlockMarkers2(code);
4470
- const tmpFile = path9.join(cwd, `doccov-example-${Date.now()}-${Math.random().toString(36).slice(2)}.ts`);
3898
+ const tmpFile = path8.join(cwd, `doccov-example-${Date.now()}-${Math.random().toString(36).slice(2)}.ts`);
4471
3899
  try {
4472
- fs10.writeFileSync(tmpFile, cleanCode, "utf-8");
3900
+ fs9.writeFileSync(tmpFile, cleanCode, "utf-8");
4473
3901
  const startTime = Date.now();
4474
3902
  return await new Promise((resolve5) => {
4475
3903
  let stdout = "";
4476
3904
  let stderr = "";
4477
3905
  let killed = false;
4478
- const proc = spawn("node", ["--experimental-strip-types", tmpFile], {
3906
+ const proc = spawn2("node", ["--experimental-strip-types", tmpFile], {
4479
3907
  cwd,
4480
3908
  timeout,
4481
3909
  stdio: ["ignore", "pipe", "pipe"]
@@ -4524,7 +3952,7 @@ async function runExample(code, options = {}) {
4524
3952
  });
4525
3953
  } finally {
4526
3954
  try {
4527
- fs10.unlinkSync(tmpFile);
3955
+ fs9.unlinkSync(tmpFile);
4528
3956
  } catch {}
4529
3957
  }
4530
3958
  }
@@ -4539,15 +3967,15 @@ async function runExamples(examples, options = {}) {
4539
3967
  return results;
4540
3968
  }
4541
3969
  function detectPackageManager2(cwd) {
4542
- if (fs10.existsSync(path9.join(cwd, "bun.lockb")))
3970
+ if (fs9.existsSync(path8.join(cwd, "bun.lockb")))
4543
3971
  return "bun";
4544
- if (fs10.existsSync(path9.join(cwd, "bun.lock")))
3972
+ if (fs9.existsSync(path8.join(cwd, "bun.lock")))
4545
3973
  return "bun";
4546
- if (fs10.existsSync(path9.join(cwd, "pnpm-lock.yaml")))
3974
+ if (fs9.existsSync(path8.join(cwd, "pnpm-lock.yaml")))
4547
3975
  return "pnpm";
4548
- if (fs10.existsSync(path9.join(cwd, "yarn.lock")))
3976
+ if (fs9.existsSync(path8.join(cwd, "yarn.lock")))
4549
3977
  return "yarn";
4550
- if (fs10.existsSync(path9.join(cwd, "package-lock.json")))
3978
+ if (fs9.existsSync(path8.join(cwd, "package-lock.json")))
4551
3979
  return "npm";
4552
3980
  return "npm";
4553
3981
  }
@@ -4568,7 +3996,7 @@ async function runCommand(cmd, args, options) {
4568
3996
  let stdout = "";
4569
3997
  let stderr = "";
4570
3998
  let killed = false;
4571
- const proc = spawn(cmd, args, {
3999
+ const proc = spawn2(cmd, args, {
4572
4000
  cwd: options.cwd,
4573
4001
  stdio: ["ignore", "pipe", "pipe"]
4574
4002
  });
@@ -4615,12 +4043,12 @@ async function runExamplesWithPackage(examples, options) {
4615
4043
  const { packagePath, packageManager, installTimeout = 60000, timeout = 5000 } = options;
4616
4044
  const startTime = Date.now();
4617
4045
  const results = new Map;
4618
- const absolutePackagePath = path9.resolve(packagePath);
4619
- const workDir = path9.join(os.tmpdir(), `doccov-examples-${Date.now()}-${Math.random().toString(36).slice(2)}`);
4046
+ const absolutePackagePath = path8.resolve(packagePath);
4047
+ const workDir = path8.join(os.tmpdir(), `doccov-examples-${Date.now()}-${Math.random().toString(36).slice(2)}`);
4620
4048
  try {
4621
- fs10.mkdirSync(workDir, { recursive: true });
4049
+ fs9.mkdirSync(workDir, { recursive: true });
4622
4050
  const pkgJson = { name: "doccov-example-runner", type: "module" };
4623
- fs10.writeFileSync(path9.join(workDir, "package.json"), JSON.stringify(pkgJson, null, 2));
4051
+ fs9.writeFileSync(path8.join(workDir, "package.json"), JSON.stringify(pkgJson, null, 2));
4624
4052
  const pm = packageManager ?? detectPackageManager2(options.cwd ?? process.cwd());
4625
4053
  const { cmd, args } = getInstallCommand2(pm, absolutePackagePath);
4626
4054
  const installResult = await runCommand(cmd, args, {
@@ -4648,7 +4076,7 @@ async function runExamplesWithPackage(examples, options) {
4648
4076
  };
4649
4077
  } finally {
4650
4078
  try {
4651
- fs10.rmSync(workDir, { recursive: true, force: true });
4079
+ fs9.rmSync(workDir, { recursive: true, force: true });
4652
4080
  } catch {}
4653
4081
  }
4654
4082
  }
@@ -4827,9 +4255,12 @@ async function validateExamples(exports, options) {
4827
4255
  }
4828
4256
  return result;
4829
4257
  }
4830
- // src/analysis/run-analysis.ts
4831
- import * as fs12 from "node:fs";
4258
+ // src/extractor.ts
4832
4259
  import * as path13 from "node:path";
4260
+
4261
+ // src/analysis/run-analysis.ts
4262
+ import * as fs11 from "node:fs";
4263
+ import * as path12 from "node:path";
4833
4264
  // src/utils/type-utils.ts
4834
4265
  function getTypeId(type, typeChecker) {
4835
4266
  const internalId = type.id;
@@ -4952,7 +4383,7 @@ function collectReferencedTypesFromNode(node, typeChecker, referencedTypes) {
4952
4383
  }
4953
4384
 
4954
4385
  // src/analysis/context.ts
4955
- import * as path11 from "node:path";
4386
+ import * as path10 from "node:path";
4956
4387
 
4957
4388
  // src/options.ts
4958
4389
  var DEFAULT_MAX_TYPE_DEPTH = 20;
@@ -4973,7 +4404,7 @@ function normalizeDocCovOptions(options = {}) {
4973
4404
  }
4974
4405
 
4975
4406
  // src/analysis/program.ts
4976
- import * as path10 from "node:path";
4407
+ import * as path9 from "node:path";
4977
4408
  var DEFAULT_COMPILER_OPTIONS = {
4978
4409
  target: ts.ScriptTarget.Latest,
4979
4410
  module: ts.ModuleKind.CommonJS,
@@ -4983,14 +4414,14 @@ var DEFAULT_COMPILER_OPTIONS = {
4983
4414
  };
4984
4415
  function createProgram({
4985
4416
  entryFile,
4986
- baseDir = path10.dirname(entryFile),
4417
+ baseDir = path9.dirname(entryFile),
4987
4418
  content
4988
4419
  }) {
4989
4420
  const configPath = ts.findConfigFile(baseDir, ts.sys.fileExists, "tsconfig.json");
4990
4421
  let compilerOptions = { ...DEFAULT_COMPILER_OPTIONS };
4991
4422
  if (configPath) {
4992
4423
  const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
4993
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path10.dirname(configPath));
4424
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path9.dirname(configPath));
4994
4425
  compilerOptions = { ...compilerOptions, ...parsedConfig.options };
4995
4426
  }
4996
4427
  const allowJsVal = compilerOptions.allowJs;
@@ -5028,7 +4459,7 @@ function createAnalysisContext({
5028
4459
  options,
5029
4460
  detectedSchemas
5030
4461
  }) {
5031
- const baseDir = packageDir ?? path11.dirname(entryFile);
4462
+ const baseDir = packageDir ?? path10.dirname(entryFile);
5032
4463
  const normalizedOptions = normalizeDocCovOptions(options);
5033
4464
  const programResult = createProgram({ entryFile, baseDir, content });
5034
4465
  if (!programResult.sourceFile) {
@@ -5049,8 +4480,8 @@ function createAnalysisContext({
5049
4480
  }
5050
4481
 
5051
4482
  // src/analysis/spec-builder.ts
5052
- import * as fs11 from "node:fs";
5053
- import * as path12 from "node:path";
4483
+ import * as fs10 from "node:fs";
4484
+ import * as path11 from "node:path";
5054
4485
  import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
5055
4486
 
5056
4487
  // src/analysis/decorator-utils.ts
@@ -6740,10 +6171,10 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
6740
6171
  if (member.questionToken || isOptionalSymbol) {
6741
6172
  flags.optional = true;
6742
6173
  }
6743
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.ReadonlyKeyword)) {
6174
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ReadonlyKeyword)) {
6744
6175
  flags.readonly = true;
6745
6176
  }
6746
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.StaticKeyword)) {
6177
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.StaticKeyword)) {
6747
6178
  flags.static = true;
6748
6179
  }
6749
6180
  members.push({
@@ -6865,20 +6296,20 @@ function serializeSignature(signature, checker, typeRefs, referencedTypes, doc,
6865
6296
  function getMemberVisibility(modifiers) {
6866
6297
  if (!modifiers)
6867
6298
  return;
6868
- if (modifiers.some((mod2) => mod2.kind === ts.SyntaxKind.PrivateKeyword)) {
6299
+ if (modifiers.some((mod) => mod.kind === ts.SyntaxKind.PrivateKeyword)) {
6869
6300
  return "private";
6870
6301
  }
6871
- if (modifiers.some((mod2) => mod2.kind === ts.SyntaxKind.ProtectedKeyword)) {
6302
+ if (modifiers.some((mod) => mod.kind === ts.SyntaxKind.ProtectedKeyword)) {
6872
6303
  return "protected";
6873
6304
  }
6874
- if (modifiers.some((mod2) => mod2.kind === ts.SyntaxKind.PublicKeyword)) {
6305
+ if (modifiers.some((mod) => mod.kind === ts.SyntaxKind.PublicKeyword)) {
6875
6306
  return "public";
6876
6307
  }
6877
6308
  return;
6878
6309
  }
6879
6310
  function getMethodFlags(member) {
6880
6311
  const flags = {};
6881
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.StaticKeyword)) {
6312
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.StaticKeyword)) {
6882
6313
  flags.static = true;
6883
6314
  }
6884
6315
  if (member.asteriskToken) {
@@ -7063,7 +6494,7 @@ function serializeInterfaceMembers(declaration, checker, typeRefs, referencedTyp
7063
6494
  if (member.questionToken) {
7064
6495
  flags.optional = true;
7065
6496
  }
7066
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.ReadonlyKeyword)) {
6497
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ReadonlyKeyword)) {
7067
6498
  flags.readonly = true;
7068
6499
  }
7069
6500
  members.push({
@@ -7361,7 +6792,7 @@ function extractNamespaceMembers(declaration, checker) {
7361
6792
  return members;
7362
6793
  }
7363
6794
  for (const statement of body.statements) {
7364
- const hasExportModifier = ts.canHaveModifiers(statement) && ts.getModifiers(statement)?.some((mod2) => mod2.kind === ts.SyntaxKind.ExportKeyword);
6795
+ const hasExportModifier = ts.canHaveModifiers(statement) && ts.getModifiers(statement)?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword);
7365
6796
  if (!hasExportModifier) {
7366
6797
  continue;
7367
6798
  }
@@ -7571,27 +7002,51 @@ function serializeVariable(declaration, symbol, context) {
7571
7002
  const typeRefs = typeRegistry.getTypeRefs();
7572
7003
  const referencedTypes = typeRegistry.getReferencedTypes();
7573
7004
  const symbolName = symbol.getName();
7574
- const detectedSchema = context.detectedSchemas?.get(symbolName);
7575
- if (detectedSchema) {
7005
+ const standardSchema = context.detectedSchemas?.get(symbolName);
7006
+ if (standardSchema) {
7576
7007
  return {
7577
7008
  id: symbolName,
7578
7009
  name: symbolName,
7579
7010
  ...metadata,
7580
7011
  kind: "variable",
7581
7012
  deprecated: isSymbolDeprecated(symbol),
7582
- schema: detectedSchema.schema,
7013
+ schema: standardSchema.schema,
7583
7014
  description,
7584
7015
  source: getSourceLocation(declaration),
7585
7016
  tags: [
7586
7017
  ...parsedDoc?.tags ?? [],
7587
- { name: "standardSchema", text: detectedSchema.vendor }
7018
+ { name: "schemaLibrary", text: standardSchema.vendor },
7019
+ { name: "schemaSource", text: "standard-schema" }
7588
7020
  ],
7589
7021
  examples: parsedDoc?.examples
7590
7022
  };
7591
7023
  }
7024
+ if (isSchemaType(variableType, checker)) {
7025
+ const schemaResult = extractSchemaType(variableType, checker);
7026
+ if (schemaResult?.outputType) {
7027
+ collectReferencedTypes(schemaResult.outputType, checker, referencedTypes);
7028
+ const outputTypeRef = formatTypeReference(schemaResult.outputType, checker, typeRefs, referencedTypes);
7029
+ return {
7030
+ id: symbolName,
7031
+ name: symbolName,
7032
+ ...metadata,
7033
+ kind: "variable",
7034
+ deprecated: isSymbolDeprecated(symbol),
7035
+ type: outputTypeRef,
7036
+ description,
7037
+ source: getSourceLocation(declaration),
7038
+ tags: [
7039
+ ...parsedDoc?.tags ?? [],
7040
+ { name: "schemaLibrary", text: schemaResult.adapter.id },
7041
+ { name: "schemaSource", text: "static-ast" }
7042
+ ],
7043
+ examples: parsedDoc?.examples
7044
+ };
7045
+ }
7046
+ }
7592
7047
  return {
7593
- id: symbol.getName(),
7594
- name: symbol.getName(),
7048
+ id: symbolName,
7049
+ name: symbolName,
7595
7050
  ...metadata,
7596
7051
  kind: "variable",
7597
7052
  deprecated: isSymbolDeprecated(symbol),
@@ -7677,9 +7132,9 @@ function createDefaultGenerationInfo(entryFile) {
7677
7132
  }
7678
7133
  function buildOpenPkgSpec(context, resolveExternalTypes, generation) {
7679
7134
  const { baseDir, checker: typeChecker, sourceFile, program, entryFile } = context;
7680
- const packageJsonPath = path12.join(baseDir, "package.json");
7681
- const packageJson = fs11.existsSync(packageJsonPath) ? JSON.parse(fs11.readFileSync(packageJsonPath, "utf-8")) : {};
7682
- const generationInfo = generation ?? createDefaultGenerationInfo(path12.relative(baseDir, entryFile));
7135
+ const packageJsonPath = path11.join(baseDir, "package.json");
7136
+ const packageJson = fs10.existsSync(packageJsonPath) ? JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8")) : {};
7137
+ const generationInfo = generation ?? createDefaultGenerationInfo(path11.relative(baseDir, entryFile));
7683
7138
  const spec = {
7684
7139
  $schema: SCHEMA_URL,
7685
7140
  openpkg: SCHEMA_VERSION,
@@ -7878,11 +7333,11 @@ function deriveImportPath(sourceFile, baseDir) {
7878
7333
  if (!sourceFile) {
7879
7334
  return;
7880
7335
  }
7881
- const relative6 = path12.relative(baseDir, sourceFile);
7882
- if (!relative6 || relative6.startsWith("..")) {
7336
+ const relative5 = path11.relative(baseDir, sourceFile);
7337
+ if (!relative5 || relative5.startsWith("..")) {
7883
7338
  return;
7884
7339
  }
7885
- const normalized = relative6.replace(/\\/g, "/");
7340
+ const normalized = relative5.replace(/\\/g, "/");
7886
7341
  const withoutExt = stripExtensions(normalized);
7887
7342
  if (!withoutExt) {
7888
7343
  return;
@@ -7921,11 +7376,11 @@ function withExportName(entry, exportName) {
7921
7376
  function findNearestPackageJson(startDir) {
7922
7377
  let current = startDir;
7923
7378
  while (true) {
7924
- const candidate = path13.join(current, "package.json");
7925
- if (fs12.existsSync(candidate)) {
7379
+ const candidate = path12.join(current, "package.json");
7380
+ if (fs11.existsSync(candidate)) {
7926
7381
  return candidate;
7927
7382
  }
7928
- const parent = path13.dirname(current);
7383
+ const parent = path12.dirname(current);
7929
7384
  if (parent === current) {
7930
7385
  return;
7931
7386
  }
@@ -7953,11 +7408,11 @@ function canResolveExternalModules(program, baseDir) {
7953
7408
  function hasNodeModulesDirectoryFallback(startDir) {
7954
7409
  let current = startDir;
7955
7410
  while (true) {
7956
- const candidate = path13.join(current, "node_modules");
7957
- if (fs12.existsSync(candidate)) {
7411
+ const candidate = path12.join(current, "node_modules");
7412
+ if (fs11.existsSync(candidate)) {
7958
7413
  return true;
7959
7414
  }
7960
- const parent = path13.dirname(current);
7415
+ const parent = path12.dirname(current);
7961
7416
  if (parent === current) {
7962
7417
  break;
7963
7418
  }
@@ -8002,8 +7457,8 @@ function hasExternalImports(sourceFile) {
8002
7457
  if (ts.isImportDeclaration(node) && node.moduleSpecifier) {
8003
7458
  const specifier = node.moduleSpecifier;
8004
7459
  if (ts.isStringLiteral(specifier)) {
8005
- const modulePath2 = specifier.text;
8006
- if (!modulePath2.startsWith(".") && !modulePath2.startsWith("/")) {
7460
+ const modulePath = specifier.text;
7461
+ if (!modulePath.startsWith(".") && !modulePath.startsWith("/")) {
8007
7462
  found = true;
8008
7463
  }
8009
7464
  }
@@ -8113,11 +7568,27 @@ function runAnalysis(input, generationInput) {
8113
7568
 
8114
7569
  // src/extractor.ts
8115
7570
  async function extractPackageSpec(entryFile, packageDir, content, options) {
7571
+ const baseDir = packageDir ?? path13.dirname(entryFile);
7572
+ const schemaMode = options?.schemaExtraction ?? "static";
7573
+ let detectedSchemas;
7574
+ if (schemaMode === "runtime" || schemaMode === "hybrid") {
7575
+ const extraction = await extractStandardSchemasFromProject(entryFile, baseDir);
7576
+ if (extraction.schemas.size > 0) {
7577
+ detectedSchemas = new Map;
7578
+ for (const [name, result2] of extraction.schemas) {
7579
+ detectedSchemas.set(name, {
7580
+ schema: result2.outputSchema,
7581
+ vendor: result2.vendor
7582
+ });
7583
+ }
7584
+ }
7585
+ }
8116
7586
  const result = runAnalysis({
8117
7587
  entryFile,
8118
7588
  packageDir,
8119
7589
  content,
8120
- options
7590
+ options,
7591
+ detectedSchemas
8121
7592
  });
8122
7593
  return result.spec;
8123
7594
  }
@@ -8232,11 +7703,11 @@ async function fetchSpecFromGitHubWithPath(parsed, specPath = "openpkg.json") {
8232
7703
  }
8233
7704
  // src/install/index.ts
8234
7705
  var DEFAULT_FALLBACK_ORDER = ["bun", "npm"];
8235
- async function installDependencies(fs13, cwd, runCommand2, options = {}) {
7706
+ async function installDependencies(fs12, cwd, runCommand2, options = {}) {
8236
7707
  const { timeout = 180000, fallbackOrder = DEFAULT_FALLBACK_ORDER, onProgress } = options;
8237
7708
  const errors = [];
8238
7709
  onProgress?.({ stage: "installing", message: "Detecting package manager..." });
8239
- const pmInfo = await detectPackageManager(fs13);
7710
+ const pmInfo = await detectPackageManager(fs12);
8240
7711
  if (pmInfo.lockfile) {
8241
7712
  onProgress?.({
8242
7713
  stage: "installing",
@@ -8311,10 +7782,10 @@ function getFallbackInstallCommand(pm) {
8311
7782
  }
8312
7783
  function createNodeCommandRunner() {
8313
7784
  return async (cmd, args, options) => {
8314
- const { execSync: execSync2 } = await import("node:child_process");
7785
+ const { execSync } = await import("node:child_process");
8315
7786
  const fullCmd = [cmd, ...args].join(" ");
8316
7787
  try {
8317
- const stdout = execSync2(fullCmd, {
7788
+ const stdout = execSync(fullCmd, {
8318
7789
  cwd: options.cwd,
8319
7790
  stdio: "pipe",
8320
7791
  timeout: options.timeout ?? 180000
@@ -9141,7 +8612,7 @@ function getDocsImpactSummary(diff) {
9141
8612
  }
9142
8613
  // src/openpkg.ts
9143
8614
  import * as fsSync from "node:fs";
9144
- import * as fs13 from "node:fs/promises";
8615
+ import * as fs12 from "node:fs/promises";
9145
8616
  import * as path14 from "node:path";
9146
8617
 
9147
8618
  // src/filtering/apply-filters.ts
@@ -9357,7 +8828,7 @@ class DocCov {
9357
8828
  }
9358
8829
  async analyzeFile(filePath, analyzeOptions = {}) {
9359
8830
  const resolvedPath = path14.resolve(filePath);
9360
- const content = await fs13.readFile(resolvedPath, "utf-8");
8831
+ const content = await fs12.readFile(resolvedPath, "utf-8");
9361
8832
  const packageDir = resolvePackageDir(resolvedPath);
9362
8833
  const spec = await extractPackageSpec(resolvedPath, packageDir, content, this.options);
9363
8834
  return this.applySpecFilters(spec, analyzeOptions.filters).spec;
@@ -9405,7 +8876,7 @@ class DocCov {
9405
8876
  };
9406
8877
  }
9407
8878
  }
9408
- const content = await fs13.readFile(resolvedPath, "utf-8");
8879
+ const content = await fs12.readFile(resolvedPath, "utf-8");
9409
8880
  const detectedSchemas = await this.detectSchemas(resolvedPath, packageDir);
9410
8881
  const analysis = runAnalysis({
9411
8882
  entryFile: resolvedPath,
@@ -9526,6 +8997,10 @@ class DocCov {
9526
8997
  }
9527
8998
  }
9528
8999
  async detectSchemas(entryFile, packageDir) {
9000
+ const mode = this.options.schemaExtraction ?? "static";
9001
+ if (mode === "static") {
9002
+ return;
9003
+ }
9529
9004
  try {
9530
9005
  const result = await detectRuntimeSchemas({
9531
9006
  baseDir: packageDir,
@@ -9621,113 +9096,13 @@ function resolvePackageDir(entryFile) {
9621
9096
  currentDir = parentDir;
9622
9097
  }
9623
9098
  }
9624
- // src/policies/index.ts
9625
- import * as path15 from "node:path";
9626
- import { minimatch as minimatch2 } from "minimatch";
9627
- function matchesPolicy(exp, policy, baseDir) {
9628
- const filePath = exp.source?.file;
9629
- if (!filePath)
9630
- return false;
9631
- let normalizedPath = filePath;
9632
- if (baseDir && path15.isAbsolute(filePath)) {
9633
- normalizedPath = path15.relative(baseDir, filePath);
9634
- }
9635
- normalizedPath = normalizedPath.replace(/^\.\//, "");
9636
- return minimatch2(normalizedPath, policy.path, { matchBase: true });
9637
- }
9638
- function calculateCoverage(exports) {
9639
- if (exports.length === 0)
9640
- return 100;
9641
- let documented = 0;
9642
- for (const exp of exports) {
9643
- if (exp.description) {
9644
- documented++;
9645
- }
9646
- }
9647
- return Math.round(documented / exports.length * 100);
9648
- }
9649
- function calculateDrift(exports) {
9650
- if (exports.length === 0)
9651
- return 0;
9652
- let withDrift = 0;
9653
- for (const exp of exports) {
9654
- if (exp.docs?.drift && exp.docs.drift.length > 0) {
9655
- withDrift++;
9656
- }
9657
- }
9658
- return Math.round(withDrift / exports.length * 100);
9659
- }
9660
- function countMissingExamples(exports) {
9661
- let missing = 0;
9662
- for (const exp of exports) {
9663
- const hasExample = exp.examples && exp.examples.length > 0;
9664
- if (!hasExample) {
9665
- missing++;
9666
- }
9667
- }
9668
- return missing;
9669
- }
9670
- function evaluatePolicy(policy, allExports, baseDir) {
9671
- const matchedExports = allExports.filter((exp) => matchesPolicy(exp, policy, baseDir));
9672
- const coverageScore = calculateCoverage(matchedExports);
9673
- const driftScore = calculateDrift(matchedExports);
9674
- const missingExamples = countMissingExamples(matchedExports);
9675
- const failures = [];
9676
- if (policy.minCoverage !== undefined && coverageScore < policy.minCoverage) {
9677
- failures.push({
9678
- type: "coverage",
9679
- message: `Coverage ${coverageScore}% below minimum ${policy.minCoverage}%`,
9680
- actual: coverageScore,
9681
- threshold: policy.minCoverage
9682
- });
9683
- }
9684
- if (policy.maxDrift !== undefined && driftScore > policy.maxDrift) {
9685
- failures.push({
9686
- type: "drift",
9687
- message: `Drift ${driftScore}% exceeds maximum ${policy.maxDrift}%`,
9688
- actual: driftScore,
9689
- threshold: policy.maxDrift
9690
- });
9691
- }
9692
- if (policy.requireExamples && missingExamples > 0) {
9693
- failures.push({
9694
- type: "examples",
9695
- message: `${missingExamples} exports missing @example`,
9696
- actual: missingExamples,
9697
- threshold: 0
9698
- });
9699
- }
9700
- return {
9701
- policy,
9702
- matchedExports,
9703
- coverageScore,
9704
- driftScore,
9705
- missingExamples,
9706
- passed: failures.length === 0,
9707
- failures
9708
- };
9709
- }
9710
- function evaluatePolicies(policies, spec, options = {}) {
9711
- const { baseDir } = options;
9712
- const exports = spec.exports ?? [];
9713
- const results = policies.map((policy) => evaluatePolicy(policy, exports, baseDir));
9714
- const passedCount = results.filter((r) => r.passed).length;
9715
- const failedCount = results.length - passedCount;
9716
- return {
9717
- results,
9718
- allPassed: failedCount === 0,
9719
- totalPolicies: policies.length,
9720
- passedCount,
9721
- failedCount
9722
- };
9723
- }
9724
9099
  // src/resolve/index.ts
9725
- import * as path16 from "node:path";
9726
- async function resolveTarget(fs14, options) {
9100
+ import * as path15 from "node:path";
9101
+ async function resolveTarget(fs13, options) {
9727
9102
  let targetDir = options.cwd;
9728
9103
  let packageInfo;
9729
9104
  if (options.package) {
9730
- const mono = await detectMonorepo(fs14);
9105
+ const mono = await detectMonorepo(fs13);
9731
9106
  if (!mono.isMonorepo) {
9732
9107
  throw new Error("Not a monorepo. Remove --package flag for single-package repos.");
9733
9108
  }
@@ -9736,21 +9111,21 @@ async function resolveTarget(fs14, options) {
9736
9111
  const available = mono.packages.map((p) => p.name).join(", ");
9737
9112
  throw new Error(`Package "${options.package}" not found. Available: ${available}`);
9738
9113
  }
9739
- targetDir = path16.join(options.cwd, pkg.path);
9114
+ targetDir = path15.join(options.cwd, pkg.path);
9740
9115
  packageInfo = pkg;
9741
9116
  }
9742
9117
  let entryFile;
9743
9118
  let entryPointInfo;
9744
9119
  if (!options.entry) {
9745
- entryPointInfo = await detectEntryPoint(fs14, getRelativePath(options.cwd, targetDir));
9746
- entryFile = path16.join(targetDir, entryPointInfo.path);
9120
+ entryPointInfo = await detectEntryPoint(fs13, getRelativePath(options.cwd, targetDir));
9121
+ entryFile = path15.join(targetDir, entryPointInfo.path);
9747
9122
  } else {
9748
- const explicitPath = path16.resolve(targetDir, options.entry);
9749
- const isDirectory = await isDir(fs14, getRelativePath(options.cwd, explicitPath));
9123
+ const explicitPath = path15.resolve(targetDir, options.entry);
9124
+ const isDirectory = await isDir(fs13, getRelativePath(options.cwd, explicitPath));
9750
9125
  if (isDirectory) {
9751
9126
  targetDir = explicitPath;
9752
- entryPointInfo = await detectEntryPoint(fs14, getRelativePath(options.cwd, explicitPath));
9753
- entryFile = path16.join(explicitPath, entryPointInfo.path);
9127
+ entryPointInfo = await detectEntryPoint(fs13, getRelativePath(options.cwd, explicitPath));
9128
+ entryFile = path15.join(explicitPath, entryPointInfo.path);
9754
9129
  } else {
9755
9130
  entryFile = explicitPath;
9756
9131
  entryPointInfo = {
@@ -9770,20 +9145,20 @@ async function resolveTarget(fs14, options) {
9770
9145
  function getRelativePath(base, target) {
9771
9146
  if (base === target)
9772
9147
  return ".";
9773
- const rel = path16.relative(base, target);
9148
+ const rel = path15.relative(base, target);
9774
9149
  return rel || ".";
9775
9150
  }
9776
- async function isDir(fs14, relativePath) {
9777
- const hasPackageJson = await fs14.exists(path16.join(relativePath, "package.json"));
9151
+ async function isDir(fs13, relativePath) {
9152
+ const hasPackageJson = await fs13.exists(path15.join(relativePath, "package.json"));
9778
9153
  if (hasPackageJson)
9779
9154
  return true;
9780
9155
  const commonEntryFiles = ["index.ts", "index.tsx", "src/index.ts", "main.ts"];
9781
9156
  for (const entry of commonEntryFiles) {
9782
- if (await fs14.exists(path16.join(relativePath, entry))) {
9157
+ if (await fs13.exists(path15.join(relativePath, entry))) {
9783
9158
  return true;
9784
9159
  }
9785
9160
  }
9786
- return !path16.extname(relativePath);
9161
+ return !path15.extname(relativePath);
9787
9162
  }
9788
9163
  // src/scan/github-context.ts
9789
9164
  function parseGitHubUrl2(url) {
@@ -9794,8 +9169,8 @@ function parseGitHubUrl2(url) {
9794
9169
  return null;
9795
9170
  }
9796
9171
  }
9797
- async function fetchRawFile(owner, repo, ref, path17, authToken) {
9798
- const url = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path17}`;
9172
+ async function fetchRawFile(owner, repo, ref, path16, authToken) {
9173
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path16}`;
9799
9174
  try {
9800
9175
  const headers = {};
9801
9176
  if (authToken) {
@@ -10026,7 +9401,6 @@ export {
10026
9401
  validateExamples,
10027
9402
  typecheckExamples,
10028
9403
  typecheckExample,
10029
- tryExtractStandardSchema,
10030
9404
  shouldValidate,
10031
9405
  serializeJSDoc,
10032
9406
  saveSpecCache,
@@ -10037,6 +9411,7 @@ export {
10037
9411
  runExamples,
10038
9412
  runExample,
10039
9413
  resolveTarget,
9414
+ resolveCompiledPath,
10040
9415
  renderSparkline,
10041
9416
  renderApiSurface,
10042
9417
  readPackageJson,
@@ -10049,18 +9424,16 @@ export {
10049
9424
  parseJSDocToPatch,
10050
9425
  parseGitHubUrl,
10051
9426
  parseExamplesFlag,
10052
- parseCodeOwners,
10053
9427
  parseAssertions,
10054
9428
  mergeFixes,
10055
9429
  mergeFilters,
10056
- mergeConfig,
10057
9430
  loadSpecCache,
10058
9431
  loadSnapshotsForDays,
10059
9432
  loadSnapshots,
10060
- loadCodeOwners,
10061
9433
  loadCachedReport,
10062
9434
  listWorkspacePackages,
10063
9435
  isStandardJSONSchema,
9436
+ isSchemaType,
10064
9437
  isFixableDrift,
10065
9438
  isExecutableLang,
10066
9439
  isCachedReportValid,
@@ -10074,22 +9447,18 @@ export {
10074
9447
  groupDriftsByCategory,
10075
9448
  getUndocumentedExports,
10076
9449
  getTrend,
9450
+ getSupportedLibraries,
10077
9451
  getSpecCachePath,
10078
9452
  getRunCommand,
10079
- getRulesForKind,
10080
- getRule,
10081
9453
  getReportPath,
9454
+ getRegisteredAdapters,
10082
9455
  getPrimaryBuildScript,
10083
9456
  getInstallCommand,
10084
- getFileBlame,
10085
9457
  getExtendedTrend,
10086
9458
  getDriftSummary,
10087
9459
  getDocumentedExports,
10088
9460
  getDocsImpactSummary,
10089
9461
  getDiffReportPath,
10090
- getDefaultConfig,
10091
- getCoverageRules,
10092
- getBlameForLines,
10093
9462
  generateWeeklySummaries,
10094
9463
  generateReportFromEnriched,
10095
9464
  generateReport,
@@ -10100,22 +9469,21 @@ export {
10100
9469
  formatDelta,
10101
9470
  findRemovedReferences,
10102
9471
  findPackageByName,
10103
- findOwners,
10104
9472
  findJSDocLocation,
10105
9473
  findExportReferences,
10106
9474
  findDeprecatedReferences,
9475
+ findAdapter,
10107
9476
  fetchSpecFromGitHub,
10108
9477
  fetchSpec,
10109
9478
  fetchGitHubContext,
10110
- extractViaStandardSchema,
9479
+ extractStandardSchemasFromProject,
9480
+ extractStandardSchemas,
10111
9481
  extractSpecSummary,
9482
+ extractSchemaType,
9483
+ extractSchemaOutputType,
10112
9484
  extractPackageSpec,
10113
9485
  extractImports,
10114
9486
  extractFunctionCalls,
10115
- evaluateQuality,
10116
- evaluatePolicy,
10117
- evaluatePolicies,
10118
- evaluateExportQuality,
10119
9487
  ensureSpecCoverage,
10120
9488
  enrichSpec,
10121
9489
  diffSpecWithDocs,
@@ -10143,33 +9511,23 @@ export {
10143
9511
  buildDisplayUrl,
10144
9512
  buildCloneUrl,
10145
9513
  blockReferencesExport,
10146
- attributeOwners,
10147
9514
  applyPatchToJSDoc,
10148
9515
  applyEdits,
10149
- analyzeSpecOwnership,
10150
- analyzeSpecContributors,
10151
9516
  analyzeProject,
10152
- analyzeOwnership,
10153
9517
  analyzeFile,
10154
9518
  analyzeDocsImpact,
10155
- analyzeContributors,
10156
9519
  analyze,
10157
9520
  VALIDATION_INFO,
10158
- TSDOC_RULES,
10159
9521
  SandboxFileSystem,
10160
- STYLE_RULES,
10161
9522
  SPEC_CACHE_FILE,
10162
9523
  RETENTION_DAYS,
10163
9524
  REPORT_VERSION,
10164
9525
  REPORT_EXTENSIONS,
10165
9526
  NodeFileSystem,
10166
- KNOWN_VENDORS,
10167
9527
  HISTORY_DIR,
10168
9528
  DocCov,
10169
9529
  DEFAULT_REPORT_PATH,
10170
9530
  DEFAULT_REPORT_DIR,
10171
- CORE_RULES,
10172
9531
  CACHE_VERSION,
10173
- BUILTIN_RULES,
10174
9532
  ALL_VALIDATIONS
10175
9533
  };