@openpkg-ts/extract 0.27.2 → 0.28.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
CHANGED
|
@@ -228,6 +228,16 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
228
228
|
return { type: "bigint" };
|
|
229
229
|
if (type.flags & ts.TypeFlags.ESSymbol)
|
|
230
230
|
return { type: "symbol" };
|
|
231
|
+
if (type.isThisType?.()) {
|
|
232
|
+
const constraint = type.getConstraint?.();
|
|
233
|
+
const symbol2 = constraint?.getSymbol() ?? type.getSymbol();
|
|
234
|
+
if (symbol2 && !isAnonymous(type)) {
|
|
235
|
+
return {
|
|
236
|
+
$ref: `#/types/${symbol2.getName()}`,
|
|
237
|
+
"x-ts-type": "this"
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
231
241
|
if (type.flags & ts.TypeFlags.StringLiteral) {
|
|
232
242
|
const literal = type.value;
|
|
233
243
|
return { type: "string", enum: [literal] };
|
|
@@ -259,8 +269,10 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
259
269
|
}
|
|
260
270
|
return { anyOf: types.map((t) => buildSchema(t, checker, ctx)) };
|
|
261
271
|
}
|
|
262
|
-
|
|
263
|
-
|
|
272
|
+
const isIntersectionType = type.isIntersection() || !!(type.flags & ts.TypeFlags.Intersection);
|
|
273
|
+
if (isIntersectionType && "types" in type) {
|
|
274
|
+
const intersectionType = type;
|
|
275
|
+
const filteredTypes = intersectionType.types.filter((t) => !(t.flags & ts.TypeFlags.Never));
|
|
264
276
|
if (filteredTypes.length === 0) {
|
|
265
277
|
return { type: "never" };
|
|
266
278
|
}
|
|
@@ -283,8 +295,9 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
283
295
|
return { type: "array", items: {} };
|
|
284
296
|
}
|
|
285
297
|
if (checker.isArrayType(type)) {
|
|
286
|
-
const
|
|
287
|
-
const
|
|
298
|
+
const arrayTypeRef = type;
|
|
299
|
+
const arrayTypeArgs = checker.getTypeArguments(arrayTypeRef);
|
|
300
|
+
const elementType = arrayTypeArgs?.[0];
|
|
288
301
|
if (elementType) {
|
|
289
302
|
if (ctx) {
|
|
290
303
|
return withDepth(ctx, () => ({
|
|
@@ -297,8 +310,8 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
297
310
|
return { type: "array" };
|
|
298
311
|
}
|
|
299
312
|
if (checker.isTupleType(type)) {
|
|
300
|
-
const
|
|
301
|
-
const elementTypes =
|
|
313
|
+
const tupleTypeRef = type;
|
|
314
|
+
const elementTypes = checker.getTypeArguments(tupleTypeRef) ?? [];
|
|
302
315
|
if (ctx) {
|
|
303
316
|
return withDepth(ctx, () => {
|
|
304
317
|
const prevInTupleElement = ctx.inTupleElement;
|
|
@@ -323,7 +336,8 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
323
336
|
};
|
|
324
337
|
}
|
|
325
338
|
const typeRef = type;
|
|
326
|
-
|
|
339
|
+
const typeArgs = typeRef.target ? checker.getTypeArguments(typeRef) : undefined;
|
|
340
|
+
if (typeRef.target && typeArgs && typeArgs.length > 0) {
|
|
327
341
|
const symbol2 = typeRef.target.getSymbol();
|
|
328
342
|
const name = symbol2?.getName();
|
|
329
343
|
if (name && BUILTIN_TYPES.has(name)) {
|
|
@@ -335,7 +349,7 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
335
349
|
return withDepth(ctx, () => {
|
|
336
350
|
const schema2 = {
|
|
337
351
|
$ref: `#/types/${name}`,
|
|
338
|
-
typeArguments:
|
|
352
|
+
typeArguments: typeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
339
353
|
};
|
|
340
354
|
if (packageOrigin) {
|
|
341
355
|
schema2["x-ts-package"] = packageOrigin;
|
|
@@ -345,7 +359,7 @@ function buildSchema(type, checker, ctx, _depth = 0) {
|
|
|
345
359
|
}
|
|
346
360
|
const schema = {
|
|
347
361
|
$ref: `#/types/${name}`,
|
|
348
|
-
typeArguments:
|
|
362
|
+
typeArguments: typeArgs.map((t) => buildSchema(t, checker, ctx))
|
|
349
363
|
};
|
|
350
364
|
if (packageOrigin) {
|
|
351
365
|
schema["x-ts-package"] = packageOrigin;
|
|
@@ -1557,6 +1571,16 @@ async function extractStandardSchemasFromProject(entryFile, baseDir, options = {
|
|
|
1557
1571
|
|
|
1558
1572
|
// src/types/parameters.ts
|
|
1559
1573
|
import ts5 from "typescript";
|
|
1574
|
+
function stripUndefinedFromType(type, checker) {
|
|
1575
|
+
if (!type.isUnion())
|
|
1576
|
+
return type;
|
|
1577
|
+
const nonUndefinedTypes = type.types.filter((t) => !(t.flags & ts5.TypeFlags.Undefined));
|
|
1578
|
+
if (nonUndefinedTypes.length === 0)
|
|
1579
|
+
return type;
|
|
1580
|
+
if (nonUndefinedTypes.length === 1)
|
|
1581
|
+
return nonUndefinedTypes[0];
|
|
1582
|
+
return checker.getUnionType(nonUndefinedTypes);
|
|
1583
|
+
}
|
|
1560
1584
|
function extractParameters(signature, ctx) {
|
|
1561
1585
|
const { typeChecker: checker } = ctx;
|
|
1562
1586
|
const result = [];
|
|
@@ -1569,12 +1593,20 @@ function extractParameters(signature, ctx) {
|
|
|
1569
1593
|
const expandedParams = expandBindingPattern(decl, type, jsdocTags, ctx);
|
|
1570
1594
|
result.push(...expandedParams);
|
|
1571
1595
|
} else {
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1596
|
+
const isOptional = !!(param.flags & 16777216);
|
|
1597
|
+
const effectiveType = isOptional ? stripUndefinedFromType(type, checker) : type;
|
|
1598
|
+
registerReferencedTypes(effectiveType, ctx);
|
|
1599
|
+
const paramName = param.getName();
|
|
1600
|
+
const description = getParamDescription(paramName, jsdocTags);
|
|
1601
|
+
const paramResult = {
|
|
1602
|
+
name: paramName,
|
|
1603
|
+
schema: buildSchema(effectiveType, checker, ctx),
|
|
1604
|
+
required: !isOptional
|
|
1605
|
+
};
|
|
1606
|
+
if (description) {
|
|
1607
|
+
paramResult.description = description;
|
|
1608
|
+
}
|
|
1609
|
+
result.push(paramResult);
|
|
1578
1610
|
}
|
|
1579
1611
|
}
|
|
1580
1612
|
return result;
|
|
@@ -1592,13 +1624,14 @@ function expandBindingPattern(paramDecl, paramType, jsdocTags, ctx) {
|
|
|
1592
1624
|
const propSymbol = allProperties.get(propertyName);
|
|
1593
1625
|
if (!propSymbol)
|
|
1594
1626
|
continue;
|
|
1595
|
-
const propType = checker.getTypeOfSymbol(propSymbol);
|
|
1596
|
-
registerReferencedTypes(propType, ctx);
|
|
1597
1627
|
const isOptional = !!(propSymbol.flags & ts5.SymbolFlags.Optional) || element.initializer !== undefined;
|
|
1628
|
+
const propType = checker.getTypeOfSymbol(propSymbol);
|
|
1629
|
+
const effectiveType = isOptional ? stripUndefinedFromType(propType, checker) : propType;
|
|
1630
|
+
registerReferencedTypes(effectiveType, ctx);
|
|
1598
1631
|
const description = getParamDescription(propertyName, jsdocTags, inferredAlias);
|
|
1599
1632
|
const param = {
|
|
1600
1633
|
name: propertyName,
|
|
1601
|
-
schema: buildSchema(
|
|
1634
|
+
schema: buildSchema(effectiveType, checker, ctx),
|
|
1602
1635
|
required: !isOptional
|
|
1603
1636
|
};
|
|
1604
1637
|
if (description) {
|
|
@@ -1914,6 +1947,11 @@ function serializeClass(node, ctx) {
|
|
|
1914
1947
|
members.push(...inheritedStatic);
|
|
1915
1948
|
const extendsClause = getExtendsClause(node, checker);
|
|
1916
1949
|
const implementsClause = getImplementsClause(node, checker);
|
|
1950
|
+
const classFlags = {};
|
|
1951
|
+
const classModifiers = ts7.getModifiers(node);
|
|
1952
|
+
if (classModifiers?.some((m) => m.kind === ts7.SyntaxKind.AbstractKeyword)) {
|
|
1953
|
+
classFlags.abstract = true;
|
|
1954
|
+
}
|
|
1917
1955
|
return {
|
|
1918
1956
|
id: name,
|
|
1919
1957
|
name,
|
|
@@ -1927,7 +1965,8 @@ function serializeClass(node, ctx) {
|
|
|
1927
1965
|
extends: extendsClause,
|
|
1928
1966
|
implements: implementsClause?.length ? implementsClause : undefined,
|
|
1929
1967
|
...deprecated ? { deprecated: true } : {},
|
|
1930
|
-
...examples.length > 0 ? { examples } : {}
|
|
1968
|
+
...examples.length > 0 ? { examples } : {},
|
|
1969
|
+
...Object.keys(classFlags).length > 0 ? { flags: classFlags } : {}
|
|
1931
1970
|
};
|
|
1932
1971
|
}
|
|
1933
1972
|
function getMemberName(member) {
|
|
@@ -2026,6 +2065,9 @@ function serializeMethod(node, ctx) {
|
|
|
2026
2065
|
if (modifiers?.some((m) => m.kind === ts7.SyntaxKind.AsyncKeyword)) {
|
|
2027
2066
|
flags.async = true;
|
|
2028
2067
|
}
|
|
2068
|
+
if (modifiers?.some((m) => m.kind === ts7.SyntaxKind.AbstractKeyword)) {
|
|
2069
|
+
flags.abstract = true;
|
|
2070
|
+
}
|
|
2029
2071
|
return {
|
|
2030
2072
|
name,
|
|
2031
2073
|
kind: "method",
|
|
@@ -2062,6 +2104,24 @@ function serializeAccessor(node, ctx) {
|
|
|
2062
2104
|
const flags = {};
|
|
2063
2105
|
if (isStatic(node))
|
|
2064
2106
|
flags.static = true;
|
|
2107
|
+
let signatures;
|
|
2108
|
+
if (ts7.isSetAccessorDeclaration(node) && node.parameters.length > 0) {
|
|
2109
|
+
const param = node.parameters[0];
|
|
2110
|
+
const paramName = param.name.getText();
|
|
2111
|
+
const paramType = checker.getTypeAtLocation(param);
|
|
2112
|
+
registerReferencedTypes(paramType, ctx);
|
|
2113
|
+
signatures = [
|
|
2114
|
+
{
|
|
2115
|
+
parameters: [
|
|
2116
|
+
{
|
|
2117
|
+
name: paramName,
|
|
2118
|
+
schema: buildSchema(paramType, checker, ctx),
|
|
2119
|
+
required: true
|
|
2120
|
+
}
|
|
2121
|
+
]
|
|
2122
|
+
}
|
|
2123
|
+
];
|
|
2124
|
+
}
|
|
2065
2125
|
return {
|
|
2066
2126
|
name,
|
|
2067
2127
|
kind,
|
|
@@ -2069,6 +2129,7 @@ function serializeAccessor(node, ctx) {
|
|
|
2069
2129
|
tags: tags.length > 0 ? tags : undefined,
|
|
2070
2130
|
visibility,
|
|
2071
2131
|
schema,
|
|
2132
|
+
signatures,
|
|
2072
2133
|
flags: Object.keys(flags).length > 0 ? flags : undefined
|
|
2073
2134
|
};
|
|
2074
2135
|
}
|
|
@@ -2232,6 +2293,7 @@ function serializeInterface(node, ctx) {
|
|
|
2232
2293
|
const typeParameters = extractTypeParameters(node, checker);
|
|
2233
2294
|
const members = [];
|
|
2234
2295
|
const methodsByName = new Map;
|
|
2296
|
+
let callSignatureMember = null;
|
|
2235
2297
|
for (const member of node.members) {
|
|
2236
2298
|
if (ts9.isPropertySignature(member)) {
|
|
2237
2299
|
const propMember = serializePropertySignature(member, ctx);
|
|
@@ -2239,23 +2301,60 @@ function serializeInterface(node, ctx) {
|
|
|
2239
2301
|
members.push(propMember);
|
|
2240
2302
|
} else if (ts9.isMethodSignature(member)) {
|
|
2241
2303
|
const methodMember = serializeMethodSignature(member, ctx);
|
|
2242
|
-
if (methodMember?.name) {
|
|
2243
|
-
|
|
2304
|
+
if (methodMember?.name && methodMember.signatures) {
|
|
2305
|
+
const existing = methodsByName.get(methodMember.name);
|
|
2306
|
+
if (existing && existing.signatures) {
|
|
2307
|
+
const startIndex = existing.signatures.length;
|
|
2308
|
+
const newSigs = methodMember.signatures.map((sig, i) => ({
|
|
2309
|
+
...sig,
|
|
2310
|
+
overloadIndex: startIndex + i
|
|
2311
|
+
}));
|
|
2312
|
+
if (existing.signatures.length > 0 && existing.signatures[0].overloadIndex === undefined) {
|
|
2313
|
+
existing.signatures = existing.signatures.map((sig, i) => ({
|
|
2314
|
+
...sig,
|
|
2315
|
+
overloadIndex: i
|
|
2316
|
+
}));
|
|
2317
|
+
}
|
|
2318
|
+
existing.signatures.push(...newSigs);
|
|
2319
|
+
} else {
|
|
2244
2320
|
methodsByName.set(methodMember.name, methodMember);
|
|
2245
2321
|
}
|
|
2246
2322
|
}
|
|
2247
2323
|
} else if (ts9.isCallSignatureDeclaration(member)) {
|
|
2248
|
-
const
|
|
2249
|
-
if (
|
|
2250
|
-
|
|
2324
|
+
const callSig = serializeCallSignature(member, ctx);
|
|
2325
|
+
if (callSig && callSig.signatures) {
|
|
2326
|
+
if (callSignatureMember && callSignatureMember.signatures) {
|
|
2327
|
+
const startIndex = callSignatureMember.signatures.length;
|
|
2328
|
+
const newSigs = callSig.signatures.map((sig, i) => ({
|
|
2329
|
+
...sig,
|
|
2330
|
+
overloadIndex: startIndex + i
|
|
2331
|
+
}));
|
|
2332
|
+
if (callSignatureMember.signatures.length > 0 && callSignatureMember.signatures[0].overloadIndex === undefined) {
|
|
2333
|
+
callSignatureMember.signatures = callSignatureMember.signatures.map((sig, i) => ({
|
|
2334
|
+
...sig,
|
|
2335
|
+
overloadIndex: i
|
|
2336
|
+
}));
|
|
2337
|
+
}
|
|
2338
|
+
callSignatureMember.signatures.push(...newSigs);
|
|
2339
|
+
if (callSig.description && !callSignatureMember.description) {
|
|
2340
|
+
callSignatureMember.description = callSig.description;
|
|
2341
|
+
}
|
|
2342
|
+
} else {
|
|
2343
|
+
callSignatureMember = callSig;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2251
2346
|
} else if (ts9.isIndexSignatureDeclaration(member)) {
|
|
2252
2347
|
const indexMember = serializeIndexSignature(member, ctx);
|
|
2253
2348
|
if (indexMember)
|
|
2254
2349
|
members.push(indexMember);
|
|
2255
2350
|
}
|
|
2256
2351
|
}
|
|
2352
|
+
if (callSignatureMember) {
|
|
2353
|
+
members.push(callSignatureMember);
|
|
2354
|
+
}
|
|
2257
2355
|
members.push(...methodsByName.values());
|
|
2258
2356
|
const extendsClause = getInterfaceExtends(node, checker);
|
|
2357
|
+
const exportSignatures = callSignatureMember?.signatures && callSignatureMember.signatures.length > 0 ? callSignatureMember.signatures : undefined;
|
|
2259
2358
|
return {
|
|
2260
2359
|
id: name,
|
|
2261
2360
|
name,
|
|
@@ -2265,6 +2364,7 @@ function serializeInterface(node, ctx) {
|
|
|
2265
2364
|
source,
|
|
2266
2365
|
typeParameters,
|
|
2267
2366
|
members: members.length > 0 ? members : undefined,
|
|
2367
|
+
signatures: exportSignatures,
|
|
2268
2368
|
extends: extendsClause,
|
|
2269
2369
|
...deprecated ? { deprecated: true } : {},
|
|
2270
2370
|
...examples.length > 0 ? { examples } : {}
|
|
@@ -2366,10 +2466,7 @@ function serializeIndexSignature(node, ctx) {
|
|
|
2366
2466
|
kind: "index-signature",
|
|
2367
2467
|
description,
|
|
2368
2468
|
tags: tags.length > 0 ? tags : undefined,
|
|
2369
|
-
schema:
|
|
2370
|
-
type: "object",
|
|
2371
|
-
additionalProperties: valueSchema
|
|
2372
|
-
}
|
|
2469
|
+
schema: valueSchema
|
|
2373
2470
|
};
|
|
2374
2471
|
}
|
|
2375
2472
|
function getInterfaceExtends(node, checker) {
|
|
@@ -2639,10 +2736,10 @@ var SCHEMA_DIALECT_URLS = {
|
|
|
2639
2736
|
"draft-07": "http://json-schema.org/draft-07/schema#"
|
|
2640
2737
|
};
|
|
2641
2738
|
var TS_PRIMITIVE_NORMALIZATIONS = {
|
|
2642
|
-
void: () => ({ type: "null" }),
|
|
2739
|
+
void: () => ({ type: "null", "x-ts-type": "void" }),
|
|
2643
2740
|
never: () => ({ not: {} }),
|
|
2644
2741
|
any: () => ({}),
|
|
2645
|
-
unknown: () => ({}),
|
|
2742
|
+
unknown: () => ({ "x-ts-type": "unknown" }),
|
|
2646
2743
|
undefined: () => ({ type: "null" }),
|
|
2647
2744
|
bigint: () => ({ type: "integer", "x-ts-type": "bigint" }),
|
|
2648
2745
|
symbol: () => ({ type: "string", "x-ts-type": "symbol" })
|
|
@@ -3316,13 +3413,13 @@ async function extract(options) {
|
|
|
3316
3413
|
await new Promise((r) => setImmediate(r));
|
|
3317
3414
|
}
|
|
3318
3415
|
try {
|
|
3319
|
-
const { declaration, targetSymbol } = resolveExportTarget(symbol, typeChecker);
|
|
3416
|
+
const { declaration, targetSymbol, isTypeOnly } = resolveExportTarget(symbol, typeChecker);
|
|
3320
3417
|
if (!declaration) {
|
|
3321
3418
|
tracker.status = "skipped";
|
|
3322
3419
|
tracker.skipReason = "no-declaration";
|
|
3323
3420
|
continue;
|
|
3324
3421
|
}
|
|
3325
|
-
const exp = serializeDeclaration(declaration, symbol, targetSymbol, exportName, ctx);
|
|
3422
|
+
const exp = serializeDeclaration(declaration, symbol, targetSymbol, exportName, ctx, isTypeOnly);
|
|
3326
3423
|
if (exp) {
|
|
3327
3424
|
exports.push(exp);
|
|
3328
3425
|
tracker.status = "success";
|
|
@@ -3586,8 +3683,23 @@ function collectForgottenExports(exports, types, program, sourceFile, exportedId
|
|
|
3586
3683
|
}
|
|
3587
3684
|
return forgottenExports;
|
|
3588
3685
|
}
|
|
3686
|
+
function isTypeOnlyExport(symbol) {
|
|
3687
|
+
const declarations = symbol.declarations ?? [];
|
|
3688
|
+
for (const decl of declarations) {
|
|
3689
|
+
if (ts11.isExportSpecifier(decl)) {
|
|
3690
|
+
if (decl.isTypeOnly)
|
|
3691
|
+
return true;
|
|
3692
|
+
const exportDecl = decl.parent?.parent;
|
|
3693
|
+
if (exportDecl && ts11.isExportDeclaration(exportDecl) && exportDecl.isTypeOnly) {
|
|
3694
|
+
return true;
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
return false;
|
|
3699
|
+
}
|
|
3589
3700
|
function resolveExportTarget(symbol, checker) {
|
|
3590
3701
|
let targetSymbol = symbol;
|
|
3702
|
+
const isTypeOnly = isTypeOnlyExport(symbol);
|
|
3591
3703
|
if (symbol.flags & ts11.SymbolFlags.Alias) {
|
|
3592
3704
|
const aliasTarget = checker.getAliasedSymbol(symbol);
|
|
3593
3705
|
if (aliasTarget && aliasTarget !== symbol) {
|
|
@@ -3596,9 +3708,9 @@ function resolveExportTarget(symbol, checker) {
|
|
|
3596
3708
|
}
|
|
3597
3709
|
const declarations = targetSymbol.declarations ?? [];
|
|
3598
3710
|
const declaration = targetSymbol.valueDeclaration || declarations.find((decl) => decl.kind !== ts11.SyntaxKind.ExportSpecifier) || declarations[0];
|
|
3599
|
-
return { declaration, targetSymbol };
|
|
3711
|
+
return { declaration, targetSymbol, isTypeOnly };
|
|
3600
3712
|
}
|
|
3601
|
-
function serializeDeclaration(declaration, exportSymbol, _targetSymbol, exportName, ctx) {
|
|
3713
|
+
function serializeDeclaration(declaration, exportSymbol, _targetSymbol, exportName, ctx, isTypeOnly = false) {
|
|
3602
3714
|
let result = null;
|
|
3603
3715
|
if (ts11.isFunctionDeclaration(declaration)) {
|
|
3604
3716
|
result = serializeFunctionExport(declaration, ctx);
|
|
@@ -3622,6 +3734,12 @@ function serializeDeclaration(declaration, exportSymbol, _targetSymbol, exportNa
|
|
|
3622
3734
|
}
|
|
3623
3735
|
if (result) {
|
|
3624
3736
|
result = withExportName(result, exportName);
|
|
3737
|
+
if (isTypeOnly) {
|
|
3738
|
+
result = {
|
|
3739
|
+
...result,
|
|
3740
|
+
flags: { ...result.flags ?? {}, typeOnly: true }
|
|
3741
|
+
};
|
|
3742
|
+
}
|
|
3625
3743
|
}
|
|
3626
3744
|
return result;
|
|
3627
3745
|
}
|
package/dist/src/index.js
CHANGED