@openpkg-ts/sdk 0.54.8 → 0.54.10
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/index.d.ts +39 -5
- package/dist/index.js +710 -450
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1830,6 +1830,18 @@ function declKey(symbol, checker) {
|
|
|
1830
1830
|
return;
|
|
1831
1831
|
return `${decl.getSourceFile().fileName}#${decl.getStart()}`;
|
|
1832
1832
|
}
|
|
1833
|
+
function fileLabel(fileName) {
|
|
1834
|
+
const base = path3.basename(fileName).replace(/(\.d)?\.[cm]?[tj]sx?$/, "");
|
|
1835
|
+
return base === "index" ? path3.basename(path3.dirname(fileName)) || base : base;
|
|
1836
|
+
}
|
|
1837
|
+
function namespaceLabel(decl) {
|
|
1838
|
+
const names = [];
|
|
1839
|
+
for (let node = decl?.parent;node; node = node.parent) {
|
|
1840
|
+
if (ts.isModuleDeclaration(node) && ts.isIdentifier(node.name))
|
|
1841
|
+
names.unshift(node.name.text);
|
|
1842
|
+
}
|
|
1843
|
+
return names.length > 0 ? names.join(".") : undefined;
|
|
1844
|
+
}
|
|
1833
1845
|
function resolveTypeId(symbol, ctx) {
|
|
1834
1846
|
const cached = ctx.typeIds.get(symbol);
|
|
1835
1847
|
if (cached)
|
|
@@ -1853,16 +1865,49 @@ function resolveTypeId(symbol, ctx) {
|
|
|
1853
1865
|
const owner = ctx.idOwner.get(name);
|
|
1854
1866
|
if (!owner || owner === key)
|
|
1855
1867
|
return claim(name);
|
|
1856
|
-
const
|
|
1857
|
-
const
|
|
1858
|
-
const
|
|
1859
|
-
|
|
1860
|
-
|
|
1868
|
+
const decl = symbol.declarations?.[0];
|
|
1869
|
+
const file = decl?.getSourceFile().fileName ?? "";
|
|
1870
|
+
const pkg = packageLabel(file, ctx.workspacePackages);
|
|
1871
|
+
const ownerFile = owner.includes("#") ? owner.slice(0, owner.lastIndexOf("#")) : "";
|
|
1872
|
+
const scopes = pkg === packageLabel(ownerFile, ctx.workspacePackages) ? [] : [pkg];
|
|
1873
|
+
const namespace = namespaceLabel(decl);
|
|
1874
|
+
if (namespace)
|
|
1875
|
+
scopes.push(namespace);
|
|
1876
|
+
if (file)
|
|
1877
|
+
scopes.push(fileLabel(file));
|
|
1878
|
+
for (const scope of scopes) {
|
|
1879
|
+
const scoped = `${scope}.${name}`;
|
|
1880
|
+
const scopedOwner = ctx.idOwner.get(scoped);
|
|
1881
|
+
if (!scopedOwner || scopedOwner === key)
|
|
1882
|
+
return claim(scoped);
|
|
1883
|
+
}
|
|
1861
1884
|
let n = 2;
|
|
1862
1885
|
while (ctx.idOwner.has(`${name}_${n}`))
|
|
1863
1886
|
n++;
|
|
1864
1887
|
return claim(`${name}_${n}`);
|
|
1865
1888
|
}
|
|
1889
|
+
var EXPORTABLE_TYPE_FLAGS = ts.SymbolFlags.Interface | ts.SymbolFlags.TypeAlias | ts.SymbolFlags.Class | ts.SymbolFlags.RegularEnum | ts.SymbolFlags.ConstEnum;
|
|
1890
|
+
function claimExportedTypeIds(exportedSymbols, ctx) {
|
|
1891
|
+
const renamed = [];
|
|
1892
|
+
for (const exported of exportedSymbols) {
|
|
1893
|
+
let target = exported;
|
|
1894
|
+
if (exported.flags & ts.SymbolFlags.Alias) {
|
|
1895
|
+
try {
|
|
1896
|
+
target = ctx.typeChecker.getAliasedSymbol(exported);
|
|
1897
|
+
} catch {
|
|
1898
|
+
continue;
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
if (!(target.flags & EXPORTABLE_TYPE_FLAGS))
|
|
1902
|
+
continue;
|
|
1903
|
+
if (target.getName() === exported.getName())
|
|
1904
|
+
resolveTypeId(target, ctx);
|
|
1905
|
+
else
|
|
1906
|
+
renamed.push(target);
|
|
1907
|
+
}
|
|
1908
|
+
for (const target of renamed)
|
|
1909
|
+
resolveTypeId(target, ctx);
|
|
1910
|
+
}
|
|
1866
1911
|
function typeRefId(type, ctx) {
|
|
1867
1912
|
const symbol = type.aliasSymbol ?? type.getSymbol();
|
|
1868
1913
|
if (!symbol)
|
|
@@ -2218,6 +2263,21 @@ function getExportKind(declaration, type) {
|
|
|
2218
2263
|
return "function";
|
|
2219
2264
|
return "variable";
|
|
2220
2265
|
}
|
|
2266
|
+
function getExtendsExpressions(node) {
|
|
2267
|
+
return node.heritageClauses?.find((clause) => clause.token === ts2.SyntaxKind.ExtendsKeyword)?.types ?? [];
|
|
2268
|
+
}
|
|
2269
|
+
function getExtendsText(node, checker) {
|
|
2270
|
+
const names = getExtendsExpressions(node).map((expr) => {
|
|
2271
|
+
const name = checker.getTypeAtLocation(expr).getSymbol()?.getName();
|
|
2272
|
+
return name && !name.startsWith("__") ? name : expr.expression.getText();
|
|
2273
|
+
});
|
|
2274
|
+
return names.length > 0 ? names.join(" & ") : undefined;
|
|
2275
|
+
}
|
|
2276
|
+
function propertyNameText(name) {
|
|
2277
|
+
if (ts2.isComputedPropertyName(name))
|
|
2278
|
+
return name.getText();
|
|
2279
|
+
return name.text;
|
|
2280
|
+
}
|
|
2221
2281
|
|
|
2222
2282
|
// src/compiler/program.ts
|
|
2223
2283
|
import * as fs4 from "node:fs";
|
|
@@ -2558,8 +2618,39 @@ function createProgram(options) {
|
|
|
2558
2618
|
import ts10 from "typescript";
|
|
2559
2619
|
|
|
2560
2620
|
// src/types/parameters.ts
|
|
2621
|
+
import ts7 from "typescript";
|
|
2622
|
+
|
|
2623
|
+
// src/ast/registry.ts
|
|
2561
2624
|
import ts6 from "typescript";
|
|
2562
2625
|
|
|
2626
|
+
// src/serializers/expansion-budget.ts
|
|
2627
|
+
var MAX_BUDGET_OPS = 1e4;
|
|
2628
|
+
var MAX_SCHEMA_OPS = 200000;
|
|
2629
|
+
function withExpansionBudget(ctx, owner, fn) {
|
|
2630
|
+
const outer = {
|
|
2631
|
+
budget: ctx.budget,
|
|
2632
|
+
currentDepth: ctx.currentDepth,
|
|
2633
|
+
visitedTypes: ctx.visitedTypes,
|
|
2634
|
+
inTupleElement: ctx.inTupleElement,
|
|
2635
|
+
aliasBody: ctx.aliasBody
|
|
2636
|
+
};
|
|
2637
|
+
const budget = { owner, ops: 0, exceeded: false };
|
|
2638
|
+
Object.assign(ctx, {
|
|
2639
|
+
budget,
|
|
2640
|
+
currentDepth: 0,
|
|
2641
|
+
visitedTypes: new Set,
|
|
2642
|
+
inTupleElement: undefined,
|
|
2643
|
+
aliasBody: undefined
|
|
2644
|
+
});
|
|
2645
|
+
try {
|
|
2646
|
+
return fn();
|
|
2647
|
+
} finally {
|
|
2648
|
+
if (budget.exceeded)
|
|
2649
|
+
ctx.exhaustedBudgets.push(owner);
|
|
2650
|
+
Object.assign(ctx, outer);
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2563
2654
|
// src/types/schema-builder.ts
|
|
2564
2655
|
import ts5 from "typescript";
|
|
2565
2656
|
|
|
@@ -2617,6 +2708,10 @@ function resolveFromModuleSpecifier(decl, symbol, checker, program) {
|
|
|
2617
2708
|
if (ts4.isExportSpecifier(decl)) {
|
|
2618
2709
|
const exportDecl = decl.parent?.parent;
|
|
2619
2710
|
if (exportDecl && ts4.isExportDeclaration(exportDecl)) {
|
|
2711
|
+
if (!exportDecl.moduleSpecifier) {
|
|
2712
|
+
const local = checker.getExportSpecifierLocalTargetSymbol(decl);
|
|
2713
|
+
return local && local !== symbol ? local : undefined;
|
|
2714
|
+
}
|
|
2620
2715
|
moduleSpecifier = exportDecl.moduleSpecifier;
|
|
2621
2716
|
importedName = (decl.propertyName ?? decl.name).text;
|
|
2622
2717
|
}
|
|
@@ -2789,7 +2884,8 @@ function resolvedSymbol(symbol, checker) {
|
|
|
2789
2884
|
return;
|
|
2790
2885
|
if (symbol.flags & ts5.SymbolFlags.Alias) {
|
|
2791
2886
|
try {
|
|
2792
|
-
|
|
2887
|
+
const target = checker.getAliasedSymbol(symbol);
|
|
2888
|
+
return checker.isUnknownSymbol(target) ? symbol : target;
|
|
2793
2889
|
} catch {
|
|
2794
2890
|
return symbol;
|
|
2795
2891
|
}
|
|
@@ -2824,10 +2920,11 @@ function buildSchemaFromTypeNode(node, checker, ctx) {
|
|
|
2824
2920
|
if (node.kind === ts5.SyntaxKind.UnknownKeyword) {
|
|
2825
2921
|
return { type: "unknown" };
|
|
2826
2922
|
}
|
|
2827
|
-
|
|
2828
|
-
|
|
2923
|
+
const nameNode = ts5.isTypeReferenceNode(node) ? node.typeName : ts5.isExpressionWithTypeArguments(node) && (ts5.isIdentifier(node.expression) || ts5.isPropertyAccessExpression(node.expression)) ? node.expression : undefined;
|
|
2924
|
+
if (nameNode) {
|
|
2925
|
+
const raw = checker.getSymbolAtLocation(ts5.isQualifiedName(nameNode) ? nameNode.right : ts5.isPropertyAccessExpression(nameNode) ? nameNode.name : nameNode);
|
|
2829
2926
|
const symbol = resolvedSymbol(raw, checker);
|
|
2830
|
-
const name = symbol?.getName() ??
|
|
2927
|
+
const name = symbol?.getName() ?? nameNode.getText();
|
|
2831
2928
|
const args = node.typeArguments?.map((arg) => {
|
|
2832
2929
|
if (typeNodeDefersExpansion(arg, checker, ctx?.program)) {
|
|
2833
2930
|
return buildSchemaFromTypeNode(arg, checker, ctx);
|
|
@@ -2843,6 +2940,9 @@ function buildSchemaFromTypeNode(node, checker, ctx) {
|
|
|
2843
2940
|
}
|
|
2844
2941
|
return { ...schema, typeArguments: args };
|
|
2845
2942
|
};
|
|
2943
|
+
if (symbol && symbol.flags & ts5.SymbolFlags.TypeParameter) {
|
|
2944
|
+
return { "x-ts-type": name };
|
|
2945
|
+
}
|
|
2846
2946
|
if (name && isBuiltinGeneric(name) && (!symbol || isBuiltinSymbol(symbol))) {
|
|
2847
2947
|
return withArgs({ ...builtinSchema(name) });
|
|
2848
2948
|
}
|
|
@@ -2850,20 +2950,42 @@ function buildSchemaFromTypeNode(node, checker, ctx) {
|
|
|
2850
2950
|
let refId = name;
|
|
2851
2951
|
if (symbol && ctx) {
|
|
2852
2952
|
try {
|
|
2853
|
-
refId =
|
|
2953
|
+
refId = typeRefId(checker.getDeclaredTypeOfSymbol(symbol), ctx) || (symbol.flags & ts5.SymbolFlags.TypeAlias ? resolveTypeId(symbol, ctx) : name);
|
|
2854
2954
|
} catch {
|
|
2855
2955
|
refId = name;
|
|
2856
2956
|
}
|
|
2857
2957
|
}
|
|
2958
|
+
if (ctx && symbol && symbol.flags & ts5.SymbolFlags.Alias && !ctx.typeRegistry.has(refId)) {
|
|
2959
|
+
ctx.typeRegistry.add({ id: refId, name, kind: "type", schema: { "x-ts-type": name } });
|
|
2960
|
+
}
|
|
2858
2961
|
return withArgs({ $ref: `#/types/${refId}` });
|
|
2859
2962
|
}
|
|
2860
|
-
return {
|
|
2963
|
+
return {
|
|
2964
|
+
"x-ts-type": scrubImportQualifiers(node.getText().replace(/\s+/g, " "))
|
|
2965
|
+
};
|
|
2861
2966
|
}
|
|
2862
2967
|
const t = checker.getTypeFromTypeNode(node);
|
|
2863
2968
|
if (!(t.flags & ts5.TypeFlags.Any)) {
|
|
2864
2969
|
return buildSchema(t, checker, ctx);
|
|
2865
2970
|
}
|
|
2866
|
-
return { "x-ts-type": scrubImportQualifiers(node.getText()) };
|
|
2971
|
+
return { "x-ts-type": scrubImportQualifiers(node.getText().replace(/\s+/g, " ")) };
|
|
2972
|
+
}
|
|
2973
|
+
function openHeritageArms(declarations, checker, ctx) {
|
|
2974
|
+
return declarations.filter((decl) => ts5.isClassLike(decl) || ts5.isInterfaceDeclaration(decl)).flatMap((decl) => [...getExtendsExpressions(decl)]).flatMap((expr) => {
|
|
2975
|
+
const base = checker.getTypeAtLocation(expr);
|
|
2976
|
+
if (!(base.flags & ts5.TypeFlags.Any))
|
|
2977
|
+
return [];
|
|
2978
|
+
const registered = ctx?.typeRegistry.registerType(base, ctx);
|
|
2979
|
+
const written = checker.getSymbolAtLocation(expr.expression);
|
|
2980
|
+
const unresolvedImport = !!written && !!(written.flags & ts5.SymbolFlags.Alias) && resolvedSymbol(written, checker) === written;
|
|
2981
|
+
if (!registered && unresolvedImport) {
|
|
2982
|
+
return [{ "x-ts-type": scrubImportQualifiers(expr.getText()) }];
|
|
2983
|
+
}
|
|
2984
|
+
return [buildSchemaFromTypeNode(expr, checker, ctx)];
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
function withOpenHeritage(schema, arms) {
|
|
2988
|
+
return arms.length > 0 ? { allOf: [schema, ...arms] } : schema;
|
|
2867
2989
|
}
|
|
2868
2990
|
function stripUndefinedFromType(type, checker) {
|
|
2869
2991
|
if (!type.isUnion())
|
|
@@ -3047,7 +3169,20 @@ function typeNodeDefersExpansion(node, checker, program) {
|
|
|
3047
3169
|
const symbol = resolveAliasSymbol(raw, checker, undefined, program);
|
|
3048
3170
|
return shouldDeferAlias(symbol);
|
|
3049
3171
|
}
|
|
3050
|
-
function
|
|
3172
|
+
function isStaleTypeParameterNode(type, checker, typeNode) {
|
|
3173
|
+
if (type.flags & ts5.TypeFlags.TypeParameter)
|
|
3174
|
+
return false;
|
|
3175
|
+
if (!ts5.isTypeReferenceNode(typeNode) || !ts5.isIdentifier(typeNode.typeName))
|
|
3176
|
+
return false;
|
|
3177
|
+
const symbol = checker.getSymbolAtLocation(typeNode.typeName);
|
|
3178
|
+
return !!symbol && (symbol.flags & ts5.SymbolFlags.TypeParameter) !== 0;
|
|
3179
|
+
}
|
|
3180
|
+
function cheapTypeText(type, checker, typeNode) {
|
|
3181
|
+
if (typeNode && isStaleTypeParameterNode(type, checker, typeNode)) {
|
|
3182
|
+
const argument = type.aliasSymbol?.getName() ?? type.getSymbol()?.getName();
|
|
3183
|
+
if (argument && !argument.startsWith("__") && !isBuiltinGeneric(argument))
|
|
3184
|
+
return argument;
|
|
3185
|
+
}
|
|
3051
3186
|
if (typeNode) {
|
|
3052
3187
|
try {
|
|
3053
3188
|
const text = scrubImportQualifiers(typeNode.getText().replace(/\s+/g, " ").trim());
|
|
@@ -3258,7 +3393,12 @@ function isUtilityOverTypeParameter(type) {
|
|
|
3258
3393
|
const args = type.aliasTypeArguments;
|
|
3259
3394
|
if (!args || args.length === 0)
|
|
3260
3395
|
return false;
|
|
3261
|
-
|
|
3396
|
+
if (!args.some((t) => containsUnresolvedTypeParameter(t)))
|
|
3397
|
+
return false;
|
|
3398
|
+
if (args[0].flags & ts5.TypeFlags.TypeParameter || !(type.flags & ts5.TypeFlags.Object)) {
|
|
3399
|
+
return true;
|
|
3400
|
+
}
|
|
3401
|
+
return type.getProperties().length === 0;
|
|
3262
3402
|
}
|
|
3263
3403
|
function writtenUtilityText(type, checker, typeNode) {
|
|
3264
3404
|
let node = typeNode;
|
|
@@ -3338,10 +3478,18 @@ function buildSchema(type, checker, ctx, typeNode) {
|
|
|
3338
3478
|
const schema = buildSchemaInternal(type, checker, ctx, typeNode);
|
|
3339
3479
|
return ensureNonEmptySchema(schema, type, checker);
|
|
3340
3480
|
}
|
|
3341
|
-
function
|
|
3481
|
+
function buildAliasBodySchema(type, checker, ctx) {
|
|
3482
|
+
ctx.aliasBody = type;
|
|
3483
|
+
try {
|
|
3484
|
+
return buildSchema(type, checker, ctx);
|
|
3485
|
+
} finally {
|
|
3486
|
+
ctx.aliasBody = undefined;
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
function buildMaxDepthSchema(type, checker, typeNode, ctx) {
|
|
3342
3490
|
if (type.flags & ts5.TypeFlags.Any) {
|
|
3343
3491
|
if (typeNode)
|
|
3344
|
-
return buildSchemaFromTypeNode(typeNode, checker);
|
|
3492
|
+
return buildSchemaFromTypeNode(typeNode, checker, ctx);
|
|
3345
3493
|
return { "x-ts-type": checker.typeToString(type) };
|
|
3346
3494
|
}
|
|
3347
3495
|
if (type.flags & ts5.TypeFlags.TypeParameter && !isFluentThisType(type)) {
|
|
@@ -3354,7 +3502,7 @@ function buildMaxDepthSchema(type, checker, typeNode) {
|
|
|
3354
3502
|
return builtinSchema(name);
|
|
3355
3503
|
}
|
|
3356
3504
|
if (!name.startsWith("__") && !isPrimitiveName(name)) {
|
|
3357
|
-
return { $ref: `#/types/${name}` };
|
|
3505
|
+
return { $ref: `#/types/${ctx ? resolveTypeId(symbol, ctx) : name}` };
|
|
3358
3506
|
}
|
|
3359
3507
|
}
|
|
3360
3508
|
if (type.flags & ts5.TypeFlags.String)
|
|
@@ -3377,22 +3525,53 @@ function buildMaxDepthSchema(type, checker, typeNode) {
|
|
|
3377
3525
|
};
|
|
3378
3526
|
}
|
|
3379
3527
|
if (type.isUnion()) {
|
|
3380
|
-
const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker));
|
|
3528
|
+
const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker, undefined, ctx));
|
|
3381
3529
|
return { anyOf: schemas };
|
|
3382
3530
|
}
|
|
3383
3531
|
if (type.isIntersection()) {
|
|
3384
|
-
const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker));
|
|
3532
|
+
const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker, undefined, ctx));
|
|
3385
3533
|
return { allOf: schemas };
|
|
3386
3534
|
}
|
|
3387
3535
|
return { type: checker.typeToString(type) };
|
|
3388
3536
|
}
|
|
3537
|
+
function writtenTypeArguments(typeNode, symbol, checker) {
|
|
3538
|
+
if (!typeNode || !symbol || !ts5.isTypeReferenceNode(typeNode) || !typeNode.typeArguments) {
|
|
3539
|
+
return;
|
|
3540
|
+
}
|
|
3541
|
+
const name = ts5.isQualifiedName(typeNode.typeName) ? typeNode.typeName.right : typeNode.typeName;
|
|
3542
|
+
const written = resolvedSymbol(checker.getSymbolAtLocation(name), checker);
|
|
3543
|
+
return written === symbol ? typeNode.typeArguments : undefined;
|
|
3544
|
+
}
|
|
3545
|
+
function genericAliasRef(type, checker, ctx, typeNode) {
|
|
3546
|
+
const aliasTypeArgs = type.aliasTypeArguments;
|
|
3547
|
+
const name = type.aliasSymbol?.getName();
|
|
3548
|
+
if (!name || !aliasTypeArgs?.length)
|
|
3549
|
+
return;
|
|
3550
|
+
if (name.startsWith("__") || BUILTIN_TYPES.has(name) || isBuiltinGeneric(name))
|
|
3551
|
+
return;
|
|
3552
|
+
const argNodes = writtenTypeArguments(typeNode, type.aliasSymbol, checker);
|
|
3553
|
+
const build = () => {
|
|
3554
|
+
const schema = {
|
|
3555
|
+
$ref: `#/types/${namedRefId(type, name, ctx)}`,
|
|
3556
|
+
typeArguments: aliasTypeArgs.map((t, i) => buildSchema(t, checker, ctx, argNodes?.[i]))
|
|
3557
|
+
};
|
|
3558
|
+
const packageOrigin = getTypeOrigin(type, checker);
|
|
3559
|
+
if (packageOrigin) {
|
|
3560
|
+
setSchemaExtension(schema, "x-ts-package", packageOrigin);
|
|
3561
|
+
}
|
|
3562
|
+
return schema;
|
|
3563
|
+
};
|
|
3564
|
+
return ctx ? withDepth(ctx, build) : build();
|
|
3565
|
+
}
|
|
3389
3566
|
function buildSchemaInternal(type, checker, ctx, typeNode) {
|
|
3390
3567
|
if (isAtMaxDepth(ctx)) {
|
|
3391
|
-
return buildMaxDepthSchema(type, checker, typeNode);
|
|
3568
|
+
return buildMaxDepthSchema(type, checker, typeNode, ctx);
|
|
3392
3569
|
}
|
|
3393
3570
|
if (ctx) {
|
|
3394
3571
|
ctx.schemaOps += 1;
|
|
3395
|
-
|
|
3572
|
+
ctx.budget.ops += 1;
|
|
3573
|
+
if (ctx.budget.ops > ctx.maxBudgetOps || ctx.schemaOps > ctx.maxSchemaOps) {
|
|
3574
|
+
ctx.budget.exceeded = true;
|
|
3396
3575
|
ctx.budgetExceeded = true;
|
|
3397
3576
|
return { "x-ts-type": cheapTypeText(type, checker, typeNode) };
|
|
3398
3577
|
}
|
|
@@ -3486,6 +3665,14 @@ function buildSchemaInternal(type, checker, ctx, typeNode) {
|
|
|
3486
3665
|
return schema;
|
|
3487
3666
|
}
|
|
3488
3667
|
}
|
|
3668
|
+
if (type.isUnion() || type.isIntersection()) {
|
|
3669
|
+
const ownBody = ctx?.aliasBody === type;
|
|
3670
|
+
if (ownBody && ctx)
|
|
3671
|
+
ctx.aliasBody = undefined;
|
|
3672
|
+
const aliasRef = ownBody ? undefined : genericAliasRef(type, checker, ctx, typeNode);
|
|
3673
|
+
if (aliasRef)
|
|
3674
|
+
return aliasRef;
|
|
3675
|
+
}
|
|
3489
3676
|
if (type.flags & ts5.TypeFlags.TemplateLiteral) {
|
|
3490
3677
|
return {
|
|
3491
3678
|
type: "string",
|
|
@@ -3610,11 +3797,12 @@ function buildSchemaInternal(type, checker, ctx, typeNode) {
|
|
|
3610
3797
|
}
|
|
3611
3798
|
if (name && !isAnonymous(typeRef.target)) {
|
|
3612
3799
|
const packageOrigin = getTypeOrigin(typeRef.target, checker);
|
|
3800
|
+
const argNodes = writtenTypeArguments(typeNode, symbol2, checker);
|
|
3613
3801
|
if (ctx) {
|
|
3614
3802
|
return withDepth(ctx, () => {
|
|
3615
3803
|
const schema2 = {
|
|
3616
3804
|
$ref: `#/types/${namedRefId(typeRef.target, name, ctx)}`,
|
|
3617
|
-
typeArguments: typeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
3805
|
+
typeArguments: typeArgs.map((t, i) => buildSchema(t, checker, ctx, argNodes?.[i]))
|
|
3618
3806
|
};
|
|
3619
3807
|
if (packageOrigin) {
|
|
3620
3808
|
setSchemaExtension(schema2, "x-ts-package", packageOrigin);
|
|
@@ -3653,29 +3841,9 @@ function buildSchemaInternal(type, checker, ctx, typeNode) {
|
|
|
3653
3841
|
});
|
|
3654
3842
|
return ctx ? withDepth(ctx, build) : build();
|
|
3655
3843
|
}
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
return withDepth(ctx, () => {
|
|
3660
|
-
const schema2 = {
|
|
3661
|
-
$ref: `#/types/${namedRefId(type, name, ctx)}`,
|
|
3662
|
-
typeArguments: aliasTypeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
3663
|
-
};
|
|
3664
|
-
if (packageOrigin) {
|
|
3665
|
-
setSchemaExtension(schema2, "x-ts-package", packageOrigin);
|
|
3666
|
-
}
|
|
3667
|
-
return schema2;
|
|
3668
|
-
});
|
|
3669
|
-
}
|
|
3670
|
-
const schema = {
|
|
3671
|
-
$ref: `#/types/${name}`,
|
|
3672
|
-
typeArguments: aliasTypeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
3673
|
-
};
|
|
3674
|
-
if (packageOrigin) {
|
|
3675
|
-
setSchemaExtension(schema, "x-ts-package", packageOrigin);
|
|
3676
|
-
}
|
|
3677
|
-
return schema;
|
|
3678
|
-
}
|
|
3844
|
+
const aliasRef = genericAliasRef(type, checker, ctx, typeNode);
|
|
3845
|
+
if (aliasRef)
|
|
3846
|
+
return aliasRef;
|
|
3679
3847
|
}
|
|
3680
3848
|
if (type.flags & ts5.TypeFlags.Object) {
|
|
3681
3849
|
const callSignatures = type.getCallSignatures();
|
|
@@ -3940,219 +4108,7 @@ function findDiscriminatorProperty(unionTypes, checker) {
|
|
|
3940
4108
|
return;
|
|
3941
4109
|
}
|
|
3942
4110
|
|
|
3943
|
-
// src/types/parameters.ts
|
|
3944
|
-
function extractParameters(signature, ctx) {
|
|
3945
|
-
const { typeChecker: checker } = ctx;
|
|
3946
|
-
const result = [];
|
|
3947
|
-
const signatureDecl = signature.getDeclaration();
|
|
3948
|
-
const jsdocTags = signatureDecl ? ts6.getJSDocTags(signatureDecl) : [];
|
|
3949
|
-
for (const param of signature.getParameters()) {
|
|
3950
|
-
const decl = param.valueDeclaration;
|
|
3951
|
-
if (!decl)
|
|
3952
|
-
continue;
|
|
3953
|
-
const defer = typeNodeDefersExpansion(decl.type, checker, ctx.program);
|
|
3954
|
-
const type = defer ? undefined : checker.getTypeOfSymbolAtLocation(param, decl);
|
|
3955
|
-
if (decl && ts6.isObjectBindingPattern(decl.name)) {
|
|
3956
|
-
const expandedParams = expandBindingPattern(decl, type ?? checker.getTypeOfSymbolAtLocation(param, decl), jsdocTags, ctx);
|
|
3957
|
-
result.push(...expandedParams);
|
|
3958
|
-
} else {
|
|
3959
|
-
const isOptional = !!decl?.questionToken || !!decl?.initializer;
|
|
3960
|
-
const isRest = !!decl.dotDotDotToken;
|
|
3961
|
-
const paramName = param.getName();
|
|
3962
|
-
const description = getParamDescription(paramName, jsdocTags);
|
|
3963
|
-
const schema = defer ? buildSchemaFromTypeNode(decl.type, checker, ctx) : buildSchema(isOptional ? stripUndefinedFromType(type, checker) : type, checker, ctx, decl.type);
|
|
3964
|
-
if (!defer && type) {
|
|
3965
|
-
registerReferencedTypes(isOptional ? stripUndefinedFromType(type, checker) : type, ctx);
|
|
3966
|
-
}
|
|
3967
|
-
const paramResult = {
|
|
3968
|
-
name: paramName,
|
|
3969
|
-
schema,
|
|
3970
|
-
required: !isOptional && !isRest,
|
|
3971
|
-
...isRest ? { rest: true } : {}
|
|
3972
|
-
};
|
|
3973
|
-
if (description) {
|
|
3974
|
-
paramResult.description = description;
|
|
3975
|
-
const inlineTags = parseInlineTags(description);
|
|
3976
|
-
if (inlineTags)
|
|
3977
|
-
paramResult.inlineTags = inlineTags;
|
|
3978
|
-
}
|
|
3979
|
-
if (decl.initializer) {
|
|
3980
|
-
applyDefault(paramResult, decl.initializer);
|
|
3981
|
-
}
|
|
3982
|
-
result.push(paramResult);
|
|
3983
|
-
}
|
|
3984
|
-
}
|
|
3985
|
-
return result;
|
|
3986
|
-
}
|
|
3987
|
-
function expandBindingPattern(paramDecl, paramType, jsdocTags, ctx) {
|
|
3988
|
-
const { typeChecker: checker } = ctx;
|
|
3989
|
-
const result = [];
|
|
3990
|
-
const bindingPattern = paramDecl.name;
|
|
3991
|
-
const allProperties = getEffectiveProperties(paramType, checker);
|
|
3992
|
-
const inferredAlias = inferParamAlias(jsdocTags);
|
|
3993
|
-
for (const element of bindingPattern.elements) {
|
|
3994
|
-
if (!ts6.isBindingElement(element))
|
|
3995
|
-
continue;
|
|
3996
|
-
const propertyName = element.propertyName ? ts6.isIdentifier(element.propertyName) ? element.propertyName.text : element.propertyName.getText() : ts6.isIdentifier(element.name) ? element.name.text : element.name.getText();
|
|
3997
|
-
const propSymbol = allProperties.get(propertyName);
|
|
3998
|
-
if (!propSymbol)
|
|
3999
|
-
continue;
|
|
4000
|
-
const isOptional = !!(propSymbol.flags & ts6.SymbolFlags.Optional) || element.initializer !== undefined;
|
|
4001
|
-
const propType = checker.getTypeOfSymbol(propSymbol);
|
|
4002
|
-
const effectiveType = isOptional ? stripUndefinedFromType(propType, checker) : propType;
|
|
4003
|
-
registerReferencedTypes(effectiveType, ctx);
|
|
4004
|
-
const description = getParamDescription(propertyName, jsdocTags, inferredAlias);
|
|
4005
|
-
const param = {
|
|
4006
|
-
name: propertyName,
|
|
4007
|
-
schema: buildSchema(effectiveType, checker, ctx, declaredTypeNode(propSymbol.valueDeclaration)),
|
|
4008
|
-
required: !isOptional
|
|
4009
|
-
};
|
|
4010
|
-
if (description) {
|
|
4011
|
-
param.description = description;
|
|
4012
|
-
const inlineTags = parseInlineTags(description);
|
|
4013
|
-
if (inlineTags)
|
|
4014
|
-
param.inlineTags = inlineTags;
|
|
4015
|
-
}
|
|
4016
|
-
if (element.initializer) {
|
|
4017
|
-
applyDefault(param, element.initializer);
|
|
4018
|
-
}
|
|
4019
|
-
result.push(param);
|
|
4020
|
-
}
|
|
4021
|
-
return result;
|
|
4022
|
-
}
|
|
4023
|
-
function getEffectiveProperties(type, _checker) {
|
|
4024
|
-
const properties = new Map;
|
|
4025
|
-
if (type.isIntersection()) {
|
|
4026
|
-
for (const subType of type.types) {
|
|
4027
|
-
for (const prop of subType.getProperties()) {
|
|
4028
|
-
properties.set(prop.getName(), prop);
|
|
4029
|
-
}
|
|
4030
|
-
}
|
|
4031
|
-
} else {
|
|
4032
|
-
for (const prop of type.getProperties()) {
|
|
4033
|
-
properties.set(prop.getName(), prop);
|
|
4034
|
-
}
|
|
4035
|
-
}
|
|
4036
|
-
return properties;
|
|
4037
|
-
}
|
|
4038
|
-
function inferParamAlias(jsdocTags) {
|
|
4039
|
-
const prefixes = [];
|
|
4040
|
-
for (const tag of jsdocTags) {
|
|
4041
|
-
if (tag.tagName.text !== "param")
|
|
4042
|
-
continue;
|
|
4043
|
-
const tagText = typeof tag.comment === "string" ? tag.comment : ts6.getTextOfJSDocComment(tag.comment) ?? "";
|
|
4044
|
-
const paramTag = tag;
|
|
4045
|
-
const paramName = paramTag.name?.getText() ?? "";
|
|
4046
|
-
if (paramName.includes(".")) {
|
|
4047
|
-
const prefix = paramName.split(".")[0];
|
|
4048
|
-
if (prefix && !prefix.startsWith("__")) {
|
|
4049
|
-
prefixes.push(prefix);
|
|
4050
|
-
}
|
|
4051
|
-
} else if (tagText.includes(".")) {
|
|
4052
|
-
const match = tagText.match(/^(\w+)\./);
|
|
4053
|
-
if (match && !match[1].startsWith("__")) {
|
|
4054
|
-
prefixes.push(match[1]);
|
|
4055
|
-
}
|
|
4056
|
-
}
|
|
4057
|
-
}
|
|
4058
|
-
if (prefixes.length === 0)
|
|
4059
|
-
return;
|
|
4060
|
-
const counts = new Map;
|
|
4061
|
-
for (const p of prefixes)
|
|
4062
|
-
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
4063
|
-
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
4064
|
-
}
|
|
4065
|
-
function extractLiteralDefault(initializer) {
|
|
4066
|
-
if (ts6.isStringLiteral(initializer)) {
|
|
4067
|
-
return { literal: true, value: initializer.text };
|
|
4068
|
-
}
|
|
4069
|
-
if (ts6.isNumericLiteral(initializer)) {
|
|
4070
|
-
return { literal: true, value: Number(initializer.text) };
|
|
4071
|
-
}
|
|
4072
|
-
if (ts6.isPrefixUnaryExpression(initializer) && initializer.operator === ts6.SyntaxKind.MinusToken && ts6.isNumericLiteral(initializer.operand)) {
|
|
4073
|
-
return { literal: true, value: -Number(initializer.operand.text) };
|
|
4074
|
-
}
|
|
4075
|
-
if (initializer.kind === ts6.SyntaxKind.TrueKeyword) {
|
|
4076
|
-
return { literal: true, value: true };
|
|
4077
|
-
}
|
|
4078
|
-
if (initializer.kind === ts6.SyntaxKind.FalseKeyword) {
|
|
4079
|
-
return { literal: true, value: false };
|
|
4080
|
-
}
|
|
4081
|
-
if (initializer.kind === ts6.SyntaxKind.NullKeyword) {
|
|
4082
|
-
return { literal: true, value: null };
|
|
4083
|
-
}
|
|
4084
|
-
return { literal: false, text: initializer.getText() };
|
|
4085
|
-
}
|
|
4086
|
-
function applyDefault(param, initializer) {
|
|
4087
|
-
const extracted = extractLiteralDefault(initializer);
|
|
4088
|
-
if (extracted.literal) {
|
|
4089
|
-
param.default = extracted.value;
|
|
4090
|
-
if (param.schema && typeof param.schema === "object" && !Array.isArray(param.schema)) {
|
|
4091
|
-
param.schema.default = extracted.value;
|
|
4092
|
-
}
|
|
4093
|
-
} else {
|
|
4094
|
-
param.default = extracted.text;
|
|
4095
|
-
if (param.schema && typeof param.schema === "object" && !Array.isArray(param.schema)) {
|
|
4096
|
-
param.schema["x-ts-default"] = extracted.text;
|
|
4097
|
-
}
|
|
4098
|
-
}
|
|
4099
|
-
}
|
|
4100
|
-
function registerReferencedTypes(type, ctx, depth = 0) {
|
|
4101
|
-
if (depth > ctx.maxTypeDepth)
|
|
4102
|
-
return;
|
|
4103
|
-
if (ctx.registeredTypes.has(type))
|
|
4104
|
-
return;
|
|
4105
|
-
const isPrimitive = type.flags & (ts6.TypeFlags.String | ts6.TypeFlags.Number | ts6.TypeFlags.Boolean | ts6.TypeFlags.Void | ts6.TypeFlags.Undefined | ts6.TypeFlags.Null | ts6.TypeFlags.Any | ts6.TypeFlags.Unknown | ts6.TypeFlags.Never | ts6.TypeFlags.StringLiteral | ts6.TypeFlags.NumberLiteral | ts6.TypeFlags.BooleanLiteral);
|
|
4106
|
-
if (!isPrimitive) {
|
|
4107
|
-
ctx.registeredTypes.add(type);
|
|
4108
|
-
}
|
|
4109
|
-
const { typeChecker: checker, typeRegistry } = ctx;
|
|
4110
|
-
typeRegistry.registerType(type, ctx);
|
|
4111
|
-
const typeArgs = type.typeArguments;
|
|
4112
|
-
if (typeArgs) {
|
|
4113
|
-
for (const arg of typeArgs) {
|
|
4114
|
-
registerReferencedTypes(arg, ctx, depth + 1);
|
|
4115
|
-
}
|
|
4116
|
-
}
|
|
4117
|
-
if (type.isUnion()) {
|
|
4118
|
-
for (const t of type.types) {
|
|
4119
|
-
registerReferencedTypes(t, ctx, depth + 1);
|
|
4120
|
-
}
|
|
4121
|
-
}
|
|
4122
|
-
if (type.isIntersection()) {
|
|
4123
|
-
for (const t of type.types) {
|
|
4124
|
-
registerReferencedTypes(t, ctx, depth + 1);
|
|
4125
|
-
}
|
|
4126
|
-
}
|
|
4127
|
-
const typeSymbol = type.aliasSymbol ?? type.getSymbol();
|
|
4128
|
-
if (typeSymbol && ctx.shouldExpandExternal && !typeSymbol.getName().startsWith("__") && !ctx.shouldExpandExternal(typeSymbol)) {
|
|
4129
|
-
return;
|
|
4130
|
-
}
|
|
4131
|
-
if (isForeignPackage(typeSymbol, ctx.workspacePackages)) {
|
|
4132
|
-
return;
|
|
4133
|
-
}
|
|
4134
|
-
if (isDeferredMappedOrConditional(type)) {
|
|
4135
|
-
return;
|
|
4136
|
-
}
|
|
4137
|
-
if (type.flags & ts6.TypeFlags.Object) {
|
|
4138
|
-
const props = type.getProperties();
|
|
4139
|
-
const limit = ctx.maxProperties;
|
|
4140
|
-
if (props.length > limit && ctx.onTruncation) {
|
|
4141
|
-
const typeName = type.getSymbol()?.getName() ?? "anonymous";
|
|
4142
|
-
ctx.onTruncation(typeName, props.length, limit);
|
|
4143
|
-
}
|
|
4144
|
-
for (const prop of props.slice(0, limit)) {
|
|
4145
|
-
const propType = checker.getTypeOfSymbol(prop);
|
|
4146
|
-
registerReferencedTypes(propType, ctx, depth + 1);
|
|
4147
|
-
}
|
|
4148
|
-
}
|
|
4149
|
-
}
|
|
4150
|
-
|
|
4151
|
-
// src/serializers/context.ts
|
|
4152
|
-
import ts8 from "typescript";
|
|
4153
|
-
|
|
4154
4111
|
// src/ast/registry.ts
|
|
4155
|
-
import ts7 from "typescript";
|
|
4156
4112
|
var BUILTINS = new Set([
|
|
4157
4113
|
"Array",
|
|
4158
4114
|
"ArrayBuffer",
|
|
@@ -4229,6 +4185,26 @@ function isExternalType(decl) {
|
|
|
4229
4185
|
return false;
|
|
4230
4186
|
return sourceFile.fileName.includes("node_modules");
|
|
4231
4187
|
}
|
|
4188
|
+
function declaredForm(type, checker, symbol = type.aliasSymbol ?? type.getSymbol()) {
|
|
4189
|
+
if (!symbol)
|
|
4190
|
+
return type;
|
|
4191
|
+
const generic = ts6.SymbolFlags.TypeAlias | ts6.SymbolFlags.Interface | ts6.SymbolFlags.Class;
|
|
4192
|
+
if (!(symbol.flags & generic))
|
|
4193
|
+
return type;
|
|
4194
|
+
const target = type.target;
|
|
4195
|
+
const instantiated = type.aliasTypeArguments?.length || target && target !== type;
|
|
4196
|
+
return instantiated ? declaredTypeOf(symbol, type, checker) : type;
|
|
4197
|
+
}
|
|
4198
|
+
function declaredTypeOf(symbol, fallback, checker) {
|
|
4199
|
+
const declared = checker.getDeclaredTypeOfSymbol(symbol);
|
|
4200
|
+
return declared.flags & ts6.TypeFlags.Any ? fallback : declared;
|
|
4201
|
+
}
|
|
4202
|
+
function registeredForm(type, symbol, checker) {
|
|
4203
|
+
const constructorSide = symbol.flags & ts6.SymbolFlags.Class && type.objectFlags & ts6.ObjectFlags.Anonymous;
|
|
4204
|
+
if (constructorSide)
|
|
4205
|
+
return declaredTypeOf(symbol, type, checker);
|
|
4206
|
+
return declaredForm(type, checker, symbol);
|
|
4207
|
+
}
|
|
4232
4208
|
|
|
4233
4209
|
class TypeRegistry {
|
|
4234
4210
|
types = new Map;
|
|
@@ -4262,13 +4238,13 @@ class TypeRegistry {
|
|
|
4262
4238
|
return;
|
|
4263
4239
|
if (name.startsWith('"'))
|
|
4264
4240
|
return;
|
|
4265
|
-
if (symbol.flags &
|
|
4241
|
+
if (symbol.flags & ts6.SymbolFlags.EnumMember)
|
|
4266
4242
|
return;
|
|
4267
|
-
if (symbol.flags &
|
|
4243
|
+
if (symbol.flags & ts6.SymbolFlags.TypeParameter)
|
|
4268
4244
|
return;
|
|
4269
|
-
if (symbol.flags &
|
|
4245
|
+
if (symbol.flags & ts6.SymbolFlags.Method)
|
|
4270
4246
|
return;
|
|
4271
|
-
if (symbol.flags &
|
|
4247
|
+
if (symbol.flags & ts6.SymbolFlags.Function)
|
|
4272
4248
|
return;
|
|
4273
4249
|
if (isGenericTypeParameter(name))
|
|
4274
4250
|
return;
|
|
@@ -4301,7 +4277,7 @@ class TypeRegistry {
|
|
|
4301
4277
|
return id;
|
|
4302
4278
|
this.processing.add(id);
|
|
4303
4279
|
try {
|
|
4304
|
-
const specType = this.buildSpecType(type, symbol, id, ctx);
|
|
4280
|
+
const specType = withExpansionBudget(ctx, `type ${id}`, () => this.buildSpecType(registeredForm(type, symbol, ctx.typeChecker), symbol, id, ctx));
|
|
4305
4281
|
if (specType) {
|
|
4306
4282
|
this.add(specType);
|
|
4307
4283
|
return specType.id;
|
|
@@ -4318,17 +4294,17 @@ class TypeRegistry {
|
|
|
4318
4294
|
let kind = "type";
|
|
4319
4295
|
const external = decl ? isExternalType(decl) : false;
|
|
4320
4296
|
if (decl) {
|
|
4321
|
-
if (
|
|
4297
|
+
if (ts6.isClassDeclaration(decl))
|
|
4322
4298
|
kind = "class";
|
|
4323
|
-
else if (
|
|
4299
|
+
else if (ts6.isInterfaceDeclaration(decl))
|
|
4324
4300
|
kind = "interface";
|
|
4325
|
-
else if (
|
|
4301
|
+
else if (ts6.isEnumDeclaration(decl))
|
|
4326
4302
|
kind = "enum";
|
|
4327
4303
|
}
|
|
4328
4304
|
if (external) {
|
|
4329
4305
|
kind = "external";
|
|
4330
4306
|
}
|
|
4331
|
-
let schema =
|
|
4307
|
+
let schema = buildAliasBodySchema(type, checker, ctx);
|
|
4332
4308
|
if (this.isSelfRef(schema, id)) {
|
|
4333
4309
|
schema = this.resolveSelRefSchema(type, checker, ctx);
|
|
4334
4310
|
}
|
|
@@ -4338,8 +4314,8 @@ class TypeRegistry {
|
|
|
4338
4314
|
schema = enumSchema;
|
|
4339
4315
|
}
|
|
4340
4316
|
}
|
|
4341
|
-
if (kind === "type" && decl &&
|
|
4342
|
-
const text = renderTypeText(type, checker, decl,
|
|
4317
|
+
if (kind === "type" && decl && ts6.isTypeAliasDeclaration(decl) && shouldEmitAliasTypeText(decl.type) && typeof schema === "object" && schema !== null && !("x-ts-type" in schema)) {
|
|
4318
|
+
const text = renderTypeText(type, checker, decl, ts6.TypeFormatFlags.InTypeAlias);
|
|
4343
4319
|
if (!PRIMITIVES.has(text) && text !== name) {
|
|
4344
4320
|
schema["x-ts-type"] = text;
|
|
4345
4321
|
const declared = writtenTypeText(declaredTypeNode(decl));
|
|
@@ -4348,8 +4324,11 @@ class TypeRegistry {
|
|
|
4348
4324
|
}
|
|
4349
4325
|
}
|
|
4350
4326
|
}
|
|
4327
|
+
const heritage = (symbol.declarations ?? []).filter((d) => ts6.isClassDeclaration(d) || ts6.isInterfaceDeclaration(d));
|
|
4328
|
+
const extendsText = heritage.map((d) => getExtendsText(d, checker)).find(Boolean);
|
|
4329
|
+
schema = withOpenHeritage(schema, openHeritageArms(heritage, checker, ctx));
|
|
4351
4330
|
let typeParameters;
|
|
4352
|
-
if (decl && (
|
|
4331
|
+
if (decl && (ts6.isTypeAliasDeclaration(decl) || ts6.isInterfaceDeclaration(decl) || ts6.isClassDeclaration(decl))) {
|
|
4353
4332
|
typeParameters = extractTypeParameters(decl, checker);
|
|
4354
4333
|
}
|
|
4355
4334
|
return {
|
|
@@ -4358,6 +4337,7 @@ class TypeRegistry {
|
|
|
4358
4337
|
kind,
|
|
4359
4338
|
...typeParameters && typeParameters.length > 0 ? { typeParameters } : {},
|
|
4360
4339
|
schema,
|
|
4340
|
+
...extendsText ? { extends: extendsText } : {},
|
|
4361
4341
|
...external ? { external: true } : {}
|
|
4362
4342
|
};
|
|
4363
4343
|
}
|
|
@@ -4370,14 +4350,14 @@ class TypeRegistry {
|
|
|
4370
4350
|
resolveSelRefSchema(type, checker, ctx) {
|
|
4371
4351
|
if (type.isUnion()) {
|
|
4372
4352
|
const types = type.types;
|
|
4373
|
-
const allStringLiterals = types.every((t) => t.flags &
|
|
4353
|
+
const allStringLiterals = types.every((t) => t.flags & ts6.TypeFlags.StringLiteral);
|
|
4374
4354
|
if (allStringLiterals) {
|
|
4375
4355
|
return {
|
|
4376
4356
|
type: "string",
|
|
4377
4357
|
enum: types.map((t) => t.value)
|
|
4378
4358
|
};
|
|
4379
4359
|
}
|
|
4380
|
-
const allNumberLiterals = types.every((t) => t.flags &
|
|
4360
|
+
const allNumberLiterals = types.every((t) => t.flags & ts6.TypeFlags.NumberLiteral);
|
|
4381
4361
|
if (allNumberLiterals) {
|
|
4382
4362
|
return {
|
|
4383
4363
|
type: "number",
|
|
@@ -4395,126 +4375,343 @@ class TypeRegistry {
|
|
|
4395
4375
|
return enumSchema;
|
|
4396
4376
|
}
|
|
4397
4377
|
}
|
|
4398
|
-
const callSignatures = type.getCallSignatures();
|
|
4399
|
-
if (callSignatures.length > 0 && type.getProperties().length === 0) {
|
|
4400
|
-
return buildFunctionSchema(callSignatures, checker, ctx);
|
|
4378
|
+
const callSignatures = type.getCallSignatures();
|
|
4379
|
+
if (callSignatures.length > 0 && type.getProperties().length === 0) {
|
|
4380
|
+
return buildFunctionSchema(callSignatures, checker, ctx);
|
|
4381
|
+
}
|
|
4382
|
+
if (checker.isTupleType(type)) {
|
|
4383
|
+
const elementTypes = checker.getTypeArguments(type) ?? [];
|
|
4384
|
+
return {
|
|
4385
|
+
type: "array",
|
|
4386
|
+
prefixItems: elementTypes.map((t) => buildSchema(t, checker, ctx)),
|
|
4387
|
+
minItems: elementTypes.length,
|
|
4388
|
+
maxItems: elementTypes.length
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
4391
|
+
if (checker.isArrayType(type)) {
|
|
4392
|
+
const elementType = checker.getTypeArguments(type)?.[0];
|
|
4393
|
+
return elementType ? { type: "array", items: buildSchema(elementType, checker, ctx) } : { type: "array" };
|
|
4394
|
+
}
|
|
4395
|
+
if (type.flags & ts6.TypeFlags.Conditional) {
|
|
4396
|
+
return { "x-ts-type": renderTypeText(type, checker) };
|
|
4397
|
+
}
|
|
4398
|
+
const constraint = checker.getBaseConstraintOfType(type);
|
|
4399
|
+
const primitive = constraint && constraint.flags & ts6.TypeFlags.StringLike ? "string" : constraint && constraint.flags & ts6.TypeFlags.NumberLike ? "number" : constraint && constraint.flags & ts6.TypeFlags.BooleanLike ? "boolean" : undefined;
|
|
4400
|
+
if (primitive) {
|
|
4401
|
+
return { type: primitive, "x-ts-type": renderTypeText(type, checker) };
|
|
4402
|
+
}
|
|
4403
|
+
return this.buildObjectSchemaFromProperties(type, checker, ctx);
|
|
4404
|
+
}
|
|
4405
|
+
buildEnumSchema(symbol, checker) {
|
|
4406
|
+
const decl = symbol.declarations?.find(ts6.isEnumDeclaration);
|
|
4407
|
+
if (!decl)
|
|
4408
|
+
return;
|
|
4409
|
+
const members = [];
|
|
4410
|
+
for (const member of decl.members) {
|
|
4411
|
+
const memberSymbol = checker.getSymbolAtLocation(member.name);
|
|
4412
|
+
if (memberSymbol) {
|
|
4413
|
+
const constantValue = checker.getConstantValue(member);
|
|
4414
|
+
if (constantValue !== undefined) {
|
|
4415
|
+
members.push({
|
|
4416
|
+
name: memberSymbol.getName(),
|
|
4417
|
+
value: constantValue
|
|
4418
|
+
});
|
|
4419
|
+
}
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4422
|
+
if (members.length === 0)
|
|
4423
|
+
return;
|
|
4424
|
+
return {
|
|
4425
|
+
type: typeof members[0].value === "string" ? "string" : "number",
|
|
4426
|
+
enum: members.map((m) => m.value),
|
|
4427
|
+
"x-enum-members": members
|
|
4428
|
+
};
|
|
4429
|
+
}
|
|
4430
|
+
buildObjectSchemaFromProperties(type, checker, ctx) {
|
|
4431
|
+
const properties = type.getProperties();
|
|
4432
|
+
const indexInfos = checker.getIndexInfosOfType(type);
|
|
4433
|
+
const stringIndex = indexInfos.find((i) => i.keyType.flags & ts6.TypeFlags.String);
|
|
4434
|
+
const numberIndex = indexInfos.find((i) => i.keyType.flags & ts6.TypeFlags.Number);
|
|
4435
|
+
if (properties.length === 0 && !stringIndex && !numberIndex) {
|
|
4436
|
+
return { type: checker.typeToString(type) };
|
|
4437
|
+
}
|
|
4438
|
+
const props = {};
|
|
4439
|
+
const required = [];
|
|
4440
|
+
const limit = ctx.maxProperties;
|
|
4441
|
+
const isArrayLike = checker.isArrayType(type) || checker.isTupleType(type) || type.symbol?.getName() === "Array" && isLibFile(type.symbol?.getDeclarations()?.[0]?.getSourceFile()?.fileName ?? "");
|
|
4442
|
+
const isStringLike = type.flags & ts6.TypeFlags.StringLike;
|
|
4443
|
+
const isNumberLike = type.flags & ts6.TypeFlags.NumberLike;
|
|
4444
|
+
const included = properties.filter((prop) => {
|
|
4445
|
+
const propName = prop.getName();
|
|
4446
|
+
if (propName.startsWith("__@"))
|
|
4447
|
+
return false;
|
|
4448
|
+
if (isArrayLike && ARRAY_PROTOTYPE_METHODS.has(propName))
|
|
4449
|
+
return false;
|
|
4450
|
+
if (isStringLike && STRING_PROTOTYPE_METHODS.has(propName))
|
|
4451
|
+
return false;
|
|
4452
|
+
if (isNumberLike && NUMBER_PROTOTYPE_METHODS.has(propName))
|
|
4453
|
+
return false;
|
|
4454
|
+
return true;
|
|
4455
|
+
});
|
|
4456
|
+
if (included.length > limit && ctx.onTruncation) {
|
|
4457
|
+
const typeName = type.getSymbol()?.getName() ?? "anonymous";
|
|
4458
|
+
ctx.onTruncation(typeName, included.length, limit);
|
|
4459
|
+
}
|
|
4460
|
+
for (const prop of included.slice(0, limit)) {
|
|
4461
|
+
const propName = prop.getName();
|
|
4462
|
+
const rawPropType = checker.getTypeOfSymbol(prop);
|
|
4463
|
+
const propType = prop.flags & ts6.SymbolFlags.Optional ? stripUndefinedFromType(rawPropType, checker) : rawPropType;
|
|
4464
|
+
this.registerType(propType, ctx);
|
|
4465
|
+
let propSchema = buildSchema(propType, checker, ctx, declaredTypeNode(prop.valueDeclaration ?? prop.getDeclarations()?.[0]));
|
|
4466
|
+
const docComment = prop.getDocumentationComment(checker);
|
|
4467
|
+
if (docComment.length > 0) {
|
|
4468
|
+
const description = docComment.map((c) => c.text).join(`
|
|
4469
|
+
`);
|
|
4470
|
+
if (description.trim()) {
|
|
4471
|
+
propSchema = withDescription(propSchema, description);
|
|
4472
|
+
}
|
|
4473
|
+
}
|
|
4474
|
+
const { deprecated, reason } = isSymbolDeprecated(prop);
|
|
4475
|
+
if (deprecated) {
|
|
4476
|
+
propSchema = withDeprecated(propSchema, reason);
|
|
4477
|
+
}
|
|
4478
|
+
propSchema = decoratePropertySchema(propSchema, prop, propType, checker);
|
|
4479
|
+
props[propName] = propSchema;
|
|
4480
|
+
if (!(prop.flags & ts6.SymbolFlags.Optional)) {
|
|
4481
|
+
required.push(propName);
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
return {
|
|
4485
|
+
type: "object",
|
|
4486
|
+
properties: props,
|
|
4487
|
+
...required.length > 0 ? { required } : {},
|
|
4488
|
+
...stringIndex ? { additionalProperties: buildSchema(stringIndex.type, checker, ctx) } : {},
|
|
4489
|
+
...numberIndex ? {
|
|
4490
|
+
patternProperties: { "^\\d+$": buildSchema(numberIndex.type, checker, ctx) },
|
|
4491
|
+
"x-ts-index-key": "number"
|
|
4492
|
+
} : {}
|
|
4493
|
+
};
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
|
|
4497
|
+
// src/types/parameters.ts
|
|
4498
|
+
function extractParameters(signature, ctx) {
|
|
4499
|
+
const { typeChecker: checker } = ctx;
|
|
4500
|
+
const result = [];
|
|
4501
|
+
const signatureDecl = signature.getDeclaration();
|
|
4502
|
+
const jsdocTags = signatureDecl ? ts7.getJSDocTags(signatureDecl) : [];
|
|
4503
|
+
for (const param of signature.getParameters()) {
|
|
4504
|
+
const decl = param.valueDeclaration;
|
|
4505
|
+
if (!decl)
|
|
4506
|
+
continue;
|
|
4507
|
+
const defer = typeNodeDefersExpansion(decl.type, checker, ctx.program);
|
|
4508
|
+
const type = defer ? undefined : checker.getTypeOfSymbolAtLocation(param, decl);
|
|
4509
|
+
if (decl && ts7.isObjectBindingPattern(decl.name)) {
|
|
4510
|
+
const expandedParams = expandBindingPattern(decl, type ?? checker.getTypeOfSymbolAtLocation(param, decl), jsdocTags, ctx);
|
|
4511
|
+
result.push(...expandedParams);
|
|
4512
|
+
} else {
|
|
4513
|
+
const isOptional = !!decl?.questionToken || !!decl?.initializer;
|
|
4514
|
+
const isRest = !!decl.dotDotDotToken;
|
|
4515
|
+
const paramName = param.getName();
|
|
4516
|
+
const description = getParamDescription(paramName, jsdocTags);
|
|
4517
|
+
const schema = defer ? buildSchemaFromTypeNode(decl.type, checker, ctx) : buildSchema(isOptional ? stripUndefinedFromType(type, checker) : type, checker, ctx, decl.type);
|
|
4518
|
+
if (!defer && type) {
|
|
4519
|
+
registerReferencedTypes(isOptional ? stripUndefinedFromType(type, checker) : type, ctx);
|
|
4520
|
+
}
|
|
4521
|
+
const paramResult = {
|
|
4522
|
+
name: paramName,
|
|
4523
|
+
schema,
|
|
4524
|
+
required: !isOptional && !isRest,
|
|
4525
|
+
...isRest ? { rest: true } : {}
|
|
4526
|
+
};
|
|
4527
|
+
if (description) {
|
|
4528
|
+
paramResult.description = description;
|
|
4529
|
+
const inlineTags = parseInlineTags(description);
|
|
4530
|
+
if (inlineTags)
|
|
4531
|
+
paramResult.inlineTags = inlineTags;
|
|
4532
|
+
}
|
|
4533
|
+
if (decl.initializer) {
|
|
4534
|
+
applyDefault(paramResult, decl.initializer);
|
|
4535
|
+
}
|
|
4536
|
+
result.push(paramResult);
|
|
4537
|
+
}
|
|
4538
|
+
}
|
|
4539
|
+
return result;
|
|
4540
|
+
}
|
|
4541
|
+
function expandBindingPattern(paramDecl, paramType, jsdocTags, ctx) {
|
|
4542
|
+
const { typeChecker: checker } = ctx;
|
|
4543
|
+
const result = [];
|
|
4544
|
+
const bindingPattern = paramDecl.name;
|
|
4545
|
+
const allProperties = getEffectiveProperties(paramType, checker);
|
|
4546
|
+
const inferredAlias = inferParamAlias(jsdocTags);
|
|
4547
|
+
for (const element of bindingPattern.elements) {
|
|
4548
|
+
if (!ts7.isBindingElement(element))
|
|
4549
|
+
continue;
|
|
4550
|
+
const propertyName = element.propertyName ? ts7.isIdentifier(element.propertyName) ? element.propertyName.text : element.propertyName.getText() : ts7.isIdentifier(element.name) ? element.name.text : element.name.getText();
|
|
4551
|
+
const propSymbol = allProperties.get(propertyName);
|
|
4552
|
+
if (!propSymbol)
|
|
4553
|
+
continue;
|
|
4554
|
+
const isOptional = !!(propSymbol.flags & ts7.SymbolFlags.Optional) || element.initializer !== undefined;
|
|
4555
|
+
const propType = checker.getTypeOfSymbol(propSymbol);
|
|
4556
|
+
const effectiveType = isOptional ? stripUndefinedFromType(propType, checker) : propType;
|
|
4557
|
+
registerReferencedTypes(effectiveType, ctx);
|
|
4558
|
+
const description = getParamDescription(propertyName, jsdocTags, inferredAlias);
|
|
4559
|
+
const param = {
|
|
4560
|
+
name: propertyName,
|
|
4561
|
+
schema: buildSchema(effectiveType, checker, ctx, declaredTypeNode(propSymbol.valueDeclaration)),
|
|
4562
|
+
required: !isOptional
|
|
4563
|
+
};
|
|
4564
|
+
if (description) {
|
|
4565
|
+
param.description = description;
|
|
4566
|
+
const inlineTags = parseInlineTags(description);
|
|
4567
|
+
if (inlineTags)
|
|
4568
|
+
param.inlineTags = inlineTags;
|
|
4569
|
+
}
|
|
4570
|
+
if (element.initializer) {
|
|
4571
|
+
applyDefault(param, element.initializer);
|
|
4572
|
+
}
|
|
4573
|
+
result.push(param);
|
|
4574
|
+
}
|
|
4575
|
+
return result;
|
|
4576
|
+
}
|
|
4577
|
+
function getEffectiveProperties(type, _checker) {
|
|
4578
|
+
const properties = new Map;
|
|
4579
|
+
if (type.isIntersection()) {
|
|
4580
|
+
for (const subType of type.types) {
|
|
4581
|
+
for (const prop of subType.getProperties()) {
|
|
4582
|
+
properties.set(prop.getName(), prop);
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4585
|
+
} else {
|
|
4586
|
+
for (const prop of type.getProperties()) {
|
|
4587
|
+
properties.set(prop.getName(), prop);
|
|
4401
4588
|
}
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4589
|
+
}
|
|
4590
|
+
return properties;
|
|
4591
|
+
}
|
|
4592
|
+
function inferParamAlias(jsdocTags) {
|
|
4593
|
+
const prefixes = [];
|
|
4594
|
+
for (const tag of jsdocTags) {
|
|
4595
|
+
if (tag.tagName.text !== "param")
|
|
4596
|
+
continue;
|
|
4597
|
+
const tagText = typeof tag.comment === "string" ? tag.comment : ts7.getTextOfJSDocComment(tag.comment) ?? "";
|
|
4598
|
+
const paramTag = tag;
|
|
4599
|
+
const paramName = paramTag.name?.getText() ?? "";
|
|
4600
|
+
if (paramName.includes(".")) {
|
|
4601
|
+
const prefix = paramName.split(".")[0];
|
|
4602
|
+
if (prefix && !prefix.startsWith("__")) {
|
|
4603
|
+
prefixes.push(prefix);
|
|
4604
|
+
}
|
|
4605
|
+
} else if (tagText.includes(".")) {
|
|
4606
|
+
const match = tagText.match(/^(\w+)\./);
|
|
4607
|
+
if (match && !match[1].startsWith("__")) {
|
|
4608
|
+
prefixes.push(match[1]);
|
|
4609
|
+
}
|
|
4410
4610
|
}
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4611
|
+
}
|
|
4612
|
+
if (prefixes.length === 0)
|
|
4613
|
+
return;
|
|
4614
|
+
const counts = new Map;
|
|
4615
|
+
for (const p of prefixes)
|
|
4616
|
+
counts.set(p, (counts.get(p) ?? 0) + 1);
|
|
4617
|
+
return Array.from(counts.entries()).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
4618
|
+
}
|
|
4619
|
+
function extractLiteralDefault(initializer) {
|
|
4620
|
+
if (ts7.isStringLiteral(initializer)) {
|
|
4621
|
+
return { literal: true, value: initializer.text };
|
|
4622
|
+
}
|
|
4623
|
+
if (ts7.isNumericLiteral(initializer)) {
|
|
4624
|
+
return { literal: true, value: Number(initializer.text) };
|
|
4625
|
+
}
|
|
4626
|
+
if (ts7.isPrefixUnaryExpression(initializer) && initializer.operator === ts7.SyntaxKind.MinusToken && ts7.isNumericLiteral(initializer.operand)) {
|
|
4627
|
+
return { literal: true, value: -Number(initializer.operand.text) };
|
|
4628
|
+
}
|
|
4629
|
+
if (initializer.kind === ts7.SyntaxKind.TrueKeyword) {
|
|
4630
|
+
return { literal: true, value: true };
|
|
4631
|
+
}
|
|
4632
|
+
if (initializer.kind === ts7.SyntaxKind.FalseKeyword) {
|
|
4633
|
+
return { literal: true, value: false };
|
|
4634
|
+
}
|
|
4635
|
+
if (initializer.kind === ts7.SyntaxKind.NullKeyword) {
|
|
4636
|
+
return { literal: true, value: null };
|
|
4637
|
+
}
|
|
4638
|
+
return { literal: false, text: initializer.getText() };
|
|
4639
|
+
}
|
|
4640
|
+
function applyDefault(param, initializer) {
|
|
4641
|
+
const extracted = extractLiteralDefault(initializer);
|
|
4642
|
+
if (extracted.literal) {
|
|
4643
|
+
param.default = extracted.value;
|
|
4644
|
+
if (param.schema && typeof param.schema === "object" && !Array.isArray(param.schema)) {
|
|
4645
|
+
param.schema.default = extracted.value;
|
|
4414
4646
|
}
|
|
4415
|
-
|
|
4416
|
-
|
|
4647
|
+
} else {
|
|
4648
|
+
param.default = extracted.text;
|
|
4649
|
+
if (param.schema && typeof param.schema === "object" && !Array.isArray(param.schema)) {
|
|
4650
|
+
param.schema["x-ts-default"] = extracted.text;
|
|
4417
4651
|
}
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4654
|
+
function registerReferencedTypes(type, ctx, depth = 0) {
|
|
4655
|
+
if (depth > ctx.maxTypeDepth)
|
|
4656
|
+
return;
|
|
4657
|
+
if (ctx.registeredTypes.has(type))
|
|
4658
|
+
return;
|
|
4659
|
+
const isPrimitive = type.flags & (ts7.TypeFlags.String | ts7.TypeFlags.Number | ts7.TypeFlags.Boolean | ts7.TypeFlags.Void | ts7.TypeFlags.Undefined | ts7.TypeFlags.Null | ts7.TypeFlags.Any | ts7.TypeFlags.Unknown | ts7.TypeFlags.Never | ts7.TypeFlags.StringLiteral | ts7.TypeFlags.NumberLiteral | ts7.TypeFlags.BooleanLiteral);
|
|
4660
|
+
if (!isPrimitive) {
|
|
4661
|
+
ctx.registeredTypes.add(type);
|
|
4662
|
+
}
|
|
4663
|
+
const { typeChecker: checker, typeRegistry } = ctx;
|
|
4664
|
+
typeRegistry.registerType(type, ctx);
|
|
4665
|
+
const typeArgs = type.typeArguments;
|
|
4666
|
+
if (typeArgs) {
|
|
4667
|
+
for (const arg of typeArgs) {
|
|
4668
|
+
registerReferencedTypes(arg, ctx, depth + 1);
|
|
4422
4669
|
}
|
|
4423
|
-
return this.buildObjectSchemaFromProperties(type, checker, ctx);
|
|
4424
4670
|
}
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
name: memberSymbol.getName(),
|
|
4437
|
-
value: constantValue
|
|
4438
|
-
});
|
|
4439
|
-
}
|
|
4440
|
-
}
|
|
4671
|
+
for (const arg of type.aliasTypeArguments ?? []) {
|
|
4672
|
+
registerReferencedTypes(arg, ctx, depth + 1);
|
|
4673
|
+
}
|
|
4674
|
+
const declared = declaredForm(type, checker);
|
|
4675
|
+
if (declared !== type) {
|
|
4676
|
+
registerReferencedTypes(declared, ctx, depth);
|
|
4677
|
+
return;
|
|
4678
|
+
}
|
|
4679
|
+
if (type.isUnion()) {
|
|
4680
|
+
for (const t of type.types) {
|
|
4681
|
+
registerReferencedTypes(t, ctx, depth + 1);
|
|
4441
4682
|
}
|
|
4442
|
-
if (members.length === 0)
|
|
4443
|
-
return;
|
|
4444
|
-
return {
|
|
4445
|
-
type: typeof members[0].value === "string" ? "string" : "number",
|
|
4446
|
-
enum: members.map((m) => m.value),
|
|
4447
|
-
"x-enum-members": members
|
|
4448
|
-
};
|
|
4449
4683
|
}
|
|
4450
|
-
|
|
4451
|
-
const
|
|
4452
|
-
|
|
4453
|
-
const stringIndex = indexInfos.find((i) => i.keyType.flags & ts7.TypeFlags.String);
|
|
4454
|
-
const numberIndex = indexInfos.find((i) => i.keyType.flags & ts7.TypeFlags.Number);
|
|
4455
|
-
if (properties.length === 0 && !stringIndex && !numberIndex) {
|
|
4456
|
-
return { type: checker.typeToString(type) };
|
|
4684
|
+
if (type.isIntersection()) {
|
|
4685
|
+
for (const t of type.types) {
|
|
4686
|
+
registerReferencedTypes(t, ctx, depth + 1);
|
|
4457
4687
|
}
|
|
4458
|
-
|
|
4459
|
-
|
|
4688
|
+
}
|
|
4689
|
+
const typeSymbol = type.aliasSymbol ?? type.getSymbol();
|
|
4690
|
+
if (typeSymbol && ctx.shouldExpandExternal && !typeSymbol.getName().startsWith("__") && !ctx.shouldExpandExternal(typeSymbol)) {
|
|
4691
|
+
return;
|
|
4692
|
+
}
|
|
4693
|
+
if (isForeignPackage(typeSymbol, ctx.workspacePackages)) {
|
|
4694
|
+
return;
|
|
4695
|
+
}
|
|
4696
|
+
if (isDeferredMappedOrConditional(type)) {
|
|
4697
|
+
return;
|
|
4698
|
+
}
|
|
4699
|
+
if (type.flags & ts7.TypeFlags.Object) {
|
|
4700
|
+
const props = type.getProperties();
|
|
4460
4701
|
const limit = ctx.maxProperties;
|
|
4461
|
-
|
|
4462
|
-
const isStringLike = type.flags & ts7.TypeFlags.StringLike;
|
|
4463
|
-
const isNumberLike = type.flags & ts7.TypeFlags.NumberLike;
|
|
4464
|
-
const included = properties.filter((prop) => {
|
|
4465
|
-
const propName = prop.getName();
|
|
4466
|
-
if (propName.startsWith("__@"))
|
|
4467
|
-
return false;
|
|
4468
|
-
if (isArrayLike && ARRAY_PROTOTYPE_METHODS.has(propName))
|
|
4469
|
-
return false;
|
|
4470
|
-
if (isStringLike && STRING_PROTOTYPE_METHODS.has(propName))
|
|
4471
|
-
return false;
|
|
4472
|
-
if (isNumberLike && NUMBER_PROTOTYPE_METHODS.has(propName))
|
|
4473
|
-
return false;
|
|
4474
|
-
return true;
|
|
4475
|
-
});
|
|
4476
|
-
if (included.length > limit && ctx.onTruncation) {
|
|
4702
|
+
if (props.length > limit && ctx.onTruncation) {
|
|
4477
4703
|
const typeName = type.getSymbol()?.getName() ?? "anonymous";
|
|
4478
|
-
ctx.onTruncation(typeName,
|
|
4704
|
+
ctx.onTruncation(typeName, props.length, limit);
|
|
4479
4705
|
}
|
|
4480
|
-
for (const prop of
|
|
4481
|
-
const
|
|
4482
|
-
|
|
4483
|
-
const propType = prop.flags & ts7.SymbolFlags.Optional ? stripUndefinedFromType(rawPropType, checker) : rawPropType;
|
|
4484
|
-
this.registerType(propType, ctx);
|
|
4485
|
-
let propSchema = buildSchema(propType, checker, ctx, declaredTypeNode(prop.valueDeclaration ?? prop.getDeclarations()?.[0]));
|
|
4486
|
-
const docComment = prop.getDocumentationComment(checker);
|
|
4487
|
-
if (docComment.length > 0) {
|
|
4488
|
-
const description = docComment.map((c) => c.text).join(`
|
|
4489
|
-
`);
|
|
4490
|
-
if (description.trim()) {
|
|
4491
|
-
propSchema = withDescription(propSchema, description);
|
|
4492
|
-
}
|
|
4493
|
-
}
|
|
4494
|
-
const { deprecated, reason } = isSymbolDeprecated(prop);
|
|
4495
|
-
if (deprecated) {
|
|
4496
|
-
propSchema = withDeprecated(propSchema, reason);
|
|
4497
|
-
}
|
|
4498
|
-
propSchema = decoratePropertySchema(propSchema, prop, propType, checker);
|
|
4499
|
-
props[propName] = propSchema;
|
|
4500
|
-
if (!(prop.flags & ts7.SymbolFlags.Optional)) {
|
|
4501
|
-
required.push(propName);
|
|
4502
|
-
}
|
|
4706
|
+
for (const prop of props.slice(0, limit)) {
|
|
4707
|
+
const propType = checker.getTypeOfSymbol(prop);
|
|
4708
|
+
registerReferencedTypes(propType, ctx, depth + 1);
|
|
4503
4709
|
}
|
|
4504
|
-
return {
|
|
4505
|
-
type: "object",
|
|
4506
|
-
properties: props,
|
|
4507
|
-
...required.length > 0 ? { required } : {},
|
|
4508
|
-
...stringIndex ? { additionalProperties: buildSchema(stringIndex.type, checker, ctx) } : {},
|
|
4509
|
-
...numberIndex ? {
|
|
4510
|
-
patternProperties: { "^\\d+$": buildSchema(numberIndex.type, checker, ctx) },
|
|
4511
|
-
"x-ts-index-key": "number"
|
|
4512
|
-
} : {}
|
|
4513
|
-
};
|
|
4514
4710
|
}
|
|
4515
4711
|
}
|
|
4516
4712
|
|
|
4517
4713
|
// src/serializers/context.ts
|
|
4714
|
+
import ts8 from "typescript";
|
|
4518
4715
|
function createContext(program, sourceFile, options = {}) {
|
|
4519
4716
|
return {
|
|
4520
4717
|
typeChecker: program.getTypeChecker(),
|
|
@@ -4534,9 +4731,12 @@ function createContext(program, sourceFile, options = {}) {
|
|
|
4534
4731
|
declIds: new Map,
|
|
4535
4732
|
idOwner: new Map,
|
|
4536
4733
|
workspacePackages: options.workspacePackages ?? new Map,
|
|
4734
|
+
budget: { owner: "", ops: 0, exceeded: false },
|
|
4735
|
+
maxBudgetOps: MAX_BUDGET_OPS,
|
|
4537
4736
|
schemaOps: 0,
|
|
4538
|
-
maxSchemaOps:
|
|
4539
|
-
budgetExceeded: false
|
|
4737
|
+
maxSchemaOps: MAX_SCHEMA_OPS,
|
|
4738
|
+
budgetExceeded: false,
|
|
4739
|
+
exhaustedBudgets: []
|
|
4540
4740
|
};
|
|
4541
4741
|
}
|
|
4542
4742
|
function getInheritedMembers(classType, ownMemberNames, ctx, isStatic = false) {
|
|
@@ -4602,7 +4802,7 @@ function getStaticMembers(classType, checker) {
|
|
|
4602
4802
|
});
|
|
4603
4803
|
}
|
|
4604
4804
|
function inheritedMethodSchema(symbol, type, ctx) {
|
|
4605
|
-
if (!ctx.
|
|
4805
|
+
if (!ctx.budget.exceeded) {
|
|
4606
4806
|
return decoratePropertySchema({ "x-ts-function": true }, symbol, type, ctx.typeChecker);
|
|
4607
4807
|
}
|
|
4608
4808
|
return {
|
|
@@ -4620,7 +4820,7 @@ function serializeInheritedMember(symbol, inheritedFrom, ctx, isStatic) {
|
|
|
4620
4820
|
const isOptional = !!(symbol.flags & ts8.SymbolFlags.Optional);
|
|
4621
4821
|
const rawType = checker.getTypeOfSymbol(symbol);
|
|
4622
4822
|
const type = isOptional ? stripUndefinedFromType(rawType, checker) : rawType;
|
|
4623
|
-
const registerTypes = !ctx.
|
|
4823
|
+
const registerTypes = !ctx.budget.exceeded;
|
|
4624
4824
|
if (registerTypes)
|
|
4625
4825
|
registerReferencedTypes(type, ctx);
|
|
4626
4826
|
let visibility;
|
|
@@ -4789,7 +4989,8 @@ function serializeClass(node, ctx) {
|
|
|
4789
4989
|
members.push(...inheritedInstance);
|
|
4790
4990
|
const inheritedStatic = getInheritedMembers(classType, ownMemberNames, ctx, true);
|
|
4791
4991
|
members.push(...inheritedStatic);
|
|
4792
|
-
const extendsClause =
|
|
4992
|
+
const extendsClause = getExtendsText(node, checker);
|
|
4993
|
+
const openArms = openHeritageArms([node], checker, ctx);
|
|
4793
4994
|
const implementsClause = getImplementsClause(node, checker);
|
|
4794
4995
|
const classFlags = {};
|
|
4795
4996
|
const classModifiers = ts10.getModifiers(node);
|
|
@@ -4807,6 +5008,7 @@ function serializeClass(node, ctx) {
|
|
|
4807
5008
|
members: members.length > 0 ? members : undefined,
|
|
4808
5009
|
signatures: signatures.length > 0 ? signatures : undefined,
|
|
4809
5010
|
extends: extendsClause,
|
|
5011
|
+
...openArms.length > 0 ? { schema: { allOf: openArms } } : {},
|
|
4810
5012
|
implements: implementsClause?.length ? implementsClause : undefined,
|
|
4811
5013
|
...deprecated ? { deprecated: true, deprecationReason } : {},
|
|
4812
5014
|
...examples.length > 0 ? { examples } : {},
|
|
@@ -4819,11 +5021,7 @@ function getMemberName(member) {
|
|
|
4819
5021
|
return "constructor";
|
|
4820
5022
|
if (!member.name)
|
|
4821
5023
|
return;
|
|
4822
|
-
|
|
4823
|
-
return member.name.text;
|
|
4824
|
-
if (ts10.isPrivateIdentifier(member.name))
|
|
4825
|
-
return member.name.text;
|
|
4826
|
-
return member.name.getText();
|
|
5024
|
+
return propertyNameText(member.name);
|
|
4827
5025
|
}
|
|
4828
5026
|
function getVisibility(member) {
|
|
4829
5027
|
const modifiers = ts10.canHaveModifiers(member) ? ts10.getModifiers(member) : undefined;
|
|
@@ -4934,8 +5132,18 @@ function serializeConstructor(node, ctx) {
|
|
|
4934
5132
|
return null;
|
|
4935
5133
|
return serializeConstructorSignature(node, sig, ctx);
|
|
4936
5134
|
}
|
|
5135
|
+
function serializeConstructSignatures(sigs, ctx) {
|
|
5136
|
+
return sigs.map((sig, index) => {
|
|
5137
|
+
const typeParameters = extractTypeParametersFromSignature(sig, ctx.typeChecker);
|
|
5138
|
+
return {
|
|
5139
|
+
...serializeConstructorSignature(sig.getDeclaration(), sig, ctx),
|
|
5140
|
+
...typeParameters ? { typeParameters } : {},
|
|
5141
|
+
...sigs.length > 1 ? { overloadIndex: index } : {}
|
|
5142
|
+
};
|
|
5143
|
+
});
|
|
5144
|
+
}
|
|
4937
5145
|
function serializeConstructorSignature(node, sig, ctx) {
|
|
4938
|
-
const { description, tags, examples, inlineTags } = getJSDocComment(node);
|
|
5146
|
+
const { description, tags, examples, inlineTags } = node ? getJSDocComment(node) : { description: undefined, tags: [], examples: [], inlineTags: undefined };
|
|
4939
5147
|
const params = extractParameters(sig, ctx);
|
|
4940
5148
|
return {
|
|
4941
5149
|
description,
|
|
@@ -5015,21 +5223,6 @@ function serializeAccessor(node, ctx) {
|
|
|
5015
5223
|
...inlineTags ? { inlineTags } : {}
|
|
5016
5224
|
};
|
|
5017
5225
|
}
|
|
5018
|
-
function getExtendsClause(node, checker) {
|
|
5019
|
-
if (!node.heritageClauses)
|
|
5020
|
-
return;
|
|
5021
|
-
for (const clause of node.heritageClauses) {
|
|
5022
|
-
if (clause.token === ts10.SyntaxKind.ExtendsKeyword) {
|
|
5023
|
-
const expr = clause.types[0];
|
|
5024
|
-
if (expr) {
|
|
5025
|
-
const type = checker.getTypeAtLocation(expr);
|
|
5026
|
-
const symbol = type.getSymbol();
|
|
5027
|
-
return symbol?.getName() ?? expr.expression.getText();
|
|
5028
|
-
}
|
|
5029
|
-
}
|
|
5030
|
-
}
|
|
5031
|
-
return;
|
|
5032
|
-
}
|
|
5033
5226
|
function getImplementsClause(node, checker) {
|
|
5034
5227
|
if (!node.heritageClauses)
|
|
5035
5228
|
return;
|
|
@@ -5222,12 +5415,12 @@ function signaturesFromDeclaredType(typeNode, ctx) {
|
|
|
5222
5415
|
const callSignatures = ctx.typeChecker.getTypeFromTypeNode(inner).getCallSignatures();
|
|
5223
5416
|
return callSignatures.length > 0 ? signaturesFromChecker(callSignatures, ctx) : undefined;
|
|
5224
5417
|
}
|
|
5225
|
-
function serializeFunctionExport(node, ctx, nameOverride, declaredType) {
|
|
5418
|
+
function serializeFunctionExport(node, ctx, nameOverride, declaredType, jsdocNode) {
|
|
5226
5419
|
const symbol = ctx.typeChecker.getSymbolAtLocation(node.name ?? node);
|
|
5227
5420
|
const name = nameOverride ?? symbol?.getName() ?? node.name?.getText() ?? anonymousDefaultName(node);
|
|
5228
5421
|
if (!name)
|
|
5229
5422
|
return null;
|
|
5230
|
-
const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker);
|
|
5423
|
+
const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker, jsdocNode);
|
|
5231
5424
|
const declaredFn = declaredType && unwrapParens(declaredType);
|
|
5232
5425
|
const typeParameters = extractTypeParameters(declaredFn && ts11.isFunctionTypeNode(declaredFn) ? declaredFn : node, ctx.typeChecker);
|
|
5233
5426
|
const signatures = (declaredType && signaturesFromDeclaredType(declaredType, ctx)) ?? (anySignatureDefers(node, ctx) ? signaturesFromAst(functionSignatureDecls(node, ctx), ctx) : signaturesFromChecker(ctx.typeChecker.getTypeAtLocation(node).getCallSignatures(), ctx));
|
|
@@ -5266,7 +5459,8 @@ function serializeInterface(node, ctx) {
|
|
|
5266
5459
|
const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, checker);
|
|
5267
5460
|
const typeParameters = extractTypeParameters(node, checker);
|
|
5268
5461
|
const { members, callSignatureMember } = serializeTypeElements(node.members, ctx);
|
|
5269
|
-
const extendsClause =
|
|
5462
|
+
const extendsClause = getExtendsText(node, checker);
|
|
5463
|
+
const openArms = openHeritageArms([node], checker, ctx);
|
|
5270
5464
|
const exportSignatures = callSignatureMember?.signatures && callSignatureMember.signatures.length > 0 ? callSignatureMember.signatures : undefined;
|
|
5271
5465
|
return {
|
|
5272
5466
|
id: name,
|
|
@@ -5279,6 +5473,7 @@ function serializeInterface(node, ctx) {
|
|
|
5279
5473
|
members: members.length > 0 ? members : undefined,
|
|
5280
5474
|
signatures: exportSignatures,
|
|
5281
5475
|
extends: extendsClause,
|
|
5476
|
+
...openArms.length > 0 ? { schema: { allOf: openArms } } : {},
|
|
5282
5477
|
...deprecated ? { deprecated: true, deprecationReason } : {},
|
|
5283
5478
|
...examples.length > 0 ? { examples } : {},
|
|
5284
5479
|
...inlineTags ? { inlineTags } : {}
|
|
@@ -5368,7 +5563,7 @@ function serializeMergedTypeSide(symbol, ctx) {
|
|
|
5368
5563
|
const { description, tags } = getJSDocComment(typeDecl);
|
|
5369
5564
|
return {
|
|
5370
5565
|
members,
|
|
5371
|
-
extends: interfaces.map((decl) =>
|
|
5566
|
+
extends: interfaces.map((decl) => getExtendsText(decl, checker)).find(Boolean),
|
|
5372
5567
|
typeParameters: extractTypeParameters(typeDecl, checker),
|
|
5373
5568
|
description,
|
|
5374
5569
|
tags
|
|
@@ -5376,7 +5571,7 @@ function serializeMergedTypeSide(symbol, ctx) {
|
|
|
5376
5571
|
}
|
|
5377
5572
|
function serializePropertySignature(node, ctx) {
|
|
5378
5573
|
const { typeChecker: checker } = ctx;
|
|
5379
|
-
const name = node.name
|
|
5574
|
+
const name = propertyNameText(node.name);
|
|
5380
5575
|
const { description, tags, inlineTags } = getJSDocComment(node);
|
|
5381
5576
|
const rawType = checker.getTypeAtLocation(node);
|
|
5382
5577
|
const type = node.questionToken ? stripUndefinedFromType(rawType, checker) : rawType;
|
|
@@ -5406,7 +5601,7 @@ function serializePropertySignature(node, ctx) {
|
|
|
5406
5601
|
}
|
|
5407
5602
|
function serializeMethodSignature(node, ctx) {
|
|
5408
5603
|
const { typeChecker: checker } = ctx;
|
|
5409
|
-
const name = node.name
|
|
5604
|
+
const name = propertyNameText(node.name);
|
|
5410
5605
|
const { description, tags, inlineTags } = getJSDocComment(node);
|
|
5411
5606
|
const rawType = checker.getTypeAtLocation(node);
|
|
5412
5607
|
const type = node.questionToken ? stripUndefinedFromType(rawType, checker) : rawType;
|
|
@@ -5474,20 +5669,6 @@ function serializeIndexSignature(node, ctx) {
|
|
|
5474
5669
|
...inlineTags ? { inlineTags } : {}
|
|
5475
5670
|
};
|
|
5476
5671
|
}
|
|
5477
|
-
function getInterfaceExtends(node, checker) {
|
|
5478
|
-
if (!node.heritageClauses)
|
|
5479
|
-
return;
|
|
5480
|
-
for (const clause of node.heritageClauses) {
|
|
5481
|
-
if (clause.token === ts12.SyntaxKind.ExtendsKeyword && clause.types.length > 0) {
|
|
5482
|
-
const names = clause.types.map((expr) => {
|
|
5483
|
-
const type = checker.getTypeAtLocation(expr);
|
|
5484
|
-
return type.getSymbol()?.getName() ?? expr.expression.getText();
|
|
5485
|
-
});
|
|
5486
|
-
return names.join(" & ");
|
|
5487
|
-
}
|
|
5488
|
-
}
|
|
5489
|
-
return;
|
|
5490
|
-
}
|
|
5491
5672
|
|
|
5492
5673
|
// src/serializers/type-aliases.ts
|
|
5493
5674
|
import ts13 from "typescript";
|
|
@@ -5532,7 +5713,7 @@ function serializeTypeAlias(node, ctx) {
|
|
|
5532
5713
|
schema = buildObjectSchema(type.getProperties(), ctx.typeChecker, ctx, type);
|
|
5533
5714
|
members = serializeResolvedMembers(type, node, ctx);
|
|
5534
5715
|
} else {
|
|
5535
|
-
schema =
|
|
5716
|
+
schema = buildAliasBodySchema(type, ctx.typeChecker, ctx);
|
|
5536
5717
|
if (isObjectShapedAlias(type, ctx)) {
|
|
5537
5718
|
members = serializeResolvedMembers(type, node, ctx);
|
|
5538
5719
|
}
|
|
@@ -5847,12 +6028,17 @@ function serializeVariable(node, statement, ctx) {
|
|
|
5847
6028
|
const name = symbol?.getName() ?? node.name.getText();
|
|
5848
6029
|
if (!name)
|
|
5849
6030
|
return null;
|
|
5850
|
-
|
|
5851
|
-
|
|
6031
|
+
return serializeValue(name, node, symbol, statement, ctx.typeChecker.getTypeAtLocation(node), ts15.isVariableDeclaration(node) ? node.type : undefined, ctx);
|
|
6032
|
+
}
|
|
6033
|
+
function serializeDefaultExpression(node, symbol, type, ctx) {
|
|
6034
|
+
return serializeValue(symbol.getName(), node.expression, symbol, node, type, undefined, ctx);
|
|
6035
|
+
}
|
|
6036
|
+
function serializeValue(name, node, symbol, jsdocNode, type, typeNode, ctx) {
|
|
6037
|
+
const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker, jsdocNode);
|
|
5852
6038
|
const schemaExtraction = extractSchemaType(type, ctx.typeChecker);
|
|
5853
6039
|
const typeToSerialize = schemaExtraction?.outputType ?? type;
|
|
5854
6040
|
registerReferencedTypes(typeToSerialize, ctx);
|
|
5855
|
-
const schema = buildSchema(typeToSerialize, ctx.typeChecker, ctx,
|
|
6041
|
+
const schema = buildSchema(typeToSerialize, ctx.typeChecker, ctx, typeNode);
|
|
5856
6042
|
const flags = schemaExtraction ? {
|
|
5857
6043
|
schemaLibrary: schemaExtraction.adapter.id,
|
|
5858
6044
|
...schemaExtraction.inputType && schemaExtraction.inputType !== schemaExtraction.outputType ? { hasTransform: true } : {}
|
|
@@ -6242,10 +6428,14 @@ function normalizeExport(exp, options = {}) {
|
|
|
6242
6428
|
result.members = exp.members.map((member) => normalizeMember(member, options));
|
|
6243
6429
|
}
|
|
6244
6430
|
if (!vendorSchema && shouldGenerateMembersSchema(exp.kind) && exp.members && exp.members.length > 0) {
|
|
6245
|
-
result.schema = normalizeMembers(exp.members, options);
|
|
6431
|
+
result.schema = withOpenArms(normalizeMembers(exp.members, options), result.schema);
|
|
6246
6432
|
}
|
|
6247
6433
|
return result;
|
|
6248
6434
|
}
|
|
6435
|
+
function withOpenArms(membersSchema, provided) {
|
|
6436
|
+
const arms = provided?.allOf;
|
|
6437
|
+
return Array.isArray(arms) ? { allOf: [membersSchema, ...arms] } : membersSchema;
|
|
6438
|
+
}
|
|
6249
6439
|
function normalizeType(type, options = {}) {
|
|
6250
6440
|
const result = { ...type };
|
|
6251
6441
|
if (type.schema) {
|
|
@@ -6255,7 +6445,7 @@ function normalizeType(type, options = {}) {
|
|
|
6255
6445
|
result.members = type.members.map((member) => normalizeMember(member, options));
|
|
6256
6446
|
}
|
|
6257
6447
|
if (shouldGenerateMembersSchema(type.kind) && type.members && type.members.length > 0) {
|
|
6258
|
-
result.schema = normalizeMembers(type.members, options);
|
|
6448
|
+
result.schema = withOpenArms(normalizeMembers(type.members, options), result.schema);
|
|
6259
6449
|
}
|
|
6260
6450
|
return result;
|
|
6261
6451
|
}
|
|
@@ -6438,6 +6628,7 @@ async function getExport(options) {
|
|
|
6438
6628
|
}
|
|
6439
6629
|
const ctx = createContext(program, sourceFile, { maxTypeDepth });
|
|
6440
6630
|
ctx.exportedIds = exportedIds;
|
|
6631
|
+
claimExportedTypeIds(exportedSymbols, ctx);
|
|
6441
6632
|
try {
|
|
6442
6633
|
const originalDecls = targetSymbol.declarations ?? [];
|
|
6443
6634
|
const isNamespaceExportDecl = originalDecls.some((d) => ts16.isNamespaceExport(d) || ts16.isNamespaceImport(d));
|
|
@@ -7611,7 +7802,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
7611
7802
|
const symbol = type.aliasSymbol ?? type.getSymbol();
|
|
7612
7803
|
const named = !!symbol && !symbol.getName().startsWith("__");
|
|
7613
7804
|
const allowed = !named || !symbol || symbolAllowed(symbol);
|
|
7614
|
-
if (named && allowed && symbol && !
|
|
7805
|
+
if (named && allowed && symbol && !isExportedType(symbol)) {
|
|
7615
7806
|
ctx.typeRegistry.registerType(type, ctx);
|
|
7616
7807
|
const name = symbol.getName();
|
|
7617
7808
|
if (!symbolByName.has(name)) {
|
|
@@ -7632,6 +7823,11 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
7632
7823
|
visit(t, depth + 1);
|
|
7633
7824
|
}
|
|
7634
7825
|
}
|
|
7826
|
+
const declared = declaredForm(type, checker);
|
|
7827
|
+
if (declared !== type) {
|
|
7828
|
+
visit(declared, depth);
|
|
7829
|
+
return;
|
|
7830
|
+
}
|
|
7635
7831
|
if (!allowed || isDeferredMappedOrConditional(type) || !(type.flags & ts20.TypeFlags.Object || type.isClassOrInterface())) {
|
|
7636
7832
|
return;
|
|
7637
7833
|
}
|
|
@@ -7659,6 +7855,12 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
7659
7855
|
}
|
|
7660
7856
|
};
|
|
7661
7857
|
const TYPE_SYMBOL_FLAGS = ts20.SymbolFlags.Interface | ts20.SymbolFlags.TypeAlias | ts20.SymbolFlags.Class | ts20.SymbolFlags.RegularEnum | ts20.SymbolFlags.ConstEnum;
|
|
7858
|
+
const isExportedType = (symbol) => {
|
|
7859
|
+
const name = symbol.getName();
|
|
7860
|
+
if (!ctx.exportedIds.has(name))
|
|
7861
|
+
return false;
|
|
7862
|
+
return !(symbol.flags & TYPE_SYMBOL_FLAGS) || resolveTypeId(symbol, ctx) === name;
|
|
7863
|
+
};
|
|
7662
7864
|
const visitedSymbols = new Set;
|
|
7663
7865
|
const symbolKind = (symbol) => {
|
|
7664
7866
|
if (symbol.flags & ts20.SymbolFlags.Interface)
|
|
@@ -7673,6 +7875,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
7673
7875
|
const resolved = resolveAliasSymbol(symbol, checker, undefined, ctx.program);
|
|
7674
7876
|
return resolved;
|
|
7675
7877
|
};
|
|
7878
|
+
const writtenWhenAny = (symbol, declared) => declared.flags & ts20.TypeFlags.Any ? symbol.declarations?.find(ts20.isTypeAliasDeclaration)?.type : undefined;
|
|
7676
7879
|
const symbolByName = new Map;
|
|
7677
7880
|
const registerTypeSymbol = (symbol) => {
|
|
7678
7881
|
const name = symbol.getName();
|
|
@@ -7682,7 +7885,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
7682
7885
|
return;
|
|
7683
7886
|
if (!symbolAllowed(symbol))
|
|
7684
7887
|
return;
|
|
7685
|
-
if (
|
|
7888
|
+
if (isExportedType(symbol)) {
|
|
7686
7889
|
walkDeclarations(symbol);
|
|
7687
7890
|
return;
|
|
7688
7891
|
}
|
|
@@ -7698,7 +7901,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
|
|
|
7698
7901
|
id,
|
|
7699
7902
|
name,
|
|
7700
7903
|
kind: symbolKind(symbol),
|
|
7701
|
-
schema: ensureNonEmptySchema(buildSchema(declared, checker, ctx), declared, checker)
|
|
7904
|
+
schema: withExpansionBudget(ctx, `type ${id}`, () => ensureNonEmptySchema(buildSchema(declared, checker, ctx, writtenWhenAny(symbol, declared)), declared, checker))
|
|
7702
7905
|
});
|
|
7703
7906
|
}
|
|
7704
7907
|
symbolByName.set(name, symbol);
|
|
@@ -8080,6 +8283,7 @@ async function extract(options) {
|
|
|
8080
8283
|
workspacePackages: result.workspacePackages ?? new Map
|
|
8081
8284
|
});
|
|
8082
8285
|
ctx.exportedIds = exportedIds;
|
|
8286
|
+
claimExportedTypeIds(exportedSymbols, ctx);
|
|
8083
8287
|
const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
|
|
8084
8288
|
const total = filteredSymbols.length;
|
|
8085
8289
|
for (let i = 0;i < filteredSymbols.length; i++) {
|
|
@@ -8147,10 +8351,15 @@ async function extract(options) {
|
|
|
8147
8351
|
}
|
|
8148
8352
|
continue;
|
|
8149
8353
|
}
|
|
8150
|
-
const exp = serializeDeclaration2(declaration, symbol, exportName, ctx, isTypeOnly);
|
|
8354
|
+
const exp = withExpansionBudget(ctx, exportName, () => serializeDeclaration2(declaration, symbol, exportName, ctx, isTypeOnly));
|
|
8151
8355
|
if (exp) {
|
|
8152
|
-
|
|
8153
|
-
|
|
8356
|
+
const typeSide = mergedTypeSideOf(exp, declaration, targetSymbol, ctx);
|
|
8357
|
+
if (typeSide) {
|
|
8358
|
+
mergedTypeSides.push({
|
|
8359
|
+
index: exports.length,
|
|
8360
|
+
symbol: typeSide,
|
|
8361
|
+
ontoClass: ts21.isClassDeclaration(declaration)
|
|
8362
|
+
});
|
|
8154
8363
|
}
|
|
8155
8364
|
exports.push(exp);
|
|
8156
8365
|
tracker.status = "success";
|
|
@@ -8170,8 +8379,8 @@ async function extract(options) {
|
|
|
8170
8379
|
});
|
|
8171
8380
|
}
|
|
8172
8381
|
}
|
|
8173
|
-
for (const { index, symbol } of mergedTypeSides) {
|
|
8174
|
-
exports[index] = withMergedTypeSide(exports[index], symbol, ctx);
|
|
8382
|
+
for (const { index, symbol, ontoClass } of mergedTypeSides) {
|
|
8383
|
+
exports[index] = withExpansionBudget(ctx, exports[index].name, () => withMergedTypeSide(exports[index], symbol, ctx, ontoClass));
|
|
8175
8384
|
}
|
|
8176
8385
|
const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
|
|
8177
8386
|
const meta = await getPackageMeta(entryFile, baseDir);
|
|
@@ -8182,7 +8391,7 @@ async function extract(options) {
|
|
|
8182
8391
|
});
|
|
8183
8392
|
if (ctx.budgetExceeded) {
|
|
8184
8393
|
diagnostics.push({
|
|
8185
|
-
message:
|
|
8394
|
+
message: `Stopped expanding some types after hitting the schema expansion budget${exhaustedBudgetNote(ctx)}`,
|
|
8186
8395
|
severity: "warning",
|
|
8187
8396
|
code: "TYPE_EXPANSION_LIMIT"
|
|
8188
8397
|
});
|
|
@@ -8354,21 +8563,18 @@ function serializeDeclaration2(declaration, exportSymbol, exportName, ctx, isTyp
|
|
|
8354
8563
|
result = serializeVariable(declaration, varStatement, ctx);
|
|
8355
8564
|
if (result?.kind === "variable") {
|
|
8356
8565
|
const type = ctx.typeChecker.getTypeAtLocation(declaration);
|
|
8357
|
-
|
|
8358
|
-
result = { ...result, kind: "class" };
|
|
8359
|
-
} else {
|
|
8360
|
-
const callSigs = callSignaturesForVariable(declaration, ctx);
|
|
8361
|
-
if (callSigs.length > 0) {
|
|
8362
|
-
result = {
|
|
8363
|
-
...result,
|
|
8364
|
-
kind: "function",
|
|
8365
|
-
signatures: buildSignatures(callSigs, ctx.typeChecker, ctx)
|
|
8366
|
-
};
|
|
8367
|
-
}
|
|
8368
|
-
}
|
|
8566
|
+
result = withCallableKind(result, type, callSignaturesForVariable(declaration, ctx), ctx);
|
|
8369
8567
|
}
|
|
8370
8568
|
}
|
|
8371
8569
|
}
|
|
8570
|
+
} else if (ts21.isExportAssignment(declaration) && !declaration.isExportEquals) {
|
|
8571
|
+
const expression = skipOuterExpressions(declaration.expression);
|
|
8572
|
+
if (ts21.isArrowFunction(expression) || ts21.isFunctionExpression(expression)) {
|
|
8573
|
+
result = serializeFunctionExport(expression, ctx, exportName, undefined, declaration);
|
|
8574
|
+
} else {
|
|
8575
|
+
const type = ctx.typeChecker.getTypeOfSymbol(exportSymbol);
|
|
8576
|
+
result = withCallableKind(serializeDefaultExpression(declaration, exportSymbol, type, ctx), type, type.getCallSignatures(), ctx);
|
|
8577
|
+
}
|
|
8372
8578
|
} else if (ts21.isNamespaceExport(declaration) || ts21.isModuleDeclaration(declaration) || ts21.isNamespaceImport(declaration) || ts21.isSourceFile(declaration)) {
|
|
8373
8579
|
try {
|
|
8374
8580
|
result = serializeNamespaceExport(exportSymbol, exportName, ctx);
|
|
@@ -8559,6 +8765,30 @@ function variableStatementOf(declaration) {
|
|
|
8559
8765
|
const statement = node.parent?.parent;
|
|
8560
8766
|
return statement && ts21.isVariableStatement(statement) ? statement : undefined;
|
|
8561
8767
|
}
|
|
8768
|
+
function skipOuterExpressions(expression) {
|
|
8769
|
+
let node = expression;
|
|
8770
|
+
while (ts21.isParenthesizedExpression(node) || ts21.isAsExpression(node) || ts21.isSatisfiesExpression(node) || ts21.isTypeAssertionExpression(node) || ts21.isNonNullExpression(node)) {
|
|
8771
|
+
node = node.expression;
|
|
8772
|
+
}
|
|
8773
|
+
return node;
|
|
8774
|
+
}
|
|
8775
|
+
function withCallableKind(entry, type, callSigs, ctx) {
|
|
8776
|
+
const constructSigs = type.getConstructSignatures();
|
|
8777
|
+
if (constructSigs.length > 0) {
|
|
8778
|
+
return {
|
|
8779
|
+
...entry,
|
|
8780
|
+
kind: "class",
|
|
8781
|
+
signatures: serializeConstructSignatures(constructSigs, ctx)
|
|
8782
|
+
};
|
|
8783
|
+
}
|
|
8784
|
+
if (callSigs.length === 0)
|
|
8785
|
+
return entry;
|
|
8786
|
+
return {
|
|
8787
|
+
...entry,
|
|
8788
|
+
kind: "function",
|
|
8789
|
+
signatures: buildSignatures(callSigs, ctx.typeChecker, ctx)
|
|
8790
|
+
};
|
|
8791
|
+
}
|
|
8562
8792
|
function callSignaturesForVariable(declaration, ctx) {
|
|
8563
8793
|
const checker = ctx.typeChecker;
|
|
8564
8794
|
if (ts21.isVariableDeclaration(declaration) && declaration.type && ts21.isTypeReferenceNode(declaration.type)) {
|
|
@@ -8609,18 +8839,45 @@ function isValueDeclaration(declaration) {
|
|
|
8609
8839
|
function hasTypeSide(symbol) {
|
|
8610
8840
|
return (symbol.flags & (ts21.SymbolFlags.Interface | ts21.SymbolFlags.TypeAlias)) !== 0;
|
|
8611
8841
|
}
|
|
8612
|
-
function
|
|
8842
|
+
function mergedTypeSideOf(exp, declaration, symbol, ctx) {
|
|
8843
|
+
if (ts21.isClassDeclaration(declaration)) {
|
|
8844
|
+
return symbol.flags & ts21.SymbolFlags.Interface ? symbol : undefined;
|
|
8845
|
+
}
|
|
8846
|
+
if (exp.members || !isValueDeclaration(declaration))
|
|
8847
|
+
return;
|
|
8848
|
+
if (hasTypeSide(symbol))
|
|
8849
|
+
return symbol;
|
|
8850
|
+
if (exp.kind !== "class")
|
|
8851
|
+
return;
|
|
8852
|
+
const [construct] = ctx.typeChecker.getTypeAtLocation(declaration).getConstructSignatures();
|
|
8853
|
+
const instance = construct?.getReturnType();
|
|
8854
|
+
const constructed = instance && (instance.aliasSymbol ?? instance.getSymbol());
|
|
8855
|
+
if (!constructed || !hasTypeSide(constructed))
|
|
8856
|
+
return;
|
|
8857
|
+
if (ctx.shouldExpandExternal && !ctx.shouldExpandExternal(constructed))
|
|
8858
|
+
return;
|
|
8859
|
+
return constructed;
|
|
8860
|
+
}
|
|
8861
|
+
function withMergedTypeSide(entry, symbol, ctx, ontoClass) {
|
|
8613
8862
|
const typeSide = serializeMergedTypeSide(symbol, ctx);
|
|
8614
8863
|
if (!typeSide)
|
|
8615
8864
|
return entry;
|
|
8616
8865
|
const { members, description, tags, ...instanceType } = typeSide;
|
|
8866
|
+
const own = new Set(entry.members?.map((m) => m.name));
|
|
8617
8867
|
return {
|
|
8618
8868
|
...entry,
|
|
8619
|
-
members,
|
|
8620
|
-
...entry.kind === "class" ? instanceType : {},
|
|
8869
|
+
members: [...entry.members ?? [], ...(members ?? []).filter((m) => !own.has(m.name))],
|
|
8870
|
+
...entry.kind === "class" && !ontoClass ? instanceType : {},
|
|
8621
8871
|
...entry.description ? {} : { description, tags: [...entry.tags ?? [], ...tags ?? []] }
|
|
8622
8872
|
};
|
|
8623
8873
|
}
|
|
8874
|
+
function exhaustedBudgetNote(ctx) {
|
|
8875
|
+
const owners = [...new Set(ctx.exhaustedBudgets)];
|
|
8876
|
+
if (owners.length === 0)
|
|
8877
|
+
return "";
|
|
8878
|
+
const shown = owners.slice(0, 10).join(", ");
|
|
8879
|
+
return `: ${shown}${owners.length > 10 ? ` (+${owners.length - 10} more)` : ""}`;
|
|
8880
|
+
}
|
|
8624
8881
|
function withExportName(entry, exportName) {
|
|
8625
8882
|
if (entry.name === exportName) {
|
|
8626
8883
|
return entry;
|
|
@@ -9192,6 +9449,7 @@ function getNodeName(node) {
|
|
|
9192
9449
|
export {
|
|
9193
9450
|
zodAdapter,
|
|
9194
9451
|
writtenTypeText,
|
|
9452
|
+
withOpenHeritage,
|
|
9195
9453
|
withDescription,
|
|
9196
9454
|
withDeprecated,
|
|
9197
9455
|
validateSpec2 as validateSpec,
|
|
@@ -9237,6 +9495,7 @@ export {
|
|
|
9237
9495
|
query,
|
|
9238
9496
|
pickEntry,
|
|
9239
9497
|
parseGithubRepo,
|
|
9498
|
+
openHeritageArms,
|
|
9240
9499
|
normalizeType,
|
|
9241
9500
|
normalizeSchema,
|
|
9242
9501
|
normalizeMembers,
|
|
@@ -9318,6 +9577,7 @@ export {
|
|
|
9318
9577
|
buildSchema,
|
|
9319
9578
|
buildObjectSchema,
|
|
9320
9579
|
buildFunctionSchema,
|
|
9580
|
+
buildAliasBodySchema,
|
|
9321
9581
|
assertSpec,
|
|
9322
9582
|
asStandardSchema,
|
|
9323
9583
|
arktypeAdapter,
|