@doccov/sdk 0.18.0 → 0.19.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 +393 -817
  2. package/dist/index.js +572 -1237
  3. package/package.json +6 -2
package/dist/index.js CHANGED
@@ -4,13 +4,13 @@ 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;
@@ -18,154 +18,345 @@ var __toESM = (mod2, isNodeMode, target) => {
18
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
20
  // src/analysis/schema-detection.ts
21
- import * as fs from "node:fs";
21
+ async function detectRuntimeSchemas(_context) {
22
+ return {
23
+ schemas: new Map,
24
+ errors: []
25
+ };
26
+ }
27
+ function clearSchemaCache() {}
28
+ // src/extract/schema/types.ts
29
+ function isTypeReference(type) {
30
+ return !!(type.flags & 524288 && type.objectFlags && type.objectFlags & 4);
31
+ }
32
+ function getNonNullableType(type) {
33
+ if (type.isUnion()) {
34
+ const nonNullable = type.types.filter((t) => !(t.flags & 32768) && !(t.flags & 65536));
35
+ if (nonNullable.length === 1) {
36
+ return nonNullable[0];
37
+ }
38
+ }
39
+ return type;
40
+ }
41
+ // src/extract/schema/adapters/zod.ts
42
+ var ZOD_TYPE_PATTERN = /^Zod[A-Z]/;
43
+ var zodAdapter = {
44
+ id: "zod",
45
+ packages: ["zod"],
46
+ matches(type, checker) {
47
+ const typeName = checker.typeToString(type);
48
+ return ZOD_TYPE_PATTERN.test(typeName);
49
+ },
50
+ extractOutputType(type, checker) {
51
+ const outputSymbol = type.getProperty("_output");
52
+ if (outputSymbol) {
53
+ return checker.getTypeOfSymbol(outputSymbol);
54
+ }
55
+ const typeSymbol = type.getProperty("_type");
56
+ if (typeSymbol) {
57
+ return checker.getTypeOfSymbol(typeSymbol);
58
+ }
59
+ return null;
60
+ },
61
+ extractInputType(type, checker) {
62
+ const inputSymbol = type.getProperty("_input");
63
+ if (inputSymbol) {
64
+ return checker.getTypeOfSymbol(inputSymbol);
65
+ }
66
+ return null;
67
+ }
68
+ };
22
69
 
23
- // src/extraction/standard-schema.ts
24
- function isStandardJSONSchema(value) {
25
- if (typeof value !== "object" || value === null) {
26
- return false;
70
+ // src/extract/schema/adapters/valibot.ts
71
+ var VALIBOT_TYPE_PATTERN = /Schema(<|$)/;
72
+ var valibotAdapter = {
73
+ id: "valibot",
74
+ packages: ["valibot"],
75
+ matches(type, checker) {
76
+ const typeName = checker.typeToString(type);
77
+ return VALIBOT_TYPE_PATTERN.test(typeName) && !typeName.includes("Zod");
78
+ },
79
+ extractOutputType(type, checker) {
80
+ const typesSymbol = type.getProperty("~types");
81
+ if (!typesSymbol) {
82
+ return null;
83
+ }
84
+ let typesType = checker.getTypeOfSymbol(typesSymbol);
85
+ typesType = getNonNullableType(typesType);
86
+ const outputSymbol = typesType.getProperty("output");
87
+ if (!outputSymbol) {
88
+ return null;
89
+ }
90
+ return checker.getTypeOfSymbol(outputSymbol);
91
+ },
92
+ extractInputType(type, checker) {
93
+ const typesSymbol = type.getProperty("~types");
94
+ if (!typesSymbol) {
95
+ return null;
96
+ }
97
+ let typesType = checker.getTypeOfSymbol(typesSymbol);
98
+ typesType = getNonNullableType(typesType);
99
+ const inputSymbol = typesType.getProperty("input");
100
+ if (!inputSymbol) {
101
+ return null;
102
+ }
103
+ return checker.getTypeOfSymbol(inputSymbol);
27
104
  }
28
- const obj = value;
29
- const standard = obj["~standard"];
30
- if (typeof standard !== "object" || standard === null) {
31
- return false;
105
+ };
106
+
107
+ // src/extract/schema/adapters/typebox.ts
108
+ var TYPEBOX_TYPE_PATTERN = /^T[A-Z]/;
109
+ var typeboxAdapter = {
110
+ id: "typebox",
111
+ packages: ["@sinclair/typebox"],
112
+ matches(type, checker) {
113
+ const typeName = checker.typeToString(type);
114
+ if (!TYPEBOX_TYPE_PATTERN.test(typeName)) {
115
+ return false;
116
+ }
117
+ const typeProperty = type.getProperty("type");
118
+ return typeProperty !== undefined;
119
+ },
120
+ extractOutputType(type, checker) {
121
+ const staticSymbol = type.getProperty("static");
122
+ if (staticSymbol) {
123
+ return checker.getTypeOfSymbol(staticSymbol);
124
+ }
125
+ return null;
32
126
  }
33
- const stdObj = standard;
34
- if (typeof stdObj.version !== "number") {
35
- return false;
127
+ };
128
+
129
+ // src/extract/schema/adapters/arktype.ts
130
+ var ARKTYPE_TYPE_PATTERN = /^Type</;
131
+ var arktypeAdapter = {
132
+ id: "arktype",
133
+ packages: ["arktype"],
134
+ matches(type, checker) {
135
+ const typeName = checker.typeToString(type);
136
+ return ARKTYPE_TYPE_PATTERN.test(typeName);
137
+ },
138
+ extractOutputType(type, checker) {
139
+ if (!isTypeReference(type)) {
140
+ return null;
141
+ }
142
+ const args = checker.getTypeArguments(type);
143
+ if (args.length < 1) {
144
+ return null;
145
+ }
146
+ return args[0];
147
+ },
148
+ extractInputType(type, checker) {
149
+ if (!isTypeReference(type)) {
150
+ return null;
151
+ }
152
+ const args = checker.getTypeArguments(type);
153
+ if (args.length < 2) {
154
+ return null;
155
+ }
156
+ return args[1];
36
157
  }
37
- const jsonSchema = stdObj.jsonSchema;
38
- if (typeof jsonSchema !== "object" || jsonSchema === null) {
39
- return false;
158
+ };
159
+
160
+ // src/extract/schema/registry.ts
161
+ var adapters = [
162
+ zodAdapter,
163
+ arktypeAdapter,
164
+ typeboxAdapter,
165
+ valibotAdapter
166
+ ];
167
+ function findAdapter(type, checker) {
168
+ for (const adapter of adapters) {
169
+ if (adapter.matches(type, checker)) {
170
+ return adapter;
171
+ }
40
172
  }
41
- const jsonSchemaObj = jsonSchema;
42
- return typeof jsonSchemaObj.output === "function";
173
+ return null;
43
174
  }
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 });
48
- return {
49
- schema: extractedSchema,
50
- vendor: standard.vendor,
51
- version: standard.version
52
- };
175
+ function isSchemaType(type, checker) {
176
+ return findAdapter(type, checker) !== null;
53
177
  }
54
- function tryExtractStandardSchema(value, options = {}) {
55
- if (!isStandardJSONSchema(value)) {
178
+ function extractSchemaOutputType(type, checker) {
179
+ const adapter = findAdapter(type, checker);
180
+ if (!adapter) {
56
181
  return null;
57
182
  }
58
- try {
59
- return extractViaStandardSchema(value, options);
60
- } catch {
183
+ return adapter.extractOutputType(type, checker);
184
+ }
185
+ function extractSchemaType(type, checker) {
186
+ const adapter = findAdapter(type, checker);
187
+ if (!adapter) {
61
188
  return null;
62
189
  }
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
- };
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;
190
+ const outputType = adapter.extractOutputType(type, checker);
191
+ if (!outputType) {
192
+ return null;
76
193
  }
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;
194
+ const result = {
195
+ adapter,
196
+ outputType
197
+ };
198
+ if (adapter.extractInputType) {
199
+ const inputType = adapter.extractInputType(type, checker);
200
+ if (inputType) {
201
+ result.inputType = inputType;
202
+ }
83
203
  }
204
+ return result;
205
+ }
206
+ function getRegisteredAdapters() {
207
+ return adapters;
208
+ }
209
+ function getSupportedLibraries() {
210
+ return adapters.flatMap((a) => a.packages);
211
+ }
212
+ // src/extract/schema/standard-schema.ts
213
+ import { spawn } from "node:child_process";
214
+ import * as fs from "node:fs";
215
+ import * as path from "node:path";
216
+ function isStandardJSONSchema(obj) {
217
+ if (typeof obj !== "object" || obj === null)
218
+ return false;
219
+ const std = obj["~standard"];
220
+ if (typeof std !== "object" || std === null)
221
+ return false;
222
+ const stdObj = std;
223
+ if (typeof stdObj.version !== "number")
224
+ return false;
225
+ if (typeof stdObj.vendor !== "string")
226
+ return false;
227
+ const jsonSchema = stdObj.jsonSchema;
228
+ if (typeof jsonSchema !== "object" || jsonSchema === null)
229
+ return false;
230
+ const jsObj = jsonSchema;
231
+ return typeof jsObj.output === "function";
232
+ }
233
+ var WORKER_SCRIPT = `
234
+ const path = require('path');
235
+
236
+ async function extract() {
237
+ // With node -e, argv is: [node, arg1, arg2, ...]
238
+ // (the -e script is NOT in argv)
239
+ const [modulePath, target] = process.argv.slice(1);
240
+
84
241
  try {
85
- const requireCache = eval("require").cache;
86
- if (requireCache && requireCache[modulePath]) {
87
- delete requireCache[modulePath];
242
+ // Import the module
243
+ const mod = require(path.resolve(modulePath));
244
+ const results = [];
245
+
246
+ // Check each export
247
+ for (const [name, value] of Object.entries(mod)) {
248
+ if (name.startsWith('_')) continue;
249
+ if (typeof value !== 'object' || value === null) continue;
250
+
251
+ const std = value['~standard'];
252
+ if (!std || typeof std !== 'object') continue;
253
+ if (typeof std.version !== 'number') continue;
254
+ if (typeof std.vendor !== 'string') continue;
255
+ if (!std.jsonSchema || typeof std.jsonSchema.output !== 'function') continue;
256
+
257
+ try {
258
+ const outputSchema = std.jsonSchema.output(target);
259
+ const inputSchema = std.jsonSchema.input ? std.jsonSchema.input(target) : undefined;
260
+
261
+ results.push({
262
+ exportName: name,
263
+ vendor: std.vendor,
264
+ outputSchema,
265
+ inputSchema
266
+ });
267
+ } catch (e) {
268
+ // Skip schemas that fail to extract
269
+ }
88
270
  }
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;
271
+
272
+ console.log(JSON.stringify({ success: true, results }));
273
+ } catch (e) {
274
+ console.log(JSON.stringify({ success: false, error: e.message }));
275
+ }
276
+ }
277
+
278
+ extract();
279
+ `;
280
+ function resolveCompiledPath(tsPath, baseDir) {
281
+ const relativePath = path.relative(baseDir, tsPath);
282
+ const withoutExt = relativePath.replace(/\.tsx?$/, "");
283
+ const candidates = [
284
+ path.join(baseDir, `${withoutExt}.js`),
285
+ path.join(baseDir, "dist", `${withoutExt.replace(/^src\//, "")}.js`),
286
+ path.join(baseDir, "build", `${withoutExt.replace(/^src\//, "")}.js`),
287
+ path.join(baseDir, "lib", `${withoutExt.replace(/^src\//, "")}.js`)
288
+ ];
289
+ for (const candidate of candidates) {
290
+ if (fs.existsSync(candidate)) {
291
+ return candidate;
100
292
  }
101
293
  }
102
- moduleCache.set(modulePath, { module: mod, mtime: currentMtime });
103
- return mod;
294
+ return null;
104
295
  }
105
- async function detectRuntimeSchemas(context) {
296
+ async function extractStandardSchemas(compiledJsPath, options = {}) {
297
+ const { timeout = 1e4, target = "draft-2020-12" } = options;
106
298
  const result = {
107
299
  schemas: new Map,
108
300
  errors: []
109
301
  };
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);
302
+ if (!fs.existsSync(compiledJsPath)) {
303
+ result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
304
+ return result;
305
+ }
306
+ return new Promise((resolve) => {
307
+ const child = spawn("node", ["-e", WORKER_SCRIPT, compiledJsPath, target], {
308
+ timeout,
309
+ stdio: ["ignore", "pipe", "pipe"]
310
+ });
311
+ let stdout = "";
312
+ let stderr = "";
313
+ child.stdout.on("data", (data) => {
314
+ stdout += data.toString();
315
+ });
316
+ child.stderr.on("data", (data) => {
317
+ stderr += data.toString();
318
+ });
319
+ child.on("close", (code) => {
320
+ if (code !== 0) {
321
+ result.errors.push(`Extraction process failed: ${stderr || `exit code ${code}`}`);
322
+ resolve(result);
323
+ return;
129
324
  }
130
- }
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);
325
+ try {
326
+ const parsed = JSON.parse(stdout);
327
+ if (!parsed.success) {
328
+ result.errors.push(`Extraction failed: ${parsed.error}`);
329
+ resolve(result);
330
+ return;
331
+ }
332
+ for (const item of parsed.results) {
333
+ result.schemas.set(item.exportName, {
334
+ exportName: item.exportName,
335
+ vendor: item.vendor,
336
+ outputSchema: item.outputSchema,
337
+ inputSchema: item.inputSchema
338
+ });
139
339
  }
340
+ } catch (e) {
341
+ result.errors.push(`Failed to parse extraction output: ${e}`);
140
342
  }
141
- }
142
- } catch (err) {
143
- result.errors.push(`Runtime detection failed: ${err instanceof Error ? err.message : String(err)}`);
144
- }
145
- return result;
343
+ resolve(result);
344
+ });
345
+ child.on("error", (err) => {
346
+ result.errors.push(`Subprocess error: ${err.message}`);
347
+ resolve(result);
348
+ });
349
+ });
146
350
  }
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 {}
351
+ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {}) {
352
+ const compiledPath = resolveCompiledPath(entryFile, baseDir);
353
+ if (!compiledPath) {
354
+ return {
355
+ schemas: new Map,
356
+ errors: [`Could not find compiled JS for ${entryFile}. Build the project first.`]
357
+ };
164
358
  }
165
- return null;
166
- }
167
- function clearSchemaCache() {
168
- moduleCache.clear();
359
+ return extractStandardSchemas(compiledPath, options);
169
360
  }
170
361
  // src/analysis/docs-coverage.ts
171
362
  import {
@@ -597,7 +788,7 @@ function categorizeDrifts(drifts) {
597
788
  }
598
789
  // src/fix/jsdoc-writer.ts
599
790
  import * as fs2 from "node:fs";
600
- import * as path from "node:path";
791
+ import * as path2 from "node:path";
601
792
 
602
793
  // src/ts-module.ts
603
794
  import * as tsNamespace from "typescript";
@@ -964,7 +1155,7 @@ async function applyEdits(edits) {
964
1155
  }
965
1156
  function createSourceFile(filePath) {
966
1157
  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);
1158
+ return ts.createSourceFile(path2.basename(filePath), content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
968
1159
  }
969
1160
  // src/utils/builtin-detection.ts
970
1161
  function isBuiltInTypeName(name) {
@@ -2162,480 +2353,6 @@ function ensureSpecCoverage(spec) {
2162
2353
  }
2163
2354
  };
2164
2355
  }
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
2356
  // src/analysis/enrich.ts
2640
2357
  function collectAllMissing(exports) {
2641
2358
  const allMissing = new Set;
@@ -2657,38 +2374,33 @@ function collectAllDrift(exports) {
2657
2374
  }
2658
2375
  return allDrift;
2659
2376
  }
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
- }
2377
+ function computeExportCoverage(exp) {
2378
+ const missing = [];
2379
+ if (!exp.description) {
2380
+ missing.push("has-description");
2381
+ return { score: 0, missing };
2666
2382
  }
2667
- return allViolations;
2383
+ return { score: 100, missing: [] };
2668
2384
  }
