@openpkg-ts/sdk 0.33.0 → 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 +320 -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,9 +1671,11 @@ 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);
|
|
1677
|
+
const sourceFiles = parsedConfig.fileNames.filter((f) => !f.includes(".test.") && !f.includes(".spec.") && !f.includes("/dist/") && !f.includes("/node_modules/"));
|
|
1678
|
+
additionalRootFiles.push(...sourceFiles);
|
|
1902
1679
|
}
|
|
1903
1680
|
if (isJsFile(entryFile)) {
|
|
1904
1681
|
compilerOptions = {
|
|
@@ -1922,8 +1699,8 @@ function createProgram({
|
|
|
1922
1699
|
return moduleNames.map((moduleName) => {
|
|
1923
1700
|
const srcDir = workspaceMap.packages.get(moduleName);
|
|
1924
1701
|
if (srcDir) {
|
|
1925
|
-
const indexFile =
|
|
1926
|
-
if (
|
|
1702
|
+
const indexFile = path3.join(srcDir, "index.ts");
|
|
1703
|
+
if (fs4.existsSync(indexFile)) {
|
|
1927
1704
|
return { resolvedFileName: indexFile, isExternalLibraryImport: false };
|
|
1928
1705
|
}
|
|
1929
1706
|
}
|
|
@@ -4815,7 +4592,7 @@ function serializeDeclaration(declaration, _exportSymbol, _targetSymbol, exportN
|
|
|
4815
4592
|
return result;
|
|
4816
4593
|
}
|
|
4817
4594
|
// src/primitives/list.ts
|
|
4818
|
-
import * as
|
|
4595
|
+
import * as path4 from "node:path";
|
|
4819
4596
|
import ts12 from "typescript";
|
|
4820
4597
|
async function listExports(options) {
|
|
4821
4598
|
const { entryFile, baseDir, content } = options;
|
|
@@ -4863,7 +4640,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
|
4863
4640
|
return {
|
|
4864
4641
|
name,
|
|
4865
4642
|
kind: "namespace",
|
|
4866
|
-
file:
|
|
4643
|
+
file: path4.relative(path4.dirname(entryFile), declaration.fileName),
|
|
4867
4644
|
line: 1,
|
|
4868
4645
|
reexport: true
|
|
4869
4646
|
};
|
|
@@ -4877,7 +4654,7 @@ function extractExportItem(symbol, checker, entryFile, entrySourceFile) {
|
|
|
4877
4654
|
return {
|
|
4878
4655
|
name,
|
|
4879
4656
|
kind,
|
|
4880
|
-
file:
|
|
4657
|
+
file: path4.relative(path4.dirname(entryFile), sourceFile.fileName),
|
|
4881
4658
|
line: line + 1,
|
|
4882
4659
|
...description ? { description } : {},
|
|
4883
4660
|
...deprecated ? { deprecated: true } : {},
|
|
@@ -4929,8 +4706,8 @@ function getDescriptionPreview(symbol, checker) {
|
|
|
4929
4706
|
return `${firstLine.slice(0, 77)}...`;
|
|
4930
4707
|
}
|
|
4931
4708
|
// src/builder/spec-builder.ts
|
|
4932
|
-
import * as
|
|
4933
|
-
import * as
|
|
4709
|
+
import * as fs7 from "node:fs";
|
|
4710
|
+
import * as path7 from "node:path";
|
|
4934
4711
|
import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
|
|
4935
4712
|
import ts15 from "typescript";
|
|
4936
4713
|
|
|
@@ -4966,9 +4743,9 @@ function resolveExportTarget2(symbol, checker) {
|
|
|
4966
4743
|
|
|
4967
4744
|
// src/schema/standard-schema.ts
|
|
4968
4745
|
import { spawn, spawnSync } from "node:child_process";
|
|
4969
|
-
import * as
|
|
4746
|
+
import * as fs5 from "node:fs";
|
|
4970
4747
|
import * as os from "node:os";
|
|
4971
|
-
import * as
|
|
4748
|
+
import * as path5 from "node:path";
|
|
4972
4749
|
function isStandardJSONSchema(obj) {
|
|
4973
4750
|
if (typeof obj !== "object" || obj === null)
|
|
4974
4751
|
return false;
|
|
@@ -5214,21 +4991,21 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5214
4991
|
result.errors.push("No TypeScript runtime available. Install bun, tsx, or ts-node, or use Node 22+.");
|
|
5215
4992
|
return result;
|
|
5216
4993
|
}
|
|
5217
|
-
if (!
|
|
4994
|
+
if (!fs5.existsSync(tsFilePath)) {
|
|
5218
4995
|
result.errors.push(`TypeScript file not found: ${tsFilePath}`);
|
|
5219
4996
|
return result;
|
|
5220
4997
|
}
|
|
5221
4998
|
const tempDir = os.tmpdir();
|
|
5222
|
-
const workerPath =
|
|
4999
|
+
const workerPath = path5.join(tempDir, `openpkg-extract-worker-${Date.now()}.ts`);
|
|
5223
5000
|
try {
|
|
5224
|
-
|
|
5001
|
+
fs5.writeFileSync(workerPath, TS_WORKER_SCRIPT);
|
|
5225
5002
|
const optionsJson = JSON.stringify({ target, libraryOptions });
|
|
5226
5003
|
const args = [...runtime.args, workerPath, tsFilePath, optionsJson];
|
|
5227
5004
|
return await new Promise((resolve2) => {
|
|
5228
5005
|
const child = spawn(runtime.cmd, args, {
|
|
5229
5006
|
timeout,
|
|
5230
5007
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5231
|
-
cwd:
|
|
5008
|
+
cwd: path5.dirname(tsFilePath)
|
|
5232
5009
|
});
|
|
5233
5010
|
let stdout = "";
|
|
5234
5011
|
let stderr = "";
|
|
@@ -5240,7 +5017,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5240
5017
|
});
|
|
5241
5018
|
child.on("close", (code) => {
|
|
5242
5019
|
try {
|
|
5243
|
-
|
|
5020
|
+
fs5.unlinkSync(workerPath);
|
|
5244
5021
|
} catch {}
|
|
5245
5022
|
if (code !== 0) {
|
|
5246
5023
|
result.errors.push(`Extraction failed (${runtime.name}): ${stderr || `exit code ${code}`}`);
|
|
@@ -5269,7 +5046,7 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5269
5046
|
});
|
|
5270
5047
|
child.on("error", (err) => {
|
|
5271
5048
|
try {
|
|
5272
|
-
|
|
5049
|
+
fs5.unlinkSync(workerPath);
|
|
5273
5050
|
} catch {}
|
|
5274
5051
|
result.errors.push(`Subprocess error: ${err.message}`);
|
|
5275
5052
|
resolve2(result);
|
|
@@ -5277,19 +5054,19 @@ async function extractStandardSchemasFromTs(tsFilePath, options = {}) {
|
|
|
5277
5054
|
});
|
|
5278
5055
|
} catch (e) {
|
|
5279
5056
|
try {
|
|
5280
|
-
|
|
5057
|
+
fs5.unlinkSync(workerPath);
|
|
5281
5058
|
} catch {}
|
|
5282
5059
|
result.errors.push(`Failed to create worker script: ${e}`);
|
|
5283
5060
|
return result;
|
|
5284
5061
|
}
|
|
5285
5062
|
}
|
|
5286
5063
|
function readTsconfigOutDir(baseDir) {
|
|
5287
|
-
const tsconfigPath =
|
|
5064
|
+
const tsconfigPath = path5.join(baseDir, "tsconfig.json");
|
|
5288
5065
|
try {
|
|
5289
|
-
if (!
|
|
5066
|
+
if (!fs5.existsSync(tsconfigPath)) {
|
|
5290
5067
|
return null;
|
|
5291
5068
|
}
|
|
5292
|
-
const content =
|
|
5069
|
+
const content = fs5.readFileSync(tsconfigPath, "utf-8");
|
|
5293
5070
|
const stripped = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
5294
5071
|
const tsconfig = JSON.parse(stripped);
|
|
5295
5072
|
if (tsconfig.compilerOptions?.outDir) {
|
|
@@ -5299,7 +5076,7 @@ function readTsconfigOutDir(baseDir) {
|
|
|
5299
5076
|
return null;
|
|
5300
5077
|
}
|
|
5301
5078
|
function resolveCompiledPath(tsPath, baseDir) {
|
|
5302
|
-
const relativePath =
|
|
5079
|
+
const relativePath = path5.relative(baseDir, tsPath);
|
|
5303
5080
|
const withoutExt = relativePath.replace(/\.tsx?$/, "");
|
|
5304
5081
|
const srcPrefix = withoutExt.replace(/^src\//, "");
|
|
5305
5082
|
const tsconfigOutDir = readTsconfigOutDir(baseDir);
|
|
@@ -5307,7 +5084,7 @@ function resolveCompiledPath(tsPath, baseDir) {
|
|
|
5307
5084
|
const candidates = [];
|
|
5308
5085
|
if (tsconfigOutDir) {
|
|
5309
5086
|
for (const ext of extensions) {
|
|
5310
|
-
candidates.push(
|
|
5087
|
+
candidates.push(path5.join(baseDir, tsconfigOutDir, `${srcPrefix}${ext}`));
|
|
5311
5088
|
}
|
|
5312
5089
|
}
|
|
5313
5090
|
const commonOutDirs = ["dist", "build", "lib", "out"];
|
|
@@ -5315,21 +5092,21 @@ function resolveCompiledPath(tsPath, baseDir) {
|
|
|
5315
5092
|
if (outDir === tsconfigOutDir)
|
|
5316
5093
|
continue;
|
|
5317
5094
|
for (const ext of extensions) {
|
|
5318
|
-
candidates.push(
|
|
5095
|
+
candidates.push(path5.join(baseDir, outDir, `${srcPrefix}${ext}`));
|
|
5319
5096
|
}
|
|
5320
5097
|
}
|
|
5321
5098
|
for (const ext of extensions) {
|
|
5322
|
-
candidates.push(
|
|
5099
|
+
candidates.push(path5.join(baseDir, `${withoutExt}${ext}`));
|
|
5323
5100
|
}
|
|
5324
5101
|
const workspaceMatch = baseDir.match(/^(.+\/packages\/[^/]+)$/);
|
|
5325
5102
|
if (workspaceMatch) {
|
|
5326
5103
|
const pkgRoot = workspaceMatch[1];
|
|
5327
5104
|
for (const ext of extensions) {
|
|
5328
|
-
candidates.push(
|
|
5105
|
+
candidates.push(path5.join(pkgRoot, "dist", `${srcPrefix}${ext}`));
|
|
5329
5106
|
}
|
|
5330
5107
|
}
|
|
5331
5108
|
for (const candidate of candidates) {
|
|
5332
|
-
if (
|
|
5109
|
+
if (fs5.existsSync(candidate)) {
|
|
5333
5110
|
return candidate;
|
|
5334
5111
|
}
|
|
5335
5112
|
}
|
|
@@ -5341,7 +5118,7 @@ async function extractStandardSchemas(compiledJsPath, options = {}) {
|
|
|
5341
5118
|
schemas: new Map,
|
|
5342
5119
|
errors: []
|
|
5343
5120
|
};
|
|
5344
|
-
if (!
|
|
5121
|
+
if (!fs5.existsSync(compiledJsPath)) {
|
|
5345
5122
|
result.errors.push(`Compiled JS not found: ${compiledJsPath}`);
|
|
5346
5123
|
return result;
|
|
5347
5124
|
}
|
|
@@ -5423,8 +5200,8 @@ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {
|
|
|
5423
5200
|
}
|
|
5424
5201
|
|
|
5425
5202
|
// src/builder/external-resolver.ts
|
|
5426
|
-
import * as
|
|
5427
|
-
import * as
|
|
5203
|
+
import * as fs6 from "node:fs";
|
|
5204
|
+
import * as path6 from "node:path";
|
|
5428
5205
|
import picomatch from "picomatch";
|
|
5429
5206
|
import ts14 from "typescript";
|
|
5430
5207
|
function matchesExternalPattern(packageName, include, exclude) {
|
|
@@ -5458,20 +5235,20 @@ function findPackageJson(resolvedPath, packageName) {
|
|
|
5458
5235
|
const isScoped = packageName.startsWith("@");
|
|
5459
5236
|
const packageParts = isScoped ? packageName.split("/").slice(0, 2) : [packageName.split("/")[0]];
|
|
5460
5237
|
const packageDir = packageParts.join("/");
|
|
5461
|
-
let dir =
|
|
5238
|
+
let dir = path6.dirname(resolvedPath);
|
|
5462
5239
|
const maxDepth = 10;
|
|
5463
5240
|
for (let i = 0;i < maxDepth; i++) {
|
|
5464
5241
|
if (dir.endsWith(`node_modules/${packageDir}`)) {
|
|
5465
|
-
const pkgPath =
|
|
5466
|
-
if (
|
|
5242
|
+
const pkgPath = path6.join(dir, "package.json");
|
|
5243
|
+
if (fs6.existsSync(pkgPath)) {
|
|
5467
5244
|
try {
|
|
5468
|
-
return JSON.parse(
|
|
5245
|
+
return JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
5469
5246
|
} catch {
|
|
5470
5247
|
return;
|
|
5471
5248
|
}
|
|
5472
5249
|
}
|
|
5473
5250
|
}
|
|
5474
|
-
const parent =
|
|
5251
|
+
const parent = path6.dirname(dir);
|
|
5475
5252
|
if (parent === dir)
|
|
5476
5253
|
break;
|
|
5477
5254
|
dir = parent;
|
|
@@ -5916,7 +5693,7 @@ async function extract(options) {
|
|
|
5916
5693
|
const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
|
|
5917
5694
|
const meta = await getPackageMeta(entryFile, baseDir);
|
|
5918
5695
|
const types = ctx.typeRegistry.getAll();
|
|
5919
|
-
const projectBaseDir = baseDir ??
|
|
5696
|
+
const projectBaseDir = baseDir ?? path7.dirname(entryFile);
|
|
5920
5697
|
const definedTypes = new Set(types.map((t) => t.id));
|
|
5921
5698
|
const forgottenExports = collectForgottenExports(exports, types, program, sourceFile, exportedIds, projectBaseDir, definedTypes);
|
|
5922
5699
|
for (const forgotten of forgottenExports) {
|
|
@@ -5949,7 +5726,7 @@ async function extract(options) {
|
|
|
5949
5726
|
}
|
|
5950
5727
|
let runtimeMetadata;
|
|
5951
5728
|
if (options.schemaExtraction === "hybrid") {
|
|
5952
|
-
const projectBaseDir2 = baseDir ||
|
|
5729
|
+
const projectBaseDir2 = baseDir || path7.dirname(entryFile);
|
|
5953
5730
|
const runtimeResult = await extractStandardSchemasFromProject(entryFile, projectBaseDir2, {
|
|
5954
5731
|
target: options.schemaTarget || "draft-2020-12",
|
|
5955
5732
|
timeout: 15000
|
|
@@ -6099,8 +5876,8 @@ function isExternalType2(definedIn, baseDir) {
|
|
|
6099
5876
|
return true;
|
|
6100
5877
|
if (definedIn.includes("node_modules"))
|
|
6101
5878
|
return true;
|
|
6102
|
-
const normalizedDefined =
|
|
6103
|
-
const normalizedBase =
|
|
5879
|
+
const normalizedDefined = path7.resolve(definedIn);
|
|
5880
|
+
const normalizedBase = path7.resolve(baseDir);
|
|
6104
5881
|
return !normalizedDefined.startsWith(normalizedBase);
|
|
6105
5882
|
}
|
|
6106
5883
|
function hasInternalTag(typeName, program, sourceFile) {
|
|
@@ -6402,7 +6179,7 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
|
|
|
6402
6179
|
return {
|
|
6403
6180
|
...includeSchema ? { $schema: SCHEMA_URL } : {},
|
|
6404
6181
|
openpkg: SCHEMA_VERSION,
|
|
6405
|
-
meta: { name:
|
|
6182
|
+
meta: { name: path7.basename(entryFile, path7.extname(entryFile)) },
|
|
6406
6183
|
exports: [],
|
|
6407
6184
|
generation: {
|
|
6408
6185
|
generator: "@openpkg-ts/sdk",
|
|
@@ -6415,19 +6192,19 @@ function createEmptySpec(entryFile, includeSchema, isDtsSource) {
|
|
|
6415
6192
|
};
|
|
6416
6193
|
}
|
|
6417
6194
|
async function getPackageMeta(entryFile, baseDir) {
|
|
6418
|
-
const searchDir = baseDir ??
|
|
6419
|
-
const pkgPath =
|
|
6195
|
+
const searchDir = baseDir ?? path7.dirname(entryFile);
|
|
6196
|
+
const pkgPath = path7.join(searchDir, "package.json");
|
|
6420
6197
|
try {
|
|
6421
|
-
if (
|
|
6422
|
-
const pkg = JSON.parse(
|
|
6198
|
+
if (fs7.existsSync(pkgPath)) {
|
|
6199
|
+
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
|
|
6423
6200
|
return {
|
|
6424
|
-
name: pkg.name ??
|
|
6201
|
+
name: pkg.name ?? path7.basename(searchDir),
|
|
6425
6202
|
version: pkg.version,
|
|
6426
6203
|
description: pkg.description
|
|
6427
6204
|
};
|
|
6428
6205
|
}
|
|
6429
6206
|
} catch {}
|
|
6430
|
-
return { name:
|
|
6207
|
+
return { name: path7.basename(searchDir) };
|
|
6431
6208
|
}
|
|
6432
6209
|
|
|
6433
6210
|
// src/primitives/spec.ts
|
|
@@ -6453,6 +6230,8 @@ export {
|
|
|
6453
6230
|
typeboxAdapter,
|
|
6454
6231
|
toSearchIndexJSON,
|
|
6455
6232
|
toSearchIndex,
|
|
6233
|
+
toReactString,
|
|
6234
|
+
toReact,
|
|
6456
6235
|
toPagefindRecords,
|
|
6457
6236
|
toNavigation,
|
|
6458
6237
|
toMarkdown,
|
|
@@ -6477,6 +6256,7 @@ export {
|
|
|
6477
6256
|
registerReferencedTypes,
|
|
6478
6257
|
registerAdapter,
|
|
6479
6258
|
recommendSemverBump,
|
|
6259
|
+
query,
|
|
6480
6260
|
normalizeType,
|
|
6481
6261
|
normalizeSchema,
|
|
6482
6262
|
normalizeMembers,
|
|
@@ -6545,6 +6325,7 @@ export {
|
|
|
6545
6325
|
arktypeAdapter,
|
|
6546
6326
|
analyzeSpec,
|
|
6547
6327
|
TypeRegistry,
|
|
6328
|
+
QueryBuilder,
|
|
6548
6329
|
CONFIG_FILENAME,
|
|
6549
6330
|
BUILTIN_TYPE_SCHEMAS,
|
|
6550
6331
|
ARRAY_PROTOTYPE_METHODS
|