@doccov/sdk 0.7.0 → 0.8.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.
Files changed (2) hide show
  1. package/dist/index.js +142 -10
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2063,6 +2063,35 @@ import * as fs2 from "node:fs";
2063
2063
  import * as path3 from "node:path";
2064
2064
  import { SCHEMA_URL, SCHEMA_VERSION } from "@openpkg-ts/spec";
2065
2065
 
2066
+ // src/analysis/decorator-utils.ts
2067
+ function extractDecorators(node) {
2068
+ if (!ts2.canHaveDecorators(node)) {
2069
+ return;
2070
+ }
2071
+ const decorators = ts2.getDecorators(node);
2072
+ if (!decorators || decorators.length === 0) {
2073
+ return;
2074
+ }
2075
+ return decorators.map((decorator) => {
2076
+ const expression = decorator.expression;
2077
+ if (ts2.isIdentifier(expression)) {
2078
+ return { name: expression.text };
2079
+ }
2080
+ if (ts2.isCallExpression(expression)) {
2081
+ const name = ts2.isIdentifier(expression.expression) ? expression.expression.text : expression.expression.getText();
2082
+ const argumentsText = expression.arguments.map((arg) => arg.getText());
2083
+ return { name, argumentsText };
2084
+ }
2085
+ if (ts2.isPropertyAccessExpression(expression)) {
2086
+ return { name: expression.getText() };
2087
+ }
2088
+ return { name: expression.getText() };
2089
+ });
2090
+ }
2091
+ function extractParameterDecorators(param) {
2092
+ return extractDecorators(param);
2093
+ }
2094
+
2066
2095
  // src/utils/parameter-utils.ts
