@openpkg-ts/sdk 0.33.1 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,32 @@
1
+ import {
2
+ QueryBuilder,
3
+ analyzeSpec,
4
+ buildSignatureString,
5
+ findMissingParamDocs,
6
+ formatBadges,
7
+ formatConditionalType,
8
+ formatMappedType,
9
+ formatParameters,
10
+ formatReturnType,
11
+ formatSchema,
12
+ formatTypeParameters,
13
+ getDeprecationMessage,
14
+ getMemberBadges,
15
+ getMethods,
16
+ getProperties,
17
+ groupByVisibility,
18
+ hasDeprecatedTag,
19
+ isMethod,
20
+ isProperty,
21
+ query,
22
+ resolveTypeRef,
23
+ sortByName,
24
+ toAlgoliaRecords,
25
+ toPagefindRecords,
26
+ toSearchIndex,
27
+ toSearchIndexJSON
28
+ } from "./shared/chunk-skapcfq1.js";
29
+
1
30
  // src/primitives/diff.ts
2
31
  import {
3
32
  calculateNextVersion,
@@ -42,312 +71,9 @@ function mergeConfig(fileConfig, cliOptions) {
42
71
  }
43
72
  };
44
73
  }
45
- // src/core/diagnostics.ts
46
- function hasDeprecatedTag(exp) {
47
- if (exp.deprecated === true)
48
- return true;
49
- return exp.tags?.some((t) => t.name === "deprecated" || t.name === "@deprecated") ?? false;
50
- }
51
- function getDeprecationMessage(exp) {
52
- const tag = exp.tags?.find((t) => t.name === "deprecated" || t.name === "@deprecated");
53
- if (tag?.text.trim()) {
54
- return tag.text.trim();
55
- }
56
- return;
57
- }
58
- function findMissingParamDocs(exp) {
59
- const missing = [];
60
- for (const sig of exp.signatures ?? []) {
61
- for (const param of sig.parameters ?? []) {
62
- if (!param.description?.trim()) {
63
- missing.push(param.name);
64
- }
65
- }
66
- }
67
- return missing;
68
- }
69
- function checkMemberDescriptions(exp, members) {
70
- const items = [];
71
- for (const member of members) {
72
- if (!member.description?.trim() && member.name) {
73
- items.push({
74
- exportId: exp.id,
75
- exportName: exp.name,
76
- issue: "member missing description",
77
- member: member.name
78
- });
79
- }
80
- }
81
- return items;
82
- }
83
- function analyzeSpec(spec) {
84
- const missingDescriptions = [];
85
- const deprecatedNoReason = [];
86
- const missingParamDocs = [];
87
- for (const exp of spec.exports) {
88
- if (!exp.description?.trim()) {
89
- missingDescriptions.push({
90
- exportId: exp.id,
91
- exportName: exp.name,
92
- issue: "missing description"
93
- });
94
- }
95
- if (exp.members) {
96
- missingDescriptions.push(...checkMemberDescriptions(exp, exp.members));
97
- }
98
- if (hasDeprecatedTag(exp) && !getDeprecationMessage(exp)) {
99
- deprecatedNoReason.push({
100
- exportId: exp.id,
101
- exportName: exp.name,
102
- issue: "deprecated without reason"
103
- });
104
- }
105
- const missingParams = findMissingParamDocs(exp);
106
- for (const param of missingParams) {
107
- missingParamDocs.push({
108
- exportId: exp.id,
109
- exportName: exp.name,
110
- issue: "param missing description",
111
- param
112
- });
113
- }
114
- }
115
- return {
116
- missingDescriptions,
117
- deprecatedNoReason,
118
- missingParamDocs
119
- };
120
- }
121
- // src/core/format.ts
122
- function getMemberBadges(member) {
123
- const badges = [];
124
- const visibility = member.visibility ?? "public";
125
- if (visibility !== "public") {
126
- badges.push(visibility);
127
- }
128
- const flags = member.flags;
129
- if (flags?.static)
130
- badges.push("static");
131
- if (flags?.readonly)
132
- badges.push("readonly");
133
- if (flags?.async)
134
- badges.push("async");
135
- if (flags?.abstract)
136
- badges.push("abstract");
137
- return badges;
138
- }
139
- function formatBadges(badges) {
140
- return badges.join(" ");
141
- }
142
74
  // src/core/loader.ts
143
75
  import * as fs2 from "node:fs";
144
-
145
- // src/core/query.ts
146
- function formatFunctionSchema(schema) {
147
- const sigs = schema["x-ts-signatures"];
148
- if (!sigs?.length)
149
- return "(...args: unknown[]) => unknown";
150
- const sig = sigs[0];
151
- const params = formatParameters(sig);
152
- const ret = sig.returns ? formatSchema(sig.returns.schema) : "void";
153
- return `${params} => ${ret}`;
154
- }
155
- function formatSchema(schema, options) {
156
- if (!schema)
157
- return "unknown";
158
- if (typeof schema === "string")
159
- return schema;
160
- const withPackage = (typeStr) => {
161
- if (options?.includePackage && typeof schema === "object" && "x-ts-package" in schema) {
162
- const pkg = schema["x-ts-package"];
163
- return `${typeStr} (from ${pkg})`;
164
- }
165
- return typeStr;
166
- };
167
- if (typeof schema === "object" && schema !== null) {
168
- if ("x-ts-type" in schema && typeof schema["x-ts-type"] === "string") {
169
- const tsType = schema["x-ts-type"];
170
- if (tsType === "function" || schema["x-ts-function"]) {
171
- return withPackage(formatFunctionSchema(schema));
172
- }
173
- return withPackage(tsType);
174
- }
175
- if ("x-ts-function" in schema && schema["x-ts-function"]) {
176
- return withPackage(formatFunctionSchema(schema));
177
- }
178
- if ("x-ts-type-predicate" in schema) {
179
- const pred = schema["x-ts-type-predicate"];
180
- return `${pred.parameterName} is ${formatSchema(pred.type, options)}`;
181
- }
182
- if ("$ref" in schema && typeof schema.$ref === "string") {
183
- const baseName = schema.$ref.replace("#/types/", "");
184
- if ("x-ts-type-arguments" in schema && Array.isArray(schema["x-ts-type-arguments"])) {
185
- const args = schema["x-ts-type-arguments"].map((s) => formatSchema(s, options)).join(", ");
186
- return withPackage(`${baseName}<${args}>`);
187
- }
188
- return withPackage(baseName);
189
- }
190
- if ("anyOf" in schema && Array.isArray(schema.anyOf)) {
191
- const threshold = options?.collapseUnionThreshold;
192
- const members = schema.anyOf;
193
- if (threshold && members.length > threshold) {
194
- const shown = members.slice(0, 3);
195
- const remaining = members.length - 3;
196
- const shownStr = shown.map((s) => formatSchema(s, options)).join(" | ");
197
- return `${shownStr} | ... (${remaining} more)`;
198
- }
199
- return members.map((s) => formatSchema(s, options)).join(" | ");
200
- }
201
- if ("allOf" in schema && Array.isArray(schema.allOf)) {
202
- return schema.allOf.map((s) => formatSchema(s, options)).join(" & ");
203
- }
204
- if ("type" in schema && schema.type === "array") {
205
- const items = "items" in schema ? formatSchema(schema.items, options) : "unknown";
206
- return `${items}[]`;
207
- }
208
- if ("type" in schema && schema.type === "tuple" && "items" in schema) {
209
- const items = schema.items.map((s) => formatSchema(s, options)).join(", ");
210
- return `[${items}]`;
211
- }
212
- if ("type" in schema && schema.type === "object") {
213
- if ("properties" in schema && schema.properties) {
214
- const props = Object.entries(schema.properties).map(([k, v]) => `${k}: ${formatSchema(v, options)}`).join("; ");
215
- return `{ ${props} }`;
216
- }
217
- return "object";
218
- }
219
- if ("type" in schema && typeof schema.type === "string") {
220
- return withPackage(schema.type);
221
- }
222
- }
223
- return "unknown";
224
- }
225
- function formatTypeParameters(typeParams) {
226
- if (!typeParams?.length)
227
- return "";
228
- const params = typeParams.map((tp) => {
229
- let str = "";
230
- if ("const" in tp && tp.const)
231
- str += "const ";
232
- if (tp.variance === "in")
233
- str += "in ";
234
- else if (tp.variance === "out")
235
- str += "out ";
236
- else if (tp.variance === "inout")
237
- str += "in out ";
238
- str += tp.name;
239
- if (tp.constraint)
240
- str += ` extends ${tp.constraint}`;
241
- if (tp.default)
242
- str += ` = ${tp.default}`;
243
- return str;
244
- });
245
- return `<${params.join(", ")}>`;
246
- }
247
- function formatParameters(sig) {
248
- if (!sig?.parameters?.length)
249
- return "()";
250
- const params = sig.parameters.map((p) => {
251
- const optional = p.required === false ? "?" : "";
252
- const rest = p.rest ? "..." : "";
253
- const type = formatSchema(p.schema);
254
- return `${rest}${p.name}${optional}: ${type}`;
255
- });
256
- return `(${params.join(", ")})`;
257
- }
258
- function formatReturnType(sig) {
259
- if (!sig?.returns)
260
- return "void";
261
- return formatSchema(sig.returns.schema);
262
- }
263
- function buildSignatureString(exp, sigIndex = 0) {
264
- const sig = exp.signatures?.[sigIndex];
265
- const typeParams = formatTypeParameters(exp.typeParameters || sig?.typeParameters);
266
- switch (exp.kind) {
267
- case "function": {
268
- const params = formatParameters(sig);
269
- const returnType = formatReturnType(sig);
270
- return `function ${exp.name}${typeParams}${params}: ${returnType}`;
271
- }
272
- case "class": {
273
- const ext = exp.extends ? ` extends ${exp.extends}` : "";
274
- const impl = exp.implements?.length ? ` implements ${exp.implements.join(", ")}` : "";
275
- return `class ${exp.name}${typeParams}${ext}${impl}`;
276
- }
277
- case "interface": {
278
- const ext = exp.extends ? ` extends ${exp.extends}` : "";
279
- return `interface ${exp.name}${typeParams}${ext}`;
280
- }
281
- case "type": {
282
- const typeValue = typeof exp.type === "string" ? exp.type : formatSchema(exp.schema);
283
- return `type ${exp.name}${typeParams} = ${typeValue}`;
284
- }
285
- case "enum": {
286
- return `enum ${exp.name}`;
287
- }
288
- case "variable": {
289
- const typeValue = typeof exp.type === "string" ? exp.type : formatSchema(exp.schema);
290
- return `const ${exp.name}: ${typeValue}`;
291
- }
292
- default:
293
- return exp.name;
294
- }
295
- }
296
- function resolveTypeRef(ref, spec) {
297
- const id = ref.replace("#/types/", "");
298
- return spec.types?.find((t) => t.id === id);
299
- }
300
- function isMethod(member) {
301
- return !!member.signatures?.length;
302
- }
303
- function isProperty(member) {
304
- return !member.signatures?.length;
305
- }
306
- function getMethods(members) {
307
- return members?.filter(isMethod) ?? [];
308
- }
309
- function getProperties(members) {
310
- return members?.filter(isProperty) ?? [];
311
- }
312
- function groupByVisibility(members) {
313
- const groups = {
314
- public: [],
315
- protected: [],
316
- private: []
317
- };
318
- for (const member of members ?? []) {
319
- const visibility = member.visibility ?? "public";
320
- groups[visibility].push(member);
321
- }
322
- return groups;
323
- }
324
- function sortByName(items) {
325
- return [...items].sort((a, b) => a.name.localeCompare(b.name));
326
- }
327
- function formatConditionalType(condType) {
328
- const check = formatSchema(condType.checkType);
329
- const ext = formatSchema(condType.extendsType);
330
- const trueT = formatSchema(condType.trueType);
331
- const falseT = formatSchema(condType.falseType);
332
- return `${check} extends ${ext} ? ${trueT} : ${falseT}`;
333
- }
334
- function formatMappedType(mappedType) {
335
- const keyStr = formatSchema(mappedType.keyType);
336
- const valueStr = formatSchema(mappedType.valueType);
337
- let readonlyMod = "";
338
- if (mappedType.readonly === true || mappedType.readonly === "add") {
339
- readonlyMod = "readonly ";
340
- } else if (mappedType.readonly === "remove") {
341
- readonlyMod = "-readonly ";
342
- }
343
- let optionalMod = "";
344
- if (mappedType.optional === true || mappedType.optional === "add") {
345
- optionalMod = "?";
346
- } else if (mappedType.optional === "remove") {
347
- optionalMod = "-?";
348
- }
349
- return `{ ${readonlyMod}[${keyStr}]${optionalMod}: ${valueStr} }`;
350
- }
76
+ import { validateSpec } from "@openpkg-ts/spec";
351
77
 
