@openpkg-ts/sdk 0.54.8 → 0.54.9

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 CHANGED
@@ -1845,8 +1845,9 @@ import { SpecExport as SpecExport14 } from "@openpkg-ts/spec";
1845
1845
  import ts11 from "typescript";
1846
1846
  /**
1847
1847
  * @param declaredType - Written annotation of the variable holding `node`; when callable it supplies the signatures.
1848
+ * @param jsdocNode - Statement carrying the docs when that is not `node` (`() => {}`).
1848
1849
  */
1849
- declare function serializeFunctionExport(node: ts11.FunctionDeclaration | ts11.ArrowFunction | ts11.FunctionExpression, ctx: SerializerContext, nameOverride?: string, declaredType?: ts11.TypeNode): SpecExport14 | null;
1850
+ declare function serializeFunctionExport(node: ts11.FunctionDeclaration | ts11.ArrowFunction | ts11.FunctionExpression, ctx: SerializerContext, nameOverride?: string, declaredType?: ts11.TypeNode, jsdocNode?: ts11.Node): SpecExport14 | null;
1850
1851
  import { SpecExport as SpecExport15 } from "@openpkg-ts/spec";
1851
1852
  import ts12 from "typescript";
1852
1853
  declare function serializeInterface(node: ts12.InterfaceDeclaration, ctx: SerializerContext): SpecExport15 | null;
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 file = symbol.declarations?.[0]?.getSourceFile().fileName ?? "";
1857
- const scoped = `${packageLabel(file, ctx.workspacePackages)}.${name}`;
1858
- const scopedOwner = ctx.idOwner.get(scoped);
1859
- if (!scopedOwner || scopedOwner === key)
1860
- return claim(scoped);
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)
@@ -2850,20 +2895,22 @@ function buildSchemaFromTypeNode(node, checker, ctx) {
2850
2895
  let refId = name;
2851
2896
  if (symbol && ctx) {
2852
2897
  try {
2853
- refId = namedRefId(checker.getDeclaredTypeOfSymbol(symbol), name, ctx);
2898
+ refId = typeRefId(checker.getDeclaredTypeOfSymbol(symbol), ctx) || (symbol.flags & ts5.SymbolFlags.TypeAlias ? resolveTypeId(symbol, ctx) : name);
2854
2899
  } catch {
2855
2900
  refId = name;
2856
2901
  }
2857
2902
  }
2858
2903
  return withArgs({ $ref: `#/types/${refId}` });
2859
2904
  }
2860
- return { "x-ts-type": scrubImportQualifiers(node.getText()) };
2905
+ return {
2906
+ "x-ts-type": scrubImportQualifiers(node.getText().replace(/\s+/g, " "))
2907
+ };
2861
2908
  }
2862
2909
  const t = checker.getTypeFromTypeNode(node);
2863
2910
  if (!(t.flags & ts5.TypeFlags.Any)) {
2864
2911
  return buildSchema(t, checker, ctx);
2865
2912
  }
2866
- return { "x-ts-type": scrubImportQualifiers(node.getText()) };
2913
+ return { "x-ts-type": scrubImportQualifiers(node.getText().replace(/\s+/g, " ")) };
2867
2914
  }