2067
2096
  var BUILTIN_TYPE_SCHEMAS = {
2068
2097
  Date: { type: "string", format: "date-time" },
@@ -2991,6 +3020,10 @@ function structureParameter(param, paramDecl, paramType, typeChecker, typeRefs,
2991
3020
  if (paramDecl.dotDotDotToken) {
2992
3021
  out.rest = true;
2993
3022
  }
3023
+ const decorators = extractParameterDecorators(paramDecl);
3024
+ if (decorators) {
3025
+ out.decorators = decorators;
3026
+ }
2994
3027
  return out;
2995
3028
  }
2996
3029
 
@@ -2999,6 +3032,7 @@ function parseJSDocBlock(commentText) {
2999
3032
  const result = {
3000
3033
  description: "",
3001
3034
  params: [],
3035
+ throws: [],
3002
3036
  examples: [],
3003
3037
  tags: [],
3004
3038
  rawParamNames: []
@@ -3104,6 +3138,22 @@ function parseReturnContent(content) {
3104
3138
  description: processInlineLinks(remaining)
3105
3139
  };
3106
3140
  }
3141
+ function parseThrowsContent(content) {
3142
+ const trimmed = content.trim();
3143
+ let remaining = trimmed;
3144
+ let type;
3145
+ if (remaining.startsWith("{")) {
3146
+ const typeEnd = findMatchingBrace(remaining, 0);
3147
+ if (typeEnd > 0) {
3148
+ type = remaining.slice(1, typeEnd).trim();
3149
+ remaining = remaining.slice(typeEnd + 1).trim();
3150
+ }
3151
+ }
3152
+ return {
3153
+ type,
3154
+ description: processInlineLinks(remaining)
3155
+ };
3156
+ }
3107
3157
  function findMatchingBrace(text, startIndex) {
3108
3158
  if (text[startIndex] !== "{")
3109
3159
  return -1;
@@ -3179,6 +3229,18 @@ function processTagContent(result, tag, content) {
3179
3229
  });
3180
3230
  break;
3181
3231
  }
3232
+ case "throws":
3233
+ case "throw":
3234
+ case "exception": {
3235
+ const parsed = parseThrowsContent(trimmedContent);
3236
+ result.throws.push(parsed);
3237
+ result.tags.push({
3238
+ name: "throws",
3239
+ text: trimmedContent,
3240
+ typeAnnotation: parsed.type
3241
+ });
3242
+ break;
3243
+ }
3182
3244
  case "example": {
3183
3245
  const example = processInlineLinks(trimmedContent);
3184
3246
  if (example) {
@@ -3334,6 +3396,9 @@ function parseJSDocText(commentText) {
3334
3396
  result.returns = parsed.returns.description;
3335
3397
  result.returnsType = parsed.returns.type;
3336
3398
  }
3399
+ if (parsed.throws.length > 0) {
3400
+ result.throws = parsed.throws;
3401
+ }
3337
3402
  return result;
3338
3403
  }
3339
3404
  function extractDestructuredParams(parsedDoc, paramName) {
@@ -3473,6 +3538,7 @@ function serializeClass(declaration, symbol, context) {
3473
3538
  const parsedDoc = parseJSDocComment(symbol, context.checker);
3474
3539
  const description = parsedDoc?.description ?? getJSDocComment(symbol, context.checker);
3475
3540
  const metadata = extractPresentationMetadata(parsedDoc);
3541
+ const decorators = extractDecorators(declaration);
3476
3542
  const exportEntry = {
3477
3543
  id: symbol.getName(),
3478
3544
  name: symbol.getName(),
@@ -3486,7 +3552,8 @@ function serializeClass(declaration, symbol, context) {
3486
3552
  ...heritage.extends ? { extends: heritage.extends } : {},
3487
3553
  ...heritage.implements && heritage.implements.length > 0 ? { implements: heritage.implements } : {},
3488
3554
  tags: parsedDoc?.tags,
3489
- examples: parsedDoc?.examples
3555
+ examples: parsedDoc?.examples,
3556
+ decorators
3490
3557
  };
3491
3558
  const typeDefinition = {
3492
3559
  id: symbol.getName(),
@@ -3579,7 +3646,8 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
3579
3646
  schema,
3580
3647
  description: memberDoc?.description ?? (memberSymbol ? getJSDocComment(memberSymbol, checker) : undefined),
3581
3648
  flags: Object.keys(flags).length > 0 ? flags : undefined,
3582
- tags: memberDoc?.tags
3649
+ tags: memberDoc?.tags,
3650
+ decorators: extractDecorators(member)
3583
3651
  });
3584
3652
  continue;
3585
3653
  }
@@ -3601,7 +3669,8 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
3601
3669
  signatures,
3602
3670
  description: methodDoc?.description ?? (memberSymbol ? getJSDocComment(memberSymbol, checker) : undefined),
3603
3671
  flags: getMethodFlags(member),
3604
- tags: methodDoc?.tags
3672
+ tags: methodDoc?.tags,
3673
+ decorators: extractDecorators(member)
3605
3674
  });
3606
3675
  continue;
3607
3676
  }
@@ -3621,7 +3690,8 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
3621
3690
  visibility: getMemberVisibility(member.modifiers),
3622
3691
  signatures,
3623
3692
  description: ctorDoc?.description ?? (ctorSymbol ? getJSDocComment(ctorSymbol, checker) : undefined),
3624
- tags: ctorDoc?.tags
3693
+ tags: ctorDoc?.tags,
3694
+ decorators: extractDecorators(member)
3625
3695
  });
3626
3696
  continue;
3627
3697
  }
@@ -3654,7 +3724,8 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
3654
3724
  schema,
3655
3725
  description: memberDoc?.description ?? (memberSymbol ? getJSDocComment(memberSymbol, checker) : undefined),
3656
3726
  flags: Object.keys(flags).length > 0 ? flags : undefined,
3657
- tags: memberDoc?.tags
3727
+ tags: memberDoc?.tags,
3728
+ decorators: extractDecorators(primaryMember)
3658
3729
  });
3659
3730
  }
3660
3731
  }
@@ -3662,6 +3733,10 @@ function serializeClassMembers(declaration, checker, typeRefs, referencedTypes)
3662
3733
  }
