@doccov/sdk 0.3.4 → 0.3.6

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.
Files changed (2) hide show
  1. package/dist/index.js +99 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1870,6 +1870,16 @@ function schemasAreEqual(left, right) {
1870
1870
  };
1871
1871
  return JSON.stringify(normalize(left)) === JSON.stringify(normalize(right));
1872
1872
  }
1873
+ function deduplicateSchemas(schemas) {
1874
+ const result = [];
1875
+ for (const schema of schemas) {
1876
+ const isDuplicate = result.some((existing) => schemasAreEqual(existing, schema));
1877
+ if (!isDuplicate) {
1878
+ result.push(schema);
1879
+ }
1880
+ }
1881
+ return result;
1882
+ }
1873
1883
  function formatTypeReference(type, typeChecker, typeRefs, referencedTypes, visitedAliases) {
1874
1884
  const visited = visitedAliases ?? new Set;
1875
1885
  const aliasSymbol = type.aliasSymbol;
@@ -1929,15 +1939,19 @@ function formatTypeReference(type, typeChecker, typeRefs, referencedTypes, visit
1929
1939
  if (type.isUnion()) {
1930
1940
  const unionType = type;
1931
1941
  const parts = unionType.types.map((t) => formatTypeReference(t, typeChecker, typeRefs, referencedTypes, visited));
1942
+ const uniqueParts = deduplicateSchemas(parts);
1943
+ if (uniqueParts.length === 1) {
1944
+ return uniqueParts[0];
1945
+ }
1932
1946
  const discriminatorProp = findDiscriminatorProperty(unionType.types, typeChecker);
1933
1947
  if (discriminatorProp) {
1934
1948
  return {
1935
- anyOf: parts,
1949
+ anyOf: uniqueParts,
1936
1950
  discriminator: { propertyName: discriminatorProp }
1937
1951
  };
1938
1952
  }
1939
1953
  return {
1940
- anyOf: parts
1954
+ anyOf: uniqueParts
1941
1955
  };
1942
1956
  }
1943
1957
  if (type.isIntersection()) {
@@ -2910,6 +2924,86 @@ function serializeFunctionExport(declaration, symbol, context) {
2910
2924
  }
2911
2925
 
2912
2926
  // src/analysis/serializers/interfaces.ts
2927
+ function serializeInterfaceMembers(declaration, checker, typeRefs, referencedTypes) {
2928
+ const members = [];
2929
+ for (const member of declaration.members) {
2930
+ if (ts2.isPropertySignature(member)) {
2931
+ const memberName = member.name?.getText();
2932
+ if (!memberName)
2933
+ continue;
2934
+ const memberSymbol = member.name ? checker.getSymbolAtLocation(member.name) : undefined;
2935
+ const memberDoc = memberSymbol ? parseJSDocComment(memberSymbol, checker) : null;
2936
+ const memberType = member.type ? checker.getTypeAtLocation(member.type) : checker.getAnyType();
2937
+ collectReferencedTypes(memberType, checker, referencedTypes);
2938
+ const schema = formatTypeReference(memberType, checker, typeRefs, referencedTypes);
2939
+ const flags = {};
2940
+ if (member.questionToken) {
2941
+ flags.optional = true;
2942
+ }
2943
+ if (member.modifiers?.some((mod) => mod.kind === ts2.SyntaxKind.ReadonlyKeyword)) {
2944
+ flags.readonly = true;
2945
+ }
2946
+ members.push({
2947
+ id: memberName,
2948
+ name: memberName,
2949
+ kind: "property",
2950
+ schema,
2951
+ description: memberDoc?.description ?? (memberSymbol ? getJSDocComment(memberSymbol, checker) : undefined),
2952
+ flags: Object.keys(flags).length > 0 ? flags : undefined,
2953
+ tags: memberDoc?.tags
2954
+ });
2955
+ } else if (ts2.isMethodSignature(member)) {
2956
+ const methodName = member.name?.getText();
2957
+ if (!methodName)
2958
+ continue;
2959
+ const memberSymbol = member.name ? checker.getSymbolAtLocation(member.name) : undefined;
2960
+ const methodDoc = memberSymbol ? parseJSDocComment(memberSymbol, checker) : null;
2961
+ const signature = checker.getSignatureFromDeclaration(member);
2962
+ if (signature) {
2963
+ const parameters = signature.getParameters().map((param) => {
2964
+ const paramDecl = param.declarations?.find(ts2.isParameter);
2965
+ const paramType = paramDecl ? checker.getTypeAtLocation(paramDecl) : checker.getTypeOfSymbolAtLocation(param, member);
2966
+ collectReferencedTypes(paramType, checker, referencedTypes);
2967
+ if (paramDecl) {
2968
+ const paramDoc = getParameterDocumentation(param, paramDecl, checker);
2969
+ return structureParameter(param, paramDecl, paramType, checker, typeRefs, null, paramDoc, referencedTypes);
2970
+ }
2971
+ return {
2972
+ name: param.getName(),
2973
+ required: !(param.flags & ts2.SymbolFlags.Optional),
2974
+ schema: formatTypeReference(paramType, checker, typeRefs, referencedTypes)
2975
+ };
2976
+ });
2977
+ const returnType = signature.getReturnType();
2978
+ if (returnType) {
2979
+ collectReferencedTypes(returnType, checker, referencedTypes);
2980
+ }
2981
+ const flags = {};
2982
+ if (member.questionToken) {
2983
+ flags.optional = true;
2984
+ }
2985
+ members.push({
2986
+ id: methodName,
2987
+ name: methodName,
2988
+ kind: "method",
2989
+ signatures: [
2990
+ {
2991
+ parameters,
2992
+ returns: {
2993
+ schema: returnType ? formatTypeReference(returnType, checker, typeRefs, referencedTypes) : { type: "void" }
2994
+ },
2995
+ description: methodDoc?.description
2996
+ }
2997
+ ],
2998
+ description: methodDoc?.description ?? (memberSymbol ? getJSDocComment(memberSymbol, checker) : undefined),
2999
+ flags: Object.keys(flags).length > 0 ? flags : undefined,
3000
+ tags: methodDoc?.tags
3001
+ });
3002
+ }
3003
+ }
3004
+ }
3005
+ return members;
3006
+ }
2913
3007
  function serializeInterface(declaration, symbol, context) {
2914
3008
  const { checker, typeRegistry } = context;
2915
3009
  const parsedDoc = parseJSDocComment(symbol, checker);
@@ -2918,6 +3012,7 @@ function serializeInterface(declaration, symbol, context) {
2918
3012
  const referencedTypes = typeRegistry.getReferencedTypes();
2919
3013
  const typeRefs = typeRegistry.getTypeRefs();
2920
3014
  const typeParameters = serializeTypeParameterDeclarations(declaration.typeParameters, checker, referencedTypes);
3015
+ const members = serializeInterfaceMembers(declaration, checker, typeRefs, referencedTypes);
2921
3016
  const exportEntry = {
2922
3017
  id: symbol.getName(),
2923
3018
  name: symbol.getName(),
@@ -2926,6 +3021,7 @@ function serializeInterface(declaration, symbol, context) {
2926
3021
  deprecated: isSymbolDeprecated(symbol),
2927
3022
  description,
2928
3023
  source: getSourceLocation(declaration),
3024
+ members,
2929
3025
  typeParameters,
2930
3026
  tags: parsedDoc?.tags,
2931
3027
  examples: parsedDoc?.examples
@@ -2937,6 +3033,7 @@ function serializeInterface(declaration, symbol, context) {
2937
3033
  ...metadata,
2938
3034
  kind: "interface",
2939
3035
  schema,
3036
+ members,
2940
3037
  description,
2941
3038
  source: getSourceLocation(declaration),
2942
3039
  tags: parsedDoc?.tags
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doccov/sdk",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "DocCov SDK - Documentation coverage and drift detection for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",