2868
2915
  function stripUndefinedFromType(type, checker) {
2869
2916
  if (!type.isUnion())
@@ -3047,7 +3094,20 @@ function typeNodeDefersExpansion(node, checker, program) {
3047
3094
  const symbol = resolveAliasSymbol(raw, checker, undefined, program);
3048
3095
  return shouldDeferAlias(symbol);
3049
3096
  }
3050
- function cheapTypeText(type, _checker, typeNode) {
3097
+ function isStaleTypeParameterNode(type, checker, typeNode) {
3098
+ if (type.flags & ts5.TypeFlags.TypeParameter)
3099
+ return false;
3100
+ if (!ts5.isTypeReferenceNode(typeNode) || !ts5.isIdentifier(typeNode.typeName))
3101
+ return false;
3102
+ const symbol = checker.getSymbolAtLocation(typeNode.typeName);
3103
+ return !!symbol && (symbol.flags & ts5.SymbolFlags.TypeParameter) !== 0;
3104
+ }
3105
+ function cheapTypeText(type, checker, typeNode) {
3106
+ if (typeNode && isStaleTypeParameterNode(type, checker, typeNode)) {
3107
+ const argument = type.aliasSymbol?.getName() ?? type.getSymbol()?.getName();
3108
+ if (argument && !argument.startsWith("__") && !isBuiltinGeneric(argument))
3109
+ return argument;
3110
+ }
3051
3111
  if (typeNode) {
3052
3112
  try {
3053
3113
  const text = scrubImportQualifiers(typeNode.getText().replace(/\s+/g, " ").trim());
@@ -3338,10 +3398,10 @@ function buildSchema(type, checker, ctx, typeNode) {
3338
3398
  const schema = buildSchemaInternal(type, checker, ctx, typeNode);
3339
3399
  return ensureNonEmptySchema(schema, type, checker);
3340
3400
  }
3341
- function buildMaxDepthSchema(type, checker, typeNode) {
3401
+ function buildMaxDepthSchema(type, checker, typeNode, ctx) {
3342
3402
  if (type.flags & ts5.TypeFlags.Any) {
3343
3403
  if (typeNode)
3344
- return buildSchemaFromTypeNode(typeNode, checker);
3404
+ return buildSchemaFromTypeNode(typeNode, checker, ctx);
3345
3405
  return { "x-ts-type": checker.typeToString(type) };
3346
3406
  }
3347
3407
  if (type.flags & ts5.TypeFlags.TypeParameter && !isFluentThisType(type)) {
@@ -3354,7 +3414,7 @@ function buildMaxDepthSchema(type, checker, typeNode) {
3354
3414
  return builtinSchema(name);
3355
3415
  }
3356
3416
  if (!name.startsWith("__") && !isPrimitiveName(name)) {
3357
- return { $ref: `#/types/${name}` };
3417
+ return { $ref: `#/types/${ctx ? resolveTypeId(symbol, ctx) : name}` };
3358
3418
  }
3359
3419
  }
3360
3420
  if (type.flags & ts5.TypeFlags.String)
@@ -3377,18 +3437,18 @@ function buildMaxDepthSchema(type, checker, typeNode) {
3377
3437
  };
3378
3438
  }
3379
3439
  if (type.isUnion()) {
3380
- const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker));
3440
+ const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker, undefined, ctx));
3381
3441
  return { anyOf: schemas };
3382
3442
  }
3383
3443
  if (type.isIntersection()) {
3384
- const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker));
3444
+ const schemas = type.types.map((t) => buildMaxDepthSchema(t, checker, undefined, ctx));
3385
3445
  return { allOf: schemas };
3386
3446
  }
3387
3447
  return { type: checker.typeToString(type) };
3388
3448
  }