3663
3734
  function serializeSignature(signature, checker, typeRefs, referencedTypes, doc, symbol) {
3664
3735
  const typeParameters = serializeTypeParameterDeclarations(signature.declaration?.typeParameters, checker, referencedTypes);
3736
+ const throws = doc?.throws?.map((t) => ({
3737
+ type: t.type,
3738
+ description: t.description
3739
+ }));
3665
3740
  return {
3666
3741
  parameters: signature.getParameters().map((param) => {
3667
3742
  const paramDecl = param.valueDeclaration;
@@ -3675,7 +3750,8 @@ function serializeSignature(signature, checker, typeRefs, referencedTypes, doc,
3675
3750
  description: doc?.returns || ""
3676
3751
  },
3677
3752
  description: doc?.description || (symbol ? getJSDocComment(symbol, checker) : undefined),
3678
- typeParameters
3753
+ typeParameters,
3754
+ throws: throws && throws.length > 0 ? throws : undefined
3679
3755
  };
3680
3756
  }
3681
3757
  function getMemberVisibility(modifiers) {
@@ -3793,6 +3869,10 @@ function serializeCallSignatures(signatures, symbol, context, parsedDoc) {
3793
3869
  ...isAsserts ? { asserts: true } : {}
3794
3870
  };
3795
3871
  }
3872
+ const throws = functionDoc?.throws?.map((t) => ({
3873
+ type: t.type,
3874
+ description: t.description
3875
+ }));
3796
3876
  return {
3797
3877
  parameters,
3798
3878
  returns: {
@@ -3803,7 +3883,8 @@ function serializeCallSignatures(signatures, symbol, context, parsedDoc) {
3803
3883
  },
3804
3884
  description: functionDoc?.description || undefined,
3805
3885
  typeParameters,
3806
- overloadIndex: signatures.length > 1 ? index : undefined
3886
+ overloadIndex: signatures.length > 1 ? index : undefined,
3887
+ throws: throws && throws.length > 0 ? throws : undefined
3807
3888
  };
3808
3889
  });
3809
3890
  }
@@ -4095,6 +4176,8 @@ function serializeNamespace(declaration, symbol, context) {
4095
4176
  const description = parsedDoc?.description ?? getJSDocComment(symbol, checker);
4096
4177
  const metadata = extractPresentationMetadata(parsedDoc);
4097
4178
  const members = extractNamespaceMembers(declaration, checker);
4179
+ const isAugmentation = ts2.isStringLiteral(declaration.name);
4180
+ const augmentedModule = isAugmentation ? declaration.name.text : undefined;
4098
4181
  return {
4099
4182
  id: symbol.getName(),
4100
4183
  name: symbol.getName(),
@@ -4105,7 +4188,9 @@ function serializeNamespace(declaration, symbol, context) {
4105
4188
  source: getSourceLocation(declaration),
4106
4189
  members: members.length > 0 ? members : undefined,
4107
4190
  tags: parsedDoc?.tags,
4108
- examples: parsedDoc?.examples
4191
+ examples: parsedDoc?.examples,
4192
+ isAugmentation: isAugmentation || undefined,
4193
+ augmentedModule
4109
4194
  };
4110
4195
  }
4111
4196
  function extractNamespaceMembers(declaration, checker) {
@@ -4197,6 +4282,46 @@ function extractNamespaceMembers(declaration, checker) {
4197
4282
  }
4198
4283
 
4199
4284
  // src/analysis/serializers/type-aliases.ts
4285
+ function analyzeTypeAliasKind(typeNode) {
4286
+ if (ts2.isConditionalTypeNode(typeNode)) {
4287
+ return {
4288
+ typeAliasKind: "conditional",
4289
+ conditionalType: {
4290
+ checkType: typeNode.checkType.getText(),
4291
+ extendsType: typeNode.extendsType.getText(),
4292
+ trueType: typeNode.trueType.getText(),
4293
+ falseType: typeNode.falseType.getText()
4294
+ }
4295
+ };
4296
+ }
4297
+ if (ts2.isMappedTypeNode(typeNode)) {
4298
+ const readonlyToken = typeNode.readonlyToken;
4299
+ const questionToken = typeNode.questionToken;
4300
+ return {
4301
+ typeAliasKind: "mapped",
4302
+ mappedType: {
4303
+ typeParameter: typeNode.typeParameter.getText(),
4304
+ nameType: typeNode.nameType?.getText(),
4305
+ valueType: typeNode.type?.getText(),
4306
+ readonly: readonlyToken ? readonlyToken.kind === ts2.SyntaxKind.MinusToken ? "-" : readonlyToken.kind === ts2.SyntaxKind.PlusToken ? "+" : true : undefined,
4307
+ optional: questionToken ? questionToken.kind === ts2.SyntaxKind.MinusToken ? "-" : questionToken.kind === ts2.SyntaxKind.PlusToken ? "+" : true : undefined
4308
+ }
4309
+ };
4310
+ }
4311
+ if (ts2.isTemplateLiteralTypeNode(typeNode)) {
4312
+ return { typeAliasKind: "template-literal" };
4313
+ }
4314
+ if (containsInferType(typeNode)) {
4315
+ return { typeAliasKind: "infer" };
4316
+ }
4317
+ return { typeAliasKind: "alias" };
4318
+ }
4319
+ function containsInferType(node) {
4320
+ if (ts2.isInferTypeNode(node)) {
4321
+ return true;
4322
+ }
4323
+ return ts2.forEachChild(node, containsInferType) ?? false;
4324
+ }
4200
4325
  function serializeTypeAlias(declaration, symbol, context) {
4201
4326
  const { checker, typeRegistry } = context;
4202
4327
  const typeRefs = typeRegistry.getTypeRefs();
@@ -4205,6 +4330,7 @@ function serializeTypeAlias(declaration, symbol, context) {
4205
4330
  const description = parsedDoc?.description ?? getJSDocComment(symbol, checker);
4206
4331
  const metadata = extractPresentationMetadata(parsedDoc);
4207
4332
  const typeParameters = serializeTypeParameterDeclarations(declaration.typeParameters, checker, referencedTypes);
4333
+ const typeAnalysis = analyzeTypeAliasKind(declaration.type);
4208
4334
  const exportEntry = {
4209
4335
  id: symbol.getName(),
4210
4336
  name: symbol.getName(),
@@ -4216,7 +4342,10 @@ function serializeTypeAlias(declaration, symbol, context) {
4216
4342
  source: getSourceLocation(declaration),
4217
4343
  typeParameters,
4218
4344
  tags: parsedDoc?.tags,
4219
- examples: parsedDoc?.examples
4345
+ examples: parsedDoc?.examples,
4346
+ typeAliasKind: typeAnalysis.typeAliasKind !== "alias" ? typeAnalysis.typeAliasKind : undefined,
4347
+ conditionalType: typeAnalysis.conditionalType,
4348
+ mappedType: typeAnalysis.mappedType
4220
4349
  };
4221
4350
  const aliasType = checker.getTypeAtLocation(declaration.type);
4222
4351
  const aliasName = symbol.getName();
@@ -4235,7 +4364,10 @@ function serializeTypeAlias(declaration, symbol, context) {
4235
4364
  kind: "type",
4236
4365
  description,
4237
4366
  source: getSourceLocation(declaration),
4238
- tags: parsedDoc?.tags
4367
+ tags: parsedDoc?.tags,
4368
+ typeAliasKind: typeAnalysis.typeAliasKind !== "alias" ? typeAnalysis.typeAliasKind : undefined,
4369
+ conditionalType: typeAnalysis.conditionalType,
4370
+ mappedType: typeAnalysis.mappedType
4239
4371
  };
4240
4372
  if (typeof aliasSchema === "string") {
4241
4373
  typeDefinition.type = aliasSchema;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doccov/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "DocCov SDK - Documentation coverage and drift detection for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",
@@ -39,7 +39,7 @@
39
39
  "dist"
40
40
  ],
41
41
  "dependencies": {
42
- "@openpkg-ts/spec": "^0.5.0",
42
+ "@openpkg-ts/spec": "^0.6.0",
43
43
  "@vercel/sandbox": "^1.0.3",
44
44
  "mdast": "^3.0.0",
45
45
  "remark-mdx": "^3.1.0",