@openpkg-ts/extract 0.11.4 → 0.12.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/dist/bin/tspec.js +1 -1
- package/dist/shared/{chunk-twaykyxs.js → chunk-wddga8ye.js} +514 -47
- package/dist/src/index.d.ts +30 -21
- package/dist/src/index.js +8 -27
- package/package.json +2 -2
package/dist/bin/tspec.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/ast/registry.ts
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
2
4
|
import ts from "typescript";
|
|
3
5
|
var PRIMITIVES = new Set([
|
|
4
6
|
"string",
|
|
@@ -86,6 +88,54 @@ function isGenericTypeParameter(name) {
|
|
|
86
88
|
return true;
|
|
87
89
|
return false;
|
|
88
90
|
}
|
|
91
|
+
function isExternalType(decl) {
|
|
92
|
+
const sourceFile = decl.getSourceFile();
|
|
93
|
+
if (!sourceFile)
|
|
94
|
+
return false;
|
|
95
|
+
return sourceFile.fileName.includes("node_modules");
|
|
96
|
+
}
|
|
97
|
+
function extractPackageName(filePath) {
|
|
98
|
+
const nmIndex = filePath.lastIndexOf("node_modules");
|
|
99
|
+
if (nmIndex === -1)
|
|
100
|
+
return;
|
|
101
|
+
const afterNm = filePath.slice(nmIndex + "node_modules/".length);
|
|
102
|
+
const parts = afterNm.split("/");
|
|
103
|
+
if (parts[0].startsWith("@") && parts.length >= 2) {
|
|
104
|
+
return `${parts[0]}/${parts[1]}`;
|
|
105
|
+
}
|
|
106
|
+
return parts[0];
|
|
107
|
+
}
|
|
108
|
+
function getPackageVersion(filePath, packageName) {
|
|
109
|
+
const nmIndex = filePath.lastIndexOf("node_modules");
|
|
110
|
+
if (nmIndex === -1)
|
|
111
|
+
return;
|
|
112
|
+
const nmDir = filePath.slice(0, nmIndex + "node_modules".length);
|
|
113
|
+
const pkgJsonPath = path.join(nmDir, packageName, "package.json");
|
|
114
|
+
try {
|
|
115
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
116
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
117
|
+
return pkg.version;
|
|
118
|
+
}
|
|
119
|
+
} catch {}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
function buildExternalSource(decl) {
|
|
123
|
+
const sourceFile = decl.getSourceFile();
|
|
124
|
+
if (!sourceFile)
|
|
125
|
+
return;
|
|
126
|
+
const filePath = sourceFile.fileName;
|
|
127
|
+
if (!filePath.includes("node_modules"))
|
|
128
|
+
return;
|
|
129
|
+
const packageName = extractPackageName(filePath);
|
|
130
|
+
if (!packageName)
|
|
131
|
+
return;
|
|
132
|
+
const version = getPackageVersion(filePath, packageName);
|
|
133
|
+
return {
|
|
134
|
+
file: filePath,
|
|
135
|
+
package: packageName,
|
|
136
|
+
version
|
|
137
|
+
};
|
|
138
|
+
}
|
|
89
139
|
|
|
90
140
|
class TypeRegistry {
|
|
91
141
|
types = new Map;
|
|
@@ -141,6 +191,7 @@ class TypeRegistry {
|
|
|
141
191
|
const name = symbol.getName();
|
|
142
192
|
const decl = symbol.declarations?.[0];
|
|
143
193
|
let kind = "type";
|
|
194
|
+
const external = decl ? isExternalType(decl) : false;
|
|
144
195
|
if (decl) {
|
|
145
196
|
if (ts.isClassDeclaration(decl))
|
|
146
197
|
kind = "class";
|
|
@@ -149,12 +200,18 @@ class TypeRegistry {
|
|
|
149
200
|
else if (ts.isEnumDeclaration(decl))
|
|
150
201
|
kind = "enum";
|
|
151
202
|
}
|
|
203
|
+
if (external) {
|
|
204
|
+
kind = "external";
|
|
205
|
+
}
|
|
152
206
|
const typeString = checker.typeToString(type);
|
|
207
|
+
const source = decl ? buildExternalSource(decl) : undefined;
|
|
153
208
|
return {
|
|
154
209
|
id: name,
|
|
155
210
|
name,
|
|
156
211
|
kind,
|
|
157
|
-
type: typeString !== name ? typeString : undefined
|
|
212
|
+
type: typeString !== name ? typeString : undefined,
|
|
213
|
+
...external ? { external: true } : {},
|
|
214
|
+
...source ? { source } : {}
|
|
158
215
|
};
|
|
159
216
|
}
|
|
160
217
|
registerFromSymbol(symbol, checker) {
|
|
@@ -218,9 +275,23 @@ function getSourceLocation(node, sourceFile) {
|
|
|
218
275
|
line: line + 1
|
|
219
276
|
};
|
|
220
277
|
}
|
|
278
|
+
function getParamDescription(propertyName, jsdocTags, inferredAlias) {
|
|
279
|
+
for (const tag of jsdocTags) {
|
|
280
|
+
if (tag.tagName.text !== "param")
|
|
281
|
+
continue;
|
|
282
|
+
const paramTag = tag;
|
|
283
|
+
const tagParamName = paramTag.name?.getText() ?? "";
|
|
284
|
+
const isMatch = tagParamName === propertyName || inferredAlias && tagParamName === `${inferredAlias}.${propertyName}` || tagParamName.endsWith(`.${propertyName}`);
|
|
285
|
+
if (isMatch) {
|
|
286
|
+
const comment = typeof tag.comment === "string" ? tag.comment : ts2.getTextOfJSDocComment(tag.comment);
|
|
287
|
+
return comment?.trim() || undefined;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
221
292
|
|
|
222
293
|
// src/compiler/program.ts
|
|
223
|
-
import * as
|
|
294
|
+
import * as path2 from "node:path";
|
|
224
295
|
import ts3 from "typescript";
|
|
225
296
|
var DEFAULT_COMPILER_OPTIONS = {
|
|
226
297
|
target: ts3.ScriptTarget.Latest,
|
|
@@ -231,14 +302,14 @@ var DEFAULT_COMPILER_OPTIONS = {
|
|
|
231
302
|
};
|
|
232
303
|
function createProgram({
|
|
233
304
|
entryFile,
|
|
234
|
-
baseDir =
|
|
305
|
+
baseDir = path2.dirname(entryFile),
|
|
235
306
|
content
|
|
236
307
|
}) {
|
|
237
308
|
const configPath = ts3.findConfigFile(baseDir, ts3.sys.fileExists, "tsconfig.json");
|
|
238
309
|
let compilerOptions = { ...DEFAULT_COMPILER_OPTIONS };
|
|
239
310
|
if (configPath) {
|
|
240
311
|
const configFile = ts3.readConfigFile(configPath, ts3.sys.readFile);
|
|
241
|
-
const parsedConfig = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys,
|
|
312
|
+
const parsedConfig = ts3.parseJsonConfigFileContent(configFile.config, ts3.sys, path2.dirname(configPath));
|
|
242
313
|
compilerOptions = { ...compilerOptions, ...parsedConfig.options };
|
|
243
314
|
}
|
|
244
315
|
const allowJsVal = compilerOptions.allowJs;
|
|
@@ -319,18 +390,413 @@ function serializeEnum(node, ctx) {
|
|
|
319
390
|
};
|
|
320
391
|
}
|
|
321
392
|
|
|
393
|
+
// src/types/schema-builder.ts
|
|
394
|
+
import ts4 from "typescript";
|
|
395
|
+
var PRIMITIVES2 = new Set([
|
|
396
|
+
"string",
|
|
397
|
+
"number",
|
|
398
|
+
"boolean",
|
|
399
|
+
"void",
|
|
400
|
+
"undefined",
|
|
401
|
+
"null",
|
|
402
|
+
"any",
|
|
403
|
+
"unknown",
|
|
404
|
+
"never",
|
|
405
|
+
"object",
|
|
406
|
+
"symbol",
|
|
407
|
+
"bigint"
|
|
408
|
+
]);
|
|
409
|
+
var BUILTIN_GENERICS = new Set([
|
|
410
|
+
"Array",
|
|
411
|
+
"ReadonlyArray",
|
|
412
|
+
"Promise",
|
|
413
|
+
"PromiseLike",
|
|
414
|
+
"Map",
|
|
415
|
+
"Set",
|
|
416
|
+
"WeakMap",
|
|
417
|
+
"WeakSet",
|
|
418
|
+
"Iterable",
|
|
419
|
+
"Iterator",
|
|
420
|
+
"IterableIterator",
|
|
421
|
+
"AsyncIterable",
|
|
422
|
+
"AsyncIterator",
|
|
423
|
+
"AsyncIterableIterator",
|
|
424
|
+
"Generator",
|
|
425
|
+
"AsyncGenerator",
|
|
426
|
+
"Partial",
|
|
427
|
+
"Required",
|
|
428
|
+
"Readonly",
|
|
429
|
+
"Pick",
|
|
430
|
+
"Omit",
|
|
431
|
+
"Record",
|
|
432
|
+
"Exclude",
|
|
433
|
+
"Extract",
|
|
434
|
+
"NonNullable",
|
|
435
|
+
"Parameters",
|
|
436
|
+
"ReturnType",
|
|
437
|
+
"ConstructorParameters",
|
|
438
|
+
"InstanceType",
|
|
439
|
+
"Awaited"
|
|
440
|
+
]);
|
|
441
|
+
var BUILTIN_TYPES = new Set([
|
|
442
|
+
"Date",
|
|
443
|
+
"RegExp",
|
|
444
|
+
"Error",
|
|
445
|
+
"Function",
|
|
446
|
+
"ArrayBuffer",
|
|
447
|
+
"SharedArrayBuffer",
|
|
448
|
+
"DataView",
|
|
449
|
+
"Uint8Array",
|
|
450
|
+
"Int8Array",
|
|
451
|
+
"Uint16Array",
|
|
452
|
+
"Int16Array",
|
|
453
|
+
"Uint32Array",
|
|
454
|
+
"Int32Array",
|
|
455
|
+
"Float32Array",
|
|
456
|
+
"Float64Array",
|
|
457
|
+
"BigInt64Array",
|
|
458
|
+
"BigUint64Array"
|
|
459
|
+
]);
|
|
460
|
+
function isPrimitiveName(name) {
|
|
461
|
+
return PRIMITIVES2.has(name);
|
|
462
|
+
}
|
|
463
|
+
function isBuiltinGeneric(name) {
|
|
464
|
+
return BUILTIN_GENERICS.has(name);
|
|
465
|
+
}
|
|
466
|
+
function isAnonymous(type) {
|
|
467
|
+
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
468
|
+
if (!symbol)
|
|
469
|
+
return true;
|
|
470
|
+
const name = symbol.getName();
|
|
471
|
+
return name.startsWith("__") || name === "";
|
|
472
|
+
}
|
|
473
|
+
function withDepth(ctx, fn) {
|
|
474
|
+
ctx.currentDepth++;
|
|
475
|
+
try {
|
|
476
|
+
return fn();
|
|
477
|
+
} finally {
|
|
478
|
+
ctx.currentDepth--;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
function isAtMaxDepth(ctx) {
|
|
482
|
+
if (!ctx)
|
|
483
|
+
return false;
|
|
484
|
+
return ctx.currentDepth >= ctx.maxTypeDepth;
|
|
485
|
+
}
|
|
486
|
+
function buildSchema(type, checker, ctx, _depth = 0) {
|
|
487
|
+
if (isAtMaxDepth(ctx)) {
|
|
488
|
+
return { type: checker.typeToString(type) };
|
|
489
|
+
}
|
|
490
|
+
if (ctx && ctx.visitedTypes.has(type)) {
|
|
491
|
+
const symbol2 = type.getSymbol() || type.aliasSymbol;
|
|
492
|
+
if (symbol2) {
|
|
493
|
+
return { $ref: symbol2.getName() };
|
|
494
|
+
}
|
|
495
|
+
return { type: checker.typeToString(type) };
|
|
496
|
+
}
|
|
497
|
+
if (type.flags & ts4.TypeFlags.String)
|
|
498
|
+
return { type: "string" };
|
|
499
|
+
if (type.flags & ts4.TypeFlags.Number)
|
|
500
|
+
return { type: "number" };
|
|
501
|
+
if (type.flags & ts4.TypeFlags.Boolean)
|
|
502
|
+
return { type: "boolean" };
|
|
503
|
+
if (type.flags & ts4.TypeFlags.Undefined)
|
|
504
|
+
return { type: "undefined" };
|
|
505
|
+
if (type.flags & ts4.TypeFlags.Null)
|
|
506
|
+
return { type: "null" };
|
|
507
|
+
if (type.flags & ts4.TypeFlags.Void)
|
|
508
|
+
return { type: "void" };
|
|
509
|
+
if (type.flags & ts4.TypeFlags.Any)
|
|
510
|
+
return { type: "any" };
|
|
511
|
+
if (type.flags & ts4.TypeFlags.Unknown)
|
|
512
|
+
return { type: "unknown" };
|
|
513
|
+
if (type.flags & ts4.TypeFlags.Never)
|
|
514
|
+
return { type: "never" };
|
|
515
|
+
if (type.flags & ts4.TypeFlags.BigInt)
|
|
516
|
+
return { type: "bigint" };
|
|
517
|
+
if (type.flags & ts4.TypeFlags.ESSymbol)
|
|
518
|
+
return { type: "symbol" };
|
|
519
|
+
if (type.flags & ts4.TypeFlags.StringLiteral) {
|
|
520
|
+
const literal = type.value;
|
|
521
|
+
return { type: "string", enum: [literal] };
|
|
522
|
+
}
|
|
523
|
+
if (type.flags & ts4.TypeFlags.NumberLiteral) {
|
|
524
|
+
const literal = type.value;
|
|
525
|
+
return { type: "number", enum: [literal] };
|
|
526
|
+
}
|
|
527
|
+
if (type.flags & ts4.TypeFlags.BooleanLiteral) {
|
|
528
|
+
const intrinsicName = type.intrinsicName;
|
|
529
|
+
return { type: "boolean", enum: [intrinsicName === "true"] };
|
|
530
|
+
}
|
|
531
|
+
if (type.isUnion()) {
|
|
532
|
+
const types = type.types;
|
|
533
|
+
const allStringLiterals = types.every((t) => t.flags & ts4.TypeFlags.StringLiteral);
|
|
534
|
+
if (allStringLiterals) {
|
|
535
|
+
const enumValues = types.map((t) => t.value);
|
|
536
|
+
return { type: "string", enum: enumValues };
|
|
537
|
+
}
|
|
538
|
+
const allNumberLiterals = types.every((t) => t.flags & ts4.TypeFlags.NumberLiteral);
|
|
539
|
+
if (allNumberLiterals) {
|
|
540
|
+
const enumValues = types.map((t) => t.value);
|
|
541
|
+
return { type: "number", enum: enumValues };
|
|
542
|
+
}
|
|
543
|
+
if (ctx) {
|
|
544
|
+
return withDepth(ctx, () => ({
|
|
545
|
+
anyOf: types.map((t) => buildSchema(t, checker, ctx))
|
|
546
|
+
}));
|
|
547
|
+
}
|
|
548
|
+
return { anyOf: types.map((t) => buildSchema(t, checker, ctx)) };
|
|
549
|
+
}
|
|
550
|
+
if (type.isIntersection()) {
|
|
551
|
+
if (ctx) {
|
|
552
|
+
return withDepth(ctx, () => ({
|
|
553
|
+
allOf: type.types.map((t) => buildSchema(t, checker, ctx))
|
|
554
|
+
}));
|
|
555
|
+
}
|
|
556
|
+
return { allOf: type.types.map((t) => buildSchema(t, checker, ctx)) };
|
|
557
|
+
}
|
|
558
|
+
if (checker.isArrayType(type)) {
|
|
559
|
+
const typeRef2 = type;
|
|
560
|
+
const elementType = typeRef2.typeArguments?.[0];
|
|
561
|
+
if (elementType) {
|
|
562
|
+
if (ctx) {
|
|
563
|
+
return withDepth(ctx, () => ({
|
|
564
|
+
type: "array",
|
|
565
|
+
items: buildSchema(elementType, checker, ctx)
|
|
566
|
+
}));
|
|
567
|
+
}
|
|
568
|
+
return { type: "array", items: buildSchema(elementType, checker, ctx) };
|
|
569
|
+
}
|
|
570
|
+
return { type: "array" };
|
|
571
|
+
}
|
|
572
|
+
if (checker.isTupleType(type)) {
|
|
573
|
+
const typeRef2 = type;
|
|
574
|
+
const elementTypes = typeRef2.typeArguments ?? [];
|
|
575
|
+
if (ctx) {
|
|
576
|
+
return withDepth(ctx, () => ({
|
|
577
|
+
type: "tuple",
|
|
578
|
+
items: elementTypes.map((t) => buildSchema(t, checker, ctx)),
|
|
579
|
+
minItems: elementTypes.length,
|
|
580
|
+
maxItems: elementTypes.length
|
|
581
|
+
}));
|
|
582
|
+
}
|
|
583
|
+
return {
|
|
584
|
+
type: "tuple",
|
|
585
|
+
items: elementTypes.map((t) => buildSchema(t, checker, ctx)),
|
|
586
|
+
minItems: elementTypes.length,
|
|
587
|
+
maxItems: elementTypes.length
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
const typeRef = type;
|
|
591
|
+
if (typeRef.target && typeRef.typeArguments && typeRef.typeArguments.length > 0) {
|
|
592
|
+
const symbol2 = typeRef.target.getSymbol();
|
|
593
|
+
const name = symbol2?.getName();
|
|
594
|
+
if (name && (isBuiltinGeneric(name) || !isAnonymous(typeRef.target))) {
|
|
595
|
+
if (ctx) {
|
|
596
|
+
return withDepth(ctx, () => ({
|
|
597
|
+
$ref: name,
|
|
598
|
+
typeArguments: typeRef.typeArguments.map((t) => buildSchema(t, checker, ctx))
|
|
599
|
+
}));
|
|
600
|
+
}
|
|
601
|
+
return {
|
|
602
|
+
$ref: name,
|
|
603
|
+
typeArguments: typeRef.typeArguments.map((t) => buildSchema(t, checker, ctx))
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
const symbol = type.getSymbol() || type.aliasSymbol;
|
|
608
|
+
if (symbol && !isAnonymous(type)) {
|
|
609
|
+
const name = symbol.getName();
|
|
610
|
+
if (isPrimitiveName(name)) {
|
|
611
|
+
return { type: name };
|
|
612
|
+
}
|
|
613
|
+
if (BUILTIN_TYPES.has(name)) {
|
|
614
|
+
return { $ref: name };
|
|
615
|
+
}
|
|
616
|
+
if (!name.startsWith("__")) {
|
|
617
|
+
return { $ref: name };
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (type.flags & ts4.TypeFlags.Object) {
|
|
621
|
+
const objectType = type;
|
|
622
|
+
const callSignatures = type.getCallSignatures();
|
|
623
|
+
if (callSignatures.length > 0) {
|
|
624
|
+
return buildFunctionSchema(callSignatures, checker, ctx);
|
|
625
|
+
}
|
|
626
|
+
const properties = type.getProperties();
|
|
627
|
+
if (properties.length > 0 || objectType.objectFlags & ts4.ObjectFlags.Anonymous) {
|
|
628
|
+
return buildObjectSchema(properties, checker, ctx);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return { type: checker.typeToString(type) };
|
|
632
|
+
}
|
|
633
|
+
function buildFunctionSchema(callSignatures, checker, ctx) {
|
|
634
|
+
const buildSignatures = () => {
|
|
635
|
+
const signatures = callSignatures.map((sig) => {
|
|
636
|
+
const params = sig.getParameters().map((param) => {
|
|
637
|
+
const paramType = checker.getTypeOfSymbolAtLocation(param, param.valueDeclaration);
|
|
638
|
+
return {
|
|
639
|
+
name: param.getName(),
|
|
640
|
+
schema: buildSchema(paramType, checker, ctx),
|
|
641
|
+
required: !(param.flags & ts4.SymbolFlags.Optional)
|
|
642
|
+
};
|
|
643
|
+
});
|
|
644
|
+
const returnType = checker.getReturnTypeOfSignature(sig);
|
|
645
|
+
return {
|
|
646
|
+
parameters: params,
|
|
647
|
+
returns: {
|
|
648
|
+
schema: buildSchema(returnType, checker, ctx)
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
});
|
|
652
|
+
return signatures;
|
|
653
|
+
};
|
|
654
|
+
if (ctx) {
|
|
655
|
+
return withDepth(ctx, () => ({ type: "function", signatures: buildSignatures() }));
|
|
656
|
+
}
|
|
657
|
+
return { type: "function", signatures: buildSignatures() };
|
|
658
|
+
}
|
|
659
|
+
function buildObjectSchema(properties, checker, ctx) {
|
|
660
|
+
const buildProps = () => {
|
|
661
|
+
const props = {};
|
|
662
|
+
const required = [];
|
|
663
|
+
for (const prop of properties) {
|
|
664
|
+
const propName = prop.getName();
|
|
665
|
+
if (propName.startsWith("_"))
|
|
666
|
+
continue;
|
|
667
|
+
const propType = checker.getTypeOfSymbol(prop);
|
|
668
|
+
props[propName] = buildSchema(propType, checker, ctx);
|
|
669
|
+
if (!(prop.flags & ts4.SymbolFlags.Optional)) {
|
|
670
|
+
required.push(propName);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
type: "object",
|
|
675
|
+
properties: props,
|
|
676
|
+
...required.length > 0 ? { required } : {}
|
|
677
|
+
};
|
|
678
|
+
};
|
|
679
|
+
if (ctx) {
|
|
680
|
+
return withDepth(ctx, buildProps);
|
|
681
|
+
}
|
|
682
|
+
return buildProps();
|
|
683
|
+
}
|
|
684
|
+
|
|
322
685
|
// src/types/parameters.ts
|
|
686
|
+
import ts5 from "typescript";
|
|
323
687
|
function extractParameters(signature, ctx) {
|
|
324
|
-
const { typeChecker: checker
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
688
|
+
const { typeChecker: checker } = ctx;
|
|
689
|
+
const result = [];
|
|
690
|
+
const signatureDecl = signature.getDeclaration();
|
|
691
|
+
const jsdocTags = signatureDecl ? ts5.getJSDocTags(signatureDecl) : [];
|
|
692
|
+
for (const param of signature.getParameters()) {
|
|
693
|
+
const decl = param.valueDeclaration;
|
|
694
|
+
const type = checker.getTypeOfSymbolAtLocation(param, decl ?? param.valueDeclaration);
|
|
695
|
+
if (decl && ts5.isObjectBindingPattern(decl.name)) {
|
|
696
|
+
const expandedParams = expandBindingPattern(decl, type, jsdocTags, ctx);
|
|
697
|
+
result.push(...expandedParams);
|
|
698
|
+
} else {
|
|
699
|
+
registerReferencedTypes(type, ctx);
|
|
700
|
+
result.push({
|
|
701
|
+
name: param.getName(),
|
|
702
|
+
schema: buildSchema(type, checker, ctx),
|
|
703
|
+
required: !(param.flags & 16777216)
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return result;
|
|
708
|
+
}
|
|
709
|
+
function expandBindingPattern(paramDecl, paramType, jsdocTags, ctx) {
|
|
710
|
+
const { typeChecker: checker } = ctx;
|
|
711
|
+
const result = [];
|
|
712
|
+
const bindingPattern = paramDecl.name;
|
|
713
|
+
const allProperties = getEffectiveProperties(paramType, checker);
|
|
714
|
+
const inferredAlias = inferParamAlias(jsdocTags);
|
|
715
|
+
for (const element of bindingPattern.elements) {
|
|
716
|
+
if (!ts5.isBindingElement(element))
|
|
717
|
+
continue;
|
|
718
|
+
const propertyName = element.propertyName ? ts5.isIdentifier(element.propertyName) ? element.propertyName.text : element.propertyName.getText() : ts5.isIdentifier(element.name) ? element.name.text : element.name.getText();
|
|
719
|
+
const propSymbol = allProperties.get(propertyName);
|
|
720
|
+
if (!propSymbol)
|
|
721
|
+
continue;
|
|
722
|
+
const propType = checker.getTypeOfSymbol(propSymbol);
|
|
723
|
+
registerReferencedTypes(propType, ctx);
|
|
724
|
+
const isOptional = !!(propSymbol.flags & ts5.SymbolFlags.Optional) || element.initializer !== undefined;
|
|
725
|
+
const description = getParamDescription(propertyName, jsdocTags, inferredAlias);
|
|
726
|
+
const param = {
|
|
727
|
+
name: propertyName,
|
|
728
|
+
schema: buildSchema(propType, checker, ctx),
|
|
729
|
+
required: !isOptional
|
|
332
730
|
};
|
|
333
|
-
|
|
731
|
+
if (description) {
|
|
732
|
+
param.description = description;
|
|
733
|
+
}
|
|
734
|
+
if (element.initializer) {
|
|
735
|
+
param.default = extractDefaultValue(element.initializer);
|
|
736
|
+
}
|
|
737
|
+
result.push(param);
|
|
738
|
+
}
|
|
739
|
+
return result;
|
|
740
|
+
}
|
|
741
|
+
function getEffectiveProperties(type, _checker) {
|
|
742
|
+
const properties = new Map;
|
|
743
|
+
if (type.isIntersection()) {
|
|
744
|
+
for (const subType of type.types) {
|
|
745
|
+
for (const prop of subType.getProperties()) {
|
|
746
|
+
properties.set(prop.getName(), prop);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
for (const prop of type.getProperties()) {
|
|
751
|
+
properties.set(prop.getName(), prop);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return properties;
|
|
755
|
+
}
|
|
756
|
+
function inferParamAlias(jsdocTags) {
|
|
757
|
+
const prefixes = [];
|
|
758
|
+
for (const tag of jsdocTags) {
|
|
759
|
+
if (tag.tagName.text !== "param")
|
|
760
|
+
continue;
|
|
761
|
+
const tagText = typeof tag.comment === "string" ? tag.comment : ts5.getTextOfJSDocComment(tag.comment) ?? "";
|
|
762
|
+
const paramTag = tag;
|
|
763
|
+
const paramName = paramTag.name?.getText() ?? "";
|
|
764
|
+
if (paramName.includes(".")) {
|
|
765
|
+
const prefix = paramName.split(".")[0];
|
|
766
|
+
if (prefix && !prefix.startsWith("__")) {
|
|
767
|
+
prefixes.push(prefix);
|
|
768
|
+
}
|
|
769
|
+
} else if (tagText.includes(".")) {
|
|
770
|
+
const match = tagText.match(/^(\w+)\./);
|
|
771
|
+
if (match && !match[1].startsWith("__")) {
|
|
772
|
+
prefixes.push(match[1]);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
if (prefixes.length === 0)
|
|
777
|
+
return;
|
|
778
|
+
const counts = new Map;
|
|
779
|
+
for (const p of prefixes)
|
|
780
|
+
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
781
|
+
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
782
|
+
}
|
|
783
|
+
function extractDefaultValue(initializer) {
|
|
784
|
+
if (ts5.isStringLiteral(initializer)) {
|
|
785
|
+
return initializer.text;
|
|
786
|
+
}
|
|
787
|
+
if (ts5.isNumericLiteral(initializer)) {
|
|
788
|
+
return Number(initializer.text);
|
|
789
|
+
}
|
|
790
|
+
if (initializer.kind === ts5.SyntaxKind.TrueKeyword) {
|
|
791
|
+
return true;
|
|
792
|
+
}
|
|
793
|
+
if (initializer.kind === ts5.SyntaxKind.FalseKeyword) {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
if (initializer.kind === ts5.SyntaxKind.NullKeyword) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
return initializer.getText();
|
|
334
800
|
}
|
|
335
801
|
function registerReferencedTypes(type, ctx) {
|
|
336
802
|
if (ctx.visitedTypes.has(type))
|
|
@@ -374,7 +840,7 @@ function serializeFunctionExport(node, ctx) {
|
|
|
374
840
|
return {
|
|
375
841
|
parameters: params,
|
|
376
842
|
returns: {
|
|
377
|
-
schema:
|
|
843
|
+
schema: buildSchema(returnType, ctx.typeChecker, ctx)
|
|
378
844
|
}
|
|
379
845
|
};
|
|
380
846
|
});
|
|
@@ -421,7 +887,7 @@ function serializeTypeAlias(node, ctx) {
|
|
|
421
887
|
const { description, tags, examples } = getJSDocComment(node);
|
|
422
888
|
const source = getSourceLocation(node, declSourceFile);
|
|
423
889
|
const type = ctx.typeChecker.getTypeAtLocation(node);
|
|
424
|
-
|
|
890
|
+
registerReferencedTypes(type, ctx);
|
|
425
891
|
return {
|
|
426
892
|
id: name,
|
|
427
893
|
name,
|
|
@@ -429,7 +895,7 @@ function serializeTypeAlias(node, ctx) {
|
|
|
429
895
|
description,
|
|
430
896
|
tags,
|
|
431
897
|
source,
|
|
432
|
-
|
|
898
|
+
schema: buildSchema(type, ctx.typeChecker, ctx),
|
|
433
899
|
...examples.length > 0 ? { examples } : {}
|
|
434
900
|
};
|
|
435
901
|
}
|
|
@@ -444,7 +910,6 @@ function serializeVariable(node, statement, ctx) {
|
|
|
444
910
|
const { description, tags, examples } = getJSDocComment(statement);
|
|
445
911
|
const source = getSourceLocation(node, declSourceFile);
|
|
446
912
|
const type = ctx.typeChecker.getTypeAtLocation(node);
|
|
447
|
-
const typeString = ctx.typeChecker.typeToString(type);
|
|
448
913
|
registerReferencedTypes(type, ctx);
|
|
449
914
|
return {
|
|
450
915
|
id: name,
|
|
@@ -453,16 +918,16 @@ function serializeVariable(node, statement, ctx) {
|
|
|
453
918
|
description,
|
|
454
919
|
tags,
|
|
455
920
|
source,
|
|
456
|
-
|
|
921
|
+
schema: buildSchema(type, ctx.typeChecker, ctx),
|
|
457
922
|
...examples.length > 0 ? { examples } : {}
|
|
458
923
|
};
|
|
459
924
|
}
|
|
460
925
|
|
|
461
926
|
// src/builder/spec-builder.ts
|
|
462
|
-
import * as
|
|
463
|
-
import * as
|
|
927
|
+
import * as fs2 from "node:fs";
|
|
928
|
+
import * as path3 from "node:path";
|
|
464
929
|
import { SCHEMA_VERSION } from "@openpkg-ts/spec";
|
|
465
|
-
import
|
|
930
|
+
import ts6 from "typescript";
|
|
466
931
|
|
|
467
932
|
// src/serializers/context.ts
|
|
468
933
|
function createContext(program, sourceFile, options = {}) {
|
|
@@ -470,7 +935,9 @@ function createContext(program, sourceFile, options = {}) {
|
|
|
470
935
|
typeChecker: program.getTypeChecker(),
|
|
471
936
|
program,
|
|
472
937
|
sourceFile,
|
|
473
|
-
maxTypeDepth: options.maxTypeDepth ??
|
|
938
|
+
maxTypeDepth: options.maxTypeDepth ?? 4,
|
|
939
|
+
maxExternalTypeDepth: options.maxExternalTypeDepth ?? 2,
|
|
940
|
+
currentDepth: 0,
|
|
474
941
|
resolveExternalTypes: options.resolveExternalTypes ?? true,
|
|
475
942
|
typeRegistry: new TypeRegistry,
|
|
476
943
|
exportedIds: new Set,
|
|
@@ -480,7 +947,7 @@ function createContext(program, sourceFile, options = {}) {
|
|
|
480
947
|
|
|
481
948
|
// src/builder/spec-builder.ts
|
|
482
949
|
async function extract(options) {
|
|
483
|
-
const { entryFile, baseDir, content, maxTypeDepth, resolveExternalTypes } = options;
|
|
950
|
+
const { entryFile, baseDir, content, maxTypeDepth, maxExternalTypeDepth, resolveExternalTypes } = options;
|
|
484
951
|
const diagnostics = [];
|
|
485
952
|
const exports = [];
|
|
486
953
|
const result = createProgram({ entryFile, baseDir, content });
|
|
@@ -504,7 +971,7 @@ async function extract(options) {
|
|
|
504
971
|
for (const symbol of exportedSymbols) {
|
|
505
972
|
exportedIds.add(symbol.getName());
|
|
506
973
|
}
|
|
507
|
-
const ctx = createContext(program, sourceFile, { maxTypeDepth, resolveExternalTypes });
|
|
974
|
+
const ctx = createContext(program, sourceFile, { maxTypeDepth, maxExternalTypeDepth, resolveExternalTypes });
|
|
508
975
|
ctx.exportedIds = exportedIds;
|
|
509
976
|
for (const symbol of exportedSymbols) {
|
|
510
977
|
try {
|
|
@@ -537,36 +1004,36 @@ async function extract(options) {
|
|
|
537
1004
|
}
|
|
538
1005
|
function resolveExportTarget(symbol, checker) {
|
|
539
1006
|
let targetSymbol = symbol;
|
|
540
|
-
if (symbol.flags &
|
|
1007
|
+
if (symbol.flags & ts6.SymbolFlags.Alias) {
|
|
541
1008
|
const aliasTarget = checker.getAliasedSymbol(symbol);
|
|
542
1009
|
if (aliasTarget && aliasTarget !== symbol) {
|
|
543
1010
|
targetSymbol = aliasTarget;
|
|
544
1011
|
}
|
|
545
1012
|
}
|
|
546
1013
|
const declarations = targetSymbol.declarations ?? [];
|
|
547
|
-
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !==
|
|
1014
|
+
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !== ts6.SyntaxKind.ExportSpecifier) || declarations[0];
|
|
548
1015
|
return { declaration, targetSymbol };
|
|
549
1016
|
}
|
|
550
1017
|
function serializeDeclaration(declaration, exportSymbol, targetSymbol, exportName, ctx) {
|
|
551
1018
|
let result = null;
|
|
552
|
-
if (
|
|
1019
|
+
if (ts6.isFunctionDeclaration(declaration)) {
|
|
553
1020
|
result = serializeFunctionExport(declaration, ctx);
|
|
554
|
-
} else if (
|
|
1021
|
+
} else if (ts6.isClassDeclaration(declaration)) {
|
|
555
1022
|
result = serializeClass(declaration, ctx);
|
|
556
|
-
} else if (
|
|
1023
|
+
} else if (ts6.isInterfaceDeclaration(declaration)) {
|
|
557
1024
|
result = serializeInterface(declaration, ctx);
|
|
558
|
-
} else if (
|
|
1025
|
+
} else if (ts6.isTypeAliasDeclaration(declaration)) {
|
|
559
1026
|
result = serializeTypeAlias(declaration, ctx);
|
|
560
|
-
} else if (
|
|
1027
|
+
} else if (ts6.isEnumDeclaration(declaration)) {
|
|
561
1028
|
result = serializeEnum(declaration, ctx);
|
|
562
|
-
} else if (
|
|
1029
|
+
} else if (ts6.isVariableDeclaration(declaration)) {
|
|
563
1030
|
const varStatement = declaration.parent?.parent;
|
|
564
|
-
if (varStatement &&
|
|
1031
|
+
if (varStatement && ts6.isVariableStatement(varStatement)) {
|
|
565
1032
|
result = serializeVariable(declaration, varStatement, ctx);
|
|
566
1033
|
}
|
|
567
|
-
} else if (
|
|
1034
|
+
} else if (ts6.isNamespaceExport(declaration) || ts6.isModuleDeclaration(declaration)) {
|
|
568
1035
|
result = serializeNamespaceExport(exportSymbol, exportName, ctx);
|
|
569
|
-
} else if (
|
|
1036
|
+
} else if (ts6.isSourceFile(declaration)) {
|
|
570
1037
|
result = serializeNamespaceExport(exportSymbol, exportName, ctx);
|
|
571
1038
|
}
|
|
572
1039
|
if (result) {
|
|
@@ -590,11 +1057,11 @@ function getJSDocFromExportSymbol(symbol) {
|
|
|
590
1057
|
const examples = [];
|
|
591
1058
|
const decl = symbol.declarations?.[0];
|
|
592
1059
|
if (decl) {
|
|
593
|
-
const exportDecl =
|
|
594
|
-
if (exportDecl &&
|
|
595
|
-
const jsDocs =
|
|
1060
|
+
const exportDecl = ts6.isNamespaceExport(decl) ? decl.parent : decl;
|
|
1061
|
+
if (exportDecl && ts6.isExportDeclaration(exportDecl)) {
|
|
1062
|
+
const jsDocs = ts6.getJSDocCommentsAndTags(exportDecl);
|
|
596
1063
|
for (const doc of jsDocs) {
|
|
597
|
-
if (
|
|
1064
|
+
if (ts6.isJSDoc(doc) && doc.comment) {
|
|
598
1065
|
const commentText = typeof doc.comment === "string" ? doc.comment : doc.comment.map((c) => ("text" in c) ? c.text : "").join("");
|
|
599
1066
|
if (commentText) {
|
|
600
1067
|
return {
|
|
@@ -655,7 +1122,7 @@ function withExportName(entry, exportName) {
|
|
|
655
1122
|
function createEmptySpec(entryFile) {
|
|
656
1123
|
return {
|
|
657
1124
|
openpkg: SCHEMA_VERSION,
|
|
658
|
-
meta: { name:
|
|
1125
|
+
meta: { name: path3.basename(entryFile, path3.extname(entryFile)) },
|
|
659
1126
|
exports: [],
|
|
660
1127
|
generation: {
|
|
661
1128
|
generator: "@openpkg-ts/extract",
|
|
@@ -664,18 +1131,18 @@ function createEmptySpec(entryFile) {
|
|
|
664
1131
|
};
|
|
665
1132
|
}
|
|
666
1133
|
async function getPackageMeta(entryFile, baseDir) {
|
|
667
|
-
const searchDir = baseDir ??
|
|
668
|
-
const pkgPath =
|
|
1134
|
+
const searchDir = baseDir ?? path3.dirname(entryFile);
|
|
1135
|
+
const pkgPath = path3.join(searchDir, "package.json");
|
|
669
1136
|
try {
|
|
670
|
-
if (
|
|
671
|
-
const pkg = JSON.parse(
|
|
1137
|
+
if (fs2.existsSync(pkgPath)) {
|
|
1138
|
+
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
672
1139
|
return {
|
|
673
|
-
name: pkg.name ??
|
|
1140
|
+
name: pkg.name ?? path3.basename(searchDir),
|
|
674
1141
|
version: pkg.version,
|
|
675
1142
|
description: pkg.description
|
|
676
1143
|
};
|
|
677
1144
|
}
|
|
678
1145
|
} catch {}
|
|
679
|
-
return { name:
|
|
1146
|
+
return { name: path3.basename(searchDir) };
|
|
680
1147
|
}
|
|
681
|
-
export { TypeRegistry, getJSDocComment, getSourceLocation, createProgram, serializeClass, serializeEnum, extractParameters, registerReferencedTypes, serializeFunctionExport, serializeInterface, serializeTypeAlias, serializeVariable, extract };
|
|
1148
|
+
export { TypeRegistry, getJSDocComment, getSourceLocation, createProgram, serializeClass, serializeEnum, isPrimitiveName, isBuiltinGeneric, isAnonymous, buildSchema, extractParameters, registerReferencedTypes, serializeFunctionExport, serializeInterface, serializeTypeAlias, serializeVariable, extract };
|
package/dist/src/index.d.ts
CHANGED
|
@@ -24,14 +24,12 @@ declare function getJSDocComment(node: ts2.Node): {
|
|
|
24
24
|
};
|
|
25
25
|
declare function getSourceLocation(node: ts2.Node, sourceFile: ts2.SourceFile): SpecSource;
|
|
26
26
|
import { OpenPkg } from "@openpkg-ts/spec";
|
|
27
|
-
import { TypeChecker as TypeChecker_lrgbhchnsl } from "typescript";
|
|
28
|
-
import { Program as Program_jbfzpxflck } from "typescript";
|
|
29
|
-
import { SourceFile as SourceFile_eubaywigwb } from "typescript";
|
|
30
27
|
interface ExtractOptions {
|
|
31
28
|
entryFile: string;
|
|
32
29
|
baseDir?: string;
|
|
33
30
|
content?: string;
|
|
34
31
|
maxTypeDepth?: number;
|
|
32
|
+
maxExternalTypeDepth?: number;
|
|
35
33
|
resolveExternalTypes?: boolean;
|
|
36
34
|
schemaExtraction?: "static" | "hybrid";
|
|
37
35
|
}
|
|
@@ -48,13 +46,6 @@ interface Diagnostic {
|
|
|
48
46
|
column?: number;
|
|
49
47
|
};
|
|
50
48
|
}
|
|
51
|
-
interface SerializerContext {
|
|
52
|
-
typeChecker: TypeChecker_lrgbhchnsl;
|
|
53
|
-
program: Program_jbfzpxflck;
|
|
54
|
-
sourceFile: SourceFile_eubaywigwb;
|
|
55
|
-
maxTypeDepth: number;
|
|
56
|
-
resolveExternalTypes: boolean;
|
|
57
|
-
}
|
|
58
49
|
declare function extract(options: ExtractOptions): Promise<ExtractResult>;
|
|
59
50
|
import ts3 from "typescript";
|
|
60
51
|
interface ProgramOptions {
|
|
@@ -95,48 +86,66 @@ declare function extractStandardSchemas(_program: ts5.Program, _entryFile: strin
|
|
|
95
86
|
import { SpecExport } from "@openpkg-ts/spec";
|
|
96
87
|
import ts7 from "typescript";
|
|
97
88
|
import ts6 from "typescript";
|
|
98
|
-
interface
|
|
89
|
+
interface SerializerContext {
|
|
99
90
|
typeChecker: ts6.TypeChecker;
|
|
100
91
|
program: ts6.Program;
|
|
101
92
|
sourceFile: ts6.SourceFile;
|
|
102
93
|
maxTypeDepth: number;
|
|
94
|
+
maxExternalTypeDepth: number;
|
|
95
|
+
currentDepth: number;
|
|
103
96
|
resolveExternalTypes: boolean;
|
|
104
97
|
typeRegistry: TypeRegistry;
|
|
105
98
|
exportedIds: Set<string>;
|
|
106
99
|
/** Track visited types to prevent infinite recursion */
|
|
107
100
|
visitedTypes: Set<ts6.Type>;
|
|
108
101
|
}
|
|
109
|
-
declare function serializeClass(node: ts7.ClassDeclaration, ctx:
|
|
102
|
+
declare function serializeClass(node: ts7.ClassDeclaration, ctx: SerializerContext): SpecExport | null;
|
|
110
103
|
import { SpecExport as SpecExport2 } from "@openpkg-ts/spec";
|
|
111
104
|
import ts8 from "typescript";
|
|
112
|
-
declare function serializeEnum(node: ts8.EnumDeclaration, ctx:
|
|
105
|
+
declare function serializeEnum(node: ts8.EnumDeclaration, ctx: SerializerContext): SpecExport2 | null;
|
|
113
106
|
import { SpecExport as SpecExport3 } from "@openpkg-ts/spec";
|
|
114
107
|
import ts9 from "typescript";
|
|
115
|
-
declare function serializeFunctionExport(node: ts9.FunctionDeclaration | ts9.ArrowFunction, ctx:
|
|
108
|
+
declare function serializeFunctionExport(node: ts9.FunctionDeclaration | ts9.ArrowFunction, ctx: SerializerContext): SpecExport3 | null;
|
|
116
109
|
import { SpecExport as SpecExport4 } from "@openpkg-ts/spec";
|
|
117
110
|
import ts10 from "typescript";
|
|
118
|
-
declare function serializeInterface(node: ts10.InterfaceDeclaration, ctx:
|
|
111
|
+
declare function serializeInterface(node: ts10.InterfaceDeclaration, ctx: SerializerContext): SpecExport4 | null;
|
|
119
112
|
import { SpecExport as SpecExport5 } from "@openpkg-ts/spec";
|
|
120
113
|
import ts11 from "typescript";
|
|
121
|
-
declare function serializeTypeAlias(node: ts11.TypeAliasDeclaration, ctx:
|
|
114
|
+
declare function serializeTypeAlias(node: ts11.TypeAliasDeclaration, ctx: SerializerContext): SpecExport5 | null;
|
|
122
115
|
import { SpecExport as SpecExport6 } from "@openpkg-ts/spec";
|
|
123
116
|
import ts12 from "typescript";
|
|
124
|
-
declare function serializeVariable(node: ts12.VariableDeclaration, statement: ts12.VariableStatement, ctx:
|
|
117
|
+
declare function serializeVariable(node: ts12.VariableDeclaration, statement: ts12.VariableStatement, ctx: SerializerContext): SpecExport6 | null;
|
|
125
118
|
import ts13 from "typescript";
|
|
126
119
|
declare function formatTypeReference(type: ts13.Type, checker: ts13.TypeChecker): string;
|
|
127
120
|
declare function collectReferencedTypes(type: ts13.Type, checker: ts13.TypeChecker, visited?: Set<string>): string[];
|
|
128
121
|
import { SpecSignatureParameter } from "@openpkg-ts/spec";
|
|
129
122
|
import ts14 from "typescript";
|
|
130
|
-
declare function extractParameters(signature: ts14.Signature, ctx:
|
|
123
|
+
declare function extractParameters(signature: ts14.Signature, ctx: SerializerContext): SpecSignatureParameter[];
|
|
131
124
|
/**
|
|
132
125
|
* Recursively register types referenced by a ts.Type.
|
|
133
126
|
* Uses ctx.visitedTypes to prevent infinite recursion on circular types.
|
|
134
127
|
*/
|
|
135
|
-
declare function registerReferencedTypes(type: ts14.Type, ctx:
|
|
128
|
+
declare function registerReferencedTypes(type: ts14.Type, ctx: SerializerContext): void;
|
|
136
129
|
import { SpecSchema as SpecSchema3 } from "@openpkg-ts/spec";
|
|
137
130
|
import ts15 from "typescript";
|
|
138
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Check if a name is a primitive type
|
|
133
|
+
*/
|
|
134
|
+
declare function isPrimitiveName(name: string): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Check if a name is a built-in generic type
|
|
137
|
+
*/
|
|
138
|
+
declare function isBuiltinGeneric(name: string): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Check if a type is anonymous (no meaningful symbol name)
|
|
141
|
+
*/
|
|
142
|
+
declare function isAnonymous(type: ts15.Type): boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Build a structured SpecSchema from a TypeScript type.
|
|
145
|
+
* Uses $ref for named types and typeArguments for generics.
|
|
146
|
+
*/
|
|
147
|
+
declare function buildSchema(type: ts15.Type, checker: ts15.TypeChecker, ctx?: SerializerContext, _depth?: number): SpecSchema3;
|
|
139
148
|
import ts16 from "typescript";
|
|
140
149
|
declare function isExported(node: ts16.Node): boolean;
|
|
141
150
|
declare function getNodeName(node: ts16.Node): string | undefined;
|
|
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 };
|
|
151
|
+
export { zodAdapter, valibotAdapter, typeboxAdapter, serializeVariable, serializeTypeAlias, serializeInterface, serializeFunctionExport, serializeEnum, serializeClass, registerReferencedTypes, registerAdapter, isSchemaType, isPrimitiveName, isExported, isBuiltinGeneric, isAnonymous, 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
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TypeRegistry,
|
|
3
|
+
buildSchema,
|
|
3
4
|
createProgram,
|
|
4
5
|
extract,
|
|
5
6
|
extractParameters,
|
|
6
7
|
getJSDocComment,
|
|
7
8
|
getSourceLocation,
|
|
9
|
+
isAnonymous,
|
|
10
|
+
isBuiltinGeneric,
|
|
11
|
+
isPrimitiveName,
|
|
8
12
|
registerReferencedTypes,
|
|
9
13
|
serializeClass,
|
|
10
14
|
serializeEnum,
|
|
@@ -12,7 +16,7 @@ import {
|
|
|
12
16
|
serializeInterface,
|
|
13
17
|
serializeTypeAlias,
|
|
14
18
|
serializeVariable
|
|
15
|
-
} from "../shared/chunk-
|
|
19
|
+
} from "../shared/chunk-wddga8ye.js";
|
|
16
20
|
// src/schema/adapters/arktype.ts
|
|
17
21
|
var arktypeAdapter = {
|
|
18
22
|
name: "arktype",
|
|
@@ -70,32 +74,6 @@ function collectReferencedTypes(type, checker, visited = new Set) {
|
|
|
70
74
|
visited.add(name);
|
|
71
75
|
return [name];
|
|
72
76
|
}
|
|
73
|
-
// src/types/schema-builder.ts
|
|
74
|
-
function buildSchema(type, checker, depth = 0) {
|
|
75
|
-
if (depth > 10) {
|
|
76
|
-
return { type: checker.typeToString(type) };
|
|
77
|
-
}
|
|
78
|
-
const typeString = checker.typeToString(type);
|
|
79
|
-
if (type.flags & 4)
|
|
80
|
-
return { type: "string" };
|
|
81
|
-
if (type.flags & 8)
|
|
82
|
-
return { type: "number" };
|
|
83
|
-
if (type.flags & 16)
|
|
84
|
-
return { type: "boolean" };
|
|
85
|
-
if (type.flags & 32768)
|
|
86
|
-
return { type: "undefined" };
|
|
87
|
-
if (type.flags & 65536)
|
|
88
|
-
return { type: "null" };
|
|
89
|
-
if (type.flags & 16384)
|
|
90
|
-
return { type: "void" };
|
|
91
|
-
if (type.flags & 1)
|
|
92
|
-
return { type: "any" };
|
|
93
|
-
if (type.flags & 2)
|
|
94
|
-
return { type: "unknown" };
|
|
95
|
-
if (type.flags & 131072)
|
|
96
|
-
return { type: "never" };
|
|
97
|
-
return { type: typeString };
|
|
98
|
-
}
|
|
99
77
|
// src/types/utils.ts
|
|
100
78
|
function isExported(node) {
|
|
101
79
|
const modifiers = node.modifiers;
|
|
@@ -123,7 +101,10 @@ export {
|
|
|
123
101
|
registerReferencedTypes,
|
|
124
102
|
registerAdapter,
|
|
125
103
|
isSchemaType,
|
|
104
|
+
isPrimitiveName,
|
|
126
105
|
isExported,
|
|
106
|
+
isBuiltinGeneric,
|
|
107
|
+
isAnonymous,
|
|
127
108
|
getSourceLocation,
|
|
128
109
|
getNodeName,
|
|
129
110
|
getJSDocComment,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openpkg-ts/extract",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "TypeScript export extraction to OpenPkg spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openpkg",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"format": "biome format --write src/"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@openpkg-ts/spec": "^0.
|
|
43
|
+
"@openpkg-ts/spec": "^0.12.0",
|
|
44
44
|
"commander": "^12.0.0",
|
|
45
45
|
"typescript": "^5.0.0"
|
|
46
46
|
},
|