3389
3449
  function buildSchemaInternal(type, checker, ctx, typeNode) {
3390
3450
  if (isAtMaxDepth(ctx)) {
3391
- return buildMaxDepthSchema(type, checker, typeNode);
3451
+ return buildMaxDepthSchema(type, checker, typeNode, ctx);
3392
3452
  }
3393
3453
  if (ctx) {
3394
3454
  ctx.schemaOps += 1;
@@ -4934,8 +4994,18 @@ function serializeConstructor(node, ctx) {
4934
4994
  return null;
4935
4995
  return serializeConstructorSignature(node, sig, ctx);
4936
4996
  }
4997
+ function serializeConstructSignatures(sigs, ctx) {
4998
+ return sigs.map((sig, index) => {
4999
+ const typeParameters = extractTypeParametersFromSignature(sig, ctx.typeChecker);
5000
+ return {
5001
+ ...serializeConstructorSignature(sig.getDeclaration(), sig, ctx),
5002
+ ...typeParameters ? { typeParameters } : {},
5003
+ ...sigs.length > 1 ? { overloadIndex: index } : {}
5004
+ };
5005
+ });
5006
+ }
4937
5007
  function serializeConstructorSignature(node, sig, ctx) {
4938
- const { description, tags, examples, inlineTags } = getJSDocComment(node);
5008
+ const { description, tags, examples, inlineTags } = node ? getJSDocComment(node) : { description: undefined, tags: [], examples: [], inlineTags: undefined };
4939
5009
  const params = extractParameters(sig, ctx);
4940
5010
  return {
4941
5011
  description,
@@ -5222,12 +5292,12 @@ function signaturesFromDeclaredType(typeNode, ctx) {
5222
5292
  const callSignatures = ctx.typeChecker.getTypeFromTypeNode(inner).getCallSignatures();
5223
5293
  return callSignatures.length > 0 ? signaturesFromChecker(callSignatures, ctx) : undefined;
5224
5294
  }
5225
- function serializeFunctionExport(node, ctx, nameOverride, declaredType) {
5295
+ function serializeFunctionExport(node, ctx, nameOverride, declaredType, jsdocNode) {
5226
5296
  const symbol = ctx.typeChecker.getSymbolAtLocation(node.name ?? node);
5227
5297
  const name = nameOverride ?? symbol?.getName() ?? node.name?.getText() ?? anonymousDefaultName(node);
5228
5298
  if (!name)
5229
5299
  return null;
5230
- const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker);
5300
+ const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker, jsdocNode);
5231
5301
  const declaredFn = declaredType && unwrapParens(declaredType);
5232
5302
  const typeParameters = extractTypeParameters(declaredFn && ts11.isFunctionTypeNode(declaredFn) ? declaredFn : node, ctx.typeChecker);
5233
5303
  const signatures = (declaredType && signaturesFromDeclaredType(declaredType, ctx)) ?? (anySignatureDefers(node, ctx) ? signaturesFromAst(functionSignatureDecls(node, ctx), ctx) : signaturesFromChecker(ctx.typeChecker.getTypeAtLocation(node).getCallSignatures(), ctx));
@@ -5847,12 +5917,17 @@ function serializeVariable(node, statement, ctx) {
5847
5917
  const name = symbol?.getName() ?? node.name.getText();
5848
5918
  if (!name)
5849
5919
  return null;
5850
- const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker, statement);
5851
- const type = ctx.typeChecker.getTypeAtLocation(node);
5920
+ return serializeValue(name, node, symbol, statement, ctx.typeChecker.getTypeAtLocation(node), ts15.isVariableDeclaration(node) ? node.type : undefined, ctx);
5921
+ }
5922
+ function serializeDefaultExpression(node, symbol, type, ctx) {
5923
+ return serializeValue(symbol.getName(), node.expression, symbol, node, type, undefined, ctx);
5924
+ }
5925
+ function serializeValue(name, node, symbol, jsdocNode, type, typeNode, ctx) {
5926
+ const { description, tags, examples, source, deprecated, deprecationReason, inlineTags } = extractExportMetadata(node, symbol, ctx.typeChecker, jsdocNode);
5852
5927
  const schemaExtraction = extractSchemaType(type, ctx.typeChecker);
5853
5928
  const typeToSerialize = schemaExtraction?.outputType ?? type;
5854
5929
  registerReferencedTypes(typeToSerialize, ctx);
5855
- const schema = buildSchema(typeToSerialize, ctx.typeChecker, ctx, ts15.isVariableDeclaration(node) ? node.type : undefined);
5930
+ const schema = buildSchema(typeToSerialize, ctx.typeChecker, ctx, typeNode);
5856
5931
  const flags = schemaExtraction ? {
5857
5932
  schemaLibrary: schemaExtraction.adapter.id,
5858
5933
  ...schemaExtraction.inputType && schemaExtraction.inputType !== schemaExtraction.outputType ? { hasTransform: true } : {}
@@ -6438,6 +6513,7 @@ async function getExport(options) {
6438
6513
  }
6439
6514
  const ctx = createContext(program, sourceFile, { maxTypeDepth });
6440
6515
  ctx.exportedIds = exportedIds;
6516
+ claimExportedTypeIds(exportedSymbols, ctx);
6441
6517
  try {
6442
6518
  const originalDecls = targetSymbol.declarations ?? [];
6443
6519
  const isNamespaceExportDecl = originalDecls.some((d) => ts16.isNamespaceExport(d) || ts16.isNamespaceImport(d));
@@ -7611,7 +7687,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
7611
7687
  const symbol = type.aliasSymbol ?? type.getSymbol();
7612
7688
  const named = !!symbol && !symbol.getName().startsWith("__");
7613
7689
  const allowed = !named || !symbol || symbolAllowed(symbol);
7614
- if (named && allowed && symbol && !ctx.exportedIds.has(symbol.getName())) {
7690
+ if (named && allowed && symbol && !isExportedType(symbol)) {
7615
7691
  ctx.typeRegistry.registerType(type, ctx);
7616
7692
  const name = symbol.getName();
7617
7693
  if (!symbolByName.has(name)) {
@@ -7659,6 +7735,12 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
7659
7735
  }
7660
7736
  };
7661
7737
  const TYPE_SYMBOL_FLAGS = ts20.SymbolFlags.Interface | ts20.SymbolFlags.TypeAlias | ts20.SymbolFlags.Class | ts20.SymbolFlags.RegularEnum | ts20.SymbolFlags.ConstEnum;
7738
+ const isExportedType = (symbol) => {
7739
+ const name = symbol.getName();
7740
+ if (!ctx.exportedIds.has(name))
7741
+ return false;
7742
+ return !(symbol.flags & TYPE_SYMBOL_FLAGS) || resolveTypeId(symbol, ctx) === name;
7743
+ };
7662
7744
  const visitedSymbols = new Set;
7663
7745
  const symbolKind = (symbol) => {
7664
7746
  if (symbol.flags & ts20.SymbolFlags.Interface)
@@ -7673,6 +7755,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
7673
7755
  const resolved = resolveAliasSymbol(symbol, checker, undefined, ctx.program);
7674
7756
  return resolved;
7675
7757
  };
7758
+ const writtenWhenAny = (symbol, declared) => declared.flags & ts20.TypeFlags.Any ? symbol.declarations?.find(ts20.isTypeAliasDeclaration)?.type : undefined;
7676
7759
  const symbolByName = new Map;
7677
7760
  const registerTypeSymbol = (symbol) => {
7678
7761
  const name = symbol.getName();
@@ -7682,7 +7765,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
7682
7765
  return;
7683
7766
  if (!symbolAllowed(symbol))
7684
7767
  return;
7685
- if (ctx.exportedIds.has(name)) {
7768
+ if (isExportedType(symbol)) {
7686
7769
  walkDeclarations(symbol);
7687
7770
  return;
7688
7771
  }
@@ -7698,7 +7781,7 @@ function expandReachableTypes(exportedSymbols, ctx, opts) {
7698
7781
  id,
7699
7782
  name,
7700
7783
  kind: symbolKind(symbol),
7701
- schema: ensureNonEmptySchema(buildSchema(declared, checker, ctx), declared, checker)
7784
+ schema: ensureNonEmptySchema(buildSchema(declared, checker, ctx, writtenWhenAny(symbol, declared)), declared, checker)
7702
7785
  });
7703
7786
  }
7704
7787
  symbolByName.set(name, symbol);
@@ -8080,6 +8163,7 @@ async function extract(options) {
8080
8163
  workspacePackages: result.workspacePackages ?? new Map
8081
8164
  });
8082
8165
  ctx.exportedIds = exportedIds;
8166
+ claimExportedTypeIds(exportedSymbols, ctx);
8083
8167
  const filteredSymbols = exportedSymbols.filter((s) => shouldIncludeExport(s.getName(), only, ignore));
8084
8168
  const total = filteredSymbols.length;
8085
8169
  for (let i = 0;i < filteredSymbols.length; i++) {
@@ -8149,8 +8233,13 @@ async function extract(options) {
8149
8233
  }
8150
8234
  const exp = serializeDeclaration2(declaration, symbol, exportName, ctx, isTypeOnly);
8151
8235
  if (exp) {
8152
- if (!exp.members && isValueDeclaration(declaration) && hasTypeSide(targetSymbol)) {
8153
- mergedTypeSides.push({ index: exports.length, symbol: targetSymbol });
8236
+ const typeSide = mergedTypeSideOf(exp, declaration, targetSymbol, ctx);
8237
+ if (typeSide) {
8238
+ mergedTypeSides.push({
8239
+ index: exports.length,
8240
+ symbol: typeSide,
8241
+ ontoClass: ts21.isClassDeclaration(declaration)
8242
+ });
8154
8243
  }
8155
8244
  exports.push(exp);
8156
8245
  tracker.status = "success";
@@ -8170,8 +8259,8 @@ async function extract(options) {
8170
8259
  });
8171
8260
  }
8172
8261
  }
8173
- for (const { index, symbol } of mergedTypeSides) {
8174
- exports[index] = withMergedTypeSide(exports[index], symbol, ctx);
8262
+ for (const { index, symbol, ontoClass } of mergedTypeSides) {
8263
+ exports[index] = withMergedTypeSide(exports[index], symbol, ctx, ontoClass);
8175
8264
  }
8176
8265
  const verification = buildVerificationSummary(exportedSymbols.length, exports.length, exportTracker);
8177
8266
  const meta = await getPackageMeta(entryFile, baseDir);
@@ -8354,21 +8443,18 @@ function serializeDeclaration2(declaration, exportSymbol, exportName, ctx, isTyp
8354
8443
  result = serializeVariable(declaration, varStatement, ctx);
8355
8444
  if (result?.kind === "variable") {
8356
8445
  const type = ctx.typeChecker.getTypeAtLocation(declaration);
8357
- if (type.getConstructSignatures().length > 0) {
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
- }
8446
+ result = withCallableKind(result, type, callSignaturesForVariable(declaration, ctx), ctx);
8369
8447
  }
8370
8448
  }
8371
8449
  }
8450
+ } else if (ts21.isExportAssignment(declaration) && !declaration.isExportEquals) {
8451
+ const expression = skipOuterExpressions(declaration.expression);
8452
+ if (ts21.isArrowFunction(expression) || ts21.isFunctionExpression(expression)) {
8453
+ result = serializeFunctionExport(expression, ctx, exportName, undefined, declaration);
8454
+ } else {
8455
+ const type = ctx.typeChecker.getTypeOfSymbol(exportSymbol);
8456
+ result = withCallableKind(serializeDefaultExpression(declaration, exportSymbol, type, ctx), type, type.getCallSignatures(), ctx);
8457
+ }
8372
8458
  } else if (ts21.isNamespaceExport(declaration) || ts21.isModuleDeclaration(declaration) || ts21.isNamespaceImport(declaration) || ts21.isSourceFile(declaration)) {
8373
8459
  try {
8374
8460
  result = serializeNamespaceExport(exportSymbol, exportName, ctx);
@@ -8559,6 +8645,30 @@ function variableStatementOf(declaration) {
8559
8645
  const statement = node.parent?.parent;
8560
8646
  return statement && ts21.isVariableStatement(statement) ? statement : undefined;
8561
8647
  }
8648
+ function skipOuterExpressions(expression) {
8649
+ let node = expression;
8650
+ while (ts21.isParenthesizedExpression(node) || ts21.isAsExpression(node) || ts21.isSatisfiesExpression(node) || ts21.isTypeAssertionExpression(node) || ts21.isNonNullExpression(node)) {
8651
+ node = node.expression;
8652
+ }
8653
+ return node;
8654
+ }
8655
+ function withCallableKind(entry, type, callSigs, ctx) {
8656
+ const constructSigs = type.getConstructSignatures();
8657
+ if (constructSigs.length > 0) {
8658
+ return {
8659
+ ...entry,
8660
+ kind: "class",
8661
+ signatures: serializeConstructSignatures(constructSigs, ctx)
8662
+ };
8663
+ }
8664
+ if (callSigs.length === 0)
8665
+ return entry;
8666
+ return {
8667
+ ...entry,
8668
+ kind: "function",
8669
+ signatures: buildSignatures(callSigs, ctx.typeChecker, ctx)
8670
+ };
8671
+ }
8562
8672
  function callSignaturesForVariable(declaration, ctx) {
8563
8673
  const checker = ctx.typeChecker;
8564
8674
  if (ts21.isVariableDeclaration(declaration) && declaration.type && ts21.isTypeReferenceNode(declaration.type)) {
@@ -8609,15 +8719,35 @@ function isValueDeclaration(declaration) {
8609
8719
  function hasTypeSide(symbol) {
8610
8720
  return (symbol.flags & (ts21.SymbolFlags.Interface | ts21.SymbolFlags.TypeAlias)) !== 0;
8611
8721
  }
8612
- function withMergedTypeSide(entry, symbol, ctx) {
8722
+ function mergedTypeSideOf(exp, declaration, symbol, ctx) {
8723
+ if (ts21.isClassDeclaration(declaration)) {
8724
+ return symbol.flags & ts21.SymbolFlags.Interface ? symbol : undefined;
8725
+ }
8726
+ if (exp.members || !isValueDeclaration(declaration))
8727
+ return;
8728
+ if (hasTypeSide(symbol))
8729
+ return symbol;
8730
+ if (exp.kind !== "class")
8731
+ return;
8732
+ const [construct] = ctx.typeChecker.getTypeAtLocation(declaration).getConstructSignatures();
8733
+ const instance = construct?.getReturnType();
8734
+ const constructed = instance && (instance.aliasSymbol ?? instance.getSymbol());
8735
+ if (!constructed || !hasTypeSide(constructed))
8736
+ return;
8737
+ if (ctx.shouldExpandExternal && !ctx.shouldExpandExternal(constructed))
8738
+ return;
8739
+ return constructed;
8740
+ }
8741
+ function withMergedTypeSide(entry, symbol, ctx, ontoClass) {
8613
8742
  const typeSide = serializeMergedTypeSide(symbol, ctx);
8614
8743
  if (!typeSide)
8615
8744
  return entry;
8616
8745
  const { members, description, tags, ...instanceType } = typeSide;
8746
+ const own = new Set(entry.members?.map((m) => m.name));
8617
8747
  return {
8618
8748
  ...entry,
8619
- members,
8620
- ...entry.kind === "class" ? instanceType : {},
8749
+ members: [...entry.members ?? [], ...(members ?? []).filter((m) => !own.has(m.name))],
8750
+ ...entry.kind === "class" && !ontoClass ? instanceType : {},
8621
8751
  ...entry.description ? {} : { description, tags: [...entry.tags ?? [], ...tags ?? []] }
8622
8752
  };
8623
8753
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpkg-ts/sdk",
3
- "version": "0.54.8",
3
+ "version": "0.54.9",
4
4
  "description": "TypeScript API extraction SDK - programmatic primitives for OpenPkg specs",
5
5
  "keywords": [
6
6
  "openpkg",
@@ -43,7 +43,7 @@
43
43
  "test": "bun test"
44
44
  },
45
45
  "dependencies": {
46
- "@openpkg-ts/spec": "^0.54.8",
46
+ "@openpkg-ts/spec": "^0.54.9",
47
47
  "picomatch": "4.0.3",
48
48
  "typescript": "^5.0.0 || ^6.0.0"
49
49
  },