352
78
  // src/render/html.ts
353
79
  var defaultCSS = `
@@ -1368,177 +1094,26 @@ function toDocusaurusSidebarJS(spec, options = {}) {
1368
1094
  return `module.exports = ${JSON.stringify(sidebar, null, 2)};`;
1369
1095
  }
1370
1096
 
1371
- // src/core/search.ts
1372
- var defaultSlugify2 = (name) => name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
1373
- function extractKeywords(exp, options = {}) {
1374
- const keywords = new Set;
1375
- keywords.add(exp.name);
1376
- keywords.add(exp.name.toLowerCase());
1377
- const camelParts = exp.name.split(/(?=[A-Z])/);
1378
- for (const part of camelParts) {
1379
- if (part.length > 2)
1380
- keywords.add(part.toLowerCase());
1381
- }
1382
- if (exp.tags) {
1383
- for (const tag of exp.tags) {
1384
- keywords.add(tag.name.replace("@", ""));
1385
- const tagWords = tag.text.split(/\s+/);
1386
- for (const word of tagWords) {
1387
- if (word.length > 2)
1388
- keywords.add(word.toLowerCase());
1389
- }
1390
- }
1391
- }
1392
- if (exp.description) {
1393
- const descWords = exp.description.toLowerCase().split(/\W+/).filter((w) => w.length > 2);
1394
- for (const word of descWords) {
1395
- keywords.add(word);
1396
- }
1397
- }
1398
- if (options.includeMembers && exp.members) {
1399
- for (const member of exp.members) {
1400
- if (member.name) {
1401
- keywords.add(member.name.toLowerCase());
1402
- }
1403
- }
1404
- }
1405
- if (options.includeParameters && exp.signatures) {
1406
- for (const sig of exp.signatures) {
1407
- for (const param of sig.parameters || []) {
1408
- keywords.add(param.name.toLowerCase());
1409
- }
1410
- }
1411
- }
1412
- return Array.from(keywords);
1413
- }
1414
- function buildContent(exp, options = {}) {
1415
- const parts = [];
1416
- parts.push(exp.name);
1417
- if (exp.description) {
1418
- parts.push(exp.description);
1419
- }
1420
- if (options.includeSignatures !== false) {
1421
- parts.push(buildSignatureString(exp));
1422
- }
1423
- if (exp.tags) {
1424
- parts.push(...exp.tags.map((t) => `${t.name} ${t.text}`));
1425
- }
1426
- if (options.includeMembers !== false && exp.members) {
1427
- const props = getProperties(exp.members);
1428
- const methods = getMethods(exp.members);
1429
- for (const prop of props) {
1430
- if (prop.name) {
1431
- parts.push(prop.name);
1432
- if (prop.description)
1433
- parts.push(prop.description);
1434
- }
1435
- }
1436
- for (const method of methods) {
1437
- if (method.name) {
1438
- parts.push(method.name);
1439
- if (method.description)
1440
- parts.push(method.description);
1441
- }
1442
- }
1443
- }
1444
- if (options.includeParameters !== false && exp.signatures) {
1445
- for (const sig of exp.signatures) {
1446
- for (const param of sig.parameters || []) {
1447
- parts.push(param.name);
1448
- if (param.description)
1449
- parts.push(param.description);
1450
- }
1451
- }
1452
- }
1453
- return parts.join(" ");
1454
- }
1455
- function createSearchRecord(exp, _packageName, options = {}) {
1456
- const { baseUrl = "/api", slugify = defaultSlugify2 } = options;
1457
- return {
1458
- id: exp.id,
1459
- name: exp.name,
1460
- kind: exp.kind,
1461
- signature: buildSignatureString(exp),
1462
- description: exp.description,
1463
- content: buildContent(exp, options),
1464
- keywords: extractKeywords(exp, options),
1465
- url: `${baseUrl}/${slugify(exp.name)}`,
1466
- deprecated: exp.deprecated === true
1467
- };
1468
- }
1469
- function toSearchIndex(spec, options = {}) {
1470
- const records = spec.exports.map((exp) => createSearchRecord(exp, spec.meta.name, options));
1471
- return {
1472
- records,
1473
- version: spec.meta.version || "0.0.0",
1474
- generatedAt: new Date().toISOString(),
1475
- packageName: spec.meta.name
1476
- };
1477
- }
1478
- function toPagefindRecords(spec, options = {}) {
1479
- const { baseUrl = "/api", slugify = defaultSlugify2, weights = {} } = options;
1480
- const { name: nameWeight = 10, description: descWeight = 5, signature: sigWeight = 3 } = weights;
1481
- return spec.exports.map((exp) => {
1482
- const content = buildContent(exp, options);
1483
- const signature = buildSignatureString(exp);
1484
- const filters = {
1485
- kind: [exp.kind]
1486
- };
1487
- if (exp.deprecated) {
1488
- filters.deprecated = ["true"];
1489
- }
1490
- if (exp.tags?.length) {
1491
- filters.tags = exp.tags.map((t) => t.name.replace("@", ""));
1492
- }
1493
- return {
1494
- url: `${baseUrl}/${slugify(exp.name)}`,
1495
- content,
1496
- word_count: content.split(/\s+/).length,
1497
- filters,
1498
- meta: {
1499
- title: exp.name,
1500
- kind: exp.kind,
1501
- description: exp.description?.slice(0, 160),
1502
- signature
1503
- },
1504
- weighted_sections: [
1505
- { weight: nameWeight, text: exp.name },
1506
- ...exp.description ? [{ weight: descWeight, text: exp.description }] : [],
1507
- { weight: sigWeight, text: signature }
1508
- ]
1509
- };
1510
- });
1511
- }
1512
- function toAlgoliaRecords(spec, options = {}) {
1513
- const { baseUrl = "/api", slugify = defaultSlugify2 } = options;
1514
- return spec.exports.map((exp) => ({
1515
- objectID: exp.id,
1516
- name: exp.name,
1517
- kind: exp.kind,
1518
- description: exp.description,
1519
- signature: buildSignatureString(exp),
1520
- content: buildContent(exp, options),
1521
- tags: (exp.tags || []).map((t) => t.name.replace("@", "")),
1522
- deprecated: exp.deprecated === true,
1523
- url: `${baseUrl}/${slugify(exp.name)}`,
1524
- hierarchy: {
1525
- lvl0: spec.meta.name,
1526
- lvl1: `${exp.kind.charAt(0).toUpperCase() + exp.kind.slice(1)}s`,
1527
- lvl2: exp.name
1528
- }
1529
- }));
1530
- }
1531
- function toSearchIndexJSON(spec, options = {}) {
1532
- const index = toSearchIndex(spec, options);
1533
- return options.pretty ? JSON.stringify(index, null, 2) : JSON.stringify(index);
1534
- }
1535
-
1536
1097
  // src/core/loader.ts
1537
1098
  function loadSpec(spec) {
1538
1099
  return createDocsInstance(spec);
1539
1100
  }
1540
1101
  function createDocs(input) {
1541
- const spec = typeof input === "string" ? JSON.parse(fs2.readFileSync(input, "utf-8")) : input;
1102
+ let spec;
1103
+ if (typeof input === "string") {
1104
+ try {
1105
+ spec = JSON.parse(fs2.readFileSync(input, "utf-8"));
1106
+ } catch (err) {
1107
+ throw new Error(`Failed to parse spec file: ${err instanceof Error ? err.message : String(err)}`);
1108
+ }
1109
+ } else {
1110
+ spec = input;
1111
+ }
1112
+ const validation = validateSpec(spec);
1113
+ if (!validation.ok) {
1114
+ const errors = validation.errors.slice(0, 5).map((e) => `${e.instancePath || "/"}: ${e.message}`).join("; ");
1115
+ throw new Error(`Invalid OpenPkg spec: ${errors}`);
1116
+ }
1542
1117
  return createDocsInstance(spec);
1543
1118
  }
1544
1119
  function createDocsInstance(spec) {
@@ -1589,8 +1164,8 @@ function createDocsInstance(spec) {
1589
1164
  const normalizedTag = tagName.startsWith("@") ? tagName : `@${tagName}`;
1590
1165
  return exportsByTag.get(normalizedTag) ?? [];
1591
1166
  },
1592
- search(query) {
1593
- const lowerQuery = query.toLowerCase();
1167
+ search(query2) {
1168
+ const lowerQuery = query2.toLowerCase();
1594
1169
  return spec.exports.filter((exp) => {
1595
1170
  if (exp.name.toLowerCase().includes(lowerQuery))
1596
1171
  return true;
@@ -1654,6 +1229,221 @@ function extractModuleName(exp) {
1654
1229
  }
1655
1230
  return;
1656
1231
  }
1232
+ // src/render/react.ts
1233
+ import * as fs3 from "node:fs";
1234
+ import * as path2 from "node:path";
1235
+ function generateFullLayout(spec, componentsPath) {
1236
+ const pkgName = spec.meta.name;
1237
+ return `'use client';
1238
+
1239
+ import type { OpenPkg, SpecExport } from '@openpkg-ts/spec';
1240
+ import spec from './openpkg.json';
1241
+
1242
+ // Add components via: openpkg docs add function-section class-section interface-section
1243
+ // Then uncomment the imports below and customize as needed.
1244
+
1245
+ // import { FunctionSection } from '${componentsPath}/function-section';
1246
+ // import { ClassSection } from '${componentsPath}/class-section';
1247
+ // import { InterfaceSection } from '${componentsPath}/interface-section';
1248
+ // import { VariableSection } from '${componentsPath}/variable-section';
1249
+ // import { EnumSection } from '${componentsPath}/enum-section';
1250
+
1251
+ /**
1252
+ * Renders a single export based on its kind.
1253
+ * Customize this to match your design system.
1254
+ */
1255
+ function ExportSection({ exp }: { exp: SpecExport }) {
1256
+ // Uncomment the switch once you've added components:
1257
+ // switch (exp.kind) {
1258
+ // case 'function':
1259
+ // return <FunctionSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
1260
+ // case 'class':
1261
+ // return <ClassSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
1262
+ // case 'interface':
1263
+ // case 'type':
1264
+ // return <InterfaceSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
1265
+ // case 'variable':
1266
+ // return <VariableSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
1267
+ // case 'enum':
1268
+ // return <EnumSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
1269
+ // default:
1270
+ // return null;
1271
+ // }
1272
+
1273
+ // Placeholder: replace with component imports above
1274
+ return (
1275
+ <section id={exp.id} className="py-8 border-b">
1276
+ <h2 className="text-xl font-semibold">{exp.name}</h2>
1277
+ <p className="text-muted-foreground">{exp.description || 'No description'}</p>
1278
+ <code className="text-sm">{exp.kind}</code>
1279
+ </section>
1280
+ );
1281
+ }
1282
+
1283
+ /**
1284
+ * Full API Reference Page for ${pkgName}
1285
+ *
1286
+ * This layout renders all exports on a single page.
1287
+ * Customize the grouping, styling, and components to match your docs.
1288
+ */
1289
+ export default function APIReferencePage() {
1290
+ const typedSpec = spec as OpenPkg;
1291
+ const exports = typedSpec.exports;
1292
+
1293
+ // Group exports by kind
1294
+ const functions = exports.filter((e) => e.kind === 'function');
1295
+ const classes = exports.filter((e) => e.kind === 'class');
1296
+ const interfaces = exports.filter((e) => e.kind === 'interface' || e.kind === 'type');
1297
+ const variables = exports.filter((e) => e.kind === 'variable');
1298
+ const enums = exports.filter((e) => e.kind === 'enum');
1299
+
1300
+ return (
1301
+ <div className="max-w-4xl mx-auto px-4 py-8">
1302
+ <header className="mb-12">
1303
+ <h1 className="text-3xl font-bold">{typedSpec.meta.name}</h1>
1304
+ {typedSpec.meta.description && (
1305
+ <p className="text-lg text-muted-foreground mt-2">{typedSpec.meta.description}</p>
1306
+ )}
1307
+ {typedSpec.meta.version && (
1308
+ <p className="text-sm text-muted-foreground">v{typedSpec.meta.version}</p>
1309
+ )}
1310
+ </header>
1311
+
1312
+ {functions.length > 0 && (
1313
+ <section className="mb-12">
1314
+ <h2 className="text-2xl font-bold mb-6">Functions</h2>
1315
+ {functions.map((exp) => (
1316
+ <ExportSection key={exp.id} exp={exp} />
1317
+ ))}
1318
+ </section>
1319
+ )}
1320
+
1321
+ {classes.length > 0 && (
1322
+ <section className="mb-12">
1323
+ <h2 className="text-2xl font-bold mb-6">Classes</h2>
1324
+ {classes.map((exp) => (
1325
+ <ExportSection key={exp.id} exp={exp} />
1326
+ ))}
1327
+ </section>
1328
+ )}
1329
+
1330
+ {interfaces.length > 0 && (
1331
+ <section className="mb-12">
1332
+ <h2 className="text-2xl font-bold mb-6">Types & Interfaces</h2>
1333
+ {interfaces.map((exp) => (
1334
+ <ExportSection key={exp.id} exp={exp} />
1335
+ ))}
1336
+ </section>
1337
+ )}
1338
+
1339
+ {variables.length > 0 && (
1340
+ <section className="mb-12">
1341
+ <h2 className="text-2xl font-bold mb-6">Variables</h2>
1342
+ {variables.map((exp) => (
1343
+ <ExportSection key={exp.id} exp={exp} />
1344
+ ))}
1345
+ </section>
1346
+ )}
1347
+
1348
+ {enums.length > 0 && (
1349
+ <section className="mb-12">
1350
+ <h2 className="text-2xl font-bold mb-6">Enums</h2>
1351
+ {enums.map((exp) => (
1352
+ <ExportSection key={exp.id} exp={exp} />
1353
+ ))}
1354
+ </section>
1355
+ )}
1356
+ </div>
1357
+ );
1358
+ }
1359
+
1360
+ export { spec };
1361
+ `;
1362
+ }
1363
+ function generateIndexLayout(spec, componentsPath) {
1364
+ const pkgName = spec.meta.name;
1365
+ return `'use client';
1366
+
1367
+ import type { OpenPkg } from '@openpkg-ts/spec';
1368
+ import spec from './openpkg.json';
1369
+
1370
+ // Add the export-card component: openpkg docs add export-card
1371
+ // import { ExportCard } from '${componentsPath}/export-card';
1372
+
1373
+ /**
1374
+ * API Reference Index Page for ${pkgName}
1375
+ *
1376
+ * Links to individual export pages. Best with file-based routing.
1377
+ * Customize the card component and links to match your docs.
1378
+ */
1379
+ export default function APIReferenceIndex() {
1380
+ const typedSpec = spec as OpenPkg;
1381
+ const exports = typedSpec.exports;
1382
+
1383
+ // Group exports by kind
1384
+ const groups = [
1385
+ { title: 'Functions', items: exports.filter((e) => e.kind === 'function') },
1386
+ { title: 'Classes', items: exports.filter((e) => e.kind === 'class') },
1387
+ { title: 'Types & Interfaces', items: exports.filter((e) => e.kind === 'interface' || e.kind === 'type') },
1388
+ { title: 'Variables', items: exports.filter((e) => e.kind === 'variable') },
1389
+ { title: 'Enums', items: exports.filter((e) => e.kind === 'enum') },
1390
+ ].filter((g) => g.items.length > 0);
1391
+
1392
+ return (
1393
+ <div className="max-w-4xl mx-auto px-4 py-8">
1394
+ <header className="mb-12">
1395
+ <h1 className="text-3xl font-bold">{typedSpec.meta.name}</h1>
1396
+ {typedSpec.meta.description && (
1397
+ <p className="text-lg text-muted-foreground mt-2">{typedSpec.meta.description}</p>
1398
+ )}
1399
+ </header>
1400
+
1401
+ {groups.map((group) => (
1402
+ <section key={group.title} className="mb-12">
1403
+ <h2 className="text-2xl font-bold mb-6">{group.title}</h2>
1404
+ <div className="grid gap-4 md:grid-cols-2">
1405
+ {group.items.map((exp) => (
1406
+ // Replace with ExportCard once installed:
1407
+ // <ExportCard key={exp.id} export={exp} href={\`/api/\${exp.name}\`} />
1408
+ <a
1409
+ key={exp.id}
1410
+ href={\`/api/\${exp.name}\`}
1411
+ className="block p-4 border rounded-lg hover:bg-muted transition-colors"
1412
+ >
1413
+ <h3 className="font-semibold">{exp.name}</h3>
1414
+ <p className="text-sm text-muted-foreground line-clamp-2">
1415
+ {exp.description || 'No description'}
1416
+ </p>
1417
+ <span className="text-xs bg-muted px-2 py-1 rounded mt-2 inline-block">
1418
+ {exp.kind}
1419
+ </span>
1420
+ </a>
1421
+ ))}
1422
+ </div>
1423
+ </section>
1424
+ ))}
1425
+ </div>
1426
+ );
1427
+ }
1428
+
1429
+ export { spec };
1430
+ `;
1431
+ }
1432
+ async function toReact(spec, options) {
1433
+ const { outDir, variant = "full", componentsPath = "@/components/api" } = options;
1434
+ if (!fs3.existsSync(outDir)) {
1435
+ fs3.mkdirSync(outDir, { recursive: true });
1436
+ }
1437
+ const specPath = path2.join(outDir, "openpkg.json");
1438
+ fs3.writeFileSync(specPath, JSON.stringify(spec, null, 2));
1439
+ const layoutContent = variant === "index" ? generateIndexLayout(spec, componentsPath) : generateFullLayout(spec, componentsPath);
1440
+ const layoutPath = path2.join(outDir, "page.tsx");
1441
+ fs3.writeFileSync(layoutPath, layoutContent);
1442
+ }
1443
+ function toReactString(spec, options = {}) {
1444
+ const { variant = "full", componentsPath = "@/components/api" } = options;
1445
+ return variant === "index" ? generateIndexLayout(spec, componentsPath) : generateFullLayout(spec, componentsPath);
1446
+ }
1657
1447
  // src/primitives/filter.ts
1658
1448
  function matchesExport(exp, criteria) {
1659
1449
  if (criteria.kinds && criteria.kinds.length > 0) {
@@ -1761,8 +1551,8 @@ function filterSpec(spec, criteria) {
1761
1551
  import ts11 from "typescript";
1762
1552
 
1763
1553
  // src/compiler/program.ts
1764
- import * as fs3 from "node:fs";
1765
- import * as path2 from "node:path";
1554
+ import * as fs4 from "node:fs";
1555
+ import * as path3 from "node:path";
1766
1556
  import ts from "typescript";
1767
1557
  function isJsFile(file) {
1768
1558
  return /\.(js|mjs|cjs|jsx)$/.test(file);
@@ -1788,16 +1578,16 @@ function resolveProjectReferences(configPath, parsedConfig) {
1788
1578
  if (!parsedConfig.projectReferences?.length) {
1789
1579
  return additionalFiles;
1790
1580
  }
1791
- const configDir = path2.dirname(configPath);
1581
+ const configDir = path3.dirname(configPath);
1792
1582
  for (const ref of parsedConfig.projectReferences) {
1793
- const refPath = path2.resolve(configDir, ref.path);
1794
- const refConfigPath = fs3.existsSync(path2.join(refPath, "tsconfig.json")) ? path2.join(refPath, "tsconfig.json") : refPath;
1795
- if (!fs3.existsSync(refConfigPath))
1583
+ const refPath = path3.resolve(configDir, ref.path);
1584
+ const refConfigPath = fs4.existsSync(path3.join(refPath, "tsconfig.json")) ? path3.join(refPath, "tsconfig.json") : refPath;
1585
+ if (!fs4.existsSync(refConfigPath))
1796
1586
  continue;
1797
1587
  const refConfigFile = ts.readConfigFile(refConfigPath, ts.sys.readFile);
1798
1588
  if (refConfigFile.error)
1799
1589
  continue;
1800
- const refParsed = ts.parseJsonConfigFileContent(refConfigFile.config, ts.sys, path2.dirname(refConfigPath));
1590
+ const refParsed = ts.parseJsonConfigFileContent(refConfigFile.config, ts.sys, path3.dirname(refConfigPath));
1801
1591
  additionalFiles.push(...refParsed.fileNames);
1802
1592
  }
1803
1593
  return additionalFiles;
@@ -1830,10 +1620,10 @@ function buildWorkspaceMap(baseDir) {
1830
1620
  let rootDir;
1831
1621
  let workspaceGlobs = [];
1832
1622
  for (let i = 0;i < 10; i++) {
1833
- const pnpmPath = path2.join(currentDir, "pnpm-workspace.yaml");
1834
- if (fs3.existsSync(pnpmPath)) {
1623
+ const pnpmPath = path3.join(currentDir, "pnpm-workspace.yaml");
1624
+ if (fs4.existsSync(pnpmPath)) {
1835
1625
  try {
1836
- const yamlContent = fs3.readFileSync(pnpmPath, "utf-8");
1626
+ const yamlContent = fs4.readFileSync(pnpmPath, "utf-8");
1837
1627
  workspaceGlobs = parsePnpmWorkspace(yamlContent);
1838
1628
  if (workspaceGlobs.length > 0) {
1839
1629
  rootDir = currentDir;
@@ -1841,10 +1631,10 @@ function buildWorkspaceMap(baseDir) {
1841
1631
  }
1842
1632
  } catch {}
1843
1633
  }
1844
- const pkgPath = path2.join(currentDir, "package.json");
1845
- if (fs3.existsSync(pkgPath)) {
1634
+ const pkgPath = path3.join(currentDir, "package.json");
1635
+ if (fs4.existsSync(pkgPath)) {
1846
1636
  try {
1847
- const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf-8"));
1637
+ const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
1848
1638
  if (pkg.workspaces) {
1849
1639
  rootDir = currentDir;
1850
1640
  workspaceGlobs = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages || [];
@@ -1852,7 +1642,7 @@ function buildWorkspaceMap(baseDir) {
1852
1642
  }
1853
1643
  } catch {}
1854
1644
  }
1855
- const parent = path2.dirname(currentDir);
1645
+ const parent = path3.dirname(currentDir);
1856
1646
  if (parent === currentDir)
1857
1647
  break;
1858
1648
  currentDir = parent;
@@ -1861,21 +1651,21 @@ function buildWorkspaceMap(baseDir) {
1861
1651
  return;
1862
1652
  const packages = new Map;
1863
1653
  for (const glob of workspaceGlobs) {
1864
- const globDir = path2.join(rootDir, glob.replace(/\/\*$/, ""));
1865
- if (!fs3.existsSync(globDir) || !fs3.statSync(globDir).isDirectory())
1654
+ const globDir = path3.join(rootDir, glob.replace(/\/\*$/, ""));
1655
+ if (!fs4.existsSync(globDir) || !fs4.statSync(globDir).isDirectory())
1866
1656
  continue;
1867
- const entries = fs3.readdirSync(globDir, { withFileTypes: true });
1657
+ const entries = fs4.readdirSync(globDir, { withFileTypes: true });
1868
1658
  for (const entry of entries) {
1869
1659
  if (!entry.isDirectory())
1870
1660
  continue;
1871
- const pkgDir = path2.join(globDir, entry.name);
1872
- const pkgJsonPath = path2.join(pkgDir, "package.json");
1873
- if (!fs3.existsSync(pkgJsonPath))
1661
+ const pkgDir = path3.join(globDir, entry.name);
1662
+ const pkgJsonPath = path3.join(pkgDir, "package.json");
1663
+ if (!fs4.existsSync(pkgJsonPath))
1874
1664
  continue;
1875
1665
  try {
1876
- const pkg = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf-8"));
1666
+ const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
1877
1667
  if (pkg.name) {
1878
- const srcDir = fs3.existsSync(path2.join(pkgDir, "src")) ? path2.join(pkgDir, "src") : pkgDir;
1668
+ const srcDir = fs4.existsSync(path3.join(pkgDir, "src")) ? path3.join(pkgDir, "src") : pkgDir;
1879
1669
  packages.set(pkg.name, srcDir);
1880
1670
  }
1881
1671
  } catch {}
@@ -1885,7 +1675,7 @@ function buildWorkspaceMap(baseDir) {
1885
1675
  }
1886
1676
  function createProgram({
1887
1677
  entryFile,
1888
- baseDir = path2.dirname(entryFile),
1678
+ baseDir = path3.dirname(entryFile),
1889
1679
  content
1890
1680
  }) {
1891
1681
  let configPath = ts.findConfigFile(baseDir, ts.sys.fileExists, "tsconfig.json");
@@ -1896,7 +1686,7 @@ function createProgram({
1896
1686
  let additionalRootFiles = [];
1897
1687
  if (configPath) {
1898
1688
  const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
1899
- const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path2.dirname(configPath));
1689
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path3.dirname(configPath));
1900
1690
  compilerOptions = { ...compilerOptions, ...parsedConfig.options };
1901
1691
  additionalRootFiles = resolveProjectReferences(configPath, parsedConfig);
1902
1692
  const sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
@@ -1924,8 +1714,8 @@ function createProgram({
1924
1714
  return moduleNames.map((moduleName) => {
1925
1715
  const srcDir = workspaceMap.packages.get(moduleName);
1926
1716
  if (srcDir) {
1927
- const indexFile = path2.join(srcDir, "index.ts");
1928
- if (fs3.existsSync(indexFile)) {
1717
+ const indexFile = path3.join(srcDir, "index.ts");
1718
+ if (fs4.existsSync(indexFile)) {
1929
1719
  return { resolvedFileName: indexFile, isExternalLibraryImport: false };
1930
1720
  }
1931
1721
  }
@@ -4817,7 +4607,7 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
4817
4607
  return result;
4818
4608
  }
4819
4609
  // src/primitives/list.ts
4820
- import * as path3 from "node:path";
4610
+ import * as path4 from "node:path";
4821
4611
  import ts12 from "typescript";
4822
4612
  async function listExports(options) {
4823
4613
  const { entryFile, baseDir, content } = options;
@@ -4865,7 +4655,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
4865
4655
  return {
4866
4656
  name,
4867
4657
  kind: "namespace",
4868
- file: path3.relative(path3.dirname(entryFile), declaration.fileName),
4658
+ file: path4.relative(path4.dirname(entryFile), declaration.fileName),
4869
4659
  line: 1,
4870
4660
  reexport: true
4871
4661
  };
@@ -4879,7 +4669,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
4879
4669
  return {
4880
4670
  name,
4881
4671
  kind,
4882
- file: path3.relative(path3.dirname(entryFile), sourceFile.fileName),
4672
+ file: path4.relative(path4.dirname(entryFile), sourceFile.fileName),
4883
4673
  line: line + 1,
4884
4674
  ...description ? { description } : {},
4885
4675
  ...deprecated ? { deprecated: true } : {},
@@ -4931,10 +4721,10 @@ function getDescriptionPreview(symbol, checker) {
4931
4721
  return `${firstLine.slice(0, 77)}...`;
4932
4722
  }
4933
4723
  // src/builder/spec-builder.ts
4934
- import * as fs6 from "node:fs";
4935
- import * as path6 from "node:path";
4724
+ import * as fs7 from "node:fs";
4725
+ import * as path8 from "node:path";
4936
4726
  import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
4937
- import ts15 from "typescript";
4727
+ import ts16 from "typescript";
4938
4728
 
4939
4729
  // src/ast/resolve.ts
4940
4730
  import ts13 from "typescript";
@@ -4968,9 +4758,9 @@ function resolveExportTarget2(symbol, checker) {
4968
4758
 
4969
4759
  // src/schema/standard-schema.ts
4970
4760
  import { spawn, spawnSync } from "node:child_process";
4971
- import * as fs4 from "node:fs";
4761
+ import * as fs5 from "node:fs";
4972
4762
  import * as os from "node:os";
4973
- import * as path4 from "node:path";
4763
+ import * as path5 from "node:path";
4974
4764
  function isStandardJSONSchema(obj) {
4975
4765
  if (typeof obj !== "object" || obj === null)
4976
4766
  return false;
@@ -5216,21 +5006,21 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5216
5006
  result.errors.push("No TypeScript runtime available. Install bun, tsx, or ts-node, or use Node 22+.");
5217
5007
  return result;
5218
5008
  }
5219
- if (!fs4.existsSync(tsFilePath)) {
5009
+ if (!fs5.existsSync(tsFilePath)) {
5220
5010
  result.errors.push(`TypeScript file not found: ${tsFilePath}`);
5221
5011
  return result;
5222
5012
  }
5223
5013
  const tempDir = os.tmpdir();
5224
- const workerPath = path4.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
5014
+ const workerPath = path5.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
5225
5015
  try {
5226
- fs4.writeFileSync(workerPath, TS_WORKER_SCRIPT);
5016
+ fs5.writeFileSync(workerPath, TS_WORKER_SCRIPT);
5227
5017
  const optionsJson = JSON.stringify({ target, libraryOptions });
5228
5018
  const args = [...runtime.args, workerPath, tsFilePath, optionsJson];
5229
5019
  return await new Promise((resolve2) => {
5230
5020
  const child = spawn(runtime.cmd, args, {
5231
5021
  timeout,
5232
5022
  stdio: ["ignore", "pipe", "pipe"],
5233
- cwd: path4.dirname(tsFilePath)
5023
+ cwd: path5.dirname(tsFilePath)
5234
5024
  });
5235
5025
  let stdout = "";
5236
5026
  let stderr = "";
@@ -5242,7 +5032,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5242
5032
  });
5243
5033
  child.on("close", (code) => {
5244
5034
  try {
5245
- fs4.unlinkSync(workerPath);
5035
+ fs5.unlinkSync(workerPath);
5246
5036
  } catch {}
5247
5037
  if (code !== 0) {
5248
5038
  result.errors.push(`Extraction failed (${runtime.name}): ${stderr || `exit code ${code}`}`);
@@ -5271,7 +5061,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5271
5061
  });
5272
5062
  child.on("error", (err) => {
5273
5063
  try {
5274
- fs4.unlinkSync(workerPath);
5064
+ fs5.unlinkSync(workerPath);
5275
5065
  } catch {}
5276
5066
  result.errors.push(`Subprocess error: ${err.message}`);
5277
5067
  resolve2(result);
@@ -5279,19 +5069,19 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
5279
5069
  });
5280
5070
  } catch (e) {
5281
5071
  try {
5282
- fs4.unlinkSync(workerPath);
5072
+ fs5.unlinkSync(workerPath);
5283
5073
  } catch {}
5284
5074
  result.errors.push(`Failed to create worker script: ${e}`);
5285
5075
  return result;
5286
5076
  }
5287
5077
  }
5288
5078
  function readTsconfigOutDir(baseDir) {
5289
- const tsconfigPath = path4.join(baseDir, "tsconfig.json");
5079
+ const tsconfigPath = path5.join(baseDir, "tsconfig.json");
5290
5080
  try {
5291
- if (!fs4.existsSync(tsconfigPath)) {
5081
+ if (!fs5.existsSync(tsconfigPath)) {
5292
5082
  return null;
5293
5083
  }
5294
- const content = fs4.readFileSync(tsconfigPath, "utf-8");
5084
+ const content = fs5.readFileSync(tsconfigPath, "utf-8");
5295
5085
  const stripped = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
5296
5086
  const tsconfig = JSON.parse(stripped);
5297
5087
  if (tsconfig.compilerOptions?.outDir) {
@@ -5301,7 +5091,7 @@ function readTsconfigOutDir(baseDir) {
5301
5091
  return null;
5302
5092
  }
5303
5093
  function resolveCompiledPath(tsPath, baseDir) {
5304
- const relativePath = path4.relative(baseDir, tsPath);
5094
+ const relativePath = path5.relative(baseDir, tsPath);
5305
5095
  const withoutExt = relativePath.replace(/\.tsx?$/, "");
5306
5096
  const srcPrefix = withoutExt.replace(/^src\//, "");
5307
5097
  const tsconfigOutDir = readTsconfigOutDir(baseDir);
@@ -5309,7 +5099,7 @@ function resolveCompiledPath(tsPath, baseDir) {
5309
5099
  const candidates = [];
5310
5100
  if (tsconfigOutDir) {
5311
5101
  for (const ext of extensions) {
5312
- candidates.push(path4.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
5102
+ candidates.push(path5.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
5313
5103
  }
5314
5104
  }
5315
5105
  const commonOutDirs = ["dist", "build", "lib", "out"];
@@ -5317,21 +5107,21 @@ function resolveCompiledPath(tsPath, baseDir) {
5317
5107
  if (outDir === tsconfigOutDir)
5318
5108
  continue;
5319
5109
  for (const ext of extensions) {
5320
- candidates.push(path4.join(baseDir, outDir, `${srcPrefix}${ext}`));
5110
+ candidates.push(path5.join(baseDir, outDir, `${srcPrefix}${ext}`));
5321
5111
  }
5322
5112
  }
5323
5113
  for (const ext of extensions) {
5324
- candidates.push(path4.join(baseDir, `${withoutExt}${ext}`));
5114
+ candidates.push(path5.join(baseDir, `${withoutExt}${ext}`));
5325
5115
  }
5326
5116
  const workspaceMatch = baseDir.match(/^(.+\/packages\/[^/]+)$/);
5327
5117
  if (workspaceMatch) {
5328
5118
  const pkgRoot = workspaceMatch[1];
5329
5119
  for (const ext of extensions) {
5330
- candidates.push(path4.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
5120
+ candidates.push(path5.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
5331
5121
  }
5332
5122
  }
5333
5123
  for (const candidate of candidates) {
5334
- if (fs4.existsSync(candidate)) {
5124
+ if (fs5.existsSync(candidate)) {
5335
5125
  return candidate;
5336
5126
  }
5337
5127
  }
@@ -5343,7 +5133,7 @@ async function extractStandardSchemas(compiledJsPath, options = {}) {
5343
5133
  schemas: new Map,
5344
5134
  errors: []
5345
5135
  };
5346
- if (!fs4.existsSync(compiledJsPath)) {
5136
+ if (!fs5.existsSync(compiledJsPath)) {
5347
5137
  result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
5348
5138
  return result;
5349
5139
  }
@@ -5425,8 +5215,8 @@ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {
5425
5215
  }
5426
5216
 
5427
5217
  // src/builder/external-resolver.ts
5428
- import * as fs5 from "node:fs";
5429
- import * as path5 from "node:path";
5218
+ import * as fs6 from "node:fs";
5219
+ import * as path6 from "node:path";
5430
5220
  import picomatch from "picomatch";
5431
5221
  import ts14 from "typescript";
5432
5222
  function matchesExternalPattern(packageName, include, exclude) {
@@ -5460,20 +5250,20 @@ function findPackageJson(resolvedPath, packageName) {
5460
5250
  const isScoped = packageName.startsWith("@");
5461
5251
  const packageParts = isScoped ? packageName.split("/").slice(0, 2) : [packageName.split("/")[0]];
5462
5252
  const packageDir = packageParts.join("/");
5463
- let dir = path5.dirname(resolvedPath);
5253
+ let dir = path6.dirname(resolvedPath);
5464
5254
  const maxDepth = 10;
5465
5255
  for (let i = 0;i < maxDepth; i++) {
5466
5256
  if (dir.endsWith(`node_modules/${packageDir}`)) {
5467
- const pkgPath = path5.join(dir, "package.json");
5468
- if (fs5.existsSync(pkgPath)) {
5257
+ const pkgPath = path6.join(dir, "package.json");
5258
+ if (fs6.existsSync(pkgPath)) {
5469
5259
  try {
5470
- return JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
5260
+ return JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
5471
5261
  } catch {
5472
5262
  return;
5473
5263
  }
5474
5264
  }
5475
5265
  }
5476
- const parent = path5.dirname(dir);
5266
+ const parent = path6.dirname(dir);
5477
5267
  if (parent === dir)
5478
5268
  break;
5479
5269
  dir = parent;
@@ -5619,72 +5409,149 @@ function mergeRuntimeSchemas(staticExports, runtimeSchemas) {
5619
5409
  return { merged, exports };
5620
5410
  }
5621
5411
 
5622
- // src/builder/spec-builder.ts
5623
- var typeDefinitionCache = null;
5624
- function getTypeDefinitionCache() {
5625
- if (!typeDefinitionCache) {
5626
- typeDefinitionCache = new Map;
5412
+ // src/builder/type-cache.ts
5413
+ import ts15 from "typescript";
5414
+
5415
+ // src/utils/cache-manager.ts
5416
+ class CacheManager {
5417
+ cache;
5418
+ maxSize;
5419
+ ttl;
5420
+ constructor(options = {}) {
5421
+ this.maxSize = options.maxSize ?? 1000;
5422
+ this.ttl = options.ttl;
5423
+ this.cache = new Map;
5424
+ }
5425
+ get(key) {
5426
+ const entry = this.cache.get(key);
5427
+ if (!entry)
5428
+ return;
5429
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
5430
+ this.cache.delete(key);
5431
+ return;
5432
+ }
5433
+ this.cache.delete(key);
5434
+ this.cache.set(key, entry);
5435
+ return entry.value;
5627
5436
  }
5628
- return typeDefinitionCache;
5629
- }
5630
- var internalTagCache = null;
5631
- function getInternalTagCache() {
5632
- if (!internalTagCache) {
5633
- internalTagCache = new Map;
5437
+ has(key) {
5438
+ const entry = this.cache.get(key);
5439
+ if (!entry)
5440
+ return false;
5441
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
5442
+ this.cache.delete(key);
5443
+ return false;
5444
+ }
5445
+ return true;
5634
5446
  }
5635
- return internalTagCache;
5636
- }
5637
- function clearTypeDefinitionCache() {
5638
- typeDefinitionCache = null;
5639
- internalTagCache = null;
5640
- }
5641
- var YIELD_BATCH_SIZE = 5;
5642
- function computeDegradedStats(exports) {
5643
- let exportsWithoutDescription = 0;
5644
- let paramsWithoutDocs = 0;
5645
- let missingExamples = 0;
5646
- for (const exp of exports) {
5647
- if (!exp.description)
5648
- exportsWithoutDescription++;
5649
- if (!exp.examples || exp.examples.length === 0)
5650
- missingExamples++;
5651
- const signatures = exp.signatures;
5652
- if (signatures) {
5653
- for (const sig of signatures) {
5654
- for (const param of sig.parameters ?? []) {
5655
- if (!param.description)
5656
- paramsWithoutDocs++;
5657
- }
5447
+ set(key, value) {
5448
+ if (this.cache.has(key)) {
5449
+ this.cache.delete(key);
5450
+ }
5451
+ if (this.cache.size >= this.maxSize) {
5452
+ const firstKey = this.cache.keys().next().value;
5453
+ if (firstKey !== undefined) {
5454
+ this.cache.delete(firstKey);
5658
5455
  }
5659
5456
  }
5457
+ const entry = {
5458
+ value,
5459
+ ...this.ttl ? { expiresAt: Date.now() + this.ttl } : {}
5460
+ };
5461
+ this.cache.set(key, entry);
5660
5462
  }
5661
- return { exportsWithoutDescription, paramsWithoutDocs, missingExamples };
5662
- }
5663
- function buildVerificationSummary(discoveredCount, extractedCount, tracker) {
5664
- const skippedDetails = [];
5665
- const failedDetails = [];
5666
- for (const entry of tracker.values()) {
5667
- if (entry.status === "skipped" && entry.skipReason) {
5668
- skippedDetails.push({ name: entry.name, reason: entry.skipReason });
5669
- } else if (entry.status === "failed" && entry.error) {
5670
- failedDetails.push({ name: entry.name, error: entry.error });
5463
+ delete(key) {
5464
+ return this.cache.delete(key);
5465
+ }
5466
+ clear() {
5467
+ this.cache.clear();
5468
+ }
5469
+ get size() {
5470
+ return this.cache.size;
5471
+ }
5472
+ keys() {
5473
+ return this.cache.keys();
5474
+ }
5475
+ values() {
5476
+ const result = [];
5477
+ const now = Date.now();
5478
+ for (const [key, entry] of this.cache) {
5479
+ if (entry.expiresAt && now > entry.expiresAt) {
5480
+ this.cache.delete(key);
5481
+ continue;
5482
+ }
5483
+ result.push(entry.value);
5671
5484
  }
5485
+ return result;
5672
5486
  }
5673
- const skipped = skippedDetails.length;
5674
- const failed = failedDetails.length;
5675
- const delta = discoveredCount - extractedCount - skipped;
5676
- return {
5677
- discovered: discoveredCount,
5678
- extracted: extractedCount,
5679
- skipped,
5680
- failed,
5681
- delta,
5682
- details: {
5683
- skipped: skippedDetails,
5684
- failed: failedDetails
5487
+ }
5488
+
5489
+ // src/builder/type-cache.ts
5490
+ var typeDefinitionCache = new CacheManager({ maxSize: 1000 });
5491
+ var internalTagCache = new CacheManager({ maxSize: 1000 });
5492
+ var regexCache = new CacheManager({ maxSize: 100 });
5493
+ function clearTypeDefinitionCache() {
5494
+ typeDefinitionCache.clear();
5495
+ internalTagCache.clear();
5496
+ regexCache.clear();
5497
+ }
5498
+ function getRegexCache() {
5499
+ return regexCache;
5500
+ }
5501
+ function findTypeDefinition(typeName, program, sourceFile) {
5502
+ if (typeDefinitionCache.has(typeName)) {
5503
+ return typeDefinitionCache.get(typeName);
5504
+ }
5505
+ const checker = program.getTypeChecker();
5506
+ const findInNode = (node) => {
5507
+ if ((ts15.isInterfaceDeclaration(node) || ts15.isTypeAliasDeclaration(node) || ts15.isClassDeclaration(node) || ts15.isEnumDeclaration(node)) && node.name?.text === typeName) {
5508
+ const sf = node.getSourceFile();
5509
+ return sf.fileName;
5685
5510
  }
5511
+ return ts15.forEachChild(node, findInNode);
5686
5512
  };
5513
+ const entryResult = findInNode(sourceFile);
5514
+ if (entryResult) {
5515
+ typeDefinitionCache.set(typeName, entryResult);
5516
+ return entryResult;
5517
+ }
5518
+ for (const sf of program.getSourceFiles()) {
5519
+ if (sf.isDeclarationFile && !sf.fileName.includes("node_modules")) {
5520
+ const result = findInNode(sf);
5521
+ if (result) {
5522
+ typeDefinitionCache.set(typeName, result);
5523
+ return result;
5524
+ }
5525
+ }
5526
+ }
5527
+ const symbol = checker.resolveName(typeName, sourceFile, ts15.SymbolFlags.Type, false);
5528
+ if (symbol?.declarations?.[0]) {
5529
+ const result = symbol.declarations[0].getSourceFile().fileName;
5530
+ typeDefinitionCache.set(typeName, result);
5531
+ return result;
5532
+ }
5533
+ typeDefinitionCache.set(typeName, undefined);
5534
+ return;
5535
+ }
5536
+ function hasInternalTag(typeName, program, sourceFile) {
5537
+ const cached = internalTagCache.get(typeName);
5538
+ if (cached !== undefined) {
5539
+ return cached;
5540
+ }
5541
+ const checker = program.getTypeChecker();
5542
+ const symbol = checker.resolveName(typeName, sourceFile, ts15.SymbolFlags.Type, false);
5543
+ if (!symbol) {
5544
+ internalTagCache.set(typeName, false);
5545
+ return false;
5546
+ }
5547
+ const jsTags = symbol.getJsDocTags();
5548
+ const isInternal = jsTags.some((tag) => tag.name === "internal");
5549
+ internalTagCache.set(typeName, isInternal);
5550
+ return isInternal;
5687
5551
  }
5552
+
5553
+ // src/builder/verification.ts
5554
+ import * as path7 from "node:path";
5688
5555
  var BUILTIN_TYPES2 = new Set([
5689
5556
  "Array",
5690
5557
  "ArrayBuffer",
@@ -5743,19 +5610,39 @@ var BUILTIN_TYPES2 = new Set([
5743
5610
  "InstanceType",
5744
5611
  "ThisType"
5745
5612
  ]);
5746
- function matchesPattern(name, pattern) {
5747
- if (!pattern.includes("*"))
5748
- return name === pattern;
5749
- const regex = new RegExp(`^${pattern.replace(/\*/g, ".*")}$`);
5750
- return regex.test(name);
5751
- }
5752
- function shouldIncludeExport(name, only, ignore) {
5753
- if (ignore?.some((p) => matchesPattern(name, p)))
5754
- return false;
5755
- if (only && only.length > 0) {
5756
- return only.some((p) => matchesPattern(name, p));
5613
+ function buildVerificationSummary(discoveredCount, extractedCount, tracker) {
5614
+ const skippedDetails = [];
5615
+ const failedDetails = [];
5616
+ for (const entry of tracker.values()) {
5617
+ if (entry.status === "skipped" && entry.skipReason) {
5618
+ skippedDetails.push({ name: entry.name, reason: entry.skipReason });
5619
+ } else if (entry.status === "failed" && entry.error) {
5620
+ failedDetails.push({ name: entry.name, error: entry.error });
5621
+ }
5757
5622
  }
5758
- return true;
5623
+ const skipped = skippedDetails.length;
5624
+ const failed = failedDetails.length;
5625
+ const delta = discoveredCount - extractedCount - skipped;
5626
+ return {
5627
+ discovered: discoveredCount,
5628
+ extracted: extractedCount,
5629
+ skipped,
5630
+ failed,
5631
+ delta,
5632
+ details: {
5633
+ skipped: skippedDetails,
5634
+ failed: failedDetails
5635
+ }
5636
+ };
5637
+ }
5638
+ function isExternalType2(definedIn, baseDir) {
5639
+ if (!definedIn)
5640
+ return true;
5641
+ if (definedIn.includes("node_modules"))
5642
+ return true;
5643
+ const normalizedDefined = path7.resolve(definedIn);
5644
+ const normalizedBase = path7.resolve(baseDir);
5645
+ return !normalizedDefined.startsWith(normalizedBase);
5759
5646
  }
5760
5647
  function shouldSkipDanglingRef(name) {
5761
5648
  if (name.startsWith("__"))
@@ -5768,255 +5655,6 @@ function shouldSkipDanglingRef(name) {
5768
5655
  return true;
5769
5656
  return false;
5770
5657
  }
5771
- async function extract(options) {
5772
- clearTypeDefinitionCache();
5773
- const {
5774
- entryFile,
5775
- baseDir,
5776
- content,
5777
- maxTypeDepth,
5778
- maxExternalTypeDepth,
5779
- resolveExternalTypes,
5780
- includeSchema,
5781
- only,
5782
- ignore,
5783
- onProgress,
5784
- isDtsSource,
5785
- includePrivate
5786
- } = options;
5787
- const diagnostics = [];
5788
- let exports = [];
5789
- const result = createProgram({ entryFile, baseDir, content });
5790
- const { program, sourceFile } = result;
5791
- if (!sourceFile) {
5792
- return {
5793
- spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
5794
- diagnostics: [{ message: `Could not load source file: ${entryFile}`, severity: "error" }]
5795
- };
5796
- }
5797
- const typeChecker = program.getTypeChecker();
5798
- const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
5799
- if (!moduleSymbol) {
5800
- return {
5801
- spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
5802
- diagnostics: [{ message: "Could not get module symbol", severity: "warning" }]
5803
- };
5804
- }
5805
- const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
5806
- const exportedIds = new Set;
5807
- for (const symbol of exportedSymbols) {
5808
- exportedIds.add(symbol.getName());
5809
- }
5810
- const exportTracker = new Map;
5811
- for (const symbol of exportedSymbols) {
5812
- const name = symbol.getName();
5813
- const included = shouldIncludeExport(name, only, ignore);
5814
- exportTracker.set(name, {
5815
- name,
5816
- discovered: true,
5817
- status: included ? "pending" : "skipped",
5818
- ...included ? {} : { skipReason: "filtered" }
5819
- });
5820
- }
5821
- const ctx = createContext(program, sourceFile, {
5822
- maxTypeDepth,
5823
- maxExternalTypeDepth,
5824
- resolveExternalTypes,
5825
- includePrivate
5826
- });
5827
- ctx.exportedIds = exportedIds;
5828
- const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
5829
- const total = filteredSymbols.length;
5830
- for (let i = 0;i < filteredSymbols.length; i++) {
5831
- const symbol = filteredSymbols[i];
5832
- const exportName = symbol.getName();
5833
- const tracker = exportTracker.get(exportName);
5834
- onProgress?.(i + 1, total, exportName);
5835
- if (i > 0 && i % YIELD_BATCH_SIZE === 0) {
5836
- await new Promise((r) => setImmediate(r));
5837
- }
5838
- try {
5839
- const { declaration, targetSymbol, isTypeOnly } = resolveExportTarget2(symbol, typeChecker);
5840
- if (!declaration) {
5841
- let externalPackage;
5842
- const allDecls = [
5843
- ...targetSymbol.declarations ?? [],
5844
- ...symbol.declarations ?? []
5845
- ];
5846
- for (const decl of allDecls) {
5847
- const sf = decl.getSourceFile();
5848
- if (sf?.fileName.includes("node_modules")) {
5849
- const match = sf.fileName.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/);
5850
- if (match) {
5851
- externalPackage = match[1];
5852
- break;
5853
- }
5854
- }
5855
- if (ts15.isExportSpecifier(decl)) {
5856
- const exportDecl = decl.parent?.parent;
5857
- if (exportDecl && ts15.isExportDeclaration(exportDecl) && exportDecl.moduleSpecifier) {
5858
- const moduleText = exportDecl.moduleSpecifier.getText().slice(1, -1);
5859
- if (!moduleText.startsWith(".") && !moduleText.startsWith("/")) {
5860
- externalPackage = moduleText;
5861
- break;
5862
- }
5863
- }
5864
- }
5865
- }
5866
- if (externalPackage) {
5867
- const shouldResolve = matchesExternalPattern(externalPackage, options.externals?.include, options.externals?.exclude);
5868
- if (shouldResolve) {
5869
- const resolvedModule = resolveExternalModule(externalPackage, sourceFile.fileName, program.getCompilerOptions());
5870
- if (resolvedModule) {
5871
- const visitedExternals = new Set;
5872
- const extractedExport = extractExternalExport(exportName, resolvedModule, program, ctx, visitedExternals);
5873
- if (extractedExport) {
5874
- exports.push(extractedExport);
5875
- tracker.status = "success";
5876
- tracker.kind = extractedExport.kind;
5877
- continue;
5878
- }
5879
- }
5880
- }
5881
- const externalExport = {
5882
- id: exportName,
5883
- name: exportName,
5884
- kind: "external",
5885
- source: {
5886
- package: externalPackage
5887
- }
5888
- };
5889
- exports.push(externalExport);
5890
- tracker.status = "success";
5891
- tracker.kind = "external";
5892
- } else {
5893
- tracker.status = "skipped";
5894
- tracker.skipReason = "no-declaration";
5895
- }
5896
- continue;
5897
- }
5898
- const exp = serializeDeclaration2(declaration, symbol, targetSymbol, exportName, ctx, isTypeOnly);
5899
- if (exp) {
5900
- exports.push(exp);
5901
- tracker.status = "success";
5902
- tracker.kind = exp.kind;
5903
- } else {
5904
- tracker.status = "skipped";
5905
- tracker.skipReason = "internal";
5906
- }
5907
- } catch (err) {
5908
- const errorMsg = err instanceof Error ? err.message : String(err);
5909
- tracker.status = "failed";
5910
- tracker.error = errorMsg;
5911
- diagnostics.push({
5912
- message: `Failed to serialize '${exportName}': ${errorMsg}`,
5913
- severity: "warning",
5914
- code: "SERIALIZATION_FAILED"
5915
- });
5916
- }
5917
- }
5918
- const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
5919
- const meta = await getPackageMeta(entryFile, baseDir);
5920
- const types = ctx.typeRegistry.getAll();
5921
- const projectBaseDir = baseDir ?? path6.dirname(entryFile);
5922
- const definedTypes = new Set(types.map((t) => t.id));
5923
- const forgottenExports = collectForgottenExports(exports, types, program, sourceFile, exportedIds, projectBaseDir, definedTypes);
5924
- for (const forgotten of forgottenExports) {
5925
- const refSummary = forgotten.referencedBy.slice(0, 3).map((r) => `${r.exportName} (${r.location})`).join(", ");
5926
- const moreRefs = forgotten.referencedBy.length > 3 ? ` +${forgotten.referencedBy.length - 3} more` : "";
5927
- if (forgotten.isExternal) {
5928
- diagnostics.push({
5929
- message: `External type '${forgotten.name}' referenced by: ${refSummary}${moreRefs}`,
5930
- severity: "info",
5931
- code: "EXTERNAL_TYPE_REF",
5932
- suggestion: forgotten.definedIn ? `Type is from: ${forgotten.definedIn}` : "Type is from an external package"
5933
- });
5934
- } else {
5935
- diagnostics.push({
5936
- message: `Forgotten export: '${forgotten.name}' referenced by: ${refSummary}${moreRefs}`,
5937
- severity: "warning",
5938
- code: "FORGOTTEN_EXPORT",
5939
- suggestion: forgotten.fix ?? `Export this type from your public API`,
5940
- location: forgotten.definedIn ? { file: forgotten.definedIn } : undefined
5941
- });
5942
- }
5943
- }
5944
- const externalTypes = types.filter((t) => t.kind === "external");
5945
- if (externalTypes.length > 0) {
5946
- diagnostics.push({
5947
- message: `${externalTypes.length} external type(s) from dependencies: ${externalTypes.slice(0, 5).map((t) => t.id).join(", ")}${externalTypes.length > 5 ? "..." : ""}`,
5948
- severity: "info",
5949
- code: "EXTERNAL_TYPES"
5950
- });
5951
- }
5952
- let runtimeMetadata;
5953
- if (options.schemaExtraction === "hybrid") {
5954
- const projectBaseDir2 = baseDir || path6.dirname(entryFile);
5955
- const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
5956
- target: options.schemaTarget || "draft-2020-12",
5957
- timeout: 15000
5958
- });
5959
- if (runtimeResult.schemas.size > 0) {
5960
- const mergeResult = mergeRuntimeSchemas(exports, runtimeResult.schemas);
5961
- exports = mergeResult.exports;
5962
- const method = runtimeResult.info?.method === "direct-ts" ? `direct-ts (${runtimeResult.info.runtime})` : "compiled";
5963
- runtimeMetadata = {
5964
- extracted: runtimeResult.schemas.size,
5965
- merged: mergeResult.merged,
5966
- vendors: [...new Set([...runtimeResult.schemas.values()].map((s) => s.vendor))],
5967
- errors: runtimeResult.errors,
5968
- method
5969
- };
5970
- }
5971
- for (const error of runtimeResult.errors) {
5972
- diagnostics.push({
5973
- message: `Runtime schema extraction: ${error}`,
5974
- severity: "warning",
5975
- code: "RUNTIME_SCHEMA_ERROR"
5976
- });
5977
- }
5978
- }
5979
- const normalizedExports = exports.map((exp) => normalizeExport(exp, { dialect: "draft-2020-12" }));
5980
- const normalizedTypes = types.map((t) => normalizeType(t, { dialect: "draft-2020-12" }));
5981
- const spec = {
5982
- ...includeSchema ? { $schema: SCHEMA_URL } : {},
5983
- openpkg: SCHEMA_VERSION,
5984
- meta,
5985
- exports: normalizedExports,
5986
- types: normalizedTypes,
5987
- generation: {
5988
- generator: "@openpkg-ts/sdk",
5989
- timestamp: new Date().toISOString(),
5990
- mode: isDtsSource ? "declaration-only" : "source",
5991
- ...options.schemaExtraction === "hybrid" ? { schemaExtraction: "hybrid" } : {},
5992
- ...isDtsSource && {
5993
- limitations: ["No JSDoc descriptions", "No @example tags", "No @param descriptions"]
5994
- },
5995
- ...verification.details.skipped.length > 0 && {
5996
- skipped: verification.details.skipped
5997
- }
5998
- }
5999
- };
6000
- const internalForgotten = forgottenExports.filter((f) => !f.isExternal);
6001
- const degradedMode = isDtsSource ? { reason: "dts-source", stats: computeDegradedStats(normalizedExports) } : undefined;
6002
- if (verification.failed > 0) {
6003
- const failedNames = verification.details.failed.map((f) => f.name).join(", ");
6004
- diagnostics.push({
6005
- message: `Export verification: ${verification.failed} export(s) failed: ${failedNames}`,
6006
- severity: "warning",
6007
- code: "EXPORT_VERIFICATION_FAILED",
6008
- suggestion: "Check serialization errors for these exports"
6009
- });
6010
- }
6011
- return {
6012
- spec,
6013
- diagnostics,
6014
- verification,
6015
- ...internalForgotten.length > 0 ? { forgottenExports: internalForgotten } : {},
6016
- ...runtimeMetadata ? { runtimeSchemas: runtimeMetadata } : {},
6017
- ...degradedMode ? { degradedMode } : {}
6018
- };
6019
- }
6020
5658
  function collectAllRefsWithContext(obj, refs, state) {
6021
5659
  if (obj === null || obj === undefined)
6022
5660
  return;
@@ -6060,68 +5698,6 @@ function collectAllRefsWithContext(obj, refs, state) {
6060
5698
  }
6061
5699
  }
6062
5700
  }
6063
- function findTypeDefinition(typeName, program, sourceFile) {
6064
- const cache = getTypeDefinitionCache();
6065
- if (cache.has(typeName)) {
6066
- return cache.get(typeName);
6067
- }
6068
- const checker = program.getTypeChecker();
6069
- const findInNode = (node) => {
6070
- if ((ts15.isInterfaceDeclaration(node) || ts15.isTypeAliasDeclaration(node) || ts15.isClassDeclaration(node) || ts15.isEnumDeclaration(node)) && node.name?.text === typeName) {
6071
- const sf = node.getSourceFile();
6072
- return sf.fileName;
6073
- }
6074
- return ts15.forEachChild(node, findInNode);
6075
- };
6076
- const entryResult = findInNode(sourceFile);
6077
- if (entryResult) {
6078
- cache.set(typeName, entryResult);
6079
- return entryResult;
6080
- }
6081
- for (const sf of program.getSourceFiles()) {
6082
- if (sf.isDeclarationFile && !sf.fileName.includes("node_modules")) {
6083
- const result = findInNode(sf);
6084
- if (result) {
6085
- cache.set(typeName, result);
6086
- return result;
6087
- }
6088
- }
6089
- }
6090
- const symbol = checker.resolveName(typeName, sourceFile, ts15.SymbolFlags.Type, false);
6091
- if (symbol?.declarations?.[0]) {
6092
- const result = symbol.declarations[0].getSourceFile().fileName;
6093
- cache.set(typeName, result);
6094
- return result;
6095
- }
6096
- cache.set(typeName, undefined);
6097
- return;
6098
- }
6099
- function isExternalType2(definedIn, baseDir) {
6100
- if (!definedIn)
6101
- return true;
6102
- if (definedIn.includes("node_modules"))
6103
- return true;
6104
- const normalizedDefined = path6.resolve(definedIn);
6105
- const normalizedBase = path6.resolve(baseDir);
6106
- return !normalizedDefined.startsWith(normalizedBase);
6107
- }
6108
- function hasInternalTag(typeName, program, sourceFile) {
6109
- const cache = getInternalTagCache();
6110
- const cached = cache.get(typeName);
6111
- if (cached !== undefined) {
6112
- return cached;
6113
- }
6114
- const checker = program.getTypeChecker();
6115
- const symbol = checker.resolveName(typeName, sourceFile, ts15.SymbolFlags.Type, false);
6116
- if (!symbol) {
6117
- cache.set(typeName, false);
6118
- return false;
6119
- }
6120
- const jsTags = symbol.getJsDocTags();
6121
- const isInternal = jsTags.some((tag) => tag.name === "internal");
6122
- cache.set(typeName, isInternal);
6123
- return isInternal;
6124
- }
6125
5701
  function collectForgottenExports(exports, types, program, sourceFile, exportedIds, baseDir, definedTypes) {
6126
5702
  const referencedTypes = new Map;
6127
5703
  for (const exp of exports) {
@@ -6162,29 +5738,322 @@ function collectForgottenExports(exports, types, program, sourceFile, exportedId
6162
5738
  }
6163
5739
  return forgottenExports;
6164
5740
  }
5741
+
5742
+ // src/builder/spec-builder.ts
5743
+ var YIELD_BATCH_SIZE = 5;
5744
+ function computeDegradedStats(exports) {
5745
+ let exportsWithoutDescription = 0;
5746
+ let paramsWithoutDocs = 0;
5747
+ let missingExamples = 0;
5748
+ for (const exp of exports) {
5749
+ if (!exp.description)
5750
+ exportsWithoutDescription++;
5751
+ if (!exp.examples || exp.examples.length === 0)
5752
+ missingExamples++;
5753
+ const signatures = exp.signatures;
5754
+ if (signatures) {
5755
+ for (const sig of signatures) {
5756
+ for (const param of sig.parameters ?? []) {
5757
+ if (!param.description)
5758
+ paramsWithoutDocs++;
5759
+ }
5760
+ }
5761
+ }
5762
+ }
5763
+ return { exportsWithoutDescription, paramsWithoutDocs, missingExamples };
5764
+ }
5765
+ function matchesPattern(name, pattern) {
5766
+ if (!pattern.includes("*"))
5767
+ return name === pattern;
5768
+ const regexCache2 = getRegexCache();
5769
+ let regex = regexCache2.get(pattern);
5770
+ if (!regex) {
5771
+ regex = new RegExp(`^${pattern.replace(/\*/g, ".*")}$`);
5772
+ regexCache2.set(pattern, regex);
5773
+ }
5774
+ return regex.test(name);
5775
+ }
5776
+ function shouldIncludeExport(name, only, ignore) {
5777
+ if (ignore?.some((p) => matchesPattern(name, p)))
5778
+ return false;
5779
+ if (only && only.length > 0) {
5780
+ return only.some((p) => matchesPattern(name, p));
5781
+ }
5782
+ return true;
5783
+ }
5784
+ async function extract(options) {
5785
+ clearTypeDefinitionCache();
5786
+ try {
5787
+ const {
5788
+ entryFile,
5789
+ baseDir,
5790
+ content,
5791
+ maxTypeDepth,
5792
+ maxExternalTypeDepth,
5793
+ resolveExternalTypes,
5794
+ includeSchema,
5795
+ only,
5796
+ ignore,
5797
+ onProgress,
5798
+ isDtsSource,
5799
+ includePrivate
5800
+ } = options;
5801
+ const diagnostics = [];
5802
+ let exports = [];
5803
+ const result = createProgram({ entryFile, baseDir, content });
5804
+ const { program, sourceFile } = result;
5805
+ if (!sourceFile) {
5806
+ return {
5807
+ spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
5808
+ diagnostics: [{ message: `Could not load source file: ${entryFile}`, severity: "error" }]
5809
+ };
5810
+ }
5811
+ const typeChecker = program.getTypeChecker();
5812
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
5813
+ if (!moduleSymbol) {
5814
+ return {
5815
+ spec: createEmptySpec(entryFile, includeSchema, isDtsSource),
5816
+ diagnostics: [{ message: "Could not get module symbol", severity: "warning" }]
5817
+ };
5818
+ }
5819
+ const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
5820
+ const exportedIds = new Set;
5821
+ for (const symbol of exportedSymbols) {
5822
+ exportedIds.add(symbol.getName());
5823
+ }
5824
+ const exportTracker = new Map;
5825
+ for (const symbol of exportedSymbols) {
5826
+ const name = symbol.getName();
5827
+ const included = shouldIncludeExport(name, only, ignore);
5828
+ exportTracker.set(name, {
5829
+ name,
5830
+ discovered: true,
5831
+ status: included ? "pending" : "skipped",
5832
+ ...included ? {} : { skipReason: "filtered" }
5833
+ });
5834
+ }
5835
+ const ctx = createContext(program, sourceFile, {
5836
+ maxTypeDepth,
5837
+ maxExternalTypeDepth,
5838
+ resolveExternalTypes,
5839
+ includePrivate
5840
+ });
5841
+ ctx.exportedIds = exportedIds;
5842
+ const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
5843
+ const total = filteredSymbols.length;
5844
+ for (let i = 0;i < filteredSymbols.length; i++) {
5845
+ const symbol = filteredSymbols[i];
5846
+ const exportName = symbol.getName();
5847
+ const tracker = exportTracker.get(exportName);
5848
+ onProgress?.(i + 1, total, exportName);
5849
+ if (i > 0 && i % YIELD_BATCH_SIZE === 0) {
5850
+ await new Promise((r) => setImmediate(r));
5851
+ }
5852
+ try {
5853
+ const { declaration, targetSymbol, isTypeOnly } = resolveExportTarget2(symbol, typeChecker);
5854
+ if (!declaration) {
5855
+ let externalPackage;
5856
+ const allDecls = [...targetSymbol.declarations ?? [], ...symbol.declarations ?? []];
5857
+ for (const decl of allDecls) {
5858
+ const sf = decl.getSourceFile();
5859
+ if (sf?.fileName.includes("node_modules")) {
5860
+ const match = sf.fileName.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/);
5861
+ if (match) {
5862
+ externalPackage = match[1];
5863
+ break;
5864
+ }
5865
+ }
5866
+ if (ts16.isExportSpecifier(decl)) {
5867
+ const exportDecl = decl.parent?.parent;
5868
+ if (exportDecl && ts16.isExportDeclaration(exportDecl) && exportDecl.moduleSpecifier) {
5869
+ const moduleText = exportDecl.moduleSpecifier.getText().slice(1, -1);
5870
+ if (!moduleText.startsWith(".") && !moduleText.startsWith("/")) {
5871
+ externalPackage = moduleText;
5872
+ break;
5873
+ }
5874
+ }
5875
+ }
5876
+ }
5877
+ if (externalPackage) {
5878
+ const shouldResolve = matchesExternalPattern(externalPackage, options.externals?.include, options.externals?.exclude);
5879
+ if (shouldResolve) {
5880
+ const resolvedModule = resolveExternalModule(externalPackage, sourceFile.fileName, program.getCompilerOptions());
5881
+ if (resolvedModule) {
5882
+ const visitedExternals = new Set;
5883
+ const extractedExport = extractExternalExport(exportName, resolvedModule, program, ctx, visitedExternals);
5884
+ if (extractedExport) {
5885
+ exports.push(extractedExport);
5886
+ tracker.status = "success";
5887
+ tracker.kind = extractedExport.kind;
5888
+ continue;
5889
+ }
5890
+ }
5891
+ }
5892
+ const externalExport = {
5893
+ id: exportName,
5894
+ name: exportName,
5895
+ kind: "external",
5896
+ source: {
5897
+ package: externalPackage
5898
+ }
5899
+ };
5900
+ exports.push(externalExport);
5901
+ tracker.status = "success";
5902
+ tracker.kind = "external";
5903
+ } else {
5904
+ tracker.status = "skipped";
5905
+ tracker.skipReason = "no-declaration";
5906
+ }
5907
+ continue;
5908
+ }
5909
+ const exp = serializeDeclaration2(declaration, symbol, targetSymbol, exportName, ctx, isTypeOnly);
5910
+ if (exp) {
5911
+ exports.push(exp);
5912
+ tracker.status = "success";
5913
+ tracker.kind = exp.kind;
5914
+ } else {
5915
+ tracker.status = "skipped";
5916
+ tracker.skipReason = "internal";
5917
+ }
5918
+ } catch (err) {
5919
+ const errorMsg = err instanceof Error ? err.message : String(err);
5920
+ tracker.status = "failed";
5921
+ tracker.error = errorMsg;
5922
+ diagnostics.push({
5923
+ message: `Failed to serialize '${exportName}': ${errorMsg}`,
5924
+ severity: "warning",
5925
+ code: "SERIALIZATION_FAILED"
5926
+ });
5927
+ }
5928
+ }
5929
+ const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
5930
+ const meta = await getPackageMeta(entryFile, baseDir);
5931
+ const types = ctx.typeRegistry.getAll();
5932
+ const projectBaseDir = baseDir ?? path8.dirname(entryFile);
5933
+ const definedTypes = new Set(types.map((t) => t.id));
5934
+ const forgottenExports = collectForgottenExports(exports, types, program, sourceFile, exportedIds, projectBaseDir, definedTypes);
5935
+ for (const forgotten of forgottenExports) {
5936
+ const refSummary = forgotten.referencedBy.slice(0, 3).map((r) => `${r.exportName} (${r.location})`).join(", ");
5937
+ const moreRefs = forgotten.referencedBy.length > 3 ? ` +${forgotten.referencedBy.length - 3} more` : "";
5938
+ if (forgotten.isExternal) {
5939
+ diagnostics.push({
5940
+ message: `External type '${forgotten.name}' referenced by: ${refSummary}${moreRefs}`,
5941
+ severity: "info",
5942
+ code: "EXTERNAL_TYPE_REF",
5943
+ suggestion: forgotten.definedIn ? `Type is from: ${forgotten.definedIn}` : "Type is from an external package"
5944
+ });
5945
+ } else {
5946
+ diagnostics.push({
5947
+ message: `Forgotten export: '${forgotten.name}' referenced by: ${refSummary}${moreRefs}`,
5948
+ severity: "warning",
5949
+ code: "FORGOTTEN_EXPORT",
5950
+ suggestion: forgotten.fix ?? `Export this type from your public API`,
5951
+ location: forgotten.definedIn ? { file: forgotten.definedIn } : undefined
5952
+ });
5953
+ }
5954
+ }
5955
+ const externalTypes = types.filter((t) => t.kind === "external");
5956
+ if (externalTypes.length > 0) {
5957
+ diagnostics.push({
5958
+ message: `${externalTypes.length} external type(s) from dependencies: ${externalTypes.slice(0, 5).map((t) => t.id).join(", ")}${externalTypes.length > 5 ? "..." : ""}`,
5959
+ severity: "info",
5960
+ code: "EXTERNAL_TYPES"
5961
+ });
5962
+ }
5963
+ let runtimeMetadata;
5964
+ if (options.schemaExtraction === "hybrid") {
5965
+ const projectBaseDir2 = baseDir || path8.dirname(entryFile);
5966
+ const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
5967
+ target: options.schemaTarget || "draft-2020-12",
5968
+ timeout: 15000
5969
+ });
5970
+ if (runtimeResult.schemas.size > 0) {
5971
+ const mergeResult = mergeRuntimeSchemas(exports, runtimeResult.schemas);
5972
+ exports = mergeResult.exports;
5973
+ const method = runtimeResult.info?.method === "direct-ts" ? `direct-ts (${runtimeResult.info.runtime})` : "compiled";
5974
+ runtimeMetadata = {
5975
+ extracted: runtimeResult.schemas.size,
5976
+ merged: mergeResult.merged,
5977
+ vendors: [...new Set([...runtimeResult.schemas.values()].map((s) => s.vendor))],
5978
+ errors: runtimeResult.errors,
5979
+ method
5980
+ };
5981
+ }
5982
+ for (const error of runtimeResult.errors) {
5983
+ diagnostics.push({
5984
+ message: `Runtime schema extraction: ${error}`,
5985
+ severity: "warning",
5986
+ code: "RUNTIME_SCHEMA_ERROR"
5987
+ });
5988
+ }
5989
+ }
5990
+ const normalizedExports = exports.map((exp) => normalizeExport(exp, { dialect: "draft-2020-12" }));
5991
+ const normalizedTypes = types.map((t) => normalizeType(t, { dialect: "draft-2020-12" }));
5992
+ const spec = {
5993
+ ...includeSchema ? { $schema: SCHEMA_URL } : {},
5994
+ openpkg: SCHEMA_VERSION,
5995
+ meta,
5996
+ exports: normalizedExports,
5997
+ types: normalizedTypes,
5998
+ generation: {
5999
+ generator: "@openpkg-ts/sdk",
6000
+ timestamp: new Date().toISOString(),
6001
+ mode: isDtsSource ? "declaration-only" : "source",
6002
+ ...options.schemaExtraction === "hybrid" ? { schemaExtraction: "hybrid" } : {},
6003
+ ...isDtsSource && {
6004
+ limitations: ["No JSDoc descriptions", "No @example tags", "No @param descriptions"]
6005
+ },
6006
+ ...verification.details.skipped.length > 0 && {
6007
+ skipped: verification.details.skipped
6008
+ }
6009
+ }
6010
+ };
6011
+ const internalForgotten = forgottenExports.filter((f) => !f.isExternal);
6012
+ const degradedMode = isDtsSource ? { reason: "dts-source", stats: computeDegradedStats(normalizedExports) } : undefined;
6013
+ if (verification.failed > 0) {
6014
+ const failedNames = verification.details.failed.map((f) => f.name).join(", ");
6015
+ diagnostics.push({
6016
+ message: `Export verification: ${verification.failed} export(s) failed: ${failedNames}`,
6017
+ severity: "warning",
6018
+ code: "EXPORT_VERIFICATION_FAILED",
6019
+ suggestion: "Check serialization errors for these exports"
6020
+ });
6021
+ }
6022
+ return {
6023
+ spec,
6024
+ diagnostics,
6025
+ verification,
6026
+ ...internalForgotten.length > 0 ? { forgottenExports: internalForgotten } : {},
6027
+ ...runtimeMetadata ? { runtimeSchemas: runtimeMetadata } : {},
6028
+ ...degradedMode ? { degradedMode } : {}
6029
+ };
6030
+ } finally {
6031
+ clearTypeDefinitionCache();
6032
+ }
6033
+ }
6165
6034
  function serializeDeclaration2(declaration, exportSymbol, _targetSymbol, exportName, ctx, isTypeOnly = false) {
6166
6035
  let result = null;
6167
- if (ts15.isFunctionDeclaration(declaration)) {
6036
+ if (ts16.isFunctionDeclaration(declaration)) {
6168
6037
  result = serializeFunctionExport(declaration, ctx);
6169
- } else if (ts15.isClassDeclaration(declaration)) {
6038
+ } else if (ts16.isClassDeclaration(declaration)) {
6170
6039
  result = serializeClass(declaration, ctx);
6171
- } else if (ts15.isInterfaceDeclaration(declaration)) {
6040
+ } else if (ts16.isInterfaceDeclaration(declaration)) {
6172
6041
  result = serializeInterface(declaration, ctx);
6173
- } else if (ts15.isTypeAliasDeclaration(declaration)) {
6042
+ } else if (ts16.isTypeAliasDeclaration(declaration)) {
6174
6043
  result = serializeTypeAlias(declaration, ctx);
6175
- } else if (ts15.isEnumDeclaration(declaration)) {
6044
+ } else if (ts16.isEnumDeclaration(declaration)) {
6176
6045
  result = serializeEnum(declaration, ctx);
6177
- } else if (ts15.isVariableDeclaration(declaration)) {
6046
+ } else if (ts16.isVariableDeclaration(declaration)) {
6178
6047
  const varStatement = declaration.parent?.parent;
6179
- if (varStatement && ts15.isVariableStatement(varStatement)) {
6180
- if (declaration.initializer && ts15.isArrowFunction(declaration.initializer)) {
6181
- const varName = ts15.isIdentifier(declaration.name) ? declaration.name.text : declaration.name.getText();
6048
+ if (varStatement && ts16.isVariableStatement(varStatement)) {
6049
+ if (declaration.initializer && ts16.isArrowFunction(declaration.initializer)) {
6050
+ const varName = ts16.isIdentifier(declaration.name) ? declaration.name.text : declaration.name.getText();
6182
6051
  result = serializeFunctionExport(declaration.initializer, ctx, varName);
6183
6052
  } else {
6184
6053
  result = serializeVariable(declaration, varStatement, ctx);
6185
6054
  }
6186
6055
  }
6187
- } else if (ts15.isNamespaceExport(declaration) || ts15.isModuleDeclaration(declaration)) {
6056
+ } else if (ts16.isNamespaceExport(declaration) || ts16.isModuleDeclaration(declaration)) {
6188
6057
  try {
6189
6058
  result = serializeNamespaceExport(exportSymbol, exportName, ctx);
6190
6059
  } catch {
@@ -6197,7 +6066,7 @@ function serializeDeclaration2(declaration, exportSymbol, _targetSymbol, exportN
6197
6066
  examples: []
6198
6067
  };
6199
6068
  }
6200
- } else if (ts15.isNamespaceImport(declaration)) {
6069
+ } else if (ts16.isNamespaceImport(declaration)) {
6201
6070
  try {
6202
6071
  result = serializeNamespaceExport(exportSymbol, exportName, ctx);
6203
6072
  } catch {
@@ -6210,7 +6079,7 @@ function serializeDeclaration2(declaration, exportSymbol, _targetSymbol, exportN
6210
6079
  examples: []
6211
6080
  };
6212
6081
  }
6213
- } else if (ts15.isSourceFile(declaration)) {
6082
+ } else if (ts16.isSourceFile(declaration)) {
6214
6083
  try {
6215
6084
  result = serializeNamespaceExport(exportSymbol, exportName, ctx);
6216
6085
  } catch {
@@ -6240,7 +6109,7 @@ function serializeNamespaceExport(symbol, exportName, ctx) {
6240
6109
  const members = [];
6241
6110
  const checker = ctx.program.getTypeChecker();
6242
6111
  let targetSymbol = symbol;
6243
- if (symbol.flags & ts15.SymbolFlags.Alias) {
6112
+ if (symbol.flags & ts16.SymbolFlags.Alias) {
6244
6113
  const aliased = checker.getAliasedSymbol(symbol);
6245
6114
  if (aliased && aliased !== symbol) {
6246
6115
  targetSymbol = aliased;
@@ -6267,31 +6136,31 @@ function serializeNamespaceExport(symbol, exportName, ctx) {
6267
6136
  function serializeNamespaceMember(symbol, memberName, ctx) {
6268
6137
  const checker = ctx.program.getTypeChecker();
6269
6138
  let targetSymbol = symbol;
6270
- if (symbol.flags & ts15.SymbolFlags.Alias) {
6139
+ if (symbol.flags & ts16.SymbolFlags.Alias) {
6271
6140
  const aliased = checker.getAliasedSymbol(symbol);
6272
6141
  if (aliased && aliased !== symbol) {
6273
6142
  targetSymbol = aliased;
6274
6143
  }
6275
6144
  }
6276
6145
  const declarations = targetSymbol.declarations ?? [];
6277
- const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !== ts15.SyntaxKind.ExportSpecifier) || declarations[0];
6146
+ const declaration = targetSymbol.valueDeclaration || declarations.find((d) => d.kind !== ts16.SyntaxKind.ExportSpecifier) || declarations[0];
6278
6147
  if (!declaration)
6279
6148
  return null;
6280
6149
  const type = checker.getTypeAtLocation(declaration);
6281
6150
  const callSignatures = type.getCallSignatures();
6282
6151
  const deprecated = isSymbolDeprecated(targetSymbol);
6283
6152
  let kind = "variable";
6284
- if (ts15.isFunctionDeclaration(declaration) || ts15.isFunctionExpression(declaration)) {
6153
+ if (ts16.isFunctionDeclaration(declaration) || ts16.isFunctionExpression(declaration)) {
6285
6154
  kind = "function";
6286
- } else if (ts15.isClassDeclaration(declaration)) {
6155
+ } else if (ts16.isClassDeclaration(declaration)) {
6287
6156
  kind = "class";
6288
- } else if (ts15.isInterfaceDeclaration(declaration)) {
6157
+ } else if (ts16.isInterfaceDeclaration(declaration)) {
6289
6158
  kind = "interface";
6290
- } else if (ts15.isTypeAliasDeclaration(declaration)) {
6159
+ } else if (ts16.isTypeAliasDeclaration(declaration)) {
6291
6160
  kind = "type";
6292
- } else if (ts15.isEnumDeclaration(declaration)) {
6161
+ } else if (ts16.isEnumDeclaration(declaration)) {
6293
6162
  kind = "enum";
6294
- } else if (ts15.isVariableDeclaration(declaration)) {
6163
+ } else if (ts16.isVariableDeclaration(declaration)) {
6295
6164
  if (callSignatures.length > 0) {
6296
6165
  kind = "function";
6297
6166
  }
@@ -6338,11 +6207,11 @@ function getJSDocFromExportSymbol(symbol) {
6338
6207
  const examples = [];
6339
6208
  const decl = symbol.declarations?.[0];
6340
6209
  if (decl) {
6341
- const exportDecl = ts15.isNamespaceExport(decl) ? decl.parent : decl;
6342
- if (exportDecl && ts15.isExportDeclaration(exportDecl)) {
6343
- const jsDocs = ts15.getJSDocCommentsAndTags(exportDecl);
6210
+ const exportDecl = ts16.isNamespaceExport(decl) ? decl.parent : decl;
6211
+ if (exportDecl && ts16.isExportDeclaration(exportDecl)) {
6212
+ const jsDocs = ts16.getJSDocCommentsAndTags(exportDecl);
6344
6213
  for (const doc of jsDocs) {
6345
- if (ts15.isJSDoc(doc) && doc.comment) {
6214
+ if (ts16.isJSDoc(doc) && doc.comment) {
6346
6215
  const commentText = typeof doc.comment === "string" ? doc.comment : doc.comment.map((c) => ("text" in c) ? c.text : "").join("");
6347
6216
  if (commentText) {
6348
6217
  return {
@@ -6404,7 +6273,7 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
6404
6273
  return {
6405
6274
  ...includeSchema ? { $schema: SCHEMA_URL } : {},
6406
6275
  openpkg: SCHEMA_VERSION,
6407
- meta: { name: path6.basename(entryFile, path6.extname(entryFile)) },
6276
+ meta: { name: path8.basename(entryFile, path8.extname(entryFile)) },
6408
6277
  exports: [],
6409
6278
  generation: {
6410
6279
  generator: "@openpkg-ts/sdk",
@@ -6417,19 +6286,19 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
6417
6286
  };
6418
6287
  }
6419
6288
  async function getPackageMeta(entryFile, baseDir) {
6420
- const searchDir = baseDir ?? path6.dirname(entryFile);
6421
- const pkgPath = path6.join(searchDir, "package.json");
6289
+ const searchDir = baseDir ?? path8.dirname(entryFile);
6290
+ const pkgPath = path8.join(searchDir, "package.json");
6422
6291
  try {
6423
- if (fs6.existsSync(pkgPath)) {
6424
- const pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
6292
+ if (fs7.existsSync(pkgPath)) {
6293
+ const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
6425
6294
  return {
6426
- name: pkg.name ?? path6.basename(searchDir),
6295
+ name: pkg.name ?? path8.basename(searchDir),
6427
6296
  version: pkg.version,
6428
6297
  description: pkg.description
6429
6298
  };
6430
6299
  }
6431
6300
  } catch {}
6432
- return { name: path6.basename(searchDir) };
6301
+ return { name: path8.basename(searchDir) };
6433
6302
  }
6434
6303
 
6435
6304
  // src/primitives/spec.ts
@@ -6455,6 +6324,8 @@ export {
6455
6324
  typeboxAdapter,
6456
6325
  toSearchIndexJSON,
6457
6326
  toSearchIndex,
6327
+ toReactString,
6328
+ toReact,
6458
6329
  toPagefindRecords,
6459
6330
  toNavigation,
6460
6331
  toMarkdown,
@@ -6479,6 +6350,7 @@ export {
6479
6350
  registerReferencedTypes,
6480
6351
  registerAdapter,
6481
6352
  recommendSemverBump,
6353
+ query,
6482
6354
  normalizeType,
6483
6355
  normalizeSchema,
6484
6356
  normalizeMembers,
@@ -6547,6 +6419,8 @@ export {
6547
6419
  arktypeAdapter,
6548
6420
  analyzeSpec,
6549
6421
  TypeRegistry,
6422
+ QueryBuilder,
6423
+ CacheManager,
6550
6424
  CONFIG_FILENAME,
6551
6425
  BUILTIN_TYPE_SCHEMAS,
6552
6426
  ARRAY_PROTOTYPE_METHODS