2669
2385
  function enrichSpec(spec, options = {}) {
2670
- const { driftByExport, qualityConfig = { rules: {} }, rawJSDocByExport } = options;
2386
+ const { driftByExport } = options;
2671
2387
  const exportRegistry = buildExportRegistry(spec);
2672
2388
  let totalCoverage = 0;
2673
2389
  const enrichedExports = spec.exports.map((exp) => {
2674
- const rawJSDoc = rawJSDocByExport?.get(exp.id);
2675
- const quality = evaluateExportQuality(exp, rawJSDoc, qualityConfig, exportRegistry);
2390
+ const coverage = computeExportCoverage(exp);
2676
2391
  const drift = computeExportDrift(exp, exportRegistry);
2677
2392
  const additionalDrift = driftByExport?.get(exp.id);
2678
2393
  const allDrift2 = additionalDrift ? [...drift, ...additionalDrift] : drift;
2679
- totalCoverage += quality.coverageScore;
2394
+ totalCoverage += coverage.score;
2680
2395
  const docs2 = {
2681
- coverageScore: quality.coverageScore
2396
+ coverageScore: coverage.score
2682
2397
  };
2683
- if (quality.coverage.missing.length > 0) {
2684
- docs2.missing = quality.coverage.missing;
2398
+ if (coverage.missing.length > 0) {
2399
+ docs2.missing = coverage.missing;
2685
2400
  }
2686
2401
  if (allDrift2.length > 0) {
2687
2402
  docs2.drift = allDrift2;
2688
2403
  }
2689
- if (quality.violations.length > 0) {
2690
- docs2.violations = quality.violations;
2691
- }
2692
2404
  return {
2693
2405
  ...exp,
2694
2406
  docs: docs2
@@ -2697,7 +2409,6 @@ function enrichSpec(spec, options = {}) {
2697
2409
  const count = enrichedExports.length;
2698
2410
  const allMissing = collectAllMissing(enrichedExports);
2699
2411
  const allDrift = collectAllDrift(enrichedExports);
2700
- const allViolations = collectAllViolations(enrichedExports);
2701
2412
  const docs = {
2702
2413
  coverageScore: count === 0 ? 100 : Math.round(totalCoverage / count)
2703
2414
  };
@@ -2707,9 +2418,6 @@ function enrichSpec(spec, options = {}) {
2707
2418
  if (allDrift.length > 0) {
2708
2419
  docs.drift = allDrift;
2709
2420
  }
2710
- if (allViolations.length > 0) {
2711
- docs.violations = allViolations;
2712
- }
2713
2421
  const driftSummary = allDrift.length > 0 ? getDriftSummary(allDrift) : undefined;
2714
2422
  return {
2715
2423
  ...spec,
@@ -2720,7 +2428,7 @@ function enrichSpec(spec, options = {}) {
2720
2428
  }
2721
2429
  // src/analysis/report.ts
2722
2430
  import * as fs3 from "node:fs";
2723
- import * as path2 from "node:path";
2431
+ import * as path3 from "node:path";
2724
2432
 
2725
2433
  // src/types/report.ts
2726
2434
  var REPORT_VERSION = "1.0.0";
@@ -2796,7 +2504,7 @@ function generateReportFromEnriched(enriched) {
2796
2504
  }
2797
2505
  function loadCachedReport(reportPath = DEFAULT_REPORT_PATH) {
2798
2506
  try {
2799
- const fullPath = path2.resolve(reportPath);
2507
+ const fullPath = path3.resolve(reportPath);
2800
2508
  if (!fs3.existsSync(fullPath)) {
2801
2509
  return null;
2802
2510
  }
@@ -2807,8 +2515,8 @@ function loadCachedReport(reportPath = DEFAULT_REPORT_PATH) {
2807
2515
  }
2808
2516
  }
2809
2517
  function saveReport(report, reportPath = DEFAULT_REPORT_PATH) {
2810
- const fullPath = path2.resolve(reportPath);
2811
- const dir = path2.dirname(fullPath);
2518
+ const fullPath = path3.resolve(reportPath);
2519
+ const dir = path3.dirname(fullPath);
2812
2520
  if (!fs3.existsSync(dir)) {
2813
2521
  fs3.mkdirSync(dir, { recursive: true });
2814
2522
  }
@@ -3010,7 +2718,7 @@ function renderApiSurface(spec) {
3010
2718
  }
3011
2719
  // src/analysis/history.ts
3012
2720
  import * as fs4 from "node:fs";
3013
- import * as path3 from "node:path";
2721
+ import * as path4 from "node:path";
3014
2722
  var HISTORY_DIR = ".doccov/history";
3015
2723
  var RETENTION_DAYS = {
3016
2724
  free: 7,
@@ -3048,16 +2756,16 @@ function computeSnapshot(spec, options) {
3048
2756
  };
3049
2757
  }
3050
2758
  function saveSnapshot(snapshot, cwd) {
3051
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2759
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3052
2760
  if (!fs4.existsSync(historyDir)) {
3053
2761
  fs4.mkdirSync(historyDir, { recursive: true });
3054
2762
  }
3055
2763
  const filename = getSnapshotFilename(new Date(snapshot.timestamp));
3056
- const filepath = path3.join(historyDir, filename);
2764
+ const filepath = path4.join(historyDir, filename);
3057
2765
  fs4.writeFileSync(filepath, JSON.stringify(snapshot, null, 2));
3058
2766
  }
3059
2767
  function loadSnapshots(cwd) {
3060
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2768
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3061
2769
  if (!fs4.existsSync(historyDir)) {
3062
2770
  return [];
3063
2771
  }
@@ -3065,7 +2773,7 @@ function loadSnapshots(cwd) {
3065
2773
  const snapshots = [];
3066
2774
  for (const file of files) {
3067
2775
  try {
3068
- const content = fs4.readFileSync(path3.join(historyDir, file), "utf-8");
2776
+ const content = fs4.readFileSync(path4.join(historyDir, file), "utf-8");
3069
2777
  snapshots.push(JSON.parse(content));
3070
2778
  } catch {}
3071
2779
  }
@@ -3105,7 +2813,7 @@ function formatDelta(delta) {
3105
2813
  return "→0%";
3106
2814
  }
3107
2815
  function pruneHistory(cwd, keepCount = 100) {
3108
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2816
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3109
2817
  if (!fs4.existsSync(historyDir)) {
3110
2818
  return 0;
3111
2819
  }
@@ -3113,7 +2821,7 @@ function pruneHistory(cwd, keepCount = 100) {
3113
2821
  const toDelete = files.slice(keepCount);
3114
2822
  for (const file of toDelete) {
3115
2823
  try {
3116
- fs4.unlinkSync(path3.join(historyDir, file));
2824
+ fs4.unlinkSync(path4.join(historyDir, file));
3117
2825
  } catch {}
3118
2826
  }
3119
2827
  return toDelete.length;
@@ -3122,7 +2830,7 @@ function pruneByTier(cwd, tier) {
3122
2830
  const retentionDays = RETENTION_DAYS[tier];
3123
2831
  const cutoffDate = new Date;
3124
2832
  cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
3125
- const historyDir = path3.resolve(cwd, HISTORY_DIR);
2833
+ const historyDir = path4.resolve(cwd, HISTORY_DIR);
3126
2834
  if (!fs4.existsSync(historyDir)) {
3127
2835
  return 0;
3128
2836
  }
@@ -3130,7 +2838,7 @@ function pruneByTier(cwd, tier) {
3130
2838
  let deleted = 0;
3131
2839
  for (const file of files) {
3132
2840
  try {
3133
- const filepath = path3.join(historyDir, file);
2841
+ const filepath = path4.join(historyDir, file);
3134
2842
  const content = fs4.readFileSync(filepath, "utf-8");
3135
2843
  const snapshot = JSON.parse(content);
3136
2844
  const snapshotDate = new Date(snapshot.timestamp);
@@ -3237,7 +2945,7 @@ function getExtendedTrend(spec, cwd, options) {
3237
2945
  // src/cache/hash.ts
3238
2946
  import * as crypto from "node:crypto";
3239
2947
  import * as fs5 from "node:fs";
3240
- import * as path4 from "node:path";
2948
+ import * as path5 from "node:path";
3241
2949
  function hashFile(filePath) {
3242
2950
  try {
3243
2951
  const content = fs5.readFileSync(filePath);
@@ -3254,21 +2962,21 @@ function hashFiles(filePaths, cwd) {
3254
2962
  for (const filePath of filePaths) {
3255
2963
  const hash = hashFile(filePath);
3256
2964
  if (hash) {
3257
- const relativePath = path4.relative(cwd, filePath);
2965
+ const relativePath = path5.relative(cwd, filePath);
3258
2966
  hashes[relativePath] = hash;
3259
2967
  }
3260
2968
  }
3261
2969
  return hashes;
3262
2970
  }
3263
- function diffHashes(cached2, current) {
2971
+ function diffHashes(cached, current) {
3264
2972
  const changed = [];
3265
- for (const [file, hash] of Object.entries(cached2)) {
2973
+ for (const [file, hash] of Object.entries(cached)) {
3266
2974
  if (current[file] !== hash) {
3267
2975
  changed.push(file);
3268
2976
  }
3269
2977
  }
3270
2978
  for (const file of Object.keys(current)) {
3271
- if (!(file in cached2)) {
2979
+ if (!(file in cached)) {
3272
2980
  changed.push(file);
3273
2981
  }
3274
2982
  }
@@ -3276,12 +2984,12 @@ function diffHashes(cached2, current) {
3276
2984
  }
3277
2985
  // src/cache/spec-cache.ts
3278
2986
  import * as fs6 from "node:fs";
3279
- import * as path5 from "node:path";
2987
+ import * as path6 from "node:path";
3280
2988
  var CACHE_VERSION = "1.0.0";
3281
2989
  var SPEC_CACHE_FILE = ".doccov/spec.cache.json";
3282
2990
  function loadSpecCache(cwd) {
3283
2991
  try {
3284
- const cachePath = path5.resolve(cwd, SPEC_CACHE_FILE);
2992
+ const cachePath = path6.resolve(cwd, SPEC_CACHE_FILE);
3285
2993
  if (!fs6.existsSync(cachePath)) {
3286
2994
  return null;
3287
2995
  }
@@ -3297,7 +3005,7 @@ function saveSpecCache(spec, context) {
3297
3005
  cacheVersion: CACHE_VERSION,
3298
3006
  generatedAt: new Date().toISOString(),
3299
3007
  specVersion: spec.openpkg,
3300
- entryFile: path5.relative(cwd, entryFile),
3008
+ entryFile: path6.relative(cwd, entryFile),
3301
3009
  hashes: {
3302
3010
  tsconfig: tsconfigPath ? hashFile(tsconfigPath) : null,
3303
3011
  packageJson: hashFile(packageJsonPath) ?? "",
@@ -3306,8 +3014,8 @@ function saveSpecCache(spec, context) {
3306
3014
  config,
3307
3015
  spec
3308
3016
  };
3309
- const cachePath = path5.resolve(cwd, SPEC_CACHE_FILE);
3310
- const dir = path5.dirname(cachePath);
3017
+ const cachePath = path6.resolve(cwd, SPEC_CACHE_FILE);
3018
+ const dir = path6.dirname(cachePath);
3311
3019
  if (!fs6.existsSync(dir)) {
3312
3020
  fs6.mkdirSync(dir, { recursive: true });
3313
3021
  }
@@ -3318,7 +3026,7 @@ function validateSpecCache(cache, context) {
3318
3026
  if (cache.cacheVersion !== CACHE_VERSION) {
3319
3027
  return { valid: false, reason: "cache-version-mismatch" };
3320
3028
  }
3321
- const relativeEntry = path5.relative(cwd, entryFile);
3029
+ const relativeEntry = path6.relative(cwd, entryFile);
3322
3030
  if (cache.entryFile !== relativeEntry) {
3323
3031
  return { valid: false, reason: "entry-file-changed" };
3324
3032
  }
@@ -3341,7 +3049,7 @@ function validateSpecCache(cache, context) {
3341
3049
  return { valid: true };
3342
3050
  }
3343
3051
  function clearSpecCache(cwd) {
3344
- const cachePath = path5.resolve(cwd, SPEC_CACHE_FILE);
3052
+ const cachePath = path6.resolve(cwd, SPEC_CACHE_FILE);
3345
3053
  if (fs6.existsSync(cachePath)) {
3346
3054
  fs6.unlinkSync(cachePath);
3347
3055
  return true;
@@ -3349,325 +3057,26 @@ function clearSpecCache(cwd) {
3349
3057
  return false;
3350
3058
  }
3351
3059
  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);
3060
+ return path6.resolve(cwd, SPEC_CACHE_FILE);
3652
3061
  }
3653
3062
  // src/config/types.ts
3654
3063
  function defineConfig(config) {
3655
3064
  return config;
3656
3065
  }
3657
3066
  // src/detect/utils.ts
3658
- async function safeParseJson(fs8, path8) {
3067
+ async function safeParseJson(fs7, path7) {
3659
3068
  try {
3660
- if (!await fs8.exists(path8))
3069
+ if (!await fs7.exists(path7))
3661
3070
  return null;
3662
- const content = await fs8.readFile(path8);
3071
+ const content = await fs7.readFile(path7);
3663
3072
  return JSON.parse(content);
3664
3073
  } catch {
3665
3074
  return null;
3666
3075
  }
3667
3076
  }
3668
- async function readPackageJson(fs8, dir) {
3669
- const path8 = dir === "." ? "package.json" : `${dir}/package.json`;
3670
- return safeParseJson(fs8, path8);
3077
+ async function readPackageJson(fs7, dir) {
3078
+ const path7 = dir === "." ? "package.json" : `${dir}/package.json`;
3079
+ return safeParseJson(fs7, path7);
3671
3080
  }
3672
3081
 
3673
3082
  // src/detect/build.ts
@@ -3697,8 +3106,8 @@ var BUILD_TOOL_PATTERNS = [
3697
3106
  "babel",
3698
3107
  "ncc build"
3699
3108
  ];
3700
- async function detectBuildInfo(fs8, packagePath = ".") {
3701
- const pkgJson = await readPackageJson(fs8, packagePath);
3109
+ async function detectBuildInfo(fs7, packagePath = ".") {
3110
+ const pkgJson = await readPackageJson(fs7, packagePath);
3702
3111
  const scripts = pkgJson?.scripts ?? {};
3703
3112
  const scriptNames = Object.keys(scripts);
3704
3113
  const buildScriptsByName = scriptNames.filter((name) => BUILD_SCRIPT_NAMES.has(name) || BUILD_SCRIPT_PREFIXES.some((prefix) => name.startsWith(prefix)));
@@ -3710,10 +3119,10 @@ async function detectBuildInfo(fs8, packagePath = ".") {
3710
3119
  });
3711
3120
  const buildScripts = [...new Set([...buildScriptsByName, ...buildScriptsByContent])];
3712
3121
  const tsconfigPath = packagePath === "." ? "tsconfig.json" : `${packagePath}/tsconfig.json`;
3713
- const hasTsConfig = await fs8.exists(tsconfigPath);
3122
+ const hasTsConfig = await fs7.exists(tsconfigPath);
3714
3123
  const hasTsDep = pkgJson?.devDependencies?.typescript !== undefined || pkgJson?.dependencies?.typescript !== undefined;
3715
3124
  const hasTypeScript = hasTsConfig || hasTsDep;
3716
- const wasm = await detectWasmProject(fs8, packagePath, pkgJson);
3125
+ const wasm = await detectWasmProject(fs7, packagePath, pkgJson);
3717
3126
  const napi = detectNapiProject(pkgJson);
3718
3127
  return {
3719
3128
  scripts: buildScripts,
@@ -3730,11 +3139,11 @@ var WASM_PACKAGES = new Set([
3730
3139
  "wasm-bindgen",
3731
3140
  "@aspect/aspect-cli"
3732
3141
  ]);
3733
- async function detectWasmProject(fs8, packagePath, pkgJson) {
3142
+ async function detectWasmProject(fs7, packagePath, pkgJson) {
3734
3143
  const pkgCargoPath = packagePath === "." ? "Cargo.toml" : `${packagePath}/Cargo.toml`;
3735
- if (await fs8.exists(pkgCargoPath))
3144
+ if (await fs7.exists(pkgCargoPath))
3736
3145
  return true;
3737
- if (packagePath !== "." && await fs8.exists("Cargo.toml"))
3146
+ if (packagePath !== "." && await fs7.exists("Cargo.toml"))
3738
3147
  return true;
3739
3148
  if (pkgJson) {
3740
3149
  const deps = Object.keys({
@@ -3775,15 +3184,15 @@ function getPrimaryBuildScript(buildInfo) {
3775
3184
  return buildInfo.scripts[0] ?? null;
3776
3185
  }
3777
3186
  // src/detect/entry-point.ts
3778
- async function detectEntryPoint(fs8, packagePath = ".") {
3779
- const pkgJson = await readPackageJson(fs8, packagePath);
3187
+ async function detectEntryPoint(fs7, packagePath = ".") {
3188
+ const pkgJson = await readPackageJson(fs7, packagePath);
3780
3189
  if (!pkgJson) {
3781
3190
  throw new Error("No package.json found - not a valid npm package");
3782
3191
  }
3783
- const tsConfig = await parseTsConfig(fs8, packagePath);
3192
+ const tsConfig = await parseTsConfig(fs7, packagePath);
3784
3193
  const typesField = pkgJson.types || pkgJson.typings;
3785
3194
  if (typesField && typeof typesField === "string") {
3786
- const resolved = await resolveToSource(fs8, packagePath, typesField, tsConfig);
3195
+ const resolved = await resolveToSource(fs7, packagePath, typesField, tsConfig);
3787
3196
  if (resolved) {
3788
3197
  return { ...resolved, source: "types" };
3789
3198
  }
@@ -3793,7 +3202,7 @@ async function detectEntryPoint(fs8, packagePath = ".") {
3793
3202
  if (dotExport && typeof dotExport === "object" && "types" in dotExport) {
3794
3203
  const typesPath = dotExport.types;
3795
3204
  if (typesPath && typeof typesPath === "string") {
3796
- const resolved = await resolveToSource(fs8, packagePath, typesPath, tsConfig);
3205
+ const resolved = await resolveToSource(fs7, packagePath, typesPath, tsConfig);
3797
3206
  if (resolved) {
3798
3207
  return { ...resolved, source: "exports" };
3799
3208
  }
@@ -3801,13 +3210,13 @@ async function detectEntryPoint(fs8, packagePath = ".") {
3801
3210
  }
3802
3211
  }
3803
3212
  if (pkgJson.main && typeof pkgJson.main === "string") {
3804
- const resolved = await resolveToSource(fs8, packagePath, pkgJson.main, tsConfig);
3213
+ const resolved = await resolveToSource(fs7, packagePath, pkgJson.main, tsConfig);
3805
3214
  if (resolved) {
3806
3215
  return { ...resolved, source: "main" };
3807
3216
  }
3808
3217
  }
3809
3218
  if (pkgJson.module && typeof pkgJson.module === "string") {
3810
- const resolved = await resolveToSource(fs8, packagePath, pkgJson.module, tsConfig);
3219
+ const resolved = await resolveToSource(fs7, packagePath, pkgJson.module, tsConfig);
3811
3220
  if (resolved) {
3812
3221
  return { ...resolved, source: "module" };
3813
3222
  }
@@ -3825,27 +3234,27 @@ async function detectEntryPoint(fs8, packagePath = ".") {
3825
3234
  ];
3826
3235
  for (const fallback of fallbacks) {
3827
3236
  const checkPath = packagePath === "." ? fallback : `${packagePath}/${fallback}`;
3828
- if (await fs8.exists(checkPath)) {
3237
+ if (await fs7.exists(checkPath)) {
3829
3238
  return { path: fallback, source: "fallback", isDeclarationOnly: false };
3830
3239
  }
3831
3240
  }
3832
3241
  throw new Error("Could not detect TypeScript entry point. No types field in package.json and no common entry paths found.");
3833
3242
  }
3834
- async function parseTsConfig(fs8, packagePath) {
3243
+ async function parseTsConfig(fs7, packagePath) {
3835
3244
  const tsconfigPath = packagePath === "." ? "tsconfig.json" : `${packagePath}/tsconfig.json`;
3836
- const tsconfig = await safeParseJson(fs8, tsconfigPath);
3245
+ const tsconfig = await safeParseJson(fs7, tsconfigPath);
3837
3246
  if (!tsconfig?.compilerOptions) {
3838
3247
  return null;
3839
3248
  }
3840
3249
  const { outDir, rootDir, baseUrl, paths } = tsconfig.compilerOptions;
3841
3250
  return { outDir, rootDir, baseUrl, paths };
3842
3251
  }
3843
- async function resolveToSource(fs8, basePath, filePath, tsConfig) {
3252
+ async function resolveToSource(fs7, basePath, filePath, tsConfig) {
3844
3253
  const normalized = filePath.replace(/^\.\//, "");
3845
3254
  const checkPath = (p) => basePath === "." ? p : `${basePath}/${p}`;
3846
3255
  const isSourceTs = normalized.endsWith(".ts") && !normalized.endsWith(".d.ts") || normalized.endsWith(".tsx");
3847
3256
  if (isSourceTs) {
3848
- if (await fs8.exists(checkPath(normalized))) {
3257
+ if (await fs7.exists(checkPath(normalized))) {
3849
3258
  return { path: normalized, isDeclarationOnly: false };
3850
3259
  }
3851
3260
  }
@@ -3887,19 +3296,19 @@ async function resolveToSource(fs8, basePath, filePath, tsConfig) {
3887
3296
  for (const candidate of candidates) {
3888
3297
  if (candidate.endsWith(".d.ts"))
3889
3298
  continue;
3890
- if (await fs8.exists(checkPath(candidate))) {
3299
+ if (await fs7.exists(checkPath(candidate))) {
3891
3300
  return { path: candidate, isDeclarationOnly: false };
3892
3301
  }
3893
3302
  }
3894
3303
  if (normalized.endsWith(".d.ts")) {
3895
- if (await fs8.exists(checkPath(normalized))) {
3304
+ if (await fs7.exists(checkPath(normalized))) {
3896
3305
  return { path: normalized, isDeclarationOnly: true };
3897
3306
  }
3898
3307
  }
3899
3308
  return null;
3900
3309
  }
3901
3310
  // src/detect/filesystem.ts
3902
- import * as fs8 from "node:fs";
3311
+ import * as fs7 from "node:fs";
3903
3312
  import * as nodePath from "node:path";
3904
3313
  import { Writable } from "node:stream";
3905
3314
 
@@ -3912,19 +3321,19 @@ class NodeFileSystem {
3912
3321
  return nodePath.join(this.basePath, relativePath);
3913
3322
  }
3914
3323
  async exists(relativePath) {
3915
- return fs8.existsSync(this.resolve(relativePath));
3324
+ return fs7.existsSync(this.resolve(relativePath));
3916
3325
  }
3917
3326
  async readFile(relativePath) {
3918
- return fs8.readFileSync(this.resolve(relativePath), "utf-8");
3327
+ return fs7.readFileSync(this.resolve(relativePath), "utf-8");
3919
3328
  }
3920
3329
  async readDir(relativePath) {
3921
- return fs8.readdirSync(this.resolve(relativePath));
3330
+ return fs7.readdirSync(this.resolve(relativePath));
3922
3331
  }
3923
3332
  async isDirectory(relativePath) {
3924
3333
  const fullPath = this.resolve(relativePath);
3925
- if (!fs8.existsSync(fullPath))
3334
+ if (!fs7.existsSync(fullPath))
3926
3335
  return false;
3927
- return fs8.statSync(fullPath).isDirectory();
3336
+ return fs7.statSync(fullPath).isDirectory();
3928
3337
  }
3929
3338
  }
3930
3339
  function createCaptureStream() {
@@ -3940,9 +3349,9 @@ function createCaptureStream() {
3940
3349
 
3941
3350
  class FileNotFoundError extends Error {
3942
3351
  path;
3943
- constructor(path8, message) {
3944
- super(message ?? `File not found: ${path8}`);
3945
- this.path = path8;
3352
+ constructor(path7, message) {
3353
+ super(message ?? `File not found: ${path7}`);
3354
+ this.path = path7;
3946
3355
  this.name = "FileNotFoundError";
3947
3356
  }
3948
3357
  }
@@ -3952,34 +3361,34 @@ class SandboxFileSystem {
3952
3361
  constructor(sandbox) {
3953
3362
  this.sandbox = sandbox;
3954
3363
  }
3955
- async exists(path8) {
3364
+ async exists(path7) {
3956
3365
  const result = await this.sandbox.runCommand({
3957
3366
  cmd: "test",
3958
- args: ["-e", path8]
3367
+ args: ["-e", path7]
3959
3368
  });
3960
3369
  return result.exitCode === 0;
3961
3370
  }
3962
- async readFile(path8) {
3963
- const exists = await this.exists(path8);
3371
+ async readFile(path7) {
3372
+ const exists = await this.exists(path7);
3964
3373
  if (!exists) {
3965
- throw new FileNotFoundError(path8);
3374
+ throw new FileNotFoundError(path7);
3966
3375
  }
3967
3376
  const capture = createCaptureStream();
3968
3377
  const result = await this.sandbox.runCommand({
3969
3378
  cmd: "cat",
3970
- args: [path8],
3379
+ args: [path7],
3971
3380
  stdout: capture.stream
3972
3381
  });
3973
3382
  if (result.exitCode !== 0) {
3974
- throw new FileNotFoundError(path8, `Failed to read file: ${path8}`);
3383
+ throw new FileNotFoundError(path7, `Failed to read file: ${path7}`);
3975
3384
  }
3976
3385
  return capture.getOutput();
3977
3386
  }
3978
- async readDir(path8) {
3387
+ async readDir(path7) {
3979
3388
  const capture = createCaptureStream();
3980
3389
  const result = await this.sandbox.runCommand({
3981
3390
  cmd: "ls",
3982
- args: ["-1", path8],
3391
+ args: ["-1", path7],
3983
3392
  stdout: capture.stream
3984
3393
  });
3985
3394
  if (result.exitCode !== 0) {
@@ -3988,20 +3397,20 @@ class SandboxFileSystem {
3988
3397
  return capture.getOutput().split(`
3989
3398
  `).filter(Boolean);
3990
3399
  }
3991
- async isDirectory(path8) {
3400
+ async isDirectory(path7) {
3992
3401
  const result = await this.sandbox.runCommand({
3993
3402
  cmd: "test",
3994
- args: ["-d", path8]
3403
+ args: ["-d", path7]
3995
3404
  });
3996
3405
  return result.exitCode === 0;
3997
3406
  }
3998
3407
  }
3999
3408
  // src/detect/monorepo.ts
4000
- async function detectMonorepo(fs9) {
4001
- const pkgJson = await readPackageJson(fs9, ".");
3409
+ async function detectMonorepo(fs8) {
3410
+ const pkgJson = await readPackageJson(fs8, ".");
4002
3411
  if (pkgJson?.workspaces) {
4003
3412
  const patterns = extractWorkspacePatterns(pkgJson.workspaces);
4004
- const packages = await resolveWorkspacePackages(fs9, patterns, pkgJson.name, pkgJson.private);
3413
+ const packages = await resolveWorkspacePackages(fs8, patterns, pkgJson.name, pkgJson.private);
4005
3414
  return {
4006
3415
  isMonorepo: packages.length > 0,
4007
3416
  type: "npm-workspaces",
@@ -4009,10 +3418,10 @@ async function detectMonorepo(fs9) {
4009
3418
  packages
4010
3419
  };
4011
3420
  }
4012
- if (await fs9.exists("pnpm-workspace.yaml")) {
4013
- const content = await fs9.readFile("pnpm-workspace.yaml");
3421
+ if (await fs8.exists("pnpm-workspace.yaml")) {
3422
+ const content = await fs8.readFile("pnpm-workspace.yaml");
4014
3423
  const patterns = parsePnpmWorkspace(content);
4015
- const packages = await resolveWorkspacePackages(fs9, patterns, pkgJson?.name, pkgJson?.private);
3424
+ const packages = await resolveWorkspacePackages(fs8, patterns, pkgJson?.name, pkgJson?.private);
4016
3425
  return {
4017
3426
  isMonorepo: packages.length > 0,
4018
3427
  type: "pnpm-workspaces",
@@ -4020,10 +3429,10 @@ async function detectMonorepo(fs9) {
4020
3429
  packages
4021
3430
  };
4022
3431
  }
4023
- if (await fs9.exists("lerna.json")) {
4024
- const lerna = await safeParseJson(fs9, "lerna.json");
3432
+ if (await fs8.exists("lerna.json")) {
3433
+ const lerna = await safeParseJson(fs8, "lerna.json");
4025
3434
  const patterns = lerna?.packages ?? ["packages/*"];
4026
- const packages = await resolveWorkspacePackages(fs9, patterns, pkgJson?.name, pkgJson?.private);
3435
+ const packages = await resolveWorkspacePackages(fs8, patterns, pkgJson?.name, pkgJson?.private);
4027
3436
  return {
4028
3437
  isMonorepo: packages.length > 0,
4029
3438
  type: "lerna",
@@ -4097,7 +3506,7 @@ function parsePnpmWorkspace(content) {
4097
3506
  }
4098
3507
  return patterns.length > 0 ? patterns : ["packages/*"];
4099
3508
  }
4100
- async function resolveWorkspacePackages(fs9, patterns, rootPackageName, rootIsPrivate) {
3509
+ async function resolveWorkspacePackages(fs8, patterns, rootPackageName, rootIsPrivate) {
4101
3510
  const packages = [];
4102
3511
  const seen = new Set;
4103
3512
  if (rootPackageName && !rootIsPrivate && rootPackageName !== "root") {
@@ -4119,18 +3528,18 @@ async function resolveWorkspacePackages(fs9, patterns, rootPackageName, rootIsPr
4119
3528
  }
4120
3529
  dirsToScan.add("packages");
4121
3530
  for (const dir of dirsToScan) {
4122
- if (!await fs9.exists(dir))
3531
+ if (!await fs8.exists(dir))
4123
3532
  continue;
4124
- if (!await fs9.isDirectory(dir))
3533
+ if (!await fs8.isDirectory(dir))
4125
3534
  continue;
4126
- const subdirs = await fs9.readDir(dir);
3535
+ const subdirs = await fs8.readDir(dir);
4127
3536
  for (const subdir of subdirs) {
4128
3537
  const pkgPath = `${dir}/${subdir}`;
4129
3538
  const pkgJsonPath = `${pkgPath}/package.json`;
4130
- if (!await fs9.exists(pkgJsonPath))
3539
+ if (!await fs8.exists(pkgJsonPath))
4131
3540
  continue;
4132
3541
  try {
4133
- const content = await fs9.readFile(pkgJsonPath);
3542
+ const content = await fs8.readFile(pkgJsonPath);
4134
3543
  const pkg = JSON.parse(content);
4135
3544
  if (pkg.name && !seen.has(pkg.name)) {
4136
3545
  seen.add(pkg.name);
@@ -4202,14 +3611,14 @@ var DEFAULT_PM = {
4202
3611
  installArgs: ["install", "--legacy-peer-deps"],
4203
3612
  runPrefix: ["npm", "run"]
4204
3613
  };
4205
- async function detectPackageManager(fs9) {
4206
- const pkgJson = await safeParseJson(fs9, "package.json");
3614
+ async function detectPackageManager(fs8) {
3615
+ const pkgJson = await safeParseJson(fs8, "package.json");
4207
3616
  if (pkgJson?.packageManager) {
4208
3617
  const pmName = parsePackageManagerField(pkgJson.packageManager);
4209
3618
  if (pmName && PM_CONFIGS[pmName]) {
4210
3619
  const config = PM_CONFIGS[pmName];
4211
3620
  for (const lockfile of config.lockfiles) {
4212
- if (await fs9.exists(lockfile)) {
3621
+ if (await fs8.exists(lockfile)) {
4213
3622
  return { ...config.info, lockfile };
4214
3623
  }
4215
3624
  }
@@ -4219,7 +3628,7 @@ async function detectPackageManager(fs9) {
4219
3628
  const foundLockfiles = [];
4220
3629
  for (const [pmName, config] of Object.entries(PM_CONFIGS)) {
4221
3630
  for (const lockfile of config.lockfiles) {
4222
- if (await fs9.exists(lockfile)) {
3631
+ if (await fs8.exists(lockfile)) {
4223
3632
  foundLockfiles.push({ lockfile, pm: pmName });
4224
3633
  }
4225
3634
  }
@@ -4251,10 +3660,10 @@ function getRunCommand(pm, script) {
4251
3660
  return [...pm.runPrefix, script];
4252
3661
  }
4253
3662
  // src/detect/index.ts
4254
- async function analyzeProject(fs9, options = {}) {
3663
+ async function analyzeProject(fs8, options = {}) {
4255
3664
  const [packageManager, monorepo] = await Promise.all([
4256
- detectPackageManager(fs9),
4257
- detectMonorepo(fs9)
3665
+ detectPackageManager(fs8),
3666
+ detectMonorepo(fs8)
4258
3667
  ]);
4259
3668
  let targetPath = ".";
4260
3669
  if (monorepo.isMonorepo) {
@@ -4271,8 +3680,8 @@ async function analyzeProject(fs9, options = {}) {
4271
3680
  targetPath = pkg.path;
4272
3681
  }
4273
3682
  const [entryPoint, build] = await Promise.all([
4274
- detectEntryPoint(fs9, targetPath),
4275
- detectBuildInfo(fs9, targetPath)
3683
+ detectEntryPoint(fs8, targetPath),
3684
+ detectBuildInfo(fs8, targetPath)
4276
3685
  ]);
4277
3686
  return { packageManager, monorepo, entryPoint, build };
4278
3687
  }
@@ -4316,17 +3725,17 @@ function shouldValidate(validations, check) {
4316
3725
  return validations.includes(check);
4317
3726
  }
4318
3727
  // src/typecheck/example-typechecker.ts
4319
- import * as fs9 from "node:fs";
4320
- import * as path8 from "node:path";
3728
+ import * as fs8 from "node:fs";
3729
+ import * as path7 from "node:path";
4321
3730
  import ts3 from "typescript";
4322
3731
  function stripCodeBlockMarkers(code) {
4323
3732
  return code.replace(/^```(?:ts|typescript|js|javascript)?\n?/i, "").replace(/\n?```$/i, "").trim();
4324
3733
  }
4325
3734
  function getPackageName(packagePath) {
4326
- const pkgJsonPath = path8.join(packagePath, "package.json");
4327
- if (fs9.existsSync(pkgJsonPath)) {
3735
+ const pkgJsonPath = path7.join(packagePath, "package.json");
3736
+ if (fs8.existsSync(pkgJsonPath)) {
4328
3737
  try {
4329
- const pkgJson = JSON.parse(fs9.readFileSync(pkgJsonPath, "utf-8"));
3738
+ const pkgJson = JSON.parse(fs8.readFileSync(pkgJsonPath, "utf-8"));
4330
3739
  return pkgJson.name;
4331
3740
  } catch {
4332
3741
  return;
@@ -4336,12 +3745,12 @@ function getPackageName(packagePath) {
4336
3745
  }
4337
3746
  function findTsConfig(packagePath) {
4338
3747
  let dir = packagePath;
4339
- while (dir !== path8.dirname(dir)) {
4340
- const tsConfigPath = path8.join(dir, "tsconfig.json");
4341
- if (fs9.existsSync(tsConfigPath)) {
3748
+ while (dir !== path7.dirname(dir)) {
3749
+ const tsConfigPath = path7.join(dir, "tsconfig.json");
3750
+ if (fs8.existsSync(tsConfigPath)) {
4342
3751
  return tsConfigPath;
4343
3752
  }
4344
- dir = path8.dirname(dir);
3753
+ dir = path7.dirname(dir);
4345
3754
  }
4346
3755
  return;
4347
3756
  }
@@ -4357,10 +3766,10 @@ function createVirtualSource(example, packageName, exportNames) {
4357
3766
  `);
4358
3767
  }
4359
3768
  function getCompilerOptions(tsconfigPath) {
4360
- if (tsconfigPath && fs9.existsSync(tsconfigPath)) {
3769
+ if (tsconfigPath && fs8.existsSync(tsconfigPath)) {
4361
3770
  const configFile = ts3.readConfigFile(tsconfigPath, ts3.sys.readFile);
4362
3771
  if (!configFile.error) {
4363
- const parsed = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys, path8.dirname(tsconfigPath));
3772
+ const parsed = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys, path7.dirname(tsconfigPath));
4364
3773
  return {
4365
3774
  ...parsed.options,
4366
3775
  noEmit: true,
@@ -4386,7 +3795,7 @@ function typecheckExample(example, packagePath, options = {}) {
4386
3795
  const tsconfigPath = options.tsconfig ?? findTsConfig(packagePath);
4387
3796
  const compilerOptions = getCompilerOptions(tsconfigPath);
4388
3797
  const virtualSource = createVirtualSource(cleanCode, packageName, exportNames);
4389
- const virtualFileName = path8.join(packagePath, "__doccov_example__.ts");
3798
+ const virtualFileName = path7.join(packagePath, "__doccov_example__.ts");
4390
3799
  const hasImport = packageName !== undefined && exportNames && exportNames.length > 0;
4391
3800
  const lineOffset = hasImport ? 2 : 0;
4392
3801
  const sourceFile = ts3.createSourceFile(virtualFileName, virtualSource, ts3.ScriptTarget.ES2022, true);
@@ -4457,25 +3866,25 @@ function typecheckExamples(examples, packagePath, options = {}) {
4457
3866
  }
4458
3867
 
4459
3868
  // src/utils/example-runner.ts
4460
- import { spawn } from "node:child_process";
4461
- import * as fs10 from "node:fs";
3869
+ import { spawn as spawn2 } from "node:child_process";
3870
+ import * as fs9 from "node:fs";
4462
3871
  import * as os from "node:os";
4463
- import * as path9 from "node:path";
3872
+ import * as path8 from "node:path";
4464
3873
  function stripCodeBlockMarkers2(code) {
4465
3874
  return code.replace(/^```(?:ts|typescript|js|javascript)?\n?/i, "").replace(/\n?```$/i, "").trim();
4466
3875
  }
4467
3876
  async function runExample(code, options = {}) {
4468
3877
  const { timeout = 5000, cwd = process.cwd() } = options;
4469
3878
  const cleanCode = stripCodeBlockMarkers2(code);
4470
- const tmpFile = path9.join(cwd, `doccov-example-${Date.now()}-${Math.random().toString(36).slice(2)}.ts`);
3879
+ const tmpFile = path8.join(cwd, `doccov-example-${Date.now()}-${Math.random().toString(36).slice(2)}.ts`);
4471
3880
  try {
4472
- fs10.writeFileSync(tmpFile, cleanCode, "utf-8");
3881
+ fs9.writeFileSync(tmpFile, cleanCode, "utf-8");
4473
3882
  const startTime = Date.now();
4474
3883
  return await new Promise((resolve5) => {
4475
3884
  let stdout = "";
4476
3885
  let stderr = "";
4477
3886
  let killed = false;
4478
- const proc = spawn("node", ["--experimental-strip-types", tmpFile], {
3887
+ const proc = spawn2("node", ["--experimental-strip-types", tmpFile], {
4479
3888
  cwd,
4480
3889
  timeout,
4481
3890
  stdio: ["ignore", "pipe", "pipe"]
@@ -4524,7 +3933,7 @@ async function runExample(code, options = {}) {
4524
3933
  });
4525
3934
  } finally {
4526
3935
  try {
4527
- fs10.unlinkSync(tmpFile);
3936
+ fs9.unlinkSync(tmpFile);
4528
3937
  } catch {}
4529
3938
  }
4530
3939
  }
@@ -4539,15 +3948,15 @@ async function runExamples(examples, options = {}) {
4539
3948
  return results;
4540
3949
  }
4541
3950
  function detectPackageManager2(cwd) {
4542
- if (fs10.existsSync(path9.join(cwd, "bun.lockb")))
3951
+ if (fs9.existsSync(path8.join(cwd, "bun.lockb")))
4543
3952
  return "bun";
4544
- if (fs10.existsSync(path9.join(cwd, "bun.lock")))
3953
+ if (fs9.existsSync(path8.join(cwd, "bun.lock")))
4545
3954
  return "bun";
4546
- if (fs10.existsSync(path9.join(cwd, "pnpm-lock.yaml")))
3955
+ if (fs9.existsSync(path8.join(cwd, "pnpm-lock.yaml")))
4547
3956
  return "pnpm";
4548
- if (fs10.existsSync(path9.join(cwd, "yarn.lock")))
3957
+ if (fs9.existsSync(path8.join(cwd, "yarn.lock")))
4549
3958
  return "yarn";
4550
- if (fs10.existsSync(path9.join(cwd, "package-lock.json")))
3959
+ if (fs9.existsSync(path8.join(cwd, "package-lock.json")))
4551
3960
  return "npm";
4552
3961
  return "npm";
4553
3962
  }
@@ -4568,7 +3977,7 @@ async function runCommand(cmd, args, options) {
4568
3977
  let stdout = "";
4569
3978
  let stderr = "";
4570
3979
  let killed = false;
4571
- const proc = spawn(cmd, args, {
3980
+ const proc = spawn2(cmd, args, {
4572
3981
  cwd: options.cwd,
4573
3982
  stdio: ["ignore", "pipe", "pipe"]
4574
3983
  });
@@ -4615,12 +4024,12 @@ async function runExamplesWithPackage(examples, options) {
4615
4024
  const { packagePath, packageManager, installTimeout = 60000, timeout = 5000 } = options;
4616
4025
  const startTime = Date.now();
4617
4026
  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)}`);
4027
+ const absolutePackagePath = path8.resolve(packagePath);
4028
+ const workDir = path8.join(os.tmpdir(), `doccov-examples-${Date.now()}-${Math.random().toString(36).slice(2)}`);
4620
4029
  try {
4621
- fs10.mkdirSync(workDir, { recursive: true });
4030
+ fs9.mkdirSync(workDir, { recursive: true });
4622
4031
  const pkgJson = { name: "doccov-example-runner", type: "module" };
4623
- fs10.writeFileSync(path9.join(workDir, "package.json"), JSON.stringify(pkgJson, null, 2));
4032
+ fs9.writeFileSync(path8.join(workDir, "package.json"), JSON.stringify(pkgJson, null, 2));
4624
4033
  const pm = packageManager ?? detectPackageManager2(options.cwd ?? process.cwd());
4625
4034
  const { cmd, args } = getInstallCommand2(pm, absolutePackagePath);
4626
4035
  const installResult = await runCommand(cmd, args, {
@@ -4648,7 +4057,7 @@ async function runExamplesWithPackage(examples, options) {
4648
4057
  };
4649
4058
  } finally {
4650
4059
  try {
4651
- fs10.rmSync(workDir, { recursive: true, force: true });
4060
+ fs9.rmSync(workDir, { recursive: true, force: true });
4652
4061
  } catch {}
4653
4062
  }
4654
4063
  }
@@ -4827,9 +4236,12 @@ async function validateExamples(exports, options) {
4827
4236
  }
4828
4237
  return result;
4829
4238
  }
4830
- // src/analysis/run-analysis.ts
4831
- import * as fs12 from "node:fs";
4239
+ // src/extractor.ts
4832
4240
  import * as path13 from "node:path";
4241
+
4242
+ // src/analysis/run-analysis.ts
4243
+ import * as fs11 from "node:fs";
4244
+ import * as path12 from "node:path";
4833
4245
  // src/utils/type-utils.ts
4834
4246
  function getTypeId(type, typeChecker) {
4835
4247
  const internalId = type.id;
@@ -4952,7 +4364,7 @@ function collectReferencedTypesFromNode(node, typeChecker, referencedTypes) {
4952
4364
  }
4953
4365
 
4954
4366
  // src/analysis/context.ts
4955
- import * as path11 from "node:path";
4367
+ import * as path10 from "node:path";
4956
4368
 
4957
4369
  // src/options.ts
4958
4370
  var DEFAULT_MAX_TYPE_DEPTH = 20;
@@ -4973,7 +4385,7 @@ function normalizeDocCovOptions(options = {}) {
4973
4385
  }
4974
4386
 
4975
4387
  // src/analysis/program.ts
4976
- import * as path10 from "node:path";
4388
+ import * as path9 from "node:path";
4977
4389
  var DEFAULT_COMPILER_OPTIONS = {
4978
4390
  target: ts.ScriptTarget.Latest,
4979
4391
  module: ts.ModuleKind.CommonJS,
@@ -4983,14 +4395,14 @@ var DEFAULT_COMPILER_OPTIONS = {
4983
4395
  };
4984
4396
  function createProgram({
4985
4397
  entryFile,
4986
- baseDir = path10.dirname(entryFile),
4398
+ baseDir = path9.dirname(entryFile),
4987
4399
  content
4988
4400
  }) {
4989
4401
  const configPath = ts.findConfigFile(baseDir, ts.sys.fileExists, "tsconfig.json");
4990
4402
  let compilerOptions = { ...DEFAULT_COMPILER_OPTIONS };
4991
4403
  if (configPath) {
4992
4404
  const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
4993
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path10.dirname(configPath));
4405
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path9.dirname(configPath));
4994
4406
  compilerOptions = { ...compilerOptions, ...parsedConfig.options };
4995
4407
  }
4996
4408
  const allowJsVal = compilerOptions.allowJs;
@@ -5028,7 +4440,7 @@ function createAnalysisContext({
5028
4440
  options,
5029
4441
  detectedSchemas
5030
4442
  }) {
5031
- const baseDir = packageDir ?? path11.dirname(entryFile);
4443
+ const baseDir = packageDir ?? path10.dirname(entryFile);
5032
4444
  const normalizedOptions = normalizeDocCovOptions(options);
5033
4445
  const programResult = createProgram({ entryFile, baseDir, content });
5034
4446
  if (!programResult.sourceFile) {
@@ -5049,8 +4461,8 @@ function createAnalysisContext({
5049
4461
  }
5050
4462
 
5051
4463
  // src/analysis/spec-builder.ts
5052
- import * as fs11 from "node:fs";
5053
- import * as path12 from "node:path";
4464
+ import * as fs10 from "node:fs";
4465
+ import * as path11 from "node:path";
5054
4466
  import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
5055
4467
 
5056
4468
  // src/analysis/decorator-utils.ts
@@ -6740,10 +6152,10 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
6740
6152
  if (member.questionToken || isOptionalSymbol) {
6741
6153
  flags.optional = true;
6742
6154
  }
6743
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.ReadonlyKeyword)) {
6155
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ReadonlyKeyword)) {
6744
6156
  flags.readonly = true;
6745
6157
  }
6746
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.StaticKeyword)) {
6158
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.StaticKeyword)) {
6747
6159
  flags.static = true;
6748
6160
  }
6749
6161
  members.push({
@@ -6865,20 +6277,20 @@ function serializeSignature(signature, checker, typeRefs, referencedTypes, doc,
6865
6277
  function getMemberVisibility(modifiers) {
6866
6278
  if (!modifiers)
6867
6279
  return;
6868
- if (modifiers.some((mod2) => mod2.kind === ts.SyntaxKind.PrivateKeyword)) {
6280
+ if (modifiers.some((mod) => mod.kind === ts.SyntaxKind.PrivateKeyword)) {
6869
6281
  return "private";
6870
6282
  }
6871
- if (modifiers.some((mod2) => mod2.kind === ts.SyntaxKind.ProtectedKeyword)) {
6283
+ if (modifiers.some((mod) => mod.kind === ts.SyntaxKind.ProtectedKeyword)) {
6872
6284
  return "protected";
6873
6285
  }
6874
- if (modifiers.some((mod2) => mod2.kind === ts.SyntaxKind.PublicKeyword)) {
6286
+ if (modifiers.some((mod) => mod.kind === ts.SyntaxKind.PublicKeyword)) {
6875
6287
  return "public";
6876
6288
  }
6877
6289
  return;
6878
6290
  }
6879
6291
  function getMethodFlags(member) {
6880
6292
  const flags = {};
6881
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.StaticKeyword)) {
6293
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.StaticKeyword)) {
6882
6294
  flags.static = true;
6883
6295
  }
6884
6296
  if (member.asteriskToken) {
@@ -7063,7 +6475,7 @@ function serializeInterfaceMembers(declaration, checker, typeRefs, referencedTyp
7063
6475
  if (member.questionToken) {
7064
6476
  flags.optional = true;
7065
6477
  }
7066
- if (member.modifiers?.some((mod2) => mod2.kind === ts.SyntaxKind.ReadonlyKeyword)) {
6478
+ if (member.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ReadonlyKeyword)) {
7067
6479
  flags.readonly = true;
7068
6480
  }
7069
6481
  members.push({
@@ -7361,7 +6773,7 @@ function extractNamespaceMembers(declaration, checker) {
7361
6773
  return members;
7362
6774
  }
7363
6775
  for (const statement of body.statements) {
7364
- const hasExportModifier = ts.canHaveModifiers(statement) && ts.getModifiers(statement)?.some((mod2) => mod2.kind === ts.SyntaxKind.ExportKeyword);
6776
+ const hasExportModifier = ts.canHaveModifiers(statement) && ts.getModifiers(statement)?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword);
7365
6777
  if (!hasExportModifier) {
7366
6778
  continue;
7367
6779
  }
@@ -7571,27 +6983,51 @@ function serializeVariable(declaration, symbol, context) {
7571
6983
  const typeRefs = typeRegistry.getTypeRefs();
7572
6984
  const referencedTypes = typeRegistry.getReferencedTypes();
7573
6985
  const symbolName = symbol.getName();
7574
- const detectedSchema = context.detectedSchemas?.get(symbolName);
7575
- if (detectedSchema) {
6986
+ const standardSchema = context.detectedSchemas?.get(symbolName);
6987
+ if (standardSchema) {
7576
6988
  return {
7577
6989
  id: symbolName,
7578
6990
  name: symbolName,
7579
6991
  ...metadata,
7580
6992
  kind: "variable",
7581
6993
  deprecated: isSymbolDeprecated(symbol),
7582
- schema: detectedSchema.schema,
6994
+ schema: standardSchema.schema,
7583
6995
  description,
7584
6996
  source: getSourceLocation(declaration),
7585
6997
  tags: [
7586
6998
  ...parsedDoc?.tags ?? [],
7587
- { name: "standardSchema", text: detectedSchema.vendor }
6999
+ { name: "schemaLibrary", text: standardSchema.vendor },
7000
+ { name: "schemaSource", text: "standard-schema" }
7588
7001
  ],
7589
7002
  examples: parsedDoc?.examples
7590
7003
  };
7591
7004
  }
7005
+ if (isSchemaType(variableType, checker)) {
7006
+ const schemaResult = extractSchemaType(variableType, checker);
7007
+ if (schemaResult?.outputType) {
7008
+ collectReferencedTypes(schemaResult.outputType, checker, referencedTypes);
7009
+ const outputTypeRef = formatTypeReference(schemaResult.outputType, checker, typeRefs, referencedTypes);
7010
+ return {
7011
+ id: symbolName,
7012
+ name: symbolName,
7013
+ ...metadata,
7014
+ kind: "variable",
7015
+ deprecated: isSymbolDeprecated(symbol),
7016
+ type: outputTypeRef,
7017
+ description,
7018
+ source: getSourceLocation(declaration),
7019
+ tags: [
7020
+ ...parsedDoc?.tags ?? [],
7021
+ { name: "schemaLibrary", text: schemaResult.adapter.id },
7022
+ { name: "schemaSource", text: "static-ast" }
7023
+ ],
7024
+ examples: parsedDoc?.examples
7025
+ };
7026
+ }
7027
+ }
7592
7028
  return {
7593
- id: symbol.getName(),
7594
- name: symbol.getName(),
7029
+ id: symbolName,
7030
+ name: symbolName,
7595
7031
  ...metadata,
7596
7032
  kind: "variable",
7597
7033
  deprecated: isSymbolDeprecated(symbol),
@@ -7677,9 +7113,9 @@ function createDefaultGenerationInfo(entryFile) {
7677
7113
  }
7678
7114
  function buildOpenPkgSpec(context, resolveExternalTypes, generation) {
7679
7115
  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));
7116
+ const packageJsonPath = path11.join(baseDir, "package.json");
7117
+ const packageJson = fs10.existsSync(packageJsonPath) ? JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8")) : {};
7118
+ const generationInfo = generation ?? createDefaultGenerationInfo(path11.relative(baseDir, entryFile));
7683
7119
  const spec = {
7684
7120
  $schema: SCHEMA_URL,
7685
7121
  openpkg: SCHEMA_VERSION,
@@ -7878,11 +7314,11 @@ function deriveImportPath(sourceFile, baseDir) {
7878
7314
  if (!sourceFile) {
7879
7315
  return;
7880
7316
  }
7881
- const relative6 = path12.relative(baseDir, sourceFile);
7882
- if (!relative6 || relative6.startsWith("..")) {
7317
+ const relative5 = path11.relative(baseDir, sourceFile);
7318
+ if (!relative5 || relative5.startsWith("..")) {
7883
7319
  return;
7884
7320
  }
7885
- const normalized = relative6.replace(/\\/g, "/");
7321
+ const normalized = relative5.replace(/\\/g, "/");
7886
7322
  const withoutExt = stripExtensions(normalized);
7887
7323
  if (!withoutExt) {
7888
7324
  return;
@@ -7921,11 +7357,11 @@ function withExportName(entry, exportName) {
7921
7357
  function findNearestPackageJson(startDir) {
7922
7358
  let current = startDir;
7923
7359
  while (true) {
7924
- const candidate = path13.join(current, "package.json");
7925
- if (fs12.existsSync(candidate)) {
7360
+ const candidate = path12.join(current, "package.json");
7361
+ if (fs11.existsSync(candidate)) {
7926
7362
  return candidate;
7927
7363
  }
7928
- const parent = path13.dirname(current);
7364
+ const parent = path12.dirname(current);
7929
7365
  if (parent === current) {
7930
7366
  return;
7931
7367
  }
@@ -7953,11 +7389,11 @@ function canResolveExternalModules(program, baseDir) {
7953
7389
  function hasNodeModulesDirectoryFallback(startDir) {
7954
7390
  let current = startDir;
7955
7391
  while (true) {
7956
- const candidate = path13.join(current, "node_modules");
7957
- if (fs12.existsSync(candidate)) {
7392
+ const candidate = path12.join(current, "node_modules");
7393
+ if (fs11.existsSync(candidate)) {
7958
7394
  return true;
7959
7395
  }
7960
- const parent = path13.dirname(current);
7396
+ const parent = path12.dirname(current);
7961
7397
  if (parent === current) {
7962
7398
  break;
7963
7399
  }
@@ -8002,8 +7438,8 @@ function hasExternalImports(sourceFile) {
8002
7438
  if (ts.isImportDeclaration(node) && node.moduleSpecifier) {
8003
7439
  const specifier = node.moduleSpecifier;
8004
7440
  if (ts.isStringLiteral(specifier)) {
8005
- const modulePath2 = specifier.text;
8006
- if (!modulePath2.startsWith(".") && !modulePath2.startsWith("/")) {
7441
+ const modulePath = specifier.text;
7442
+ if (!modulePath.startsWith(".") && !modulePath.startsWith("/")) {
8007
7443
  found = true;
8008
7444
  }
8009
7445
  }
@@ -8113,11 +7549,27 @@ function runAnalysis(input, generationInput) {
8113
7549
 
8114
7550
  // src/extractor.ts
8115
7551
  async function extractPackageSpec(entryFile, packageDir, content, options) {
7552
+ const baseDir = packageDir ?? path13.dirname(entryFile);
7553
+ const schemaMode = options?.schemaExtraction ?? "static";
7554
+ let detectedSchemas;
7555
+ if (schemaMode === "runtime" || schemaMode === "hybrid") {
7556
+ const extraction = await extractStandardSchemasFromProject(entryFile, baseDir);
7557
+ if (extraction.schemas.size > 0) {
7558
+ detectedSchemas = new Map;
7559
+ for (const [name, result2] of extraction.schemas) {
7560
+ detectedSchemas.set(name, {
7561
+ schema: result2.outputSchema,
7562
+ vendor: result2.vendor
7563
+ });
7564
+ }
7565
+ }
7566
+ }
8116
7567
  const result = runAnalysis({
8117
7568
  entryFile,
8118
7569
  packageDir,
8119
7570
  content,
8120
- options
7571
+ options,
7572
+ detectedSchemas
8121
7573
  });
8122
7574
  return result.spec;
8123
7575
  }
@@ -8232,11 +7684,11 @@ async function fetchSpecFromGitHubWithPath(parsed, specPath = "openpkg.json") {
8232
7684
  }
8233
7685
  // src/install/index.ts
8234
7686
  var DEFAULT_FALLBACK_ORDER = ["bun", "npm"];
8235
- async function installDependencies(fs13, cwd, runCommand2, options = {}) {
7687
+ async function installDependencies(fs12, cwd, runCommand2, options = {}) {
8236
7688
  const { timeout = 180000, fallbackOrder = DEFAULT_FALLBACK_ORDER, onProgress } = options;
8237
7689
  const errors = [];
8238
7690
  onProgress?.({ stage: "installing", message: "Detecting package manager..." });
8239
- const pmInfo = await detectPackageManager(fs13);
7691
+ const pmInfo = await detectPackageManager(fs12);
8240
7692
  if (pmInfo.lockfile) {
8241
7693
  onProgress?.({
8242
7694
  stage: "installing",
@@ -8311,10 +7763,10 @@ function getFallbackInstallCommand(pm) {
8311
7763
  }
8312
7764
  function createNodeCommandRunner() {
8313
7765
  return async (cmd, args, options) => {
8314
- const { execSync: execSync2 } = await import("node:child_process");
7766
+ const { execSync } = await import("node:child_process");
8315
7767
  const fullCmd = [cmd, ...args].join(" ");
8316
7768
  try {
8317
- const stdout = execSync2(fullCmd, {
7769
+ const stdout = execSync(fullCmd, {
8318
7770
  cwd: options.cwd,
8319
7771
  stdio: "pipe",
8320
7772
  timeout: options.timeout ?? 180000
@@ -9141,7 +8593,7 @@ function getDocsImpactSummary(diff) {
9141
8593
  }
9142
8594
  // src/openpkg.ts
9143
8595
  import * as fsSync from "node:fs";
9144
- import * as fs13 from "node:fs/promises";
8596
+ import * as fs12 from "node:fs/promises";
9145
8597
  import * as path14 from "node:path";
9146
8598
 
9147
8599
  // src/filtering/apply-filters.ts
@@ -9357,7 +8809,7 @@ class DocCov {
9357
8809
  }
9358
8810
  async analyzeFile(filePath, analyzeOptions = {}) {
9359
8811
  const resolvedPath = path14.resolve(filePath);
9360
- const content = await fs13.readFile(resolvedPath, "utf-8");
8812
+ const content = await fs12.readFile(resolvedPath, "utf-8");
9361
8813
  const packageDir = resolvePackageDir(resolvedPath);
9362
8814
  const spec = await extractPackageSpec(resolvedPath, packageDir, content, this.options);
9363
8815
  return this.applySpecFilters(spec, analyzeOptions.filters).spec;
@@ -9405,7 +8857,7 @@ class DocCov {
9405
8857
  };
9406
8858
  }
9407
8859
  }
9408
- const content = await fs13.readFile(resolvedPath, "utf-8");
8860
+ const content = await fs12.readFile(resolvedPath, "utf-8");
9409
8861
  const detectedSchemas = await this.detectSchemas(resolvedPath, packageDir);
9410
8862
  const analysis = runAnalysis({
9411
8863
  entryFile: resolvedPath,
@@ -9621,113 +9073,13 @@ function resolvePackageDir(entryFile) {
9621
9073
  currentDir = parentDir;
9622
9074
  }
9623
9075
  }
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
9076
  // src/resolve/index.ts
9725
- import * as path16 from "node:path";
9726
- async function resolveTarget(fs14, options) {
9077
+ import * as path15 from "node:path";
9078
+ async function resolveTarget(fs13, options) {
9727
9079
  let targetDir = options.cwd;
9728
9080
  let packageInfo;
9729
9081
  if (options.package) {
9730
- const mono = await detectMonorepo(fs14);
9082
+ const mono = await detectMonorepo(fs13);
9731
9083
  if (!mono.isMonorepo) {
9732
9084
  throw new Error("Not a monorepo. Remove --package flag for single-package repos.");
9733
9085
  }
@@ -9736,21 +9088,21 @@ async function resolveTarget(fs14, options) {
9736
9088
  const available = mono.packages.map((p) => p.name).join(", ");
9737
9089
  throw new Error(`Package "${options.package}" not found. Available: ${available}`);
9738
9090
  }
9739
- targetDir = path16.join(options.cwd, pkg.path);
9091
+ targetDir = path15.join(options.cwd, pkg.path);
9740
9092
  packageInfo = pkg;
9741
9093
  }
9742
9094
  let entryFile;
9743
9095
  let entryPointInfo;
9744
9096
  if (!options.entry) {
9745
- entryPointInfo = await detectEntryPoint(fs14, getRelativePath(options.cwd, targetDir));
9746
- entryFile = path16.join(targetDir, entryPointInfo.path);
9097
+ entryPointInfo = await detectEntryPoint(fs13, getRelativePath(options.cwd, targetDir));
9098
+ entryFile = path15.join(targetDir, entryPointInfo.path);
9747
9099
  } else {
9748
- const explicitPath = path16.resolve(targetDir, options.entry);
9749
- const isDirectory = await isDir(fs14, getRelativePath(options.cwd, explicitPath));
9100
+ const explicitPath = path15.resolve(targetDir, options.entry);
9101
+ const isDirectory = await isDir(fs13, getRelativePath(options.cwd, explicitPath));
9750
9102
  if (isDirectory) {
9751
9103
  targetDir = explicitPath;
9752
- entryPointInfo = await detectEntryPoint(fs14, getRelativePath(options.cwd, explicitPath));
9753
- entryFile = path16.join(explicitPath, entryPointInfo.path);
9104
+ entryPointInfo = await detectEntryPoint(fs13, getRelativePath(options.cwd, explicitPath));
9105
+ entryFile = path15.join(explicitPath, entryPointInfo.path);
9754
9106
  } else {
9755
9107
  entryFile = explicitPath;
9756
9108
  entryPointInfo = {
@@ -9770,20 +9122,20 @@ async function resolveTarget(fs14, options) {
9770
9122
  function getRelativePath(base, target) {
9771
9123
  if (base === target)
9772
9124
  return ".";
9773
- const rel = path16.relative(base, target);
9125
+ const rel = path15.relative(base, target);
9774
9126
  return rel || ".";
9775
9127
  }
9776
- async function isDir(fs14, relativePath) {
9777
- const hasPackageJson = await fs14.exists(path16.join(relativePath, "package.json"));
9128
+ async function isDir(fs13, relativePath) {
9129
+ const hasPackageJson = await fs13.exists(path15.join(relativePath, "package.json"));
9778
9130
  if (hasPackageJson)
9779
9131
  return true;
9780
9132
  const commonEntryFiles = ["index.ts", "index.tsx", "src/index.ts", "main.ts"];
9781
9133
  for (const entry of commonEntryFiles) {
9782
- if (await fs14.exists(path16.join(relativePath, entry))) {
9134
+ if (await fs13.exists(path15.join(relativePath, entry))) {
9783
9135
  return true;
9784
9136
  }
9785
9137
  }
9786
- return !path16.extname(relativePath);
9138
+ return !path15.extname(relativePath);
9787
9139
  }
9788
9140
  // src/scan/github-context.ts
9789
9141
  function parseGitHubUrl2(url) {
@@ -9794,8 +9146,8 @@ function parseGitHubUrl2(url) {
9794
9146
  return null;
9795
9147
  }
9796
9148
  }
9797
- async function fetchRawFile(owner, repo, ref, path17, authToken) {
9798
- const url = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path17}`;
9149
+ async function fetchRawFile(owner, repo, ref, path16, authToken) {
9150
+ const url = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path16}`;
9799
9151
  try {
9800
9152
  const headers = {};
9801
9153
  if (authToken) {
@@ -10026,7 +9378,6 @@ export {
10026
9378
  validateExamples,
10027
9379
  typecheckExamples,
10028
9380
  typecheckExample,
10029
- tryExtractStandardSchema,
10030
9381
  shouldValidate,
10031
9382
  serializeJSDoc,
10032
9383
  saveSpecCache,
@@ -10037,6 +9388,7 @@ export {
10037
9388
  runExamples,
10038
9389
  runExample,
10039
9390
  resolveTarget,
9391
+ resolveCompiledPath,
10040
9392
  renderSparkline,
10041
9393
  renderApiSurface,
10042
9394
  readPackageJson,
@@ -10049,18 +9401,16 @@ export {
10049
9401
  parseJSDocToPatch,
10050
9402
  parseGitHubUrl,
10051
9403
  parseExamplesFlag,
10052
- parseCodeOwners,
10053
9404
  parseAssertions,
10054
9405
  mergeFixes,
10055
9406
  mergeFilters,
10056
- mergeConfig,
10057
9407
  loadSpecCache,
10058
9408
  loadSnapshotsForDays,
10059
9409
  loadSnapshots,
10060
- loadCodeOwners,
10061
9410
  loadCachedReport,
10062
9411
  listWorkspacePackages,
10063
9412
  isStandardJSONSchema,
9413
+ isSchemaType,
10064
9414
  isFixableDrift,
10065
9415
  isExecutableLang,
10066
9416
  isCachedReportValid,
@@ -10074,22 +9424,18 @@ export {
10074
9424
  groupDriftsByCategory,
10075
9425
  getUndocumentedExports,
10076
9426
  getTrend,
9427
+ getSupportedLibraries,
10077
9428
  getSpecCachePath,
10078
9429
  getRunCommand,
10079
- getRulesForKind,
10080
- getRule,
10081
9430
  getReportPath,
9431
+ getRegisteredAdapters,
10082
9432
  getPrimaryBuildScript,
10083
9433
  getInstallCommand,
10084
- getFileBlame,
10085
9434
  getExtendedTrend,
10086
9435
  getDriftSummary,
10087
9436
  getDocumentedExports,
10088
9437
  getDocsImpactSummary,
10089
9438
  getDiffReportPath,
10090
- getDefaultConfig,
10091
- getCoverageRules,
10092
- getBlameForLines,
10093
9439
  generateWeeklySummaries,
10094
9440
  generateReportFromEnriched,
10095
9441
  generateReport,
@@ -10100,22 +9446,21 @@ export {
10100
9446
  formatDelta,
10101
9447
  findRemovedReferences,
10102
9448
  findPackageByName,
10103
- findOwners,
10104
9449
  findJSDocLocation,
10105
9450
  findExportReferences,
10106
9451
  findDeprecatedReferences,
9452
+ findAdapter,
10107
9453
  fetchSpecFromGitHub,
10108
9454
  fetchSpec,
10109
9455
  fetchGitHubContext,
10110
- extractViaStandardSchema,
9456
+ extractStandardSchemasFromProject,
9457
+ extractStandardSchemas,
10111
9458
  extractSpecSummary,
9459
+ extractSchemaType,
9460
+ extractSchemaOutputType,
10112
9461
  extractPackageSpec,
10113
9462
  extractImports,
10114
9463
  extractFunctionCalls,
10115
- evaluateQuality,
10116
- evaluatePolicy,
10117
- evaluatePolicies,
10118
- evaluateExportQuality,
10119
9464
  ensureSpecCoverage,
10120
9465
  enrichSpec,
10121
9466
  diffSpecWithDocs,
@@ -10143,33 +9488,23 @@ export {
10143
9488
  buildDisplayUrl,
10144
9489
  buildCloneUrl,
10145
9490
  blockReferencesExport,
10146
- attributeOwners,
10147
9491
  applyPatchToJSDoc,
10148
9492
  applyEdits,
10149
- analyzeSpecOwnership,
10150
- analyzeSpecContributors,
10151
9493
  analyzeProject,
10152
- analyzeOwnership,
10153
9494
  analyzeFile,
10154
9495
  analyzeDocsImpact,
10155
- analyzeContributors,
10156
9496
  analyze,
10157
9497
  VALIDATION_INFO,
10158
- TSDOC_RULES,
10159
9498
  SandboxFileSystem,
10160
- STYLE_RULES,
10161
9499
  SPEC_CACHE_FILE,
10162
9500
  RETENTION_DAYS,
10163
9501
  REPORT_VERSION,
10164
9502
  REPORT_EXTENSIONS,
10165
9503
  NodeFileSystem,
10166
- KNOWN_VENDORS,
10167
9504
  HISTORY_DIR,
10168
9505
  DocCov,
10169
9506
  DEFAULT_REPORT_PATH,
10170
9507
  DEFAULT_REPORT_DIR,
10171
- CORE_RULES,
10172
9508
  CACHE_VERSION,
10173
- BUILTIN_RULES,
10174
9509
  ALL_VALIDATIONS
10175
9510
  };