@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/README.md +76 -1
- package/dist/browser.d.ts +678 -0
- package/dist/browser.js +56 -0
- package/dist/index.d.ts +234 -39
- package/dist/index.js +815 -941
- package/dist/shared/chunk-skapcfq1.js +552 -0
- package/package.json +7 -3
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
|
-
|
|
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(
|
|
1593
|
-
const lowerQuery =
|
|
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
|
|
1765
|
-
import * as
|
|
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 =
|
|
1581
|
+
const configDir = path3.dirname(configPath);
|
|
1792
1582
|
for (const ref of parsedConfig.projectReferences) {
|
|
1793
|
-
const refPath =
|
|
1794
|
-
const refConfigPath =
|
|
1795
|
-
if (!
|
|
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,
|
|
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 =
|
|
1834
|
-
if (
|
|
1623
|
+
const pnpmPath = path3.join(currentDir, "pnpm-workspace.yaml");
|
|
1624
|
+
if (fs4.existsSync(pnpmPath)) {
|
|
1835
1625
|
try {
|
|
1836
|
-
const yamlContent =
|
|
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 =
|
|
1845
|
-
if (
|
|
1634
|
+
const pkgPath = path3.join(currentDir, "package.json");
|
|
1635
|
+
if (fs4.existsSync(pkgPath)) {
|
|
1846
1636
|
try {
|
|
1847
|
-
const pkg = JSON.parse(
|
|
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 =
|
|
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 =
|
|
1865
|
-
if (!
|
|
1654
|
+
const globDir = path3.join(rootDir, glob.replace(/\/\*$/, ""));
|
|
1655
|
+
if (!fs4.existsSync(globDir) || !fs4.statSync(globDir).isDirectory())
|
|
1866
1656
|
continue;
|
|
1867
|
-
const entries =
|
|
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 =
|
|
1872
|
-
const pkgJsonPath =
|
|
1873
|
-
if (!
|
|
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(
|
|
1666
|
+
const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
|
|
1877
1667
|
if (pkg.name) {
|
|
1878
|
-
const srcDir =
|
|
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 =
|
|
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,
|
|
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 =
|
|
1928
|
-
if (
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
4935
|
-
import * as
|
|
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
|
|
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
|
|
4761
|
+
import * as fs5 from "node:fs";
|
|
4972
4762
|
import * as os from "node:os";
|
|
4973
|
-
import * as
|
|
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 (!
|
|
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 =
|
|
5014
|
+
const workerPath = path5.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
|
|
5225
5015
|
try {
|
|
5226
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
5079
|
+
const tsconfigPath = path5.join(baseDir, "tsconfig.json");
|
|
5290
5080
|
try {
|
|
5291
|
-
if (!
|
|
5081
|
+
if (!fs5.existsSync(tsconfigPath)) {
|
|
5292
5082
|
return null;
|
|
5293
5083
|
}
|
|
5294
|
-
const content =
|
|
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 =
|
|
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(
|
|
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(
|
|
5110
|
+
candidates.push(path5.join(baseDir, outDir, `${srcPrefix}${ext}`));
|
|
5321
5111
|
}
|
|
5322
5112
|
}
|
|
5323
5113
|
for (const ext of extensions) {
|
|
5324
|
-
candidates.push(
|
|
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(
|
|
5120
|
+
candidates.push(path5.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
|
|
5331
5121
|
}
|
|
5332
5122
|
}
|
|
5333
5123
|
for (const candidate of candidates) {
|
|
5334
|
-
if (
|
|
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 (!
|
|
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
|
|
5429
|
-
import * as
|
|
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 =
|
|
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 =
|
|
5468
|
-
if (
|
|
5257
|
+
const pkgPath = path6.join(dir, "package.json");
|
|
5258
|
+
if (fs6.existsSync(pkgPath)) {
|
|
5469
5259
|
try {
|
|
5470
|
-
return JSON.parse(
|
|
5260
|
+
return JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
5471
5261
|
} catch {
|
|
5472
5262
|
return;
|
|
5473
5263
|
}
|
|
5474
5264
|
}
|
|
5475
5265
|
}
|
|
5476
|
-
const parent =
|
|
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/
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
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
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
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
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
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
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
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
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
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
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
const
|
|
5750
|
-
|
|
5751
|
-
}
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
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
|
-
|
|
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 (
|
|
6036
|
+
if (ts16.isFunctionDeclaration(declaration)) {
|
|
6168
6037
|
result = serializeFunctionExport(declaration, ctx);
|
|
6169
|
-
} else if (
|
|
6038
|
+
} else if (ts16.isClassDeclaration(declaration)) {
|
|
6170
6039
|
result = serializeClass(declaration, ctx);
|
|
6171
|
-
} else if (
|
|
6040
|
+
} else if (ts16.isInterfaceDeclaration(declaration)) {
|
|
6172
6041
|
result = serializeInterface(declaration, ctx);
|
|
6173
|
-
} else if (
|
|
6042
|
+
} else if (ts16.isTypeAliasDeclaration(declaration)) {
|
|
6174
6043
|
result = serializeTypeAlias(declaration, ctx);
|
|
6175
|
-
} else if (
|
|
6044
|
+
} else if (ts16.isEnumDeclaration(declaration)) {
|
|
6176
6045
|
result = serializeEnum(declaration, ctx);
|
|
6177
|
-
} else if (
|
|
6046
|
+
} else if (ts16.isVariableDeclaration(declaration)) {
|
|
6178
6047
|
const varStatement = declaration.parent?.parent;
|
|
6179
|
-
if (varStatement &&
|
|
6180
|
-
if (declaration.initializer &&
|
|
6181
|
-
const varName =
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 &
|
|
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 &
|
|
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 !==
|
|
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 (
|
|
6153
|
+
if (ts16.isFunctionDeclaration(declaration) || ts16.isFunctionExpression(declaration)) {
|
|
6285
6154
|
kind = "function";
|
|
6286
|
-
} else if (
|
|
6155
|
+
} else if (ts16.isClassDeclaration(declaration)) {
|
|
6287
6156
|
kind = "class";
|
|
6288
|
-
} else if (
|
|
6157
|
+
} else if (ts16.isInterfaceDeclaration(declaration)) {
|
|
6289
6158
|
kind = "interface";
|
|
6290
|
-
} else if (
|
|
6159
|
+
} else if (ts16.isTypeAliasDeclaration(declaration)) {
|
|
6291
6160
|
kind = "type";
|
|
6292
|
-
} else if (
|
|
6161
|
+
} else if (ts16.isEnumDeclaration(declaration)) {
|
|
6293
6162
|
kind = "enum";
|
|
6294
|
-
} else if (
|
|
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 =
|
|
6342
|
-
if (exportDecl &&
|
|
6343
|
-
const jsDocs =
|
|
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 (
|
|
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:
|
|
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 ??
|
|
6421
|
-
const pkgPath =
|
|
6289
|
+
const searchDir = baseDir ?? path8.dirname(entryFile);
|
|
6290
|
+
const pkgPath = path8.join(searchDir, "package.json");
|
|
6422
6291
|
try {
|
|
6423
|
-
if (
|
|
6424
|
-
const pkg = JSON.parse(
|
|
6292
|
+
if (fs7.existsSync(pkgPath)) {
|
|
6293
|
+
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
|
|
6425
6294
|
return {
|
|
6426
|
-
name: pkg.name ??
|
|
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:
|
|
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
|