@api-extractor-tools/eslint-plugin 0.1.0-alpha.0 → 0.1.0-alpha.2
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/ARCHITECTURE.md +204 -0
- package/CHANGELOG.md +32 -0
- package/README.md +306 -10
- package/api-extractor.json +1 -0
- package/dist/configs/recommended.d.ts +1 -1
- package/dist/configs/recommended.d.ts.map +1 -1
- package/dist/configs/recommended.js +7 -1
- package/dist/configs/recommended.js.map +1 -1
- package/dist/index.d.ts +9 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -15
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +28 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +41 -0
- package/dist/node.js.map +1 -0
- package/dist/rules/extra-release-tag.d.ts +24 -0
- package/dist/rules/extra-release-tag.d.ts.map +1 -0
- package/dist/rules/extra-release-tag.js +141 -0
- package/dist/rules/extra-release-tag.js.map +1 -0
- package/dist/rules/forgotten-export.d.ts +24 -0
- package/dist/rules/forgotten-export.d.ts.map +1 -0
- package/dist/rules/forgotten-export.js +212 -0
- package/dist/rules/forgotten-export.js.map +1 -0
- package/dist/rules/incompatible-release-tags.d.ts +25 -0
- package/dist/rules/incompatible-release-tags.d.ts.map +1 -0
- package/dist/rules/incompatible-release-tags.js +237 -0
- package/dist/rules/incompatible-release-tags.js.map +1 -0
- package/dist/rules/index.d.ts +8 -2
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +13 -1
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/missing-release-tag.d.ts +4 -0
- package/dist/rules/missing-release-tag.d.ts.map +1 -1
- package/dist/rules/missing-release-tag.js +14 -21
- package/dist/rules/missing-release-tag.js.map +1 -1
- package/dist/rules/override-keyword.d.ts +4 -0
- package/dist/rules/override-keyword.d.ts.map +1 -1
- package/dist/rules/override-keyword.js +9 -11
- package/dist/rules/override-keyword.js.map +1 -1
- package/dist/rules/package-documentation.d.ts +5 -2
- package/dist/rules/package-documentation.d.ts.map +1 -1
- package/dist/rules/package-documentation.js +45 -35
- package/dist/rules/package-documentation.js.map +1 -1
- package/dist/rules/public-on-non-exported.d.ts +24 -0
- package/dist/rules/public-on-non-exported.d.ts.map +1 -0
- package/dist/rules/public-on-non-exported.js +191 -0
- package/dist/rules/public-on-non-exported.js.map +1 -0
- package/dist/rules/public-on-private-member.d.ts +24 -0
- package/dist/rules/public-on-private-member.d.ts.map +1 -0
- package/dist/rules/public-on-private-member.js +111 -0
- package/dist/rules/public-on-private-member.js.map +1 -0
- package/dist/rules/valid-enum-type.d.ts +17 -0
- package/dist/rules/valid-enum-type.d.ts.map +1 -0
- package/dist/rules/valid-enum-type.js +206 -0
- package/dist/rules/valid-enum-type.js.map +1 -0
- package/dist/types.d.ts +66 -24
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/tsdoc-parser.d.ts +37 -6
- package/dist/utils/tsdoc-parser.d.ts.map +1 -1
- package/dist/utils/tsdoc-parser.js +40 -0
- package/dist/utils/tsdoc-parser.js.map +1 -1
- package/docs/rules/valid-enum-type.md +153 -0
- package/package.json +22 -8
- package/src/configs/recommended.ts +7 -1
- package/src/index.ts +21 -15
- package/src/node.ts +50 -0
- package/src/rules/extra-release-tag.ts +201 -0
- package/src/rules/forgotten-export.ts +274 -0
- package/src/rules/incompatible-release-tags.ts +331 -0
- package/src/rules/index.ts +13 -1
- package/src/rules/missing-release-tag.ts +11 -26
- package/src/rules/override-keyword.ts +6 -8
- package/src/rules/package-documentation.ts +54 -40
- package/src/rules/public-on-non-exported.ts +265 -0
- package/src/rules/public-on-private-member.ts +157 -0
- package/src/rules/valid-enum-type.ts +252 -0
- package/src/types.ts +60 -17
- package/src/utils/config-loader.ts +1 -0
- package/src/utils/entry-point.ts +1 -0
- package/src/utils/tsdoc-parser.ts +67 -0
- package/temp/eslint-plugin.api.md +101 -32
- package/test/index.test.ts +1 -0
- package/test/rules/extra-release-tag.test.ts +276 -0
- package/test/rules/forgotten-export.test.ts +190 -0
- package/test/rules/incompatible-release-tags.test.ts +340 -0
- package/test/rules/missing-release-tag.test.ts +2 -1
- package/test/rules/override-keyword.test.ts +2 -1
- package/test/rules/package-documentation.test.ts +113 -64
- package/test/rules/public-on-non-exported.test.ts +201 -0
- package/test/rules/public-on-private-member.test.ts +207 -0
- package/test/rules/valid-enum-type.test.ts +409 -0
- package/test/types.test-d.ts +20 -0
- package/test/utils/config-loader.test.ts +1 -0
- package/test/utils/tsdoc-parser.test.ts +117 -9
- package/tsconfig.json +1 -0
- package/vitest.config.mts +1 -0
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -21
- package/dist/utils/index.js.map +0 -1
- package/src/utils/index.ts +0 -17
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# ESLint Plugin Architecture
|
|
2
|
+
|
|
3
|
+
This document describes the architecture of `@api-extractor-tools/eslint-plugin`.
|
|
4
|
+
|
|
5
|
+
## Design Principles
|
|
6
|
+
|
|
7
|
+
### Isomorphic Core
|
|
8
|
+
|
|
9
|
+
The plugin is designed to work in both Node.js and browser environments. While the core functionality aims to be environment-agnostic, the current implementation uses `@typescript-eslint/utils` which has transitive Node.js dependencies. Browser usage requires polyfills (see usage examples).
|
|
10
|
+
|
|
11
|
+
### Explicit Configuration
|
|
12
|
+
|
|
13
|
+
Rules accept configuration explicitly via options rather than automatically discovering configuration files. This makes the rules predictable, testable, and environment-agnostic.
|
|
14
|
+
|
|
15
|
+
### Optional Node.js Enhancements
|
|
16
|
+
|
|
17
|
+
Node.js-specific functionality (reading files from disk, discovering configuration) is provided as a separate entry point. This is purely a convenience layer - users can always provide equivalent configuration explicitly.
|
|
18
|
+
|
|
19
|
+
## Package Structure
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
src/
|
|
23
|
+
├── index.ts # Main entry point (isomorphic)
|
|
24
|
+
├── node.ts # Node.js utilities entry point
|
|
25
|
+
├── types.ts # TypeScript types (isomorphic)
|
|
26
|
+
├── rules/
|
|
27
|
+
│ ├── index.ts # Rule exports
|
|
28
|
+
│ ├── missing-release-tag.ts
|
|
29
|
+
│ ├── override-keyword.ts
|
|
30
|
+
│ └── package-documentation.ts
|
|
31
|
+
├── configs/
|
|
32
|
+
│ ├── index.ts # Config exports
|
|
33
|
+
│ └── recommended.ts # Recommended ruleset
|
|
34
|
+
└── utils/
|
|
35
|
+
├── tsdoc-parser.ts # TSDoc parsing (isomorphic)
|
|
36
|
+
├── config-loader.ts # Config file loading (Node.js only)
|
|
37
|
+
└── entry-point.ts # Entry point detection (Node.js only)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Entry Points
|
|
41
|
+
|
|
42
|
+
### Main Entry Point (`.`)
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import plugin from '@api-extractor-tools/eslint-plugin'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Exports:
|
|
49
|
+
|
|
50
|
+
- `default` - The ESLint plugin object with `rules` and `configs`
|
|
51
|
+
- `rules` - All ESLint rules
|
|
52
|
+
- `recommendedRules` - Recommended rule configuration
|
|
53
|
+
- Types - `ApiExtractorConfig`, `ReleaseTag`, rule option types, etc.
|
|
54
|
+
- TSDoc utilities - `parseTSDocComment`, `extractReleaseTag`, etc.
|
|
55
|
+
|
|
56
|
+
This entry point can be used in browser environments with appropriate polyfills for `@typescript-eslint/utils` dependencies.
|
|
57
|
+
|
|
58
|
+
### Node.js Entry Point (`./node`)
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import {
|
|
62
|
+
findApiExtractorConfig,
|
|
63
|
+
loadApiExtractorConfig,
|
|
64
|
+
} from '@api-extractor-tools/eslint-plugin/node'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Exports:
|
|
68
|
+
|
|
69
|
+
- `findApiExtractorConfig(startDir)` - Discovers api-extractor.json by searching upward
|
|
70
|
+
- `loadApiExtractorConfig(path)` - Loads and parses an api-extractor.json file
|
|
71
|
+
- `resolveConfig(filePath, configPath?)` - Resolves config for a file
|
|
72
|
+
- `getMessageLogLevel(config, messageId)` - Gets log level for a message
|
|
73
|
+
- `findPackageJson(startDir)` - Discovers package.json by searching upward
|
|
74
|
+
- `isEntryPoint(filePath, pkgPath)` - Checks if a file is a package entry point
|
|
75
|
+
|
|
76
|
+
This entry point requires Node.js (`fs`, `path` modules).
|
|
77
|
+
|
|
78
|
+
## Rules
|
|
79
|
+
|
|
80
|
+
### missing-release-tag
|
|
81
|
+
|
|
82
|
+
Requires exported symbols to have a release tag (`@public`, `@beta`, `@alpha`, or `@internal`).
|
|
83
|
+
|
|
84
|
+
**Options:**
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
interface MissingReleaseTagRuleOptions {
|
|
88
|
+
severity?: 'error' | 'warning' | 'none' // default: 'warning'
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### override-keyword
|
|
93
|
+
|
|
94
|
+
Requires the TypeScript `override` keyword when the `@override` TSDoc tag is present.
|
|
95
|
+
|
|
96
|
+
**Options:** None (purely syntactic)
|
|
97
|
+
|
|
98
|
+
### package-documentation
|
|
99
|
+
|
|
100
|
+
Enforces correct usage of the `@packageDocumentation` tag based on whether a file is a package entry point (barrel file). The rule automatically detects entry points by examining the nearest `package.json`.
|
|
101
|
+
|
|
102
|
+
- **Barrel files** (entry points): Requires `@packageDocumentation` tag to be present.
|
|
103
|
+
- **Non-barrel files**: Reports an error if `@packageDocumentation` tag is found.
|
|
104
|
+
|
|
105
|
+
**Options:** None
|
|
106
|
+
|
|
107
|
+
Note: This rule uses `findPackageJson` and `isEntryPoint` from the entry-point utilities to determine barrel file status. If no `package.json` is found, the rule is skipped.
|
|
108
|
+
|
|
109
|
+
## Usage Examples
|
|
110
|
+
|
|
111
|
+
### Browser Environment (ESLint 9 Flat Config)
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
import { Linter } from 'eslint-linter-browserify'
|
|
115
|
+
import * as tsParser from '@typescript-eslint/parser'
|
|
116
|
+
import { rules } from '@api-extractor-tools/eslint-plugin'
|
|
117
|
+
|
|
118
|
+
const linter = new Linter()
|
|
119
|
+
|
|
120
|
+
// Lint code using ESLint 9 flat config style
|
|
121
|
+
const messages = linter.verify(
|
|
122
|
+
code,
|
|
123
|
+
{
|
|
124
|
+
files: ['**/*.ts', '**/*.d.ts'],
|
|
125
|
+
plugins: {
|
|
126
|
+
'@api-extractor-tools': { rules },
|
|
127
|
+
},
|
|
128
|
+
languageOptions: {
|
|
129
|
+
parser: tsParser,
|
|
130
|
+
parserOptions: {
|
|
131
|
+
ecmaVersion: 'latest',
|
|
132
|
+
sourceType: 'module',
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
rules: {
|
|
136
|
+
'@api-extractor-tools/missing-release-tag': [
|
|
137
|
+
'warn',
|
|
138
|
+
{ severity: 'warning' },
|
|
139
|
+
],
|
|
140
|
+
'@api-extractor-tools/override-keyword': 'error',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{ filename: 'file.d.ts' },
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Note:** When using in a browser, you'll need to polyfill or stub Node.js modules that `@typescript-eslint/parser` depends on (e.g., `fs`, `path`, `process`). See the demo-site for a working example using Vite aliases.
|
|
148
|
+
|
|
149
|
+
### Node.js with ESLint Flat Config
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
// eslint.config.js
|
|
153
|
+
import apiExtractorPlugin from '@api-extractor-tools/eslint-plugin'
|
|
154
|
+
|
|
155
|
+
export default [apiExtractorPlugin.configs.recommended]
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Node.js with Config Discovery
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
// eslint.config.js
|
|
162
|
+
import apiExtractorPlugin from '@api-extractor-tools/eslint-plugin'
|
|
163
|
+
import {
|
|
164
|
+
findApiExtractorConfig,
|
|
165
|
+
loadApiExtractorConfig,
|
|
166
|
+
getMessageLogLevel,
|
|
167
|
+
} from '@api-extractor-tools/eslint-plugin/node'
|
|
168
|
+
|
|
169
|
+
// Discover and load api-extractor.json
|
|
170
|
+
const configPath = findApiExtractorConfig(process.cwd())
|
|
171
|
+
const config = configPath ? loadApiExtractorConfig(configPath) : null
|
|
172
|
+
|
|
173
|
+
// Get severity from config (or use default)
|
|
174
|
+
const severity = config
|
|
175
|
+
? getMessageLogLevel(config, 'ae-missing-release-tag')
|
|
176
|
+
: 'warning'
|
|
177
|
+
|
|
178
|
+
export default [
|
|
179
|
+
{
|
|
180
|
+
plugins: { '@api-extractor-tools': apiExtractorPlugin },
|
|
181
|
+
rules: {
|
|
182
|
+
'@api-extractor-tools/missing-release-tag': ['warn', { severity }],
|
|
183
|
+
'@api-extractor-tools/override-keyword': 'error',
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Dependencies
|
|
190
|
+
|
|
191
|
+
### Runtime Dependencies
|
|
192
|
+
|
|
193
|
+
- `@microsoft/tsdoc` - TSDoc comment parsing (browser-compatible)
|
|
194
|
+
|
|
195
|
+
### Dev Dependencies
|
|
196
|
+
|
|
197
|
+
- `@typescript-eslint/utils` - ESLint rule utilities and TypeScript AST types
|
|
198
|
+
- `@typescript-eslint/rule-tester` - Testing harness for ESLint rules
|
|
199
|
+
- `@typescript-eslint/parser` - TypeScript parser for ESLint (used in tests)
|
|
200
|
+
|
|
201
|
+
### Peer Dependencies
|
|
202
|
+
|
|
203
|
+
- `eslint` >= 8.0.0
|
|
204
|
+
- `typescript` >= 5.5.0
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @api-extractor-tools/eslint-plugin
|
|
2
2
|
|
|
3
|
+
## 0.1.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#204](https://github.com/mike-north/api-extractor-tools/pull/204) [`3accc97`](https://github.com/mike-north/api-extractor-tools/commit/3accc97733d1b21eb7bbbe82b122a347e9b5ea76) Thanks [@mike-north](https://github.com/mike-north)! - fix: enforce @packageDocumentation only on package barrel files
|
|
8
|
+
|
|
9
|
+
The `package-documentation` rule now automatically detects whether a file is a package entry point by examining the nearest `package.json`. Barrel files are required to have the `@packageDocumentation` tag, and non-barrel files report an error if the tag is present. Previously the rule required the tag on every file regardless of whether it was an entry point.
|
|
10
|
+
|
|
11
|
+
## 0.1.0-alpha.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#182](https://github.com/mike-north/api-extractor-tools/pull/182) [`d77d4d1`](https://github.com/mike-north/api-extractor-tools/commit/d77d4d1657641e16dc98736b88ece121c3d27563) Thanks [@mike-north](https://github.com/mike-north)! - Integrate declaration-file-normalizer into build pipelines and add comprehensive test coverage.
|
|
16
|
+
|
|
17
|
+
**Test Coverage Improvements:**
|
|
18
|
+
- Added comprehensive test suite for declaration-file-normalizer (64 tests total)
|
|
19
|
+
- Improved coverage from 8.39% to 67.97%
|
|
20
|
+
- Coverage breakdown:
|
|
21
|
+
- index.ts: 96.77% statements, 92.3% branch coverage
|
|
22
|
+
- normalizer.ts: 100% coverage
|
|
23
|
+
- parser.ts: 86.56% statements, 66.66% branch coverage
|
|
24
|
+
- writer.ts: 90.9% statements, 66.66% branch coverage
|
|
25
|
+
- Added test suites for parser, writer, index orchestration, and CLI
|
|
26
|
+
|
|
27
|
+
**Build Pipeline Integration:**
|
|
28
|
+
- Integrated declaration-file-normalizer into build pipeline for all packages using API Extractor
|
|
29
|
+
- Build flow is now: `tsc → declaration-file-normalizer → api-extractor`
|
|
30
|
+
- This ensures stable union/intersection type ordering in API reports across builds
|
|
31
|
+
|
|
32
|
+
**Configuration:**
|
|
33
|
+
- Fixed vitest.config.mts to properly track index.ts coverage
|
|
34
|
+
|
|
3
35
|
## 0.1.0-alpha.0
|
|
4
36
|
|
|
5
37
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -34,6 +34,12 @@ export default [
|
|
|
34
34
|
'@api-extractor-tools/missing-release-tag': 'error',
|
|
35
35
|
'@api-extractor-tools/override-keyword': 'error',
|
|
36
36
|
'@api-extractor-tools/package-documentation': 'warn',
|
|
37
|
+
'@api-extractor-tools/forgotten-export': 'warn',
|
|
38
|
+
'@api-extractor-tools/incompatible-release-tags': 'warn',
|
|
39
|
+
'@api-extractor-tools/extra-release-tag': 'error',
|
|
40
|
+
'@api-extractor-tools/public-on-private-member': 'error',
|
|
41
|
+
'@api-extractor-tools/public-on-non-exported': 'error',
|
|
42
|
+
'@api-extractor-tools/valid-enum-type': 'warn',
|
|
37
43
|
},
|
|
38
44
|
},
|
|
39
45
|
]
|
|
@@ -57,6 +63,12 @@ module.exports = {
|
|
|
57
63
|
'@api-extractor-tools/missing-release-tag': 'error',
|
|
58
64
|
'@api-extractor-tools/override-keyword': 'error',
|
|
59
65
|
'@api-extractor-tools/package-documentation': 'warn',
|
|
66
|
+
'@api-extractor-tools/forgotten-export': 'warn',
|
|
67
|
+
'@api-extractor-tools/incompatible-release-tags': 'warn',
|
|
68
|
+
'@api-extractor-tools/extra-release-tag': 'error',
|
|
69
|
+
'@api-extractor-tools/public-on-private-member': 'error',
|
|
70
|
+
'@api-extractor-tools/public-on-non-exported': 'error',
|
|
71
|
+
'@api-extractor-tools/valid-enum-type': 'warn',
|
|
60
72
|
},
|
|
61
73
|
}
|
|
62
74
|
```
|
|
@@ -144,6 +156,289 @@ export function foo() {}
|
|
|
144
156
|
export function foo() {}
|
|
145
157
|
```
|
|
146
158
|
|
|
159
|
+
### `@api-extractor-tools/forgotten-export`
|
|
160
|
+
|
|
161
|
+
Requires that types and symbols referenced by exported APIs are also exported from the entry point.
|
|
162
|
+
|
|
163
|
+
This rule mirrors API Extractor's `ae-forgotten-export` message.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
// ❌ Bad - MyInterface is used but not exported
|
|
167
|
+
interface MyInterface {
|
|
168
|
+
name: string
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function myFunction(param: MyInterface): void {}
|
|
172
|
+
|
|
173
|
+
// ✅ Good - MyInterface is exported
|
|
174
|
+
export interface MyInterface {
|
|
175
|
+
name: string
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function myFunction(param: MyInterface): void {}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Options:**
|
|
182
|
+
|
|
183
|
+
- `severity` (optional): Severity level for forgotten exports. Default: `'warning'`
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"@api-extractor-tools/forgotten-export": ["warn", { "severity": "warning" }]
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `@api-extractor-tools/incompatible-release-tags`
|
|
192
|
+
|
|
193
|
+
Requires that exported APIs do not reference symbols with less visible release tags.
|
|
194
|
+
|
|
195
|
+
This rule mirrors API Extractor's `ae-incompatible-release-tags` message. For example, a `@public` API should not reference an `@internal` type.
|
|
196
|
+
|
|
197
|
+
Release tag visibility hierarchy (from least to most visible):
|
|
198
|
+
|
|
199
|
+
- `@internal` < `@alpha` < `@beta` < `@public`
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// ❌ Bad - public API using internal type
|
|
203
|
+
/**
|
|
204
|
+
* An internal interface.
|
|
205
|
+
* @internal
|
|
206
|
+
*/
|
|
207
|
+
interface MyInterface {
|
|
208
|
+
name: string
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* A public function.
|
|
213
|
+
* @public
|
|
214
|
+
*/
|
|
215
|
+
export function myFunction(param: MyInterface): void {}
|
|
216
|
+
|
|
217
|
+
// ✅ Good - public API using public type
|
|
218
|
+
/**
|
|
219
|
+
* A public interface.
|
|
220
|
+
* @public
|
|
221
|
+
*/
|
|
222
|
+
export interface MyInterface {
|
|
223
|
+
name: string
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* A public function.
|
|
228
|
+
* @public
|
|
229
|
+
*/
|
|
230
|
+
export function myFunction(param: MyInterface): void {}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Options:**
|
|
234
|
+
|
|
235
|
+
- `severity` (optional): Severity level for incompatible release tags. Default: `'warning'`
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"@api-extractor-tools/incompatible-release-tags": [
|
|
240
|
+
"error",
|
|
241
|
+
{ "severity": "warning" }
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### `@api-extractor-tools/extra-release-tag`
|
|
247
|
+
|
|
248
|
+
Requires that symbols have at most one release tag.
|
|
249
|
+
|
|
250
|
+
This rule mirrors API Extractor's `ae-extra-release-tag` message. Each symbol should have exactly one release tag (`@public`, `@beta`, `@alpha`, or `@internal`).
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
// ❌ Bad - multiple release tags
|
|
254
|
+
/**
|
|
255
|
+
* A function with multiple tags.
|
|
256
|
+
* @public
|
|
257
|
+
* @beta
|
|
258
|
+
*/
|
|
259
|
+
export function myFunction(): void {}
|
|
260
|
+
|
|
261
|
+
// ✅ Good - single release tag
|
|
262
|
+
/**
|
|
263
|
+
* A public function.
|
|
264
|
+
* @public
|
|
265
|
+
*/
|
|
266
|
+
export function myFunction(): void {}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Options:**
|
|
270
|
+
|
|
271
|
+
- `severity` (optional): Severity level for extra release tags. Default: `'error'`
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"@api-extractor-tools/extra-release-tag": ["error", { "severity": "error" }]
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### `@api-extractor-tools/public-on-private-member`
|
|
280
|
+
|
|
281
|
+
Prevents the use of `@public` tag on private or protected class members.
|
|
282
|
+
|
|
283
|
+
Private and protected members cannot be public API since they are not accessible outside the class or to external consumers.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
// ❌ Bad - @public on private member
|
|
287
|
+
export class MyClass {
|
|
288
|
+
/**
|
|
289
|
+
* A private property.
|
|
290
|
+
* @public
|
|
291
|
+
*/
|
|
292
|
+
private myProperty: string = ''
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ✅ Good - @internal on private member
|
|
296
|
+
export class MyClass {
|
|
297
|
+
/**
|
|
298
|
+
* A private property.
|
|
299
|
+
* @internal
|
|
300
|
+
*/
|
|
301
|
+
private myProperty: string = ''
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ✅ Good - @public on public member
|
|
305
|
+
export class MyClass {
|
|
306
|
+
/**
|
|
307
|
+
* A public property.
|
|
308
|
+
* @public
|
|
309
|
+
*/
|
|
310
|
+
public myProperty: string = ''
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Options:**
|
|
315
|
+
|
|
316
|
+
- `severity` (optional): Severity level for public tags on private/protected members. Default: `'error'`
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{
|
|
320
|
+
"@api-extractor-tools/public-on-private-member": [
|
|
321
|
+
"error",
|
|
322
|
+
{ "severity": "error" }
|
|
323
|
+
]
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### `@api-extractor-tools/public-on-non-exported`
|
|
328
|
+
|
|
329
|
+
Prevents the use of `@public` tag on symbols that are not exported.
|
|
330
|
+
|
|
331
|
+
The `@public` tag indicates that a symbol is part of the public API, but non-exported symbols cannot be accessed by consumers.
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
// ❌ Bad - @public on non-exported symbol
|
|
335
|
+
/**
|
|
336
|
+
* A function.
|
|
337
|
+
* @public
|
|
338
|
+
*/
|
|
339
|
+
function myFunction(): void {}
|
|
340
|
+
|
|
341
|
+
// ✅ Good - @public on exported symbol
|
|
342
|
+
/**
|
|
343
|
+
* A function.
|
|
344
|
+
* @public
|
|
345
|
+
*/
|
|
346
|
+
export function myFunction(): void {}
|
|
347
|
+
|
|
348
|
+
// ✅ Good - @internal on non-exported symbol
|
|
349
|
+
/**
|
|
350
|
+
* A function.
|
|
351
|
+
* @internal
|
|
352
|
+
*/
|
|
353
|
+
function myFunction(): void {}
|
|
354
|
+
|
|
355
|
+
// ✅ Good - exported separately
|
|
356
|
+
/**
|
|
357
|
+
* A function.
|
|
358
|
+
* @public
|
|
359
|
+
*/
|
|
360
|
+
function myFunction(): void {}
|
|
361
|
+
|
|
362
|
+
export { myFunction }
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Options:**
|
|
366
|
+
|
|
367
|
+
- `severity` (optional): Severity level for public tags on non-exported symbols. Default: `'error'`
|
|
368
|
+
|
|
369
|
+
```json
|
|
370
|
+
{
|
|
371
|
+
"@api-extractor-tools/public-on-non-exported": [
|
|
372
|
+
"error",
|
|
373
|
+
{ "severity": "error" }
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### `@api-extractor-tools/valid-enum-type`
|
|
379
|
+
|
|
380
|
+
Validates the usage of the `@enumType` TSDoc tag on enum declarations and string literal union type aliases.
|
|
381
|
+
|
|
382
|
+
The `@enumType` tag specifies whether an enum is "open" (new members may be added) or "closed" (the set of members is fixed). This is used by the change detector to properly classify API changes.
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
// ❌ Bad - missing value
|
|
386
|
+
/**
|
|
387
|
+
* @enumType
|
|
388
|
+
*/
|
|
389
|
+
export enum Status {
|
|
390
|
+
Active,
|
|
391
|
+
Inactive,
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// ❌ Bad - invalid value
|
|
395
|
+
/**
|
|
396
|
+
* @enumType invalid
|
|
397
|
+
*/
|
|
398
|
+
export enum Status {
|
|
399
|
+
Active,
|
|
400
|
+
Inactive,
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// ❌ Bad - @enumType on invalid construct
|
|
404
|
+
/**
|
|
405
|
+
* @enumType open
|
|
406
|
+
*/
|
|
407
|
+
export function myFunction(): void {}
|
|
408
|
+
|
|
409
|
+
// ✅ Good - open enum
|
|
410
|
+
/**
|
|
411
|
+
* Status values for a resource.
|
|
412
|
+
* @enumType open
|
|
413
|
+
* @public
|
|
414
|
+
*/
|
|
415
|
+
export enum Status {
|
|
416
|
+
Active = 'active',
|
|
417
|
+
Inactive = 'inactive',
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// ✅ Good - closed string literal union
|
|
421
|
+
/**
|
|
422
|
+
* Supported formats.
|
|
423
|
+
* @enumType closed
|
|
424
|
+
* @public
|
|
425
|
+
*/
|
|
426
|
+
export type Format = 'json' | 'xml'
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
**Options:**
|
|
430
|
+
|
|
431
|
+
- `requireOnExported` (optional): When `true`, requires all exported enums and string literal unions to have an `@enumType` tag. Default: `false`
|
|
432
|
+
|
|
433
|
+
```json
|
|
434
|
+
{
|
|
435
|
+
"@api-extractor-tools/valid-enum-type": [
|
|
436
|
+
"warn",
|
|
437
|
+
{ "requireOnExported": true }
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
147
442
|
## Configuration Discovery
|
|
148
443
|
|
|
149
444
|
Rules that read from `api-extractor.json` use the following strategy:
|
|
@@ -156,11 +451,17 @@ Rules that read from `api-extractor.json` use the following strategy:
|
|
|
156
451
|
|
|
157
452
|
The `recommended` configuration enables all rules with these defaults:
|
|
158
453
|
|
|
159
|
-
| Rule
|
|
160
|
-
|
|
|
161
|
-
| `missing-release-tag`
|
|
162
|
-
| `override-keyword`
|
|
163
|
-
| `package-documentation`
|
|
454
|
+
| Rule | Severity |
|
|
455
|
+
| --------------------------- | -------- |
|
|
456
|
+
| `missing-release-tag` | warn |
|
|
457
|
+
| `override-keyword` | error |
|
|
458
|
+
| `package-documentation` | warn |
|
|
459
|
+
| `forgotten-export` | warn |
|
|
460
|
+
| `incompatible-release-tags` | warn |
|
|
461
|
+
| `extra-release-tag` | error |
|
|
462
|
+
| `public-on-private-member` | error |
|
|
463
|
+
| `public-on-non-exported` | error |
|
|
464
|
+
| `valid-enum-type` | warn |
|
|
164
465
|
|
|
165
466
|
## Requirements
|
|
166
467
|
|
|
@@ -176,8 +477,3 @@ The `recommended` configuration enables all rules with these defaults:
|
|
|
176
477
|
## License
|
|
177
478
|
|
|
178
479
|
MIT
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
package/api-extractor.json
CHANGED
|
@@ -11,7 +11,7 @@ import type { TSESLint } from '@typescript-eslint/utils';
|
|
|
11
11
|
/**
|
|
12
12
|
* Recommended rule configuration.
|
|
13
13
|
* These are the rules enabled by default with appropriate severity.
|
|
14
|
-
* @
|
|
14
|
+
* @alpha
|
|
15
15
|
*/
|
|
16
16
|
export declare const recommendedRules: TSESLint.Linter.RulesRecord;
|
|
17
17
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommended.d.ts","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAExD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"recommended.d.ts","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAExD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,WAU9C,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,QAAQ,CAAC,UAAU,CAAC,MAAM,CAO5B"}
|
|
@@ -14,12 +14,18 @@ exports.createFlatRecommendedConfig = createFlatRecommendedConfig;
|
|
|
14
14
|
/**
|
|
15
15
|
* Recommended rule configuration.
|
|
16
16
|
* These are the rules enabled by default with appropriate severity.
|
|
17
|
-
* @
|
|
17
|
+
* @alpha
|
|
18
18
|
*/
|
|
19
19
|
exports.recommendedRules = {
|
|
20
20
|
'@api-extractor-tools/missing-release-tag': 'warn',
|
|
21
21
|
'@api-extractor-tools/override-keyword': 'error',
|
|
22
22
|
'@api-extractor-tools/package-documentation': 'warn',
|
|
23
|
+
'@api-extractor-tools/forgotten-export': 'warn',
|
|
24
|
+
'@api-extractor-tools/incompatible-release-tags': 'warn',
|
|
25
|
+
'@api-extractor-tools/extra-release-tag': 'error',
|
|
26
|
+
'@api-extractor-tools/public-on-private-member': 'error',
|
|
27
|
+
'@api-extractor-tools/public-on-non-exported': 'error',
|
|
28
|
+
'@api-extractor-tools/valid-enum-type': 'warn',
|
|
23
29
|
};
|
|
24
30
|
/**
|
|
25
31
|
* Flat-config recommended configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;
|
|
1
|
+
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../src/configs/recommended.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAkCH,kEASC;AAvCD;;;;GAIG;AACU,QAAA,gBAAgB,GAAgC;IAC3D,0CAA0C,EAAE,MAAM;IAClD,uCAAuC,EAAE,OAAO;IAChD,4CAA4C,EAAE,MAAM;IACpD,uCAAuC,EAAE,MAAM;IAC/C,gDAAgD,EAAE,MAAM;IACxD,wCAAwC,EAAE,OAAO;IACjD,+CAA+C,EAAE,OAAO;IACxD,6CAA6C,EAAE,OAAO;IACtD,sCAAsC,EAAE,MAAM;CAC/C,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,2BAA2B,CACzC,MAA+B;IAE/B,OAAO;QACL,OAAO,EAAE;YACP,sBAAsB,EAAE,MAAoC;SAC7D;QACD,KAAK,EAAE,wBAAgB;KACxB,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ESLint plugin providing authoring-time feedback for API Extractor.
|
|
3
3
|
*
|
|
4
|
-
* @remarks
|
|
5
|
-
* This plugin provides ESLint rules that mirror API Extractor's validations,
|
|
6
|
-
* enabling developers to catch issues during development rather than at build time.
|
|
7
|
-
*
|
|
8
4
|
* @example
|
|
9
5
|
* Using with flat config (eslint.config.js):
|
|
10
6
|
* ```js
|
|
@@ -12,15 +8,6 @@
|
|
|
12
8
|
*
|
|
13
9
|
* export default [
|
|
14
10
|
* apiExtractorPlugin.configs.recommended,
|
|
15
|
-
* // Or configure rules individually:
|
|
16
|
-
* {
|
|
17
|
-
* plugins: {
|
|
18
|
-
* '@api-extractor-tools': apiExtractorPlugin,
|
|
19
|
-
* },
|
|
20
|
-
* rules: {
|
|
21
|
-
* '@api-extractor-tools/missing-release-tag': 'error',
|
|
22
|
-
* },
|
|
23
|
-
* },
|
|
24
11
|
* ];
|
|
25
12
|
* ```
|
|
26
13
|
*
|
|
@@ -38,8 +25,14 @@
|
|
|
38
25
|
import type { TSESLint } from '@typescript-eslint/utils';
|
|
39
26
|
import { rules } from './rules';
|
|
40
27
|
import { recommendedRules } from './configs';
|
|
41
|
-
export type { ApiExtractorConfig, ApiExtractorLogLevel, ApiExtractorMessagesConfig, MessageConfig, ReleaseTag, MissingReleaseTagRuleOptions, OverrideKeywordRuleOptions, PackageDocumentationRuleOptions, ResolvedEntryPoints, } from './types';
|
|
28
|
+
export type { ApiExtractorConfig, ApiExtractorLogLevel, ApiExtractorMessagesConfig, MessageConfig, ReleaseTag, MissingReleaseTagRuleOptions, OverrideKeywordRuleOptions, PackageDocumentationRuleOptions, ResolvedEntryPoints, ValidEnumTypeRuleOptions, } from './types';
|
|
29
|
+
export type { ForgottenExportRuleOptions } from './rules/forgotten-export';
|
|
30
|
+
export type { IncompatibleReleaseTagsRuleOptions } from './rules/incompatible-release-tags';
|
|
31
|
+
export type { ExtraReleaseTagRuleOptions } from './rules/extra-release-tag';
|
|
32
|
+
export type { PublicOnPrivateMemberRuleOptions } from './rules/public-on-private-member';
|
|
33
|
+
export type { PublicOnNonExportedRuleOptions } from './rules/public-on-non-exported';
|
|
42
34
|
export { RELEASE_TAGS } from './types';
|
|
35
|
+
export { parseTSDocComment, extractReleaseTag, hasOverrideTag, hasPackageDocumentation, getLeadingTSDocComment, findAllTSDocComments, extractEnumType, type EnumTypeValue, type EnumTypeExtraction, } from './utils/tsdoc-parser';
|
|
43
36
|
/**
|
|
44
37
|
* Plugin configuration type.
|
|
45
38
|
* @internal
|
|
@@ -53,7 +46,7 @@ interface PluginConfigs {
|
|
|
53
46
|
}
|
|
54
47
|
/**
|
|
55
48
|
* The ESLint plugin type.
|
|
56
|
-
* @
|
|
49
|
+
* @alpha
|
|
57
50
|
*/
|
|
58
51
|
export interface ApiExtractorEslintPlugin {
|
|
59
52
|
meta: {
|
|
@@ -65,7 +58,7 @@ export interface ApiExtractorEslintPlugin {
|
|
|
65
58
|
}
|
|
66
59
|
/**
|
|
67
60
|
* The ESLint plugin object.
|
|
68
|
-
* @
|
|
61
|
+
* @alpha
|
|
69
62
|
*/
|
|
70
63
|
declare const plugin: ApiExtractorEslintPlugin;
|
|
71
64
|
export default plugin;
|