@openpkg-ts/sdk 0.33.1 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -1
- package/dist/browser.d.ts +678 -0
- package/dist/browser.js +56 -0
- package/dist/index.d.ts +159 -67
- package/dist/index.js +318 -539
- package/dist/shared/chunk-91b592v7.js +552 -0
- package/package.json +5 -1
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-91b592v7.js";
|
|
29
|
+
|
|
1
30
|
// src/primitives/diff.ts
|
|
2
31
|
import {
|
|
3
32
|
calculateNextVersion,
|
|
@@ -42,313 +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
76
|
|
|
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
|
-
}
|
|
351
|
-
|
|
352
77
|
// src/render/html.ts
|
|
353
78
|
var defaultCSS = `
|
|
354
79
|
:root {
|
|
@@ -1368,171 +1093,6 @@ function toDocusaurusSidebarJS(spec, options = {}) {
|
|
|
1368
1093
|
return `module.exports = ${JSON.stringify(sidebar, null, 2)};`;
|
|
1369
1094
|
}
|
|
1370
1095
|
|
|
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
1096
|
// src/core/loader.ts
|
|
1537
1097
|
function loadSpec(spec) {
|
|
1538
1098
|
return createDocsInstance(spec);
|
|
@@ -1589,8 +1149,8 @@ function createDocsInstance(spec) {
|
|
|
1589
1149
|
const normalizedTag = tagName.startsWith("@") ? tagName : `@${tagName}`;
|
|
1590
1150
|
return exportsByTag.get(normalizedTag) ?? [];
|
|
1591
1151
|
},
|
|
1592
|
-
search(
|
|
1593
|
-
const lowerQuery =
|
|
1152
|
+
search(query2) {
|
|
1153
|
+
const lowerQuery = query2.toLowerCase();
|
|
1594
1154
|
return spec.exports.filter((exp) => {
|
|
1595
1155
|
if (exp.name.toLowerCase().includes(lowerQuery))
|
|
1596
1156
|
return true;
|
|
@@ -1654,6 +1214,221 @@ function extractModuleName(exp) {
|
|
|
1654
1214
|
}
|
|
1655
1215
|
return;
|
|
1656
1216
|
}
|
|
1217
|
+
// src/render/react.ts
|
|
1218
|
+
import * as fs3 from "node:fs";
|
|
1219
|
+
import * as path2 from "node:path";
|
|
1220
|
+
function generateFullLayout(spec, componentsPath) {
|
|
1221
|
+
const pkgName = spec.meta.name;
|
|
1222
|
+
return `'use client';
|
|
1223
|
+
|
|
1224
|
+
import type { OpenPkg, SpecExport } from '@openpkg-ts/spec';
|
|
1225
|
+
import spec from './openpkg.json';
|
|
1226
|
+
|
|
1227
|
+
// Add components via: openpkg docs add function-section class-section interface-section
|
|
1228
|
+
// Then uncomment the imports below and customize as needed.
|
|
1229
|
+
|
|
1230
|
+
// import { FunctionSection } from '${componentsPath}/function-section';
|
|
1231
|
+
// import { ClassSection } from '${componentsPath}/class-section';
|
|
1232
|
+
// import { InterfaceSection } from '${componentsPath}/interface-section';
|
|
1233
|
+
// import { VariableSection } from '${componentsPath}/variable-section';
|
|
1234
|
+
// import { EnumSection } from '${componentsPath}/enum-section';
|
|
1235
|
+
|
|
1236
|
+
/**
|
|
1237
|
+
* Renders a single export based on its kind.
|
|
1238
|
+
* Customize this to match your design system.
|
|
1239
|
+
*/
|
|
1240
|
+
function ExportSection({ exp }: { exp: SpecExport }) {
|
|
1241
|
+
// Uncomment the switch once you've added components:
|
|
1242
|
+
// switch (exp.kind) {
|
|
1243
|
+
// case 'function':
|
|
1244
|
+
// return <FunctionSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
|
|
1245
|
+
// case 'class':
|
|
1246
|
+
// return <ClassSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
|
|
1247
|
+
// case 'interface':
|
|
1248
|
+
// case 'type':
|
|
1249
|
+
// return <InterfaceSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
|
|
1250
|
+
// case 'variable':
|
|
1251
|
+
// return <VariableSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
|
|
1252
|
+
// case 'enum':
|
|
1253
|
+
// return <EnumSection key={exp.id} export={exp} spec={spec as OpenPkg} />;
|
|
1254
|
+
// default:
|
|
1255
|
+
// return null;
|
|
1256
|
+
// }
|
|
1257
|
+
|
|
1258
|
+
// Placeholder: replace with component imports above
|
|
1259
|
+
return (
|
|
1260
|
+
<section id={exp.id} className="py-8 border-b">
|
|
1261
|
+
<h2 className="text-xl font-semibold">{exp.name}</h2>
|
|
1262
|
+
<p className="text-muted-foreground">{exp.description || 'No description'}</p>
|
|
1263
|
+
<code className="text-sm">{exp.kind}</code>
|
|
1264
|
+
</section>
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* Full API Reference Page for ${pkgName}
|
|
1270
|
+
*
|
|
1271
|
+
* This layout renders all exports on a single page.
|
|
1272
|
+
* Customize the grouping, styling, and components to match your docs.
|
|
1273
|
+
*/
|
|
1274
|
+
export default function APIReferencePage() {
|
|
1275
|
+
const typedSpec = spec as OpenPkg;
|
|
1276
|
+
const exports = typedSpec.exports;
|
|
1277
|
+
|
|
1278
|
+
// Group exports by kind
|
|
1279
|
+
const functions = exports.filter((e) => e.kind === 'function');
|
|
1280
|
+
const classes = exports.filter((e) => e.kind === 'class');
|
|
1281
|
+
const interfaces = exports.filter((e) => e.kind === 'interface' || e.kind === 'type');
|
|
1282
|
+
const variables = exports.filter((e) => e.kind === 'variable');
|
|
1283
|
+
const enums = exports.filter((e) => e.kind === 'enum');
|
|
1284
|
+
|
|
1285
|
+
return (
|
|
1286
|
+
<div className="max-w-4xl mx-auto px-4 py-8">
|
|
1287
|
+
<header className="mb-12">
|
|
1288
|
+
<h1 className="text-3xl font-bold">{typedSpec.meta.name}</h1>
|
|
1289
|
+
{typedSpec.meta.description && (
|
|
1290
|
+
<p className="text-lg text-muted-foreground mt-2">{typedSpec.meta.description}</p>
|
|
1291
|
+
)}
|
|
1292
|
+
{typedSpec.meta.version && (
|
|
1293
|
+
<p className="text-sm text-muted-foreground">v{typedSpec.meta.version}</p>
|
|
1294
|
+
)}
|
|
1295
|
+
</header>
|
|
1296
|
+
|
|
1297
|
+
{functions.length > 0 && (
|
|
1298
|
+
<section className="mb-12">
|
|
1299
|
+
<h2 className="text-2xl font-bold mb-6">Functions</h2>
|
|
1300
|
+
{functions.map((exp) => (
|
|
1301
|
+
<ExportSection key={exp.id} exp={exp} />
|
|
1302
|
+
))}
|
|
1303
|
+
</section>
|
|
1304
|
+
)}
|
|
1305
|
+
|
|
1306
|
+
{classes.length > 0 && (
|
|
1307
|
+
<section className="mb-12">
|
|
1308
|
+
<h2 className="text-2xl font-bold mb-6">Classes</h2>
|
|
1309
|
+
{classes.map((exp) => (
|
|
1310
|
+
<ExportSection key={exp.id} exp={exp} />
|
|
1311
|
+
))}
|
|
1312
|
+
</section>
|
|
1313
|
+
)}
|
|
1314
|
+
|
|
1315
|
+
{interfaces.length > 0 && (
|
|
1316
|
+
<section className="mb-12">
|
|
1317
|
+
<h2 className="text-2xl font-bold mb-6">Types & Interfaces</h2>
|
|
1318
|
+
{interfaces.map((exp) => (
|
|
1319
|
+
<ExportSection key={exp.id} exp={exp} />
|
|
1320
|
+
))}
|
|
1321
|
+
</section>
|
|
1322
|
+
)}
|
|
1323
|
+
|
|
1324
|
+
{variables.length > 0 && (
|
|
1325
|
+
<section className="mb-12">
|
|
1326
|
+
<h2 className="text-2xl font-bold mb-6">Variables</h2>
|
|
1327
|
+
{variables.map((exp) => (
|
|
1328
|
+
<ExportSection key={exp.id} exp={exp} />
|
|
1329
|
+
))}
|
|
1330
|
+
</section>
|
|
1331
|
+
)}
|
|
1332
|
+
|
|
1333
|
+
{enums.length > 0 && (
|
|
1334
|
+
<section className="mb-12">
|
|
1335
|
+
<h2 className="text-2xl font-bold mb-6">Enums</h2>
|
|
1336
|
+
{enums.map((exp) => (
|
|
1337
|
+
<ExportSection key={exp.id} exp={exp} />
|
|
1338
|
+
))}
|
|
1339
|
+
</section>
|
|
1340
|
+
)}
|
|
1341
|
+
</div>
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
export { spec };
|
|
1346
|
+
`;
|
|
1347
|
+
}
|
|
1348
|
+
function generateIndexLayout(spec, componentsPath) {
|
|
1349
|
+
const pkgName = spec.meta.name;
|
|
1350
|
+
return `'use client';
|
|
1351
|
+
|
|
1352
|
+
import type { OpenPkg } from '@openpkg-ts/spec';
|
|
1353
|
+
import spec from './openpkg.json';
|
|
1354
|
+
|
|
1355
|
+
// Add the export-card component: openpkg docs add export-card
|
|
1356
|
+
// import { ExportCard } from '${componentsPath}/export-card';
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* API Reference Index Page for ${pkgName}
|
|
1360
|
+
*
|
|
1361
|
+
* Links to individual export pages. Best with file-based routing.
|
|
1362
|
+
* Customize the card component and links to match your docs.
|
|
1363
|
+
*/
|
|
1364
|
+
export default function APIReferenceIndex() {
|
|
1365
|
+
const typedSpec = spec as OpenPkg;
|
|
1366
|
+
const exports = typedSpec.exports;
|
|
1367
|
+
|
|
1368
|
+
// Group exports by kind
|
|
1369
|
+
const groups = [
|
|
1370
|
+
{ title: 'Functions', items: exports.filter((e) => e.kind === 'function') },
|
|
1371
|
+
{ title: 'Classes', items: exports.filter((e) => e.kind === 'class') },
|
|
1372
|
+
{ title: 'Types & Interfaces', items: exports.filter((e) => e.kind === 'interface' || e.kind === 'type') },
|
|
1373
|
+
{ title: 'Variables', items: exports.filter((e) => e.kind === 'variable') },
|
|
1374
|
+
{ title: 'Enums', items: exports.filter((e) => e.kind === 'enum') },
|
|
1375
|
+
].filter((g) => g.items.length > 0);
|
|
1376
|
+
|
|
1377
|
+
return (
|
|
1378
|
+
<div className="max-w-4xl mx-auto px-4 py-8">
|
|
1379
|
+
<header className="mb-12">
|
|
1380
|
+
<h1 className="text-3xl font-bold">{typedSpec.meta.name}</h1>
|
|
1381
|
+
{typedSpec.meta.description && (
|
|
1382
|
+
<p className="text-lg text-muted-foreground mt-2">{typedSpec.meta.description}</p>
|
|
1383
|
+
)}
|
|
1384
|
+
</header>
|
|
1385
|
+
|
|
1386
|
+
{groups.map((group) => (
|
|
1387
|
+
<section key={group.title} className="mb-12">
|
|
1388
|
+
<h2 className="text-2xl font-bold mb-6">{group.title}</h2>
|
|
1389
|
+
<div className="grid gap-4 md:grid-cols-2">
|
|
1390
|
+
{group.items.map((exp) => (
|
|
1391
|
+
// Replace with ExportCard once installed:
|
|
1392
|
+
// <ExportCard key={exp.id} export={exp} href={\`/api/\${exp.name}\`} />
|
|
1393
|
+
<a
|
|
1394
|
+
key={exp.id}
|
|
1395
|
+
href={\`/api/\${exp.name}\`}
|
|
1396
|
+
className="block p-4 border rounded-lg hover:bg-muted transition-colors"
|
|
1397
|
+
>
|
|
1398
|
+
<h3 className="font-semibold">{exp.name}</h3>
|
|
1399
|
+
<p className="text-sm text-muted-foreground line-clamp-2">
|
|
1400
|
+
{exp.description || 'No description'}
|
|
1401
|
+
</p>
|
|
1402
|
+
<span className="text-xs bg-muted px-2 py-1 rounded mt-2 inline-block">
|
|
1403
|
+
{exp.kind}
|
|
1404
|
+
</span>
|
|
1405
|
+
</a>
|
|
1406
|
+
))}
|
|
1407
|
+
</div>
|
|
1408
|
+
</section>
|
|
1409
|
+
))}
|
|
1410
|
+
</div>
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
export { spec };
|
|
1415
|
+
`;
|
|
1416
|
+
}
|
|
1417
|
+
async function toReact(spec, options) {
|
|
1418
|
+
const { outDir, variant = "full", componentsPath = "@/components/api" } = options;
|
|
1419
|
+
if (!fs3.existsSync(outDir)) {
|
|
1420
|
+
fs3.mkdirSync(outDir, { recursive: true });
|
|
1421
|
+
}
|
|
1422
|
+
const specPath = path2.join(outDir, "openpkg.json");
|
|
1423
|
+
fs3.writeFileSync(specPath, JSON.stringify(spec, null, 2));
|
|
1424
|
+
const layoutContent = variant === "index" ? generateIndexLayout(spec, componentsPath) : generateFullLayout(spec, componentsPath);
|
|
1425
|
+
const layoutPath = path2.join(outDir, "page.tsx");
|
|
1426
|
+
fs3.writeFileSync(layoutPath, layoutContent);
|
|
1427
|
+
}
|
|
1428
|
+
function toReactString(spec, options = {}) {
|
|
1429
|
+
const { variant = "full", componentsPath = "@/components/api" } = options;
|
|
1430
|
+
return variant === "index" ? generateIndexLayout(spec, componentsPath) : generateFullLayout(spec, componentsPath);
|
|
1431
|
+
}
|
|
1657
1432
|
// src/primitives/filter.ts
|
|
1658
1433
|
function matchesExport(exp, criteria) {
|
|
1659
1434
|
if (criteria.kinds && criteria.kinds.length > 0) {
|
|
@@ -1761,8 +1536,8 @@ function filterSpec(spec, criteria) {
|
|
|
1761
1536
|
import ts11 from "typescript";
|
|
1762
1537
|
|
|
1763
1538
|
// src/compiler/program.ts
|
|
1764
|
-
import * as
|
|
1765
|
-
import * as
|
|
1539
|
+
import * as fs4 from "node:fs";
|
|
1540
|
+
import * as path3 from "node:path";
|
|
1766
1541
|
import ts from "typescript";
|
|
1767
1542
|
function isJsFile(file) {
|
|
1768
1543
|
return /\.(js|mjs|cjs|jsx)$/.test(file);
|
|
@@ -1788,16 +1563,16 @@ function resolveProjectReferences(configPath, parsedConfig) {
|
|
|
1788
1563
|
if (!parsedConfig.projectReferences?.length) {
|
|
1789
1564
|
return additionalFiles;
|
|
1790
1565
|
}
|
|
1791
|
-
const configDir =
|
|
1566
|
+
const configDir = path3.dirname(configPath);
|
|
1792
1567
|
for (const ref of parsedConfig.projectReferences) {
|
|
1793
|
-
const refPath =
|
|
1794
|
-
const refConfigPath =
|
|
1795
|
-
if (!
|
|
1568
|
+
const refPath = path3.resolve(configDir, ref.path);
|
|
1569
|
+
const refConfigPath = fs4.existsSync(path3.join(refPath, "tsconfig.json")) ? path3.join(refPath, "tsconfig.json") : refPath;
|
|
1570
|
+
if (!fs4.existsSync(refConfigPath))
|
|
1796
1571
|
continue;
|
|
1797
1572
|
const refConfigFile = ts.readConfigFile(refConfigPath, ts.sys.readFile);
|
|
1798
1573
|
if (refConfigFile.error)
|
|
1799
1574
|
continue;
|
|
1800
|
-
const refParsed = ts.parseJsonConfigFileContent(refConfigFile.config, ts.sys,
|
|
1575
|
+
const refParsed = ts.parseJsonConfigFileContent(refConfigFile.config, ts.sys, path3.dirname(refConfigPath));
|
|
1801
1576
|
additionalFiles.push(...refParsed.fileNames);
|
|
1802
1577
|
}
|
|
1803
1578
|
return additionalFiles;
|
|
@@ -1830,10 +1605,10 @@ function buildWorkspaceMap(baseDir) {
|
|
|
1830
1605
|
let rootDir;
|
|
1831
1606
|
let workspaceGlobs = [];
|
|
1832
1607
|
for (let i = 0;i < 10; i++) {
|
|
1833
|
-
const pnpmPath =
|
|
1834
|
-
if (
|
|
1608
|
+
const pnpmPath = path3.join(currentDir, "pnpm-workspace.yaml");
|
|
1609
|
+
if (fs4.existsSync(pnpmPath)) {
|
|
1835
1610
|
try {
|
|
1836
|
-
const yamlContent =
|
|
1611
|
+
const yamlContent = fs4.readFileSync(pnpmPath, "utf-8");
|
|
1837
1612
|
workspaceGlobs = parsePnpmWorkspace(yamlContent);
|
|
1838
1613
|
if (workspaceGlobs.length > 0) {
|
|
1839
1614
|
rootDir = currentDir;
|
|
@@ -1841,10 +1616,10 @@ function buildWorkspaceMap(baseDir) {
|
|
|
1841
1616
|
}
|
|
1842
1617
|
} catch {}
|
|
1843
1618
|
}
|
|
1844
|
-
const pkgPath =
|
|
1845
|
-
if (
|
|
1619
|
+
const pkgPath = path3.join(currentDir, "package.json");
|
|
1620
|
+
if (fs4.existsSync(pkgPath)) {
|
|
1846
1621
|
try {
|
|
1847
|
-
const pkg = JSON.parse(
|
|
1622
|
+
const pkg = JSON.parse(fs4.readFileSync(pkgPath, "utf-8"));
|
|
1848
1623
|
if (pkg.workspaces) {
|
|
1849
1624
|
rootDir = currentDir;
|
|
1850
1625
|
workspaceGlobs = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages || [];
|
|
@@ -1852,7 +1627,7 @@ function buildWorkspaceMap(baseDir) {
|
|
|
1852
1627
|
}
|
|
1853
1628
|
} catch {}
|
|
1854
1629
|
}
|
|
1855
|
-
const parent =
|
|
1630
|
+
const parent = path3.dirname(currentDir);
|
|
1856
1631
|
if (parent === currentDir)
|
|
1857
1632
|
break;
|
|
1858
1633
|
currentDir = parent;
|
|
@@ -1861,21 +1636,21 @@ function buildWorkspaceMap(baseDir) {
|
|
|
1861
1636
|
return;
|
|
1862
1637
|
const packages = new Map;
|
|
1863
1638
|
for (const glob of workspaceGlobs) {
|
|
1864
|
-
const globDir =
|
|
1865
|
-
if (!
|
|
1639
|
+
const globDir = path3.join(rootDir, glob.replace(/\/\*$/, ""));
|
|
1640
|
+
if (!fs4.existsSync(globDir) || !fs4.statSync(globDir).isDirectory())
|
|
1866
1641
|
continue;
|
|
1867
|
-
const entries =
|
|
1642
|
+
const entries = fs4.readdirSync(globDir, { withFileTypes: true });
|
|
1868
1643
|
for (const entry of entries) {
|
|
1869
1644
|
if (!entry.isDirectory())
|
|
1870
1645
|
continue;
|
|
1871
|
-
const pkgDir =
|
|
1872
|
-
const pkgJsonPath =
|
|
1873
|
-
if (!
|
|
1646
|
+
const pkgDir = path3.join(globDir, entry.name);
|
|
1647
|
+
const pkgJsonPath = path3.join(pkgDir, "package.json");
|
|
1648
|
+
if (!fs4.existsSync(pkgJsonPath))
|
|
1874
1649
|
continue;
|
|
1875
1650
|
try {
|
|
1876
|
-
const pkg = JSON.parse(
|
|
1651
|
+
const pkg = JSON.parse(fs4.readFileSync(pkgJsonPath, "utf-8"));
|
|
1877
1652
|
if (pkg.name) {
|
|
1878
|
-
const srcDir =
|
|
1653
|
+
const srcDir = fs4.existsSync(path3.join(pkgDir, "src")) ? path3.join(pkgDir, "src") : pkgDir;
|
|
1879
1654
|
packages.set(pkg.name, srcDir);
|
|
1880
1655
|
}
|
|
1881
1656
|
} catch {}
|
|
@@ -1885,7 +1660,7 @@ function buildWorkspaceMap(baseDir) {
|
|
|
1885
1660
|
}
|
|
1886
1661
|
function createProgram({
|
|
1887
1662
|
entryFile,
|
|
1888
|
-
baseDir =
|
|
1663
|
+
baseDir = path3.dirname(entryFile),
|
|
1889
1664
|
content
|
|
1890
1665
|
}) {
|
|
1891
1666
|
let configPath = ts.findConfigFile(baseDir, ts.sys.fileExists, "tsconfig.json");
|
|
@@ -1896,7 +1671,7 @@ function createProgram({
|
|
|
1896
1671
|
let additionalRootFiles = [];
|
|
1897
1672
|
if (configPath) {
|
|
1898
1673
|
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
1899
|
-
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys,
|
|
1674
|
+
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path3.dirname(configPath));
|
|
1900
1675
|
compilerOptions = { ...compilerOptions, ...parsedConfig.options };
|
|
1901
1676
|
additionalRootFiles = resolveProjectReferences(configPath, parsedConfig);
|
|
1902
1677
|
const sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
|
|
@@ -1924,8 +1699,8 @@ function createProgram({
|
|
|
1924
1699
|
return moduleNames.map((moduleName) => {
|
|
1925
1700
|
const srcDir = workspaceMap.packages.get(moduleName);
|
|
1926
1701
|
if (srcDir) {
|
|
1927
|
-
const indexFile =
|
|
1928
|
-
if (
|
|
1702
|
+
const indexFile = path3.join(srcDir, "index.ts");
|
|
1703
|
+
if (fs4.existsSync(indexFile)) {
|
|
1929
1704
|
return { resolvedFileName: indexFile, isExternalLibraryImport: false };
|
|
1930
1705
|
}
|
|
1931
1706
|
}
|
|
@@ -4817,7 +4592,7 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
|
|
|
4817
4592
|
return result;
|
|
4818
4593
|
}
|
|
4819
4594
|
// src/primitives/list.ts
|
|
4820
|
-
import * as
|
|
4595
|
+
import * as path4 from "node:path";
|
|
4821
4596
|
import ts12 from "typescript";
|
|
4822
4597
|
async function listExports(options) {
|
|
4823
4598
|
const { entryFile, baseDir, content } = options;
|
|
@@ -4865,7 +4640,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
|
4865
4640
|
return {
|
|
4866
4641
|
name,
|
|
4867
4642
|
kind: "namespace",
|
|
4868
|
-
file:
|
|
4643
|
+
file: path4.relative(path4.dirname(entryFile), declaration.fileName),
|
|
4869
4644
|
line: 1,
|
|
4870
4645
|
reexport: true
|
|
4871
4646
|
};
|
|
@@ -4879,7 +4654,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
|
4879
4654
|
return {
|
|
4880
4655
|
name,
|
|
4881
4656
|
kind,
|
|
4882
|
-
file:
|
|
4657
|
+
file: path4.relative(path4.dirname(entryFile), sourceFile.fileName),
|
|
4883
4658
|
line: line + 1,
|
|
4884
4659
|
...description ? { description } : {},
|
|
4885
4660
|
...deprecated ? { deprecated: true } : {},
|
|
@@ -4931,8 +4706,8 @@ function getDescriptionPreview(symbol, checker) {
|
|
|
4931
4706
|
return `${firstLine.slice(0, 77)}...`;
|
|
4932
4707
|
}
|
|
4933
4708
|
// src/builder/spec-builder.ts
|
|
4934
|
-
import * as
|
|
4935
|
-
import * as
|
|
4709
|
+
import * as fs7 from "node:fs";
|
|
4710
|
+
import * as path7 from "node:path";
|
|
4936
4711
|
import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
|
|
4937
4712
|
import ts15 from "typescript";
|
|
4938
4713
|
|
|
@@ -4968,9 +4743,9 @@ function resolveExportTarget2(symbol, checker) {
|
|
|
4968
4743
|
|
|
4969
4744
|
// src/schema/standard-schema.ts
|
|
4970
4745
|
import { spawn, spawnSync } from "node:child_process";
|
|
4971
|
-
import * as
|
|
4746
|
+
import * as fs5 from "node:fs";
|
|
4972
4747
|
import * as os from "node:os";
|
|
4973
|
-
import * as
|
|
4748
|
+
import * as path5 from "node:path";
|
|
4974
4749
|
function isStandardJSONSchema(obj) {
|
|
4975
4750
|
if (typeof obj !== "object" || obj === null)
|
|
4976
4751
|
return false;
|
|
@@ -5216,21 +4991,21 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5216
4991
|
result.errors.push("No TypeScript runtime available. Install bun, tsx, or ts-node, or use Node 22+.");
|
|
5217
4992
|
return result;
|
|
5218
4993
|
}
|
|
5219
|
-
if (!
|
|
4994
|
+
if (!fs5.existsSync(tsFilePath)) {
|
|
5220
4995
|
result.errors.push(`TypeScript file not found: ${tsFilePath}`);
|
|
5221
4996
|
return result;
|
|
5222
4997
|
}
|
|
5223
4998
|
const tempDir = os.tmpdir();
|
|
5224
|
-
const workerPath =
|
|
4999
|
+
const workerPath = path5.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
|
|
5225
5000
|
try {
|
|
5226
|
-
|
|
5001
|
+
fs5.writeFileSync(workerPath, TS_WORKER_SCRIPT);
|
|
5227
5002
|
const optionsJson = JSON.stringify({ target, libraryOptions });
|
|
5228
5003
|
const args = [...runtime.args, workerPath, tsFilePath, optionsJson];
|
|
5229
5004
|
return await new Promise((resolve2) => {
|
|
5230
5005
|
const child = spawn(runtime.cmd, args, {
|
|
5231
5006
|
timeout,
|
|
5232
5007
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5233
|
-
cwd:
|
|
5008
|
+
cwd: path5.dirname(tsFilePath)
|
|
5234
5009
|
});
|
|
5235
5010
|
let stdout = "";
|
|
5236
5011
|
let stderr = "";
|
|
@@ -5242,7 +5017,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5242
5017
|
});
|
|
5243
5018
|
child.on("close", (code) => {
|
|
5244
5019
|
try {
|
|
5245
|
-
|
|
5020
|
+
fs5.unlinkSync(workerPath);
|
|
5246
5021
|
} catch {}
|
|
5247
5022
|
if (code !== 0) {
|
|
5248
5023
|
result.errors.push(`Extraction failed (${runtime.name}): ${stderr || `exit code ${code}`}`);
|
|
@@ -5271,7 +5046,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5271
5046
|
});
|
|
5272
5047
|
child.on("error", (err) => {
|
|
5273
5048
|
try {
|
|
5274
|
-
|
|
5049
|
+
fs5.unlinkSync(workerPath);
|
|
5275
5050
|
} catch {}
|
|
5276
5051
|
result.errors.push(`Subprocess error: ${err.message}`);
|
|
5277
5052
|
resolve2(result);
|
|
@@ -5279,19 +5054,19 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5279
5054
|
});
|
|
5280
5055
|
} catch (e) {
|
|
5281
5056
|
try {
|
|
5282
|
-
|
|
5057
|
+
fs5.unlinkSync(workerPath);
|
|
5283
5058
|
} catch {}
|
|
5284
5059
|
result.errors.push(`Failed to create worker script: ${e}`);
|
|
5285
5060
|
return result;
|
|
5286
5061
|
}
|
|
5287
5062
|
}
|
|
5288
5063
|
function readTsconfigOutDir(baseDir) {
|
|
5289
|
-
const tsconfigPath =
|
|
5064
|
+
const tsconfigPath = path5.join(baseDir, "tsconfig.json");
|
|
5290
5065
|
try {
|
|
5291
|
-
if (!
|
|
5066
|
+
if (!fs5.existsSync(tsconfigPath)) {
|
|
5292
5067
|
return null;
|
|
5293
5068
|
}
|
|
5294
|
-
const content =
|
|
5069
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
5295
5070
|
const stripped = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
5296
5071
|
const tsconfig = JSON.parse(stripped);
|
|
5297
5072
|
if (tsconfig.compilerOptions?.outDir) {
|
|
@@ -5301,7 +5076,7 @@ function readTsconfigOutDir(baseDir) {
|
|
|
5301
5076
|
return null;
|
|
5302
5077
|
}
|
|
5303
5078
|
function resolveCompiledPath(tsPath, baseDir) {
|
|
5304
|
-
const relativePath =
|
|
5079
|
+
const relativePath = path5.relative(baseDir, tsPath);
|
|
5305
5080
|
const withoutExt = relativePath.replace(/\.tsx?$/, "");
|
|
5306
5081
|
const srcPrefix = withoutExt.replace(/^src\//, "");
|
|
5307
5082
|
const tsconfigOutDir = readTsconfigOutDir(baseDir);
|
|
@@ -5309,7 +5084,7 @@ function resolveCompiledPath(tsPath, baseDir) {
|
|
|
5309
5084
|
const candidates = [];
|
|
5310
5085
|
if (tsconfigOutDir) {
|
|
5311
5086
|
for (const ext of extensions) {
|
|
5312
|
-
candidates.push(
|
|
5087
|
+
candidates.push(path5.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
|
|
5313
5088
|
}
|
|
5314
5089
|
}
|
|
5315
5090
|
const commonOutDirs = ["dist", "build", "lib", "out"];
|
|
@@ -5317,21 +5092,21 @@ function resolveCompiledPath(tsPath, baseDir) {
|
|
|
5317
5092
|
if (outDir === tsconfigOutDir)
|
|
5318
5093
|
continue;
|
|
5319
5094
|
for (const ext of extensions) {
|
|
5320
|
-
candidates.push(
|
|
5095
|
+
candidates.push(path5.join(baseDir, outDir, `${srcPrefix}${ext}`));
|
|
5321
5096
|
}
|
|
5322
5097
|
}
|
|
5323
5098
|
for (const ext of extensions) {
|
|
5324
|
-
candidates.push(
|
|
5099
|
+
candidates.push(path5.join(baseDir, `${withoutExt}${ext}`));
|
|
5325
5100
|
}
|
|
5326
5101
|
const workspaceMatch = baseDir.match(/^(.+\/packages\/[^/]+)$/);
|
|
5327
5102
|
if (workspaceMatch) {
|
|
5328
5103
|
const pkgRoot = workspaceMatch[1];
|
|
5329
5104
|
for (const ext of extensions) {
|
|
5330
|
-
candidates.push(
|
|
5105
|
+
candidates.push(path5.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
|
|
5331
5106
|
}
|
|
5332
5107
|
}
|
|
5333
5108
|
for (const candidate of candidates) {
|
|
5334
|
-
if (
|
|
5109
|
+
if (fs5.existsSync(candidate)) {
|
|
5335
5110
|
return candidate;
|
|
5336
5111
|
}
|
|
5337
5112
|
}
|
|
@@ -5343,7 +5118,7 @@ async function extractStandardSchemas(compiledJsPath, options = {}) {
|
|
|
5343
5118
|
schemas: new Map,
|
|
5344
5119
|
errors: []
|
|
5345
5120
|
};
|
|
5346
|
-
if (!
|
|
5121
|
+
if (!fs5.existsSync(compiledJsPath)) {
|
|
5347
5122
|
result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
|
|
5348
5123
|
return result;
|
|
5349
5124
|
}
|
|
@@ -5425,8 +5200,8 @@ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {
|
|
|
5425
5200
|
}
|
|
5426
5201
|
|
|
5427
5202
|
// src/builder/external-resolver.ts
|
|
5428
|
-
import * as
|
|
5429
|
-
import * as
|
|
5203
|
+
import * as fs6 from "node:fs";
|
|
5204
|
+
import * as path6 from "node:path";
|
|
5430
5205
|
import picomatch from "picomatch";
|
|
5431
5206
|
import ts14 from "typescript";
|
|
5432
5207
|
function matchesExternalPattern(packageName, include, exclude) {
|
|
@@ -5460,20 +5235,20 @@ function findPackageJson(resolvedPath, packageName) {
|
|
|
5460
5235
|
const isScoped = packageName.startsWith("@");
|
|
5461
5236
|
const packageParts = isScoped ? packageName.split("/").slice(0, 2) : [packageName.split("/")[0]];
|
|
5462
5237
|
const packageDir = packageParts.join("/");
|
|
5463
|
-
let dir =
|
|
5238
|
+
let dir = path6.dirname(resolvedPath);
|
|
5464
5239
|
const maxDepth = 10;
|
|
5465
5240
|
for (let i = 0;i < maxDepth; i++) {
|
|
5466
5241
|
if (dir.endsWith(`node_modules/${packageDir}`)) {
|
|
5467
|
-
const pkgPath =
|
|
5468
|
-
if (
|
|
5242
|
+
const pkgPath = path6.join(dir, "package.json");
|
|
5243
|
+
if (fs6.existsSync(pkgPath)) {
|
|
5469
5244
|
try {
|
|
5470
|
-
return JSON.parse(
|
|
5245
|
+
return JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
5471
5246
|
} catch {
|
|
5472
5247
|
return;
|
|
5473
5248
|
}
|
|
5474
5249
|
}
|
|
5475
5250
|
}
|
|
5476
|
-
const parent =
|
|
5251
|
+
const parent = path6.dirname(dir);
|
|
5477
5252
|
if (parent === dir)
|
|
5478
5253
|
break;
|
|
5479
5254
|
dir = parent;
|
|
@@ -5918,7 +5693,7 @@ async function extract(options) {
|
|
|
5918
5693
|
const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
|
|
5919
5694
|
const meta = await getPackageMeta(entryFile, baseDir);
|
|
5920
5695
|
const types = ctx.typeRegistry.getAll();
|
|
5921
|
-
const projectBaseDir = baseDir ??
|
|
5696
|
+
const projectBaseDir = baseDir ?? path7.dirname(entryFile);
|
|
5922
5697
|
const definedTypes = new Set(types.map((t) => t.id));
|
|
5923
5698
|
const forgottenExports = collectForgottenExports(exports, types, program, sourceFile, exportedIds, projectBaseDir, definedTypes);
|
|
5924
5699
|
for (const forgotten of forgottenExports) {
|
|
@@ -5951,7 +5726,7 @@ async function extract(options) {
|
|
|
5951
5726
|
}
|
|
5952
5727
|
let runtimeMetadata;
|
|
5953
5728
|
if (options.schemaExtraction === "hybrid") {
|
|
5954
|
-
const projectBaseDir2 = baseDir ||
|
|
5729
|
+
const projectBaseDir2 = baseDir || path7.dirname(entryFile);
|
|
5955
5730
|
const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
|
|
5956
5731
|
target: options.schemaTarget || "draft-2020-12",
|
|
5957
5732
|
timeout: 15000
|
|
@@ -6101,8 +5876,8 @@ function isExternalType2(definedIn, baseDir) {
|
|
|
6101
5876
|
return true;
|
|
6102
5877
|
if (definedIn.includes("node_modules"))
|
|
6103
5878
|
return true;
|
|
6104
|
-
const normalizedDefined =
|
|
6105
|
-
const normalizedBase =
|
|
5879
|
+
const normalizedDefined = path7.resolve(definedIn);
|
|
5880
|
+
const normalizedBase = path7.resolve(baseDir);
|
|
6106
5881
|
return !normalizedDefined.startsWith(normalizedBase);
|
|
6107
5882
|
}
|
|
6108
5883
|
function hasInternalTag(typeName, program, sourceFile) {
|
|
@@ -6404,7 +6179,7 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
|
|
|
6404
6179
|
return {
|
|
6405
6180
|
...includeSchema ? { $schema: SCHEMA_URL } : {},
|
|
6406
6181
|
openpkg: SCHEMA_VERSION,
|
|
6407
|
-
meta: { name:
|
|
6182
|
+
meta: { name: path7.basename(entryFile, path7.extname(entryFile)) },
|
|
6408
6183
|
exports: [],
|
|
6409
6184
|
generation: {
|
|
6410
6185
|
generator: "@openpkg-ts/sdk",
|
|
@@ -6417,19 +6192,19 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
|
|
|
6417
6192
|
};
|
|
6418
6193
|
}
|
|
6419
6194
|
async function getPackageMeta(entryFile, baseDir) {
|
|
6420
|
-
const searchDir = baseDir ??
|
|
6421
|
-
const pkgPath =
|
|
6195
|
+
const searchDir = baseDir ?? path7.dirname(entryFile);
|
|
6196
|
+
const pkgPath = path7.join(searchDir, "package.json");
|
|
6422
6197
|
try {
|
|
6423
|
-
if (
|
|
6424
|
-
const pkg = JSON.parse(
|
|
6198
|
+
if (fs7.existsSync(pkgPath)) {
|
|
6199
|
+
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
|
|
6425
6200
|
return {
|
|
6426
|
-
name: pkg.name ??
|
|
6201
|
+
name: pkg.name ?? path7.basename(searchDir),
|
|
6427
6202
|
version: pkg.version,
|
|
6428
6203
|
description: pkg.description
|
|
6429
6204
|
};
|
|
6430
6205
|
}
|
|
6431
6206
|
} catch {}
|
|
6432
|
-
return { name:
|
|
6207
|
+
return { name: path7.basename(searchDir) };
|
|
6433
6208
|
}
|
|
6434
6209
|
|
|
6435
6210
|
// src/primitives/spec.ts
|
|
@@ -6455,6 +6230,8 @@ export {
|
|
|
6455
6230
|
typeboxAdapter,
|
|
6456
6231
|
toSearchIndexJSON,
|
|
6457
6232
|
toSearchIndex,
|
|
6233
|
+
toReactString,
|
|
6234
|
+
toReact,
|
|
6458
6235
|
toPagefindRecords,
|
|
6459
6236
|
toNavigation,
|
|
6460
6237
|
toMarkdown,
|
|
@@ -6479,6 +6256,7 @@ export {
|
|
|
6479
6256
|
registerReferencedTypes,
|
|
6480
6257
|
registerAdapter,
|
|
6481
6258
|
recommendSemverBump,
|
|
6259
|
+
query,
|
|
6482
6260
|
normalizeType,
|
|
6483
6261
|
normalizeSchema,
|
|
6484
6262
|
normalizeMembers,
|
|
@@ -6547,6 +6325,7 @@ export {
|
|
|
6547
6325
|
arktypeAdapter,
|
|
6548
6326
|
analyzeSpec,
|
|
6549
6327
|
TypeRegistry,
|
|
6328
|
+
QueryBuilder,
|
|
6550
6329
|
CONFIG_FILENAME,
|
|
6551
6330
|
BUILTIN_TYPE_SCHEMAS,
|
|
6552
6331
|
ARRAY_PROTOTYPE_METHODS
|