@api-extractor-tools/eslint-plugin 0.1.0-alpha.0 → 0.1.0-alpha.1

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 (104) hide show
  1. package/ARCHITECTURE.md +201 -0
  2. package/CHANGELOG.md +24 -0
  3. package/README.md +306 -10
  4. package/api-extractor.json +1 -0
  5. package/dist/configs/recommended.d.ts +1 -1
  6. package/dist/configs/recommended.d.ts.map +1 -1
  7. package/dist/configs/recommended.js +7 -1
  8. package/dist/configs/recommended.js.map +1 -1
  9. package/dist/index.d.ts +9 -16
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +11 -15
  12. package/dist/index.js.map +1 -1
  13. package/dist/node.d.ts +28 -0
  14. package/dist/node.d.ts.map +1 -0
  15. package/dist/node.js +41 -0
  16. package/dist/node.js.map +1 -0
  17. package/dist/rules/extra-release-tag.d.ts +24 -0
  18. package/dist/rules/extra-release-tag.d.ts.map +1 -0
  19. package/dist/rules/extra-release-tag.js +141 -0
  20. package/dist/rules/extra-release-tag.js.map +1 -0
  21. package/dist/rules/forgotten-export.d.ts +24 -0
  22. package/dist/rules/forgotten-export.d.ts.map +1 -0
  23. package/dist/rules/forgotten-export.js +212 -0
  24. package/dist/rules/forgotten-export.js.map +1 -0
  25. package/dist/rules/incompatible-release-tags.d.ts +25 -0
  26. package/dist/rules/incompatible-release-tags.d.ts.map +1 -0
  27. package/dist/rules/incompatible-release-tags.js +237 -0
  28. package/dist/rules/incompatible-release-tags.js.map +1 -0
  29. package/dist/rules/index.d.ts +2 -6
  30. package/dist/rules/index.d.ts.map +1 -1
  31. package/dist/rules/index.js +13 -1
  32. package/dist/rules/index.js.map +1 -1
  33. package/dist/rules/missing-release-tag.d.ts +4 -0
  34. package/dist/rules/missing-release-tag.d.ts.map +1 -1
  35. package/dist/rules/missing-release-tag.js +14 -21
  36. package/dist/rules/missing-release-tag.js.map +1 -1
  37. package/dist/rules/override-keyword.d.ts +4 -0
  38. package/dist/rules/override-keyword.d.ts.map +1 -1
  39. package/dist/rules/override-keyword.js +9 -11
  40. package/dist/rules/override-keyword.js.map +1 -1
  41. package/dist/rules/package-documentation.d.ts +1 -1
  42. package/dist/rules/package-documentation.d.ts.map +1 -1
  43. package/dist/rules/package-documentation.js +7 -28
  44. package/dist/rules/package-documentation.js.map +1 -1
  45. package/dist/rules/public-on-non-exported.d.ts +24 -0
  46. package/dist/rules/public-on-non-exported.d.ts.map +1 -0
  47. package/dist/rules/public-on-non-exported.js +191 -0
  48. package/dist/rules/public-on-non-exported.js.map +1 -0
  49. package/dist/rules/public-on-private-member.d.ts +24 -0
  50. package/dist/rules/public-on-private-member.d.ts.map +1 -0
  51. package/dist/rules/public-on-private-member.js +111 -0
  52. package/dist/rules/public-on-private-member.js.map +1 -0
  53. package/dist/rules/valid-enum-type.d.ts +17 -0
  54. package/dist/rules/valid-enum-type.d.ts.map +1 -0
  55. package/dist/rules/valid-enum-type.js +206 -0
  56. package/dist/rules/valid-enum-type.js.map +1 -0
  57. package/dist/types.d.ts +63 -35
  58. package/dist/types.d.ts.map +1 -1
  59. package/dist/types.js +4 -1
  60. package/dist/types.js.map +1 -1
  61. package/dist/utils/tsdoc-parser.d.ts +35 -0
  62. package/dist/utils/tsdoc-parser.d.ts.map +1 -1
  63. package/dist/utils/tsdoc-parser.js +40 -0
  64. package/dist/utils/tsdoc-parser.js.map +1 -1
  65. package/docs/rules/valid-enum-type.md +153 -0
  66. package/package.json +22 -8
  67. package/src/configs/recommended.ts +7 -1
  68. package/src/index.ts +21 -15
  69. package/src/node.ts +50 -0
  70. package/src/rules/extra-release-tag.ts +201 -0
  71. package/src/rules/forgotten-export.ts +274 -0
  72. package/src/rules/incompatible-release-tags.ts +331 -0
  73. package/src/rules/index.ts +13 -1
  74. package/src/rules/missing-release-tag.ts +11 -26
  75. package/src/rules/override-keyword.ts +6 -8
  76. package/src/rules/package-documentation.ts +5 -31
  77. package/src/rules/public-on-non-exported.ts +265 -0
  78. package/src/rules/public-on-private-member.ts +157 -0
  79. package/src/rules/valid-enum-type.ts +252 -0
  80. package/src/types.ts +60 -17
  81. package/src/utils/config-loader.ts +1 -0
  82. package/src/utils/entry-point.ts +1 -0
  83. package/src/utils/tsdoc-parser.ts +67 -0
  84. package/temp/eslint-plugin.api.md +96 -47
  85. package/test/index.test.ts +1 -0
  86. package/test/rules/extra-release-tag.test.ts +276 -0
  87. package/test/rules/forgotten-export.test.ts +190 -0
  88. package/test/rules/incompatible-release-tags.test.ts +340 -0
  89. package/test/rules/missing-release-tag.test.ts +2 -1
  90. package/test/rules/override-keyword.test.ts +2 -1
  91. package/test/rules/package-documentation.test.ts +8 -6
  92. package/test/rules/public-on-non-exported.test.ts +201 -0
  93. package/test/rules/public-on-private-member.test.ts +207 -0
  94. package/test/rules/valid-enum-type.test.ts +409 -0
  95. package/test/types.test-d.ts +20 -0
  96. package/test/utils/config-loader.test.ts +1 -0
  97. package/test/utils/tsdoc-parser.test.ts +117 -9
  98. package/tsconfig.json +1 -0
  99. package/vitest.config.mts +1 -0
  100. package/dist/utils/index.d.ts +0 -8
  101. package/dist/utils/index.d.ts.map +0 -1
  102. package/dist/utils/index.js +0 -21
  103. package/dist/utils/index.js.map +0 -1
  104. package/src/utils/index.ts +0 -17
@@ -0,0 +1,331 @@
1
+ /**
2
+ * ESLint rule for detecting incompatible release tags.
3
+ *
4
+ * @remarks
5
+ * This rule detects when an exported API with a specific release tag references
6
+ * another symbol with a less visible release tag. For example, a @public API
7
+ * should not reference an @internal type.
8
+ *
9
+ * @internal
10
+ */
11
+
12
+ import { AST_NODE_TYPES, ESLintUtils, TSESTree } from '@typescript-eslint/utils'
13
+ import {
14
+ getLeadingTSDocComment,
15
+ parseTSDocComment,
16
+ extractReleaseTag,
17
+ } from '../utils/tsdoc-parser'
18
+ import type { ApiExtractorLogLevel, ReleaseTag } from '../types'
19
+
20
+ const createRule = ESLintUtils.RuleCreator(
21
+ (name) =>
22
+ `https://github.com/mike-north/api-extractor-tools/blob/main/tools/eslint-plugin/docs/rules/${name}.md`,
23
+ )
24
+
25
+ type MessageIds = 'incompatibleReleaseTags'
26
+
27
+ /**
28
+ * Options for the incompatible-release-tags rule.
29
+ * @alpha
30
+ */
31
+ export interface IncompatibleReleaseTagsRuleOptions {
32
+ /**
33
+ * Severity level for incompatible release tags.
34
+ * @defaultValue 'warning'
35
+ */
36
+ severity?: ApiExtractorLogLevel
37
+ }
38
+
39
+ // Release tag visibility levels (higher = more visible)
40
+ const RELEASE_TAG_LEVELS: Record<ReleaseTag, number> = {
41
+ internal: 0,
42
+ alpha: 1,
43
+ beta: 2,
44
+ public: 3,
45
+ }
46
+
47
+ export const incompatibleReleaseTags = createRule<
48
+ [IncompatibleReleaseTagsRuleOptions],
49
+ MessageIds
50
+ >({
51
+ name: 'incompatible-release-tags',
52
+ meta: {
53
+ type: 'problem',
54
+ docs: {
55
+ description:
56
+ 'Require that exported APIs do not reference symbols with less visible release tags',
57
+ },
58
+ messages: {
59
+ incompatibleReleaseTags:
60
+ 'The {{exportedTag}} API "{{exportedName}}" references the {{referencedTag}} symbol "{{referencedName}}". Referenced symbols must be at least as visible as the API that uses them.',
61
+ },
62
+ schema: [
63
+ {
64
+ type: 'object',
65
+ properties: {
66
+ severity: {
67
+ type: 'string',
68
+ enum: ['error', 'warning', 'none'],
69
+ description: 'Severity level for incompatible release tags',
70
+ },
71
+ },
72
+ additionalProperties: false,
73
+ },
74
+ ],
75
+ },
76
+ defaultOptions: [{}],
77
+ create(context) {
78
+ const options = context.options[0] ?? {}
79
+ const severity = options.severity ?? 'warning'
80
+
81
+ // If severity is 'none', disable the rule
82
+ if (severity === 'none') {
83
+ return {}
84
+ }
85
+
86
+ const sourceCode = context.sourceCode
87
+ const symbolReleaseTags = new Map<string, ReleaseTag>()
88
+ const exportedSymbols = new Map<
89
+ string,
90
+ { tag: ReleaseTag; node: TSESTree.Node }
91
+ >()
92
+
93
+ /**
94
+ * Gets the release tag for a node.
95
+ */
96
+ function getReleaseTag(node: TSESTree.Node): ReleaseTag | undefined {
97
+ const commentText = getLeadingTSDocComment(sourceCode, node)
98
+ if (!commentText) {
99
+ return undefined
100
+ }
101
+
102
+ const parsed = parseTSDocComment(commentText)
103
+ if (parsed.docComment) {
104
+ return extractReleaseTag(parsed.docComment)
105
+ }
106
+
107
+ return undefined
108
+ }
109
+
110
+ /**
111
+ * Gets the name of a declaration.
112
+ */
113
+ function getDeclarationName(
114
+ node:
115
+ | TSESTree.FunctionDeclaration
116
+ | TSESTree.ClassDeclaration
117
+ | TSESTree.TSInterfaceDeclaration
118
+ | TSESTree.TSTypeAliasDeclaration
119
+ | TSESTree.TSEnumDeclaration
120
+ | TSESTree.VariableDeclaration,
121
+ ): string | undefined {
122
+ if (node.type === AST_NODE_TYPES.VariableDeclaration) {
123
+ const firstDeclarator = node.declarations[0]
124
+ if (firstDeclarator?.id.type === AST_NODE_TYPES.Identifier) {
125
+ return firstDeclarator.id.name
126
+ }
127
+ return undefined
128
+ }
129
+
130
+ if ('id' in node && node.id) {
131
+ return node.id.name
132
+ }
133
+
134
+ return undefined
135
+ }
136
+
137
+ /**
138
+ * Checks if a release tag is compatible.
139
+ */
140
+ function isCompatible(
141
+ exportedTag: ReleaseTag,
142
+ referencedTag: ReleaseTag,
143
+ ): boolean {
144
+ return (
145
+ RELEASE_TAG_LEVELS[referencedTag] >= RELEASE_TAG_LEVELS[exportedTag]
146
+ )
147
+ }
148
+
149
+ /**
150
+ * Collects release tags for all declarations.
151
+ */
152
+ function collectSymbolReleaseTag(
153
+ node:
154
+ | TSESTree.FunctionDeclaration
155
+ | TSESTree.ClassDeclaration
156
+ | TSESTree.TSInterfaceDeclaration
157
+ | TSESTree.TSTypeAliasDeclaration
158
+ | TSESTree.TSEnumDeclaration
159
+ | TSESTree.VariableDeclaration,
160
+ ): void {
161
+ const name = getDeclarationName(node)
162
+ if (!name) return
163
+
164
+ const tag = getReleaseTag(node)
165
+ if (tag) {
166
+ symbolReleaseTags.set(name, tag)
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Checks if a node is exported.
172
+ */
173
+ function isExported(node: TSESTree.Node): boolean {
174
+ const parent = node.parent
175
+ return (
176
+ parent?.type === AST_NODE_TYPES.ExportNamedDeclaration ||
177
+ parent?.type === AST_NODE_TYPES.ExportDefaultDeclaration
178
+ )
179
+ }
180
+
181
+ /**
182
+ * Checks type references for incompatible release tags.
183
+ */
184
+ function checkTypeReferences(
185
+ node: TSESTree.Node,
186
+ exportedName: string,
187
+ exportedTag: ReleaseTag,
188
+ ): void {
189
+ const visited = new WeakSet<object>()
190
+
191
+ // Helper to recursively find type references
192
+ function findTypeReferences(n: TSESTree.Node): void {
193
+ // Avoid infinite recursion
194
+ if (visited.has(n)) {
195
+ return
196
+ }
197
+ visited.add(n)
198
+
199
+ if (n.type === AST_NODE_TYPES.TSTypeReference) {
200
+ const typeName = n.typeName
201
+ if (typeName.type === AST_NODE_TYPES.Identifier) {
202
+ const referencedName = typeName.name
203
+ const referencedTag = symbolReleaseTags.get(referencedName)
204
+
205
+ if (referencedTag && !isCompatible(exportedTag, referencedTag)) {
206
+ context.report({
207
+ node: n,
208
+ messageId: 'incompatibleReleaseTags',
209
+ data: {
210
+ exportedName,
211
+ exportedTag: `@${exportedTag}`,
212
+ referencedName,
213
+ referencedTag: `@${referencedTag}`,
214
+ },
215
+ })
216
+ }
217
+ }
218
+ }
219
+
220
+ // Recursively check child nodes, but skip 'parent' property to avoid cycles
221
+ for (const key in n) {
222
+ if (key === 'parent') {
223
+ continue
224
+ }
225
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
226
+ const child = (n as any)[key]
227
+ if (child && typeof child === 'object') {
228
+ if (Array.isArray(child)) {
229
+ for (const item of child) {
230
+ if (item && typeof item === 'object' && 'type' in item) {
231
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
232
+ findTypeReferences(item)
233
+ }
234
+ }
235
+ } else if ('type' in child) {
236
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
237
+ findTypeReferences(child)
238
+ }
239
+ }
240
+ }
241
+ }
242
+
243
+ findTypeReferences(node)
244
+ }
245
+
246
+ /**
247
+ * Checks a declaration for incompatible release tags.
248
+ */
249
+ function checkDeclaration(
250
+ node:
251
+ | TSESTree.FunctionDeclaration
252
+ | TSESTree.ClassDeclaration
253
+ | TSESTree.TSInterfaceDeclaration
254
+ | TSESTree.TSTypeAliasDeclaration
255
+ | TSESTree.TSEnumDeclaration
256
+ | TSESTree.VariableDeclaration,
257
+ ): void {
258
+ if (!isExported(node)) {
259
+ return
260
+ }
261
+
262
+ const name = getDeclarationName(node)
263
+ if (!name) return
264
+
265
+ // Check both the export statement and the declaration for the comment
266
+ const exportNode = node.parent
267
+ const nodeToCheck = exportNode ?? node
268
+
269
+ const tag = getReleaseTag(nodeToCheck) ?? getReleaseTag(node)
270
+ if (tag) {
271
+ exportedSymbols.set(name, { tag, node })
272
+ checkTypeReferences(node, name, tag)
273
+ }
274
+ }
275
+
276
+ const declarationsToCheck: Array<{
277
+ node:
278
+ | TSESTree.FunctionDeclaration
279
+ | TSESTree.ClassDeclaration
280
+ | TSESTree.TSInterfaceDeclaration
281
+ | TSESTree.TSTypeAliasDeclaration
282
+ | TSESTree.TSEnumDeclaration
283
+ | TSESTree.VariableDeclaration
284
+ }> = []
285
+
286
+ return {
287
+ FunctionDeclaration(node): void {
288
+ collectSymbolReleaseTag(node)
289
+ if (isExported(node)) {
290
+ declarationsToCheck.push({ node })
291
+ }
292
+ },
293
+ ClassDeclaration(node): void {
294
+ collectSymbolReleaseTag(node)
295
+ if (isExported(node)) {
296
+ declarationsToCheck.push({ node })
297
+ }
298
+ },
299
+ TSInterfaceDeclaration(node): void {
300
+ collectSymbolReleaseTag(node)
301
+ if (isExported(node)) {
302
+ declarationsToCheck.push({ node })
303
+ }
304
+ },
305
+ TSTypeAliasDeclaration(node): void {
306
+ collectSymbolReleaseTag(node)
307
+ if (isExported(node)) {
308
+ declarationsToCheck.push({ node })
309
+ }
310
+ },
311
+ TSEnumDeclaration(node): void {
312
+ collectSymbolReleaseTag(node)
313
+ if (isExported(node)) {
314
+ declarationsToCheck.push({ node })
315
+ }
316
+ },
317
+ VariableDeclaration(node): void {
318
+ collectSymbolReleaseTag(node)
319
+ if (isExported(node)) {
320
+ declarationsToCheck.push({ node })
321
+ }
322
+ },
323
+ 'Program:exit'(): void {
324
+ // Check all exported declarations after collecting all tags
325
+ for (const { node } of declarationsToCheck) {
326
+ checkDeclaration(node)
327
+ }
328
+ },
329
+ }
330
+ },
331
+ })
@@ -6,13 +6,25 @@
6
6
  import { missingReleaseTag } from './missing-release-tag'
7
7
  import { overrideKeyword } from './override-keyword'
8
8
  import { packageDocumentation } from './package-documentation'
9
+ import { forgottenExport } from './forgotten-export'
10
+ import { incompatibleReleaseTags } from './incompatible-release-tags'
11
+ import { extraReleaseTag } from './extra-release-tag'
12
+ import { publicOnPrivateMember } from './public-on-private-member'
13
+ import { publicOnNonExported } from './public-on-non-exported'
14
+ import { validEnumType } from './valid-enum-type'
9
15
 
10
16
  /**
11
17
  * All available ESLint rules.
12
- * @public
18
+ * @alpha
13
19
  */
14
20
  export const rules = {
15
21
  'missing-release-tag': missingReleaseTag,
16
22
  'override-keyword': overrideKeyword,
17
23
  'package-documentation': packageDocumentation,
24
+ 'forgotten-export': forgottenExport,
25
+ 'incompatible-release-tags': incompatibleReleaseTags,
26
+ 'extra-release-tag': extraReleaseTag,
27
+ 'public-on-private-member': publicOnPrivateMember,
28
+ 'public-on-non-exported': publicOnNonExported,
29
+ 'valid-enum-type': validEnumType,
18
30
  } as const
@@ -1,16 +1,18 @@
1
1
  /**
2
2
  * ESLint rule for detecting missing release tags on exported symbols.
3
+ *
4
+ * @remarks
5
+ * Configuration is provided explicitly via rule options.
6
+ *
3
7
  * @internal
4
8
  */
5
9
 
6
10
  import { AST_NODE_TYPES, ESLintUtils, TSESTree } from '@typescript-eslint/utils'
7
11
  import {
8
- resolveConfig,
9
- getMessageLogLevel,
10
12
  getLeadingTSDocComment,
11
13
  parseTSDocComment,
12
14
  extractReleaseTag,
13
- } from '../utils'
15
+ } from '../utils/tsdoc-parser'
14
16
  import type { MissingReleaseTagRuleOptions } from '../types'
15
17
 
16
18
  const createRule = ESLintUtils.RuleCreator(
@@ -39,9 +41,10 @@ export const missingReleaseTag = createRule<
39
41
  {
40
42
  type: 'object',
41
43
  properties: {
42
- configPath: {
44
+ severity: {
43
45
  type: 'string',
44
- description: 'Path to api-extractor.json configuration file',
46
+ enum: ['error', 'warning', 'none'],
47
+ description: 'Severity level for missing release tags',
45
48
  },
46
49
  },
47
50
  additionalProperties: false,
@@ -51,12 +54,10 @@ export const missingReleaseTag = createRule<
51
54
  defaultOptions: [{}],
52
55
  create(context) {
53
56
  const options = context.options[0] ?? {}
54
- const filename = context.filename
55
- const config = resolveConfig(filename, options.configPath)
56
- const logLevel = getMessageLogLevel(config, 'ae-missing-release-tag')
57
+ const severity = options.severity ?? 'warning'
57
58
 
58
- // If configured to 'none', disable the rule
59
- if (logLevel === 'none') {
59
+ // If severity is 'none', disable the rule
60
+ if (severity === 'none') {
60
61
  return {}
61
62
  }
62
63
 
@@ -164,40 +165,24 @@ export const missingReleaseTag = createRule<
164
165
  }
165
166
 
166
167
  return {
167
- // Check exported function declarations
168
168
  FunctionDeclaration(node): void {
169
169
  checkDeclaration(node)
170
170
  },
171
-
172
- // Check exported class declarations
173
171
  ClassDeclaration(node): void {
174
172
  checkDeclaration(node)
175
173
  },
176
-
177
- // Check exported interface declarations
178
174
  TSInterfaceDeclaration(node): void {
179
175
  checkDeclaration(node)
180
176
  },
181
-
182
- // Check exported type alias declarations
183
177
  TSTypeAliasDeclaration(node): void {
184
178
  checkDeclaration(node)
185
179
  },
186
-
187
- // Check exported enum declarations
188
180
  TSEnumDeclaration(node): void {
189
181
  checkDeclaration(node)
190
182
  },
191
-
192
- // Check exported variable declarations
193
183
  VariableDeclaration(node): void {
194
184
  checkDeclaration(node)
195
185
  },
196
-
197
- // Note: We intentionally don't handle ExportNamedDeclaration with specifiers
198
- // (e.g., `export { foo }` or `export { foo } from './bar'`) because:
199
- // - Re-exports should have release tags on the original declaration
200
- // - Named exports reference declarations that are checked elsewhere
201
186
  }
202
187
  },
203
188
  })
@@ -1,5 +1,9 @@
1
1
  /**
2
2
  * ESLint rule requiring the TypeScript `override` keyword when `@override` TSDoc tag is used.
3
+ *
4
+ * @remarks
5
+ * It is purely syntactic and requires no configuration.
6
+ *
3
7
  * @internal
4
8
  */
5
9
 
@@ -8,7 +12,7 @@ import {
8
12
  getLeadingTSDocComment,
9
13
  parseTSDocComment,
10
14
  hasOverrideTag,
11
- } from '../utils'
15
+ } from '../utils/tsdoc-parser'
12
16
  import type { OverrideKeywordRuleOptions } from '../types'
13
17
 
14
18
  const createRule = ESLintUtils.RuleCreator(
@@ -37,12 +41,7 @@ export const overrideKeyword = createRule<
37
41
  schema: [
38
42
  {
39
43
  type: 'object',
40
- properties: {
41
- configPath: {
42
- type: 'string',
43
- description: 'Path to api-extractor.json configuration file',
44
- },
45
- },
44
+ properties: {},
46
45
  additionalProperties: false,
47
46
  },
48
47
  ],
@@ -121,7 +120,6 @@ export const overrideKeyword = createRule<
121
120
  messageId: 'missingOverrideKeyword',
122
121
  data: { name },
123
122
  fix(fixer) {
124
- // Insert override keyword at the start of the member declaration
125
123
  return fixer.insertTextBefore(node, 'override ')
126
124
  },
127
125
  })
@@ -1,15 +1,13 @@
1
1
  /**
2
- * ESLint rule requiring @packageDocumentation in package entry point files.
2
+ * ESLint rule requiring @packageDocumentation in files.
3
3
  * @internal
4
4
  */
5
5
 
6
6
  import { ESLintUtils } from '@typescript-eslint/utils'
7
7
  import {
8
- findPackageJson,
9
- isEntryPoint,
10
8
  findAllTSDocComments,
11
9
  hasPackageDocumentation,
12
- } from '../utils'
10
+ } from '../utils/tsdoc-parser'
13
11
  import type { PackageDocumentationRuleOptions } from '../types'
14
12
 
15
13
  const createRule = ESLintUtils.RuleCreator(
@@ -27,58 +25,34 @@ export const packageDocumentation = createRule<
27
25
  meta: {
28
26
  type: 'suggestion',
29
27
  docs: {
30
- description:
31
- 'Require @packageDocumentation tag in package entry point files',
28
+ description: 'Require @packageDocumentation tag in files',
32
29
  },
33
30
  messages: {
34
31
  missingPackageDocumentation:
35
- 'Entry point file is missing a @packageDocumentation comment. Add a TSDoc comment with @packageDocumentation at the top of the file.',
32
+ 'File is missing a @packageDocumentation comment. Add a TSDoc comment with @packageDocumentation at the top of the file.',
36
33
  },
37
34
  schema: [
38
35
  {
39
36
  type: 'object',
40
- properties: {
41
- configPath: {
42
- type: 'string',
43
- description: 'Path to api-extractor.json configuration file',
44
- },
45
- },
37
+ properties: {},
46
38
  additionalProperties: false,
47
39
  },
48
40
  ],
49
41
  },
50
42
  defaultOptions: [{}],
51
43
  create(context) {
52
- const filename = context.filename
53
44
  const sourceCode = context.sourceCode
54
45
 
55
- // Find package.json
56
- const pkgPath = findPackageJson(filename)
57
- if (!pkgPath) {
58
- // No package.json found, nothing to check
59
- return {}
60
- }
61
-
62
- // Check if this file is an entry point
63
- if (!isEntryPoint(filename, pkgPath)) {
64
- // Not an entry point, skip
65
- return {}
66
- }
67
-
68
46
  return {
69
47
  Program(node): void {
70
- // Look for @packageDocumentation in any TSDoc comment in the file
71
48
  const tsdocComments = findAllTSDocComments(sourceCode)
72
49
 
73
50
  for (const { parsed } of tsdocComments) {
74
51
  if (parsed.docComment && hasPackageDocumentation(parsed.docComment)) {
75
- // Found @packageDocumentation, all good
76
52
  return
77
53
  }
78
54
  }
79
55
 
80
- // No @packageDocumentation found
81
- // Report at the first line of the file
82
56
  context.report({
83
57
  node,
84
58
  loc: { line: 1, column: 0 },