@openpkg-ts/extract 0.11.3 → 0.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/tspec.js
CHANGED
|
@@ -1,6 +1,95 @@
|
|
|
1
1
|
// src/ast/registry.ts
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
var PRIMITIVES = new Set([
|
|
4
|
+
"string",
|
|
5
|
+
"number",
|
|
6
|
+
"boolean",
|
|
7
|
+
"void",
|
|
8
|
+
"any",
|
|
9
|
+
"undefined",
|
|
10
|
+
"null",
|
|
11
|
+
"never",
|
|
12
|
+
"unknown",
|
|
13
|
+
"object",
|
|
14
|
+
"symbol",
|
|
15
|
+
"bigint"
|
|
16
|
+
]);
|
|
17
|
+
var BUILTINS = new Set([
|
|
18
|
+
"Array",
|
|
19
|
+
"ArrayBuffer",
|
|
20
|
+
"ArrayBufferLike",
|
|
21
|
+
"ArrayLike",
|
|
22
|
+
"Promise",
|
|
23
|
+
"Map",
|
|
24
|
+
"Set",
|
|
25
|
+
"WeakMap",
|
|
26
|
+
"WeakSet",
|
|
27
|
+
"Date",
|
|
28
|
+
"RegExp",
|
|
29
|
+
"Error",
|
|
30
|
+
"Function",
|
|
31
|
+
"Object",
|
|
32
|
+
"String",
|
|
33
|
+
"Number",
|
|
34
|
+
"Boolean",
|
|
35
|
+
"Symbol",
|
|
36
|
+
"BigInt",
|
|
37
|
+
"Uint8Array",
|
|
38
|
+
"Int8Array",
|
|
39
|
+
"Uint16Array",
|
|
40
|
+
"Int16Array",
|
|
41
|
+
"Uint32Array",
|
|
42
|
+
"Int32Array",
|
|
43
|
+
"Float32Array",
|
|
44
|
+
"Float64Array",
|
|
45
|
+
"BigInt64Array",
|
|
46
|
+
"BigUint64Array",
|
|
47
|
+
"DataView",
|
|
48
|
+
"ReadonlyArray",
|
|
49
|
+
"Readonly",
|
|
50
|
+
"Partial",
|
|
51
|
+
"Required",
|
|
52
|
+
"Pick",
|
|
53
|
+
"Omit",
|
|
54
|
+
"Record",
|
|
55
|
+
"Exclude",
|
|
56
|
+
"Extract",
|
|
57
|
+
"NonNullable",
|
|
58
|
+
"Parameters",
|
|
59
|
+
"ReturnType",
|
|
60
|
+
"ConstructorParameters",
|
|
61
|
+
"InstanceType",
|
|
62
|
+
"ThisType",
|
|
63
|
+
"Awaited",
|
|
64
|
+
"PromiseLike",
|
|
65
|
+
"Iterable",
|
|
66
|
+
"Iterator",
|
|
67
|
+
"IterableIterator",
|
|
68
|
+
"Generator",
|
|
69
|
+
"AsyncGenerator",
|
|
70
|
+
"AsyncIterable",
|
|
71
|
+
"AsyncIterator",
|
|
72
|
+
"AsyncIterableIterator",
|
|
73
|
+
"SharedArrayBuffer",
|
|
74
|
+
"Atomics",
|
|
75
|
+
"JSON",
|
|
76
|
+
"Math",
|
|
77
|
+
"console",
|
|
78
|
+
"globalThis"
|
|
79
|
+
]);
|
|
80
|
+
function isGenericTypeParameter(name) {
|
|
81
|
+
if (/^[A-Z]$/.test(name))
|
|
82
|
+
return true;
|
|
83
|
+
if (/^T[A-Z]/.test(name))
|
|
84
|
+
return true;
|
|
85
|
+
if (["Key", "Value", "Item", "Element"].includes(name))
|
|
86
|
+
return true;
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
2
90
|
class TypeRegistry {
|
|
3
91
|
types = new Map;
|
|
92
|
+
processing = new Set;
|
|
4
93
|
add(type) {
|
|
5
94
|
this.types.set(type.id, type);
|
|
6
95
|
}
|
|
@@ -13,22 +102,77 @@ class TypeRegistry {
|
|
|
13
102
|
getAll() {
|
|
14
103
|
return Array.from(this.types.values());
|
|
15
104
|
}
|
|
16
|
-
|
|
105
|
+
registerType(type, checker, exportedIds) {
|
|
106
|
+
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
107
|
+
if (!symbol)
|
|
108
|
+
return;
|
|
17
109
|
const name = symbol.getName();
|
|
110
|
+
if (PRIMITIVES.has(name))
|
|
111
|
+
return;
|
|
112
|
+
if (BUILTINS.has(name))
|
|
113
|
+
return;
|
|
114
|
+
if (name.startsWith("__"))
|
|
115
|
+
return;
|
|
116
|
+
if (symbol.flags & ts.SymbolFlags.EnumMember)
|
|
117
|
+
return;
|
|
118
|
+
if (symbol.flags & ts.SymbolFlags.TypeParameter)
|
|
119
|
+
return;
|
|
120
|
+
if (isGenericTypeParameter(name))
|
|
121
|
+
return;
|
|
18
122
|
if (this.has(name))
|
|
19
|
-
return
|
|
20
|
-
|
|
123
|
+
return name;
|
|
124
|
+
if (exportedIds.has(name))
|
|
125
|
+
return name;
|
|
126
|
+
if (this.processing.has(name))
|
|
127
|
+
return name;
|
|
128
|
+
this.processing.add(name);
|
|
129
|
+
try {
|
|
130
|
+
const specType = this.buildSpecType(symbol, type, checker);
|
|
131
|
+
if (specType) {
|
|
132
|
+
this.add(specType);
|
|
133
|
+
return specType.id;
|
|
134
|
+
}
|
|
135
|
+
} finally {
|
|
136
|
+
this.processing.delete(name);
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
buildSpecType(symbol, type, checker) {
|
|
141
|
+
const name = symbol.getName();
|
|
142
|
+
const decl = symbol.declarations?.[0];
|
|
143
|
+
let kind = "type";
|
|
144
|
+
if (decl) {
|
|
145
|
+
if (ts.isClassDeclaration(decl))
|
|
146
|
+
kind = "class";
|
|
147
|
+
else if (ts.isInterfaceDeclaration(decl))
|
|
148
|
+
kind = "interface";
|
|
149
|
+
else if (ts.isEnumDeclaration(decl))
|
|
150
|
+
kind = "enum";
|
|
151
|
+
}
|
|
152
|
+
const typeString = checker.typeToString(type);
|
|
153
|
+
return {
|
|
21
154
|
id: name,
|
|
22
155
|
name,
|
|
23
|
-
kind
|
|
156
|
+
kind,
|
|
157
|
+
type: typeString !== name ? typeString : undefined
|
|
24
158
|
};
|
|
25
|
-
|
|
26
|
-
|
|
159
|
+
}
|
|
160
|
+
registerFromSymbol(symbol, checker) {
|
|
161
|
+
const name = symbol.getName();
|
|
162
|
+
if (this.has(name))
|
|
163
|
+
return this.get(name);
|
|
164
|
+
const type = checker.getDeclaredTypeOfSymbol(symbol);
|
|
165
|
+
const specType = this.buildSpecType(symbol, type, checker);
|
|
166
|
+
if (specType) {
|
|
167
|
+
this.add(specType);
|
|
168
|
+
return specType;
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
27
171
|
}
|
|
28
172
|
}
|
|
29
173
|
|
|
30
174
|
// src/ast/utils.ts
|
|
31
|
-
import
|
|
175
|
+
import ts2 from "typescript";
|
|
32
176
|
function parseExamplesFromTags(tags) {
|
|
33
177
|
const examples = [];
|
|
34
178
|
for (const tag of tags) {
|
|
@@ -51,17 +195,17 @@ function parseExamplesFromTags(tags) {
|
|
|
51
195
|
return examples;
|
|
52
196
|
}
|
|
53
197
|
function getJSDocComment(node) {
|
|
54
|
-
const jsDocTags =
|
|
198
|
+
const jsDocTags = ts2.getJSDocTags(node);
|
|
55
199
|
const tags = jsDocTags.map((tag) => ({
|
|
56
200
|
name: tag.tagName.text,
|
|
57
|
-
text: typeof tag.comment === "string" ? tag.comment :
|
|
201
|
+
text: typeof tag.comment === "string" ? tag.comment : ts2.getTextOfJSDocComment(tag.comment) ?? ""
|
|
58
202
|
}));
|
|
59
203
|
const jsDocComments = node.jsDoc;
|
|
60
204
|
let description;
|
|
61
205
|
if (jsDocComments && jsDocComments.length > 0) {
|
|
62
206
|
const firstDoc = jsDocComments[0];
|
|
63
207
|
if (firstDoc.comment) {
|
|
64
|
-
description = typeof firstDoc.comment === "string" ? firstDoc.comment :
|
|
208
|
+
description = typeof firstDoc.comment === "string" ? firstDoc.comment : ts2.getTextOfJSDocComment(firstDoc.comment);
|
|
65
209
|
}
|
|
66
210
|
}
|
|
67
211
|
const examples = parseExamplesFromTags(tags);
|
|
@@ -77,34 +221,34 @@ function getSourceLocation(node, sourceFile) {
|
|
|
77
221
|
|
|
78
222
|
// src/compiler/program.ts
|
|
79
223
|
import * as path from "node:path";
|
|
80
|
-
import
|
|
224
|
+
import ts3 from "typescript";
|
|
81
225
|
var DEFAULT_COMPILER_OPTIONS = {
|
|
82
|
-
target:
|
|
83
|
-
module:
|
|
226
|
+
target: ts3.ScriptTarget.Latest,
|
|
227
|
+
module: ts3.ModuleKind.CommonJS,
|
|
84
228
|
lib: ["lib.es2021.d.ts"],
|
|
85
229
|
declaration: true,
|
|
86
|
-
moduleResolution:
|
|
230
|
+
moduleResolution: ts3.ModuleResolutionKind.NodeJs
|
|
87
231
|
};
|
|
88
232
|
function createProgram({
|
|
89
233
|
entryFile,
|
|
90
234
|
baseDir = path.dirname(entryFile),
|
|
91
235
|
content
|
|
92
236
|
}) {
|
|
93
|
-
const configPath =
|
|
237
|
+
const configPath = ts3.findConfigFile(baseDir, ts3.sys.fileExists, "tsconfig.json");
|
|
94
238
|
let compilerOptions = { ...DEFAULT_COMPILER_OPTIONS };
|
|
95
239
|
if (configPath) {
|
|
96
|
-
const configFile =
|
|
97
|
-
const parsedConfig =
|
|
240
|
+
const configFile = ts3.readConfigFile(configPath, ts3.sys.readFile);
|
|
241
|
+
const parsedConfig = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys, path.dirname(configPath));
|
|
98
242
|
compilerOptions = { ...compilerOptions, ...parsedConfig.options };
|
|
99
243
|
}
|
|
100
244
|
const allowJsVal = compilerOptions.allowJs;
|
|
101
245
|
if (typeof allowJsVal === "boolean" && allowJsVal) {
|
|
102
246
|
compilerOptions = { ...compilerOptions, allowJs: false, checkJs: false };
|
|
103
247
|
}
|
|
104
|
-
const compilerHost =
|
|
248
|
+
const compilerHost = ts3.createCompilerHost(compilerOptions, true);
|
|
105
249
|
let inMemorySource;
|
|
106
250
|
if (content !== undefined) {
|
|
107
|
-
inMemorySource =
|
|
251
|
+
inMemorySource = ts3.createSourceFile(entryFile, content, ts3.ScriptTarget.Latest, true, ts3.ScriptKind.TS);
|
|
108
252
|
const originalGetSourceFile = compilerHost.getSourceFile.bind(compilerHost);
|
|
109
253
|
compilerHost.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
|
|
110
254
|
if (fileName === entryFile) {
|
|
@@ -113,7 +257,7 @@ function createProgram({
|
|
|
113
257
|
return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
|
|
114
258
|
};
|
|
115
259
|
}
|
|
116
|
-
const program =
|
|
260
|
+
const program = ts3.createProgram([entryFile], compilerOptions, compilerHost);
|
|
117
261
|
const sourceFile = inMemorySource ?? program.getSourceFile(entryFile);
|
|
118
262
|
return {
|
|
119
263
|
program,
|
|
@@ -176,9 +320,11 @@ function serializeEnum(node, ctx) {
|
|
|
176
320
|
}
|
|
177
321
|
|
|
178
322
|
// src/types/parameters.ts
|
|
179
|
-
function extractParameters(signature,
|
|
323
|
+
function extractParameters(signature, ctx) {
|
|
324
|
+
const { typeChecker: checker, typeRegistry, exportedIds } = ctx;
|
|
180
325
|
return signature.getParameters().map((param) => {
|
|
181
326
|
const type = checker.getTypeOfSymbolAtLocation(param, param.valueDeclaration);
|
|
327
|
+
registerReferencedTypes(type, ctx);
|
|
182
328
|
return {
|
|
183
329
|
name: param.getName(),
|
|
184
330
|
schema: { type: checker.typeToString(type) },
|
|
@@ -186,6 +332,29 @@ function extractParameters(signature, checker) {
|
|
|
186
332
|
};
|
|
187
333
|
});
|
|
188
334
|
}
|
|
335
|
+
function registerReferencedTypes(type, ctx) {
|
|
336
|
+
if (ctx.visitedTypes.has(type))
|
|
337
|
+
return;
|
|
338
|
+
ctx.visitedTypes.add(type);
|
|
339
|
+
const { typeChecker: checker, typeRegistry, exportedIds } = ctx;
|
|
340
|
+
typeRegistry.registerType(type, checker, exportedIds);
|
|
341
|
+
const typeArgs = type.typeArguments;
|
|
342
|
+
if (typeArgs) {
|
|
343
|
+
for (const arg of typeArgs) {
|
|
344
|
+
registerReferencedTypes(arg, ctx);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (type.isUnion()) {
|
|
348
|
+
for (const t of type.types) {
|
|
349
|
+
registerReferencedTypes(t, ctx);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
if (type.isIntersection()) {
|
|
353
|
+
for (const t of type.types) {
|
|
354
|
+
registerReferencedTypes(t, ctx);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
189
358
|
|
|
190
359
|
// src/serializers/functions.ts
|
|
191
360
|
function serializeFunctionExport(node, ctx) {
|
|
@@ -199,8 +368,9 @@ function serializeFunctionExport(node, ctx) {
|
|
|
199
368
|
const type = ctx.typeChecker.getTypeAtLocation(node);
|
|
200
369
|
const callSignatures = type.getCallSignatures();
|
|
201
370
|
const signatures = callSignatures.map((sig) => {
|
|
202
|
-
const params = extractParameters(sig, ctx
|
|
371
|
+
const params = extractParameters(sig, ctx);
|
|
203
372
|
const returnType = ctx.typeChecker.getReturnTypeOfSignature(sig);
|
|
373
|
+
registerReferencedTypes(returnType, ctx);
|
|
204
374
|
return {
|
|
205
375
|
parameters: params,
|
|
206
376
|
returns: {
|
|
@@ -275,6 +445,7 @@ function serializeVariable(node, statement, ctx) {
|
|
|
275
445
|
const source = getSourceLocation(node, declSourceFile);
|
|
276
446
|
const type = ctx.typeChecker.getTypeAtLocation(node);
|
|
277
447
|
const typeString = ctx.typeChecker.typeToString(type);
|
|
448
|
+
registerReferencedTypes(type, ctx);
|
|
278
449
|
return {
|
|
279
450
|
id: name,
|
|
280
451
|
name,
|
|
@@ -291,7 +462,7 @@ function serializeVariable(node, statement, ctx) {
|
|
|
291
462
|
import * as fs from "node:fs";
|
|
292
463
|
import * as path2 from "node:path";
|
|
293
464
|
import { SCHEMA_VERSION } from "@openpkg-ts/spec";
|
|
294
|
-
import
|
|
465
|
+
import ts4 from "typescript";
|
|
295
466
|
|
|
296
467
|
// src/serializers/context.ts
|
|
297
468
|
function createContext(program, sourceFile, options = {}) {
|
|
@@ -301,7 +472,9 @@ function createContext(program, sourceFile, options = {}) {
|
|
|
301
472
|
sourceFile,
|
|
302
473
|
maxTypeDepth: options.maxTypeDepth ?? 20,
|
|
303
474
|
resolveExternalTypes: options.resolveExternalTypes ?? true,
|
|
304
|
-
typeRegistry: new TypeRegistry
|
|
475
|
+
typeRegistry: new TypeRegistry,
|
|
476
|
+
exportedIds: new Set,
|
|
477
|
+
visitedTypes: new Set
|
|
305
478
|
};
|
|
306
479
|
}
|
|
307
480
|
|
|
@@ -318,7 +491,6 @@ async function extract(options) {
|
|
|
318
491
|
diagnostics: [{ message: `Could not load source file: ${entryFile}`, severity: "error" }]
|
|
319
492
|
};
|
|
320
493
|
}
|
|
321
|
-
const ctx = createContext(program, sourceFile, { maxTypeDepth, resolveExternalTypes });
|
|
322
494
|
const typeChecker = program.getTypeChecker();
|
|
323
495
|
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
324
496
|
if (!moduleSymbol) {
|
|
@@ -328,13 +500,19 @@ async function extract(options) {
|
|
|
328
500
|
};
|
|
329
501
|
}
|
|
330
502
|
const exportedSymbols = typeChecker.getExportsOfModule(moduleSymbol);
|
|
503
|
+
const exportedIds = new Set;
|
|
504
|
+
for (const symbol of exportedSymbols) {
|
|
505
|
+
exportedIds.add(symbol.getName());
|
|
506
|
+
}
|
|
507
|
+
const ctx = createContext(program, sourceFile, { maxTypeDepth, resolveExternalTypes });
|
|
508
|
+
ctx.exportedIds = exportedIds;
|
|
331
509
|
for (const symbol of exportedSymbols) {
|
|
332
510
|
try {
|
|
333
511
|
const { declaration, targetSymbol } = resolveExportTarget(symbol, typeChecker);
|
|
334
512
|
if (!declaration)
|
|
335
513
|
continue;
|
|
336
514
|
const exportName = symbol.getName();
|
|
337
|
-
const exp = serializeDeclaration(declaration, targetSymbol, exportName, ctx);
|
|
515
|
+
const exp = serializeDeclaration(declaration, symbol, targetSymbol, exportName, ctx);
|
|
338
516
|
if (exp)
|
|
339
517
|
exports.push(exp);
|
|
340
518
|
} catch (err) {
|
|
@@ -359,39 +537,111 @@ async function extract(options) {
|
|
|
359
537
|
}
|
|
360
538
|
function resolveExportTarget(symbol, checker) {
|
|
361
539
|
let targetSymbol = symbol;
|
|
362
|
-
if (symbol.flags &
|
|
540
|
+
if (symbol.flags & ts4.SymbolFlags.Alias) {
|
|
363
541
|
const aliasTarget = checker.getAliasedSymbol(symbol);
|
|
364
542
|
if (aliasTarget && aliasTarget !== symbol) {
|
|
365
543
|
targetSymbol = aliasTarget;
|
|
366
544
|
}
|
|
367
545
|
}
|
|
368
546
|
const declarations = targetSymbol.declarations ?? [];
|
|
369
|
-
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !==
|
|
547
|
+
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !== ts4.SyntaxKind.ExportSpecifier) || declarations[0];
|
|
370
548
|
return { declaration, targetSymbol };
|
|
371
549
|
}
|
|
372
|
-
function serializeDeclaration(declaration,
|
|
550
|
+
function serializeDeclaration(declaration, exportSymbol, targetSymbol, exportName, ctx) {
|
|
373
551
|
let result = null;
|
|
374
|
-
if (
|
|
552
|
+
if (ts4.isFunctionDeclaration(declaration)) {
|
|
375
553
|
result = serializeFunctionExport(declaration, ctx);
|
|
376
|
-
} else if (
|
|
554
|
+
} else if (ts4.isClassDeclaration(declaration)) {
|
|
377
555
|
result = serializeClass(declaration, ctx);
|
|
378
|
-
} else if (
|
|
556
|
+
} else if (ts4.isInterfaceDeclaration(declaration)) {
|
|
379
557
|
result = serializeInterface(declaration, ctx);
|
|
380
|
-
} else if (
|
|
558
|
+
} else if (ts4.isTypeAliasDeclaration(declaration)) {
|
|
381
559
|
result = serializeTypeAlias(declaration, ctx);
|
|
382
|
-
} else if (
|
|
560
|
+
} else if (ts4.isEnumDeclaration(declaration)) {
|
|
383
561
|
result = serializeEnum(declaration, ctx);
|
|
384
|
-
} else if (
|
|
562
|
+
} else if (ts4.isVariableDeclaration(declaration)) {
|
|
385
563
|
const varStatement = declaration.parent?.parent;
|
|
386
|
-
if (varStatement &&
|
|
564
|
+
if (varStatement && ts4.isVariableStatement(varStatement)) {
|
|
387
565
|
result = serializeVariable(declaration, varStatement, ctx);
|
|
388
566
|
}
|
|
567
|
+
} else if (ts4.isNamespaceExport(declaration) || ts4.isModuleDeclaration(declaration)) {
|
|
568
|
+
result = serializeNamespaceExport(exportSymbol, exportName, ctx);
|
|
569
|
+
} else if (ts4.isSourceFile(declaration)) {
|
|
570
|
+
result = serializeNamespaceExport(exportSymbol, exportName, ctx);
|
|
389
571
|
}
|
|
390
572
|
if (result) {
|
|
391
573
|
result = withExportName(result, exportName);
|
|
392
574
|
}
|
|
393
575
|
return result;
|
|
394
576
|
}
|
|
577
|
+
function serializeNamespaceExport(symbol, exportName, ctx) {
|
|
578
|
+
const { description, tags, examples } = getJSDocFromExportSymbol(symbol);
|
|
579
|
+
return {
|
|
580
|
+
id: exportName,
|
|
581
|
+
name: exportName,
|
|
582
|
+
kind: "namespace",
|
|
583
|
+
description,
|
|
584
|
+
tags,
|
|
585
|
+
...examples.length > 0 ? { examples } : {}
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
function getJSDocFromExportSymbol(symbol) {
|
|
589
|
+
const tags = [];
|
|
590
|
+
const examples = [];
|
|
591
|
+
const decl = symbol.declarations?.[0];
|
|
592
|
+
if (decl) {
|
|
593
|
+
const exportDecl = ts4.isNamespaceExport(decl) ? decl.parent : decl;
|
|
594
|
+
if (exportDecl && ts4.isExportDeclaration(exportDecl)) {
|
|
595
|
+
const jsDocs = ts4.getJSDocCommentsAndTags(exportDecl);
|
|
596
|
+
for (const doc of jsDocs) {
|
|
597
|
+
if (ts4.isJSDoc(doc) && doc.comment) {
|
|
598
|
+
const commentText = typeof doc.comment === "string" ? doc.comment : doc.comment.map((c) => ("text" in c) ? c.text : "").join("");
|
|
599
|
+
if (commentText) {
|
|
600
|
+
return {
|
|
601
|
+
description: commentText,
|
|
602
|
+
tags: extractJSDocTags(doc),
|
|
603
|
+
examples: extractExamples(doc)
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
const docComment = symbol.getDocumentationComment(undefined);
|
|
611
|
+
const description = docComment.map((c) => c.text).join(`
|
|
612
|
+
`) || undefined;
|
|
613
|
+
const jsTags = symbol.getJsDocTags();
|
|
614
|
+
for (const tag of jsTags) {
|
|
615
|
+
const text = tag.text?.map((t) => t.text).join("") ?? "";
|
|
616
|
+
if (tag.name === "example") {
|
|
617
|
+
examples.push(text);
|
|
618
|
+
} else {
|
|
619
|
+
tags.push({ name: tag.name, text });
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return { description, tags, examples };
|
|
623
|
+
}
|
|
624
|
+
function extractJSDocTags(doc) {
|
|
625
|
+
const tags = [];
|
|
626
|
+
for (const tag of doc.tags ?? []) {
|
|
627
|
+
if (tag.tagName.text !== "example") {
|
|
628
|
+
const text = typeof tag.comment === "string" ? tag.comment : tag.comment?.map((c) => ("text" in c) ? c.text : "").join("") ?? "";
|
|
629
|
+
tags.push({ name: tag.tagName.text, text });
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return tags;
|
|
633
|
+
}
|
|
634
|
+
function extractExamples(doc) {
|
|
635
|
+
const examples = [];
|
|
636
|
+
for (const tag of doc.tags ?? []) {
|
|
637
|
+
if (tag.tagName.text === "example") {
|
|
638
|
+
const text = typeof tag.comment === "string" ? tag.comment : tag.comment?.map((c) => ("text" in c) ? c.text : "").join("") ?? "";
|
|
639
|
+
if (text)
|
|
640
|
+
examples.push(text);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return examples;
|
|
644
|
+
}
|
|
395
645
|
function withExportName(entry, exportName) {
|
|
396
646
|
if (entry.name === exportName) {
|
|
397
647
|
return entry;
|
|
@@ -428,4 +678,4 @@ async function getPackageMeta(entryFile, baseDir) {
|
|
|
428
678
|
} catch {}
|
|
429
679
|
return { name: path2.basename(searchDir) };
|
|
430
680
|
}
|
|
431
|
-
export { TypeRegistry, getJSDocComment, getSourceLocation, createProgram, serializeClass, serializeEnum, extractParameters, serializeFunctionExport, serializeInterface, serializeTypeAlias, serializeVariable, extract };
|
|
681
|
+
export { TypeRegistry, getJSDocComment, getSourceLocation, createProgram, serializeClass, serializeEnum, extractParameters, registerReferencedTypes, serializeFunctionExport, serializeInterface, serializeTypeAlias, serializeVariable, extract };
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,10 +2,17 @@ import { SpecType } from "@openpkg-ts/spec";
|
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
declare class TypeRegistry {
|
|
4
4
|
private types;
|
|
5
|
+
private processing;
|
|
5
6
|
add(type: SpecType): void;
|
|
6
7
|
get(id: string): SpecType | undefined;
|
|
7
8
|
has(id: string): boolean;
|
|
8
9
|
getAll(): SpecType[];
|
|
10
|
+
/**
|
|
11
|
+
* Register a type from a ts.Type, extracting its structure.
|
|
12
|
+
* Returns the type ID if registered, undefined if skipped.
|
|
13
|
+
*/
|
|
14
|
+
registerType(type: ts.Type, checker: ts.TypeChecker, exportedIds: Set<string>): string | undefined;
|
|
15
|
+
private buildSpecType;
|
|
9
16
|
registerFromSymbol(symbol: ts.Symbol, checker: ts.TypeChecker): SpecType | undefined;
|
|
10
17
|
}
|
|
11
18
|
import { SpecExample, SpecSource, SpecTag } from "@openpkg-ts/spec";
|
|
@@ -17,9 +24,9 @@ declare function getJSDocComment(node: ts2.Node): {
|
|
|
17
24
|
};
|
|
18
25
|
declare function getSourceLocation(node: ts2.Node, sourceFile: ts2.SourceFile): SpecSource;
|
|
19
26
|
import { OpenPkg } from "@openpkg-ts/spec";
|
|
20
|
-
import { TypeChecker as
|
|
21
|
-
import { Program as
|
|
22
|
-
import { SourceFile as
|
|
27
|
+
import { TypeChecker as TypeChecker_lrgbhchnsl } from "typescript";
|
|
28
|
+
import { Program as Program_jbfzpxflck } from "typescript";
|
|
29
|
+
import { SourceFile as SourceFile_eubaywigwb } from "typescript";
|
|
23
30
|
interface ExtractOptions {
|
|
24
31
|
entryFile: string;
|
|
25
32
|
baseDir?: string;
|
|
@@ -42,9 +49,9 @@ interface Diagnostic {
|
|
|
42
49
|
};
|
|
43
50
|
}
|
|
44
51
|
interface SerializerContext {
|
|
45
|
-
typeChecker:
|
|
46
|
-
program:
|
|
47
|
-
sourceFile:
|
|
52
|
+
typeChecker: TypeChecker_lrgbhchnsl;
|
|
53
|
+
program: Program_jbfzpxflck;
|
|
54
|
+
sourceFile: SourceFile_eubaywigwb;
|
|
48
55
|
maxTypeDepth: number;
|
|
49
56
|
resolveExternalTypes: boolean;
|
|
50
57
|
}
|
|
@@ -95,6 +102,9 @@ interface SerializerContext2 {
|
|
|
95
102
|
maxTypeDepth: number;
|
|
96
103
|
resolveExternalTypes: boolean;
|
|
97
104
|
typeRegistry: TypeRegistry;
|
|
105
|
+
exportedIds: Set<string>;
|
|
106
|
+
/** Track visited types to prevent infinite recursion */
|
|
107
|
+
visitedTypes: Set<ts6.Type>;
|
|
98
108
|
}
|
|
99
109
|
declare function serializeClass(node: ts7.ClassDeclaration, ctx: SerializerContext2): SpecExport | null;
|
|
100
110
|
import { SpecExport as SpecExport2 } from "@openpkg-ts/spec";
|
|
@@ -117,11 +127,16 @@ declare function formatTypeReference(type: ts13.Type, checker: ts13.TypeChecker)
|
|
|
117
127
|
declare function collectReferencedTypes(type: ts13.Type, checker: ts13.TypeChecker, visited?: Set<string>): string[];
|
|
118
128
|
import { SpecSignatureParameter } from "@openpkg-ts/spec";
|
|
119
129
|
import ts14 from "typescript";
|
|
120
|
-
declare function extractParameters(signature: ts14.Signature,
|
|
130
|
+
declare function extractParameters(signature: ts14.Signature, ctx: SerializerContext2): SpecSignatureParameter[];
|
|
131
|
+
/**
|
|
132
|
+
* Recursively register types referenced by a ts.Type.
|
|
133
|
+
* Uses ctx.visitedTypes to prevent infinite recursion on circular types.
|
|
134
|
+
*/
|
|
135
|
+
declare function registerReferencedTypes(type: ts14.Type, ctx: SerializerContext2): void;
|
|
121
136
|
import { SpecSchema as SpecSchema3 } from "@openpkg-ts/spec";
|
|
122
137
|
import ts15 from "typescript";
|
|
123
138
|
declare function buildSchema(type: ts15.Type, checker: ts15.TypeChecker, depth?: number): SpecSchema3;
|
|
124
139
|
import ts16 from "typescript";
|
|
125
140
|
declare function isExported(node: ts16.Node): boolean;
|
|
126
141
|
declare function getNodeName(node: ts16.Node): string | undefined;
|
|
127
|
-
export { zodAdapter, valibotAdapter, typeboxAdapter, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, registerAdapter, isSchemaType, isExported, getSourceLocation, getNodeName, getJSDocComment, formatTypeReference, findAdapter, extractStandardSchemas, extractSchemaType, extractParameters, extract, createProgram, collectReferencedTypes, buildSchema, arktypeAdapter, TypeRegistry, StandardSchemaResult, SerializerContext, SchemaAdapter, ProgramResult, ProgramOptions, ExtractResult, ExtractOptions, Diagnostic };
|
|
142
|
+
export { zodAdapter, valibotAdapter, typeboxAdapter, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, registerReferencedTypes, registerAdapter, isSchemaType, isExported, getSourceLocation, getNodeName, getJSDocComment, formatTypeReference, findAdapter, extractStandardSchemas, extractSchemaType, extractParameters, extract, createProgram, collectReferencedTypes, buildSchema, arktypeAdapter, TypeRegistry, StandardSchemaResult, SerializerContext, SchemaAdapter, ProgramResult, ProgramOptions, ExtractResult, ExtractOptions, Diagnostic };
|
package/dist/src/index.js
CHANGED
|
@@ -5,13 +5,14 @@ import {
|
|
|
5
5
|
extractParameters,
|
|
6
6
|
getJSDocComment,
|
|
7
7
|
getSourceLocation,
|
|
8
|
+
registerReferencedTypes,
|
|
8
9
|
serializeClass,
|
|
9
10
|
serializeEnum,
|
|
10
11
|
serializeFunctionExport,
|
|
11
12
|
serializeInterface,
|
|
12
13
|
serializeTypeAlias,
|
|
13
14
|
serializeVariable
|
|
14
|
-
} from "../shared/chunk-
|
|
15
|
+
} from "../shared/chunk-twaykyxs.js";
|
|
15
16
|
// src/schema/adapters/arktype.ts
|
|
16
17
|
var arktypeAdapter = {
|
|
17
18
|
name: "arktype",
|
|
@@ -119,6 +120,7 @@ export {
|
|
|
119
120
|
serializeFunctionExport,
|
|
120
121
|
serializeEnum,
|
|
121
122
|
serializeClass,
|
|
123
|
+
registerReferencedTypes,
|
|
122
124
|
registerAdapter,
|
|
123
125
|
isSchemaType,
|
|
124
126
|
isExported,
|