@valkyrjaio/ci-eslint 26.0.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.
- package/LICENSE.md +21 -0
- package/README.md +127 -0
- package/dist/Eslint/Constant/EslintInfo.d.ts +5 -0
- package/dist/Eslint/Constant/EslintInfo.d.ts.map +1 -0
- package/dist/Eslint/Constant/EslintInfo.js +12 -0
- package/dist/Eslint/Constant/EslintInfo.js.map +1 -0
- package/dist/Eslint/Factory/CopyrightHeaderFactory.d.ts +35 -0
- package/dist/Eslint/Factory/CopyrightHeaderFactory.d.ts.map +1 -0
- package/dist/Eslint/Factory/CopyrightHeaderFactory.js +122 -0
- package/dist/Eslint/Factory/CopyrightHeaderFactory.js.map +1 -0
- package/dist/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.d.ts +10 -0
- package/dist/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.d.ts.map +1 -0
- package/dist/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.js +17 -0
- package/dist/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.js.map +1 -0
- package/dist/Eslint/Throwable/Exception/EslintInvalidPackageNameException.d.ts +8 -0
- package/dist/Eslint/Throwable/Exception/EslintInvalidPackageNameException.d.ts.map +1 -0
- package/dist/Eslint/Throwable/Exception/EslintInvalidPackageNameException.js +18 -0
- package/dist/Eslint/Throwable/Exception/EslintInvalidPackageNameException.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -0
- package/src/Eslint/Constant/EslintInfo.ts +12 -0
- package/src/Eslint/Factory/CopyrightHeaderFactory.ts +145 -0
- package/src/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.ts +16 -0
- package/src/Eslint/Throwable/Exception/EslintInvalidPackageNameException.ts +20 -0
- package/src/index.ts +12 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016-present Melech Mizrachi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is furnished
|
|
10
|
+
to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<p align="center"><a href="https://valkyrja.io" target="_blank">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/valkyrjaio/art/refs/heads/master/long-banner/orange/typescript.png" width="100%">
|
|
3
|
+
</a></p>
|
|
4
|
+
|
|
5
|
+
# Valkyrja ESLint (TypeScript)
|
|
6
|
+
|
|
7
|
+
Shared ESLint configuration for the Valkyrja TypeScript repositories.
|
|
8
|
+
|
|
9
|
+
The package holds the copyright header that every Valkyrja TypeScript file
|
|
10
|
+
carries, and the ESLint rule that enforces it. A repository supplies only its own
|
|
11
|
+
package identifier. The header text lives here, in one place.
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@valkyrjaio/ci-eslint"><img src="https://img.shields.io/npm/v/@valkyrjaio/ci-eslint.svg" alt="Latest Version on npm"></a>
|
|
15
|
+
<a href="https://www.npmjs.com/package/@valkyrjaio/ci-eslint"><img src="https://img.shields.io/node/v/@valkyrjaio/ci-eslint.svg" alt="Supported Node.js Version"></a>
|
|
16
|
+
<a href="https://github.com/valkyrjaio/ci-eslint-ts/blob/26.x/LICENSE.md"><img src="https://img.shields.io/github/license/valkyrjaio/ci-eslint-ts.svg" alt="License"></a>
|
|
17
|
+
<a href="https://github.com/valkyrjaio/ci-eslint-ts/actions/workflows/ci.yml?query=branch%3A26.x"><img src="https://github.com/valkyrjaio/ci-eslint-ts/actions/workflows/ci.yml/badge.svg?branch=26.x" alt="CI Status"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install --save-dev @valkyrjaio/ci-eslint
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Install it in the repository's `.github/ci/eslint/` directory, next to `eslint`
|
|
27
|
+
itself.
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
Give `getRule` the repository's own package identifier, and register the rule
|
|
32
|
+
that it returns:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { CopyrightHeaderFactory } from '@valkyrjaio/ci-eslint';
|
|
36
|
+
|
|
37
|
+
export default tseslint.config(eslint.configs.recommended, {
|
|
38
|
+
plugins: {
|
|
39
|
+
local: { rules: { 'copyright-header': CopyrightHeaderFactory.getRule('Valkyrja Framework') } },
|
|
40
|
+
},
|
|
41
|
+
rules: {
|
|
42
|
+
'local/copyright-header': 'error',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`COPYRIGHT_HEADER.md` in the [`.github`][copyright header url] repository maps
|
|
48
|
+
every repository to its identifier. `valkyrja-ts` takes `Valkyrja Framework`,
|
|
49
|
+
`sindri-ts` takes `Sindri`, `valkyrja-starter-app-ts` takes
|
|
50
|
+
`Valkyrja Application`, and `project-template-ts` takes `Project Template`.
|
|
51
|
+
|
|
52
|
+
## The API
|
|
53
|
+
|
|
54
|
+
| Member | Returns |
|
|
55
|
+
| :---------------------------------------- | :-------------------------------------------------- |
|
|
56
|
+
| `CopyrightHeaderFactory.getRule(name)` | the ESLint rule that requires the header |
|
|
57
|
+
| `CopyrightHeaderFactory.getHeader(name)` | the full block comment, and the blank line below it |
|
|
58
|
+
| `CopyrightHeaderFactory.getComment(name)` | the text between the two comment delimiters |
|
|
59
|
+
|
|
60
|
+
Each member takes the package identifier, and each one rejects a value that
|
|
61
|
+
names no package.
|
|
62
|
+
|
|
63
|
+
## Why the package name is guarded
|
|
64
|
+
|
|
65
|
+
Warning: the rule is fixable. It rewrites the header of every file it reads, and
|
|
66
|
+
it then reports each file as correct, because the file and the configuration now
|
|
67
|
+
agree. A wrong package identifier therefore corrupts a repository behind a green
|
|
68
|
+
gate.
|
|
69
|
+
|
|
70
|
+
The PHP port shipped that defect. A function that took an assembled header was
|
|
71
|
+
changed to take a package name, one caller was not updated, and the formatter
|
|
72
|
+
wrote `This file is part of the ⟨whole five-line header⟩ package.` into every
|
|
73
|
+
file. Every check passed.
|
|
74
|
+
|
|
75
|
+
`getHeader` therefore rejects a name before it builds any text. It rejects a name
|
|
76
|
+
that spans more than one line, a name that carries the header's opening sentence,
|
|
77
|
+
and a name that holds no characters.
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
// Wrong — the caller passes a built header, and the rule would rewrite every file.
|
|
81
|
+
CopyrightHeaderFactory.getRule(existingHeaderText); // throws EslintInvalidPackageNameException
|
|
82
|
+
|
|
83
|
+
// Right — the caller passes the identifier for this repository.
|
|
84
|
+
CopyrightHeaderFactory.getRule('Valkyrja Framework');
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Versioning and Release Process
|
|
88
|
+
|
|
89
|
+
This package follows [semantic versioning][semantic versioning url] with a major
|
|
90
|
+
release every year, and support for each major version for 2 years from the date
|
|
91
|
+
of release.
|
|
92
|
+
|
|
93
|
+
For more information see our
|
|
94
|
+
[Versioning and Release Process documentation][Versioning and Release Process url].
|
|
95
|
+
|
|
96
|
+
### Supported Versions
|
|
97
|
+
|
|
98
|
+
Bug fixes are provided until 3 months after the next major release. Security
|
|
99
|
+
fixes are provided for 2 years after the initial release.
|
|
100
|
+
|
|
101
|
+
| Version | Node | Release | Bug Fixes Until | Security Fixes Until |
|
|
102
|
+
| :------ | :--- | :------------- | :-------------- | :------------------- |
|
|
103
|
+
| 26 | 22+ | March 31, 2026 | Q2 2027 | Q1 2028 |
|
|
104
|
+
|
|
105
|
+
## Contributing
|
|
106
|
+
|
|
107
|
+
See [`CONTRIBUTING.md`][contributing url] for the submission process and
|
|
108
|
+
[`VOCABULARY.md`][vocabulary url] for the terminology used across Valkyrja.
|
|
109
|
+
|
|
110
|
+
## Security Issues
|
|
111
|
+
|
|
112
|
+
If you discover a security vulnerability, please follow our
|
|
113
|
+
[disclosure procedure][security vulnerabilities url].
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
This package is open-source software licensed under the
|
|
118
|
+
[MIT license][MIT license url]. See [`LICENSE.md`](./LICENSE.md).
|
|
119
|
+
|
|
120
|
+
[Valkyrja url]: https://valkyrja.io
|
|
121
|
+
[copyright header url]: https://github.com/valkyrjaio/.github/blob/master/COPYRIGHT_HEADER.md
|
|
122
|
+
[vocabulary url]: https://github.com/valkyrjaio/.github/blob/master/VOCABULARY.md
|
|
123
|
+
[contributing url]: https://github.com/valkyrjaio/.github/blob/master/CONTRIBUTING.md
|
|
124
|
+
[security vulnerabilities url]: https://github.com/valkyrjaio/.github/blob/master/SECURITY.md
|
|
125
|
+
[Versioning and Release Process url]: https://github.com/valkyrjaio/architecture/blob/master/VERSIONING.md
|
|
126
|
+
[semantic versioning url]: https://semver.org/
|
|
127
|
+
[MIT license url]: https://opensource.org/licenses/MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EslintInfo.d.ts","sourceRoot":"","sources":["../../../src/Eslint/Constant/EslintInfo.ts"],"names":[],"mappings":"AAQA,qBAAa,UAAU;IACnB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAG,QAAQ,CAAU;IAC5C,MAAM,CAAC,QAAQ,CAAC,uBAAuB,EAAG,4BAA4B,CAAU;CACnF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
export class EslintInfo {
|
|
9
|
+
static VERSION = '26.0.0';
|
|
10
|
+
static VERSION_BUILD_DATE_TIME = 'August 2 2026 20:32:26 MST';
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=EslintInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EslintInfo.js","sourceRoot":"","sources":["../../../src/Eslint/Constant/EslintInfo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,OAAO,UAAU;IACnB,MAAM,CAAU,OAAO,GAAG,QAAiB,CAAC;IAC5C,MAAM,CAAU,uBAAuB,GAAG,4BAAqC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
/**
|
|
3
|
+
* Builds the copyright header, and the ESLint rule that enforces it.
|
|
4
|
+
*
|
|
5
|
+
* Every Valkyrja TypeScript repository takes its header from this factory and supplies only its
|
|
6
|
+
* own package identifier, so the text lives in one place.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CopyrightHeaderFactory {
|
|
9
|
+
/**
|
|
10
|
+
* Gets the text that sits between the two block comment delimiters.
|
|
11
|
+
*
|
|
12
|
+
* The rule compares the first comment of a file against this, so a file whose header body is
|
|
13
|
+
* wrong fails too, and not only a file that carries no header at all.
|
|
14
|
+
*/
|
|
15
|
+
static getComment(packageName: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Gets the full header block, and the empty line that separates it from the code below it.
|
|
18
|
+
*/
|
|
19
|
+
static getHeader(packageName: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Gets the ESLint rule that requires the header at the top of each linted file.
|
|
22
|
+
*/
|
|
23
|
+
static getRule(packageName: string): Rule.RuleModule;
|
|
24
|
+
/**
|
|
25
|
+
* Rejects a value that names no package.
|
|
26
|
+
*
|
|
27
|
+
* Warning: the rule rewrites the header of every file it reads, and it then reports the file
|
|
28
|
+
* as correct, because the file and the configuration agree. A wrong package name therefore
|
|
29
|
+
* corrupts a repository behind a green gate, so this guard runs before any text is built.
|
|
30
|
+
* The same defect landed in the PHP port, where a caller passed the assembled header to an
|
|
31
|
+
* argument that had become the package name.
|
|
32
|
+
*/
|
|
33
|
+
private static validatePackageName;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=CopyrightHeaderFactory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopyrightHeaderFactory.d.ts","sourceRoot":"","sources":["../../../src/Eslint/Factory/CopyrightHeaderFactory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AA2BnC;;;;;GAKG;AACH,qBAAa,sBAAsB;IAC/B;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAU9C;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAI7C;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC,UAAU;IAiDpD;;;;;;;;OAQG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;CAkBrC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
import { EslintInvalidPackageNameException } from "../Throwable/Exception/EslintInvalidPackageNameException.js";
|
|
9
|
+
/**
|
|
10
|
+
* The header body, one entry per line, with `{package}` where the package identifier goes.
|
|
11
|
+
*
|
|
12
|
+
* COPYRIGHT_HEADER.md in the `.github` repository holds the same text, and it maps every
|
|
13
|
+
* repository to its own identifier. An empty entry renders as a bare ` *` line.
|
|
14
|
+
*/
|
|
15
|
+
const LINES = [
|
|
16
|
+
'This file is part of the {package} package.',
|
|
17
|
+
'',
|
|
18
|
+
'Copyright (c) 2016-present Melech Mizrachi',
|
|
19
|
+
'',
|
|
20
|
+
'Released under the MIT License. See LICENSE.md for details.',
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* The sentence that opens the header.
|
|
24
|
+
*
|
|
25
|
+
* A caller that passes a whole assembled header where a package identifier belongs builds
|
|
26
|
+
* `This file is part of the ⟨whole header⟩ package.`, so the factory rejects a name that
|
|
27
|
+
* carries this sentence. See `validatePackageName`.
|
|
28
|
+
*/
|
|
29
|
+
const OPENING_SENTENCE = 'This file is part of the';
|
|
30
|
+
/**
|
|
31
|
+
* Builds the copyright header, and the ESLint rule that enforces it.
|
|
32
|
+
*
|
|
33
|
+
* Every Valkyrja TypeScript repository takes its header from this factory and supplies only its
|
|
34
|
+
* own package identifier, so the text lives in one place.
|
|
35
|
+
*/
|
|
36
|
+
export class CopyrightHeaderFactory {
|
|
37
|
+
/**
|
|
38
|
+
* Gets the text that sits between the two block comment delimiters.
|
|
39
|
+
*
|
|
40
|
+
* The rule compares the first comment of a file against this, so a file whose header body is
|
|
41
|
+
* wrong fails too, and not only a file that carries no header at all.
|
|
42
|
+
*/
|
|
43
|
+
static getComment(packageName) {
|
|
44
|
+
CopyrightHeaderFactory.validatePackageName(packageName);
|
|
45
|
+
const body = LINES.map((line) => (line === '' ? ' *' : ` * ${line.replace('{package}', packageName)}`)).join('\n');
|
|
46
|
+
return `\n${body}\n `;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Gets the full header block, and the empty line that separates it from the code below it.
|
|
50
|
+
*/
|
|
51
|
+
static getHeader(packageName) {
|
|
52
|
+
return `/*${CopyrightHeaderFactory.getComment(packageName)}*/\n\n`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Gets the ESLint rule that requires the header at the top of each linted file.
|
|
56
|
+
*/
|
|
57
|
+
static getRule(packageName) {
|
|
58
|
+
const header = CopyrightHeaderFactory.getHeader(packageName);
|
|
59
|
+
const comment = CopyrightHeaderFactory.getComment(packageName);
|
|
60
|
+
return {
|
|
61
|
+
meta: {
|
|
62
|
+
type: 'layout',
|
|
63
|
+
fixable: 'code',
|
|
64
|
+
schema: [],
|
|
65
|
+
messages: {
|
|
66
|
+
missing: 'Missing copyright header. Add the standard block comment at the top of the file.',
|
|
67
|
+
incorrect: 'Incorrect copyright header. The block comment must match the standard header exactly.',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
create(context) {
|
|
71
|
+
return {
|
|
72
|
+
Program(node) {
|
|
73
|
+
// `getAllComments` returns the comments in source order, so the first block
|
|
74
|
+
// comment is the one that a header occupies.
|
|
75
|
+
const first = context.sourceCode.getAllComments().find((c) => c.type === 'Block');
|
|
76
|
+
const loc = first?.loc;
|
|
77
|
+
if (first === undefined || loc == null || loc.start.line !== 1) {
|
|
78
|
+
context.report({
|
|
79
|
+
node,
|
|
80
|
+
messageId: 'missing',
|
|
81
|
+
fix: (fixer) => fixer.insertTextBefore(node, header),
|
|
82
|
+
});
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (first.value === comment) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// The file carries a header whose text differs. Replace that comment. An
|
|
89
|
+
// insert would put a second header above the first one.
|
|
90
|
+
context.report({
|
|
91
|
+
loc,
|
|
92
|
+
messageId: 'incorrect',
|
|
93
|
+
fix: (fixer) => fixer.replaceText(first, header.trimEnd()),
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Rejects a value that names no package.
|
|
102
|
+
*
|
|
103
|
+
* Warning: the rule rewrites the header of every file it reads, and it then reports the file
|
|
104
|
+
* as correct, because the file and the configuration agree. A wrong package name therefore
|
|
105
|
+
* corrupts a repository behind a green gate, so this guard runs before any text is built.
|
|
106
|
+
* The same defect landed in the PHP port, where a caller passed the assembled header to an
|
|
107
|
+
* argument that had become the package name.
|
|
108
|
+
*/
|
|
109
|
+
static validatePackageName(packageName) {
|
|
110
|
+
if (packageName.includes('\n') || packageName.includes('\r')) {
|
|
111
|
+
throw new EslintInvalidPackageNameException(`A package name is one line. Got ${JSON.stringify(packageName)}.`);
|
|
112
|
+
}
|
|
113
|
+
if (packageName.includes(OPENING_SENTENCE)) {
|
|
114
|
+
throw new EslintInvalidPackageNameException(`A package name is an identifier such as 'Valkyrja Framework', not a built header. ` +
|
|
115
|
+
`Got ${JSON.stringify(packageName)}.`);
|
|
116
|
+
}
|
|
117
|
+
if (packageName.trim() === '') {
|
|
118
|
+
throw new EslintInvalidPackageNameException('A package name holds at least one character.');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=CopyrightHeaderFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopyrightHeaderFactory.js","sourceRoot":"","sources":["../../../src/Eslint/Factory/CopyrightHeaderFactory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,iCAAiC,EAAE,MAAM,6DAA6D,CAAC;AAEhH;;;;;GAKG;AACH,MAAM,KAAK,GAAG;IACV,6CAA6C;IAC7C,EAAE;IACF,4CAA4C;IAC5C,EAAE;IACF,6DAA6D;CACvD,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,OAAO,sBAAsB;IAC/B;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,WAAmB;QACjC,sBAAsB,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAExD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CACxG,IAAI,CACP,CAAC;QAEF,OAAO,KAAK,IAAI,KAAK,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,WAAmB;QAChC,OAAO,KAAK,sBAAsB,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC;IACvE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,WAAmB;QAC9B,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,sBAAsB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAE/D,OAAO;YACH,IAAI,EAAE;gBACF,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,EAAE;gBACV,QAAQ,EAAE;oBACN,OAAO,EAAE,kFAAkF;oBAC3F,SAAS,EAAE,uFAAuF;iBACrG;aACJ;YACD,MAAM,CAAC,OAAyB;gBAC5B,OAAO;oBACH,OAAO,CAAC,IAAI;wBACR,4EAA4E;wBAC5E,6CAA6C;wBAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;wBAClF,MAAM,GAAG,GAAG,KAAK,EAAE,GAAG,CAAC;wBAEvB,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;4BAC7D,OAAO,CAAC,MAAM,CAAC;gCACX,IAAI;gCACJ,SAAS,EAAE,SAAS;gCACpB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC;6BACvD,CAAC,CAAC;4BAEH,OAAO;wBACX,CAAC;wBAED,IAAI,KAAK,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;4BAC1B,OAAO;wBACX,CAAC;wBAED,yEAAyE;wBACzE,wDAAwD;wBACxD,OAAO,CAAC,MAAM,CAAC;4BACX,GAAG;4BACH,SAAS,EAAE,WAAW;4BACtB,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;yBAC7D,CAAC,CAAC;oBACP,CAAC;iBACJ,CAAC;YACN,CAAC;SACJ,CAAC;IACN,CAAC;IAED;;;;;;;;OAQG;IACK,MAAM,CAAC,mBAAmB,CAAC,WAAmB;QAClD,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,iCAAiC,CACvC,mCAAmC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CACpE,CAAC;QACN,CAAC;QAED,IAAI,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,iCAAiC,CACvC,oFAAoF;gBAChF,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAC5C,CAAC;QACN,CAAC;QAED,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,iCAAiC,CAAC,8CAA8C,CAAC,CAAC;QAChG,CAAC;IACL,CAAC;CACJ"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base for every exception this package throws for a bad argument.
|
|
3
|
+
*
|
|
4
|
+
* The chain roots in the native `Error` rather than in `ValkyrjaInvalidArgumentException`. An
|
|
5
|
+
* ESLint configuration is plain JavaScript that Node loads directly, so this package cannot
|
|
6
|
+
* depend on `@valkyrjaio/valkyrja`, which ships TypeScript source that Node does not compile.
|
|
7
|
+
*/
|
|
8
|
+
export declare abstract class EslintInvalidArgumentException extends Error {
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=EslintInvalidArgumentException.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EslintInvalidArgumentException.d.ts","sourceRoot":"","sources":["../../../../../src/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,8BAAsB,8BAA+B,SAAQ,KAAK;CAAG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The base for every exception this package throws for a bad argument.
|
|
10
|
+
*
|
|
11
|
+
* The chain roots in the native `Error` rather than in `ValkyrjaInvalidArgumentException`. An
|
|
12
|
+
* ESLint configuration is plain JavaScript that Node loads directly, so this package cannot
|
|
13
|
+
* depend on `@valkyrjaio/valkyrja`, which ships TypeScript source that Node does not compile.
|
|
14
|
+
*/
|
|
15
|
+
export class EslintInvalidArgumentException extends Error {
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=EslintInvalidArgumentException.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EslintInvalidArgumentException.js","sourceRoot":"","sources":["../../../../../src/Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;GAMG;AACH,MAAM,OAAgB,8BAA+B,SAAQ,KAAK;CAAG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EslintInvalidArgumentException } from './Abstract/EslintInvalidArgumentException.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The package name that a caller gave does not name a package.
|
|
4
|
+
*/
|
|
5
|
+
export declare class EslintInvalidPackageNameException extends EslintInvalidArgumentException {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=EslintInvalidPackageNameException.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EslintInvalidPackageNameException.d.ts","sourceRoot":"","sources":["../../../../src/Eslint/Throwable/Exception/EslintInvalidPackageNameException.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,8BAA8B,EAAE,MAAM,8CAA8C,CAAC;AAE9F;;GAEG;AACH,qBAAa,iCAAkC,SAAQ,8BAA8B;gBACrE,OAAO,EAAE,MAAM;CAK9B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
import { EslintInvalidArgumentException } from "./Abstract/EslintInvalidArgumentException.js";
|
|
9
|
+
/**
|
|
10
|
+
* The package name that a caller gave does not name a package.
|
|
11
|
+
*/
|
|
12
|
+
export class EslintInvalidPackageNameException extends EslintInvalidArgumentException {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'EslintInvalidPackageNameException';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=EslintInvalidPackageNameException.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EslintInvalidPackageNameException.js","sourceRoot":"","sources":["../../../../src/Eslint/Throwable/Exception/EslintInvalidPackageNameException.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,8BAA8B,EAAE,MAAM,8CAA8C,CAAC;AAE9F;;GAEG;AACH,MAAM,OAAO,iCAAkC,SAAQ,8BAA8B;IACjF,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;IACpD,CAAC;CACJ"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { EslintInfo } from './Eslint/Constant/EslintInfo.ts';
|
|
2
|
+
export { CopyrightHeaderFactory } from './Eslint/Factory/CopyrightHeaderFactory.ts';
|
|
3
|
+
export { EslintInvalidArgumentException } from './Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.ts';
|
|
4
|
+
export { EslintInvalidPackageNameException } from './Eslint/Throwable/Exception/EslintInvalidPackageNameException.ts';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAE,8BAA8B,EAAE,MAAM,yEAAyE,CAAC;AACzH,OAAO,EAAE,iCAAiC,EAAE,MAAM,mEAAmE,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
export { EslintInfo } from "./Eslint/Constant/EslintInfo.js";
|
|
9
|
+
export { CopyrightHeaderFactory } from "./Eslint/Factory/CopyrightHeaderFactory.js";
|
|
10
|
+
export { EslintInvalidArgumentException } from "./Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.js";
|
|
11
|
+
export { EslintInvalidPackageNameException } from "./Eslint/Throwable/Exception/EslintInvalidPackageNameException.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4CAA4C,CAAC;AACpF,OAAO,EAAE,8BAA8B,EAAE,MAAM,yEAAyE,CAAC;AACzH,OAAO,EAAE,iCAAiC,EAAE,MAAM,mEAAmE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@valkyrjaio/ci-eslint",
|
|
3
|
+
"version": "26.0.0",
|
|
4
|
+
"description": "Shared ESLint configuration for Valkyrja TypeScript repositories",
|
|
5
|
+
"homepage": "https://www.valkyrja.io",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"ci",
|
|
8
|
+
"eslint",
|
|
9
|
+
"valkyrja"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "Melech Mizrachi",
|
|
14
|
+
"email": "melechmizrachi@gmail.com"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"src"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "cd .github/ci/typescript && npm run build",
|
|
32
|
+
"prepublishOnly": "npm run build",
|
|
33
|
+
"typescript": "cd .github/ci/typescript && npm run check",
|
|
34
|
+
"typescript-outdated-check": "cd .github/ci/typescript && npm install && npm outdated",
|
|
35
|
+
"typescript-outdated-check-major-release": "cd .github/ci/typescript && npm install && npm outdated",
|
|
36
|
+
"typescript-npm-update": "cd .github/ci/typescript && npm update",
|
|
37
|
+
"eslint": "cd .github/ci/eslint && npm run check",
|
|
38
|
+
"eslint-outdated-check": "cd .github/ci/eslint && npm install && npm outdated",
|
|
39
|
+
"eslint-outdated-check-major-release": "cd .github/ci/eslint && npm install && npm outdated",
|
|
40
|
+
"eslint-npm-update": "cd .github/ci/eslint && npm update",
|
|
41
|
+
"prettier": "cd .github/ci/prettier && npm run fix",
|
|
42
|
+
"prettier-check": "cd .github/ci/prettier && npm run check",
|
|
43
|
+
"prettier-outdated-check": "cd .github/ci/prettier && npm install && npm outdated",
|
|
44
|
+
"prettier-outdated-check-major-release": "cd .github/ci/prettier && npm install && npm outdated",
|
|
45
|
+
"prettier-npm-update": "cd .github/ci/prettier && npm update",
|
|
46
|
+
"vitest": "cd .github/ci/vitest && npm run check",
|
|
47
|
+
"vitest-coverage": "cd .github/ci/vitest && npm run coverage",
|
|
48
|
+
"vitest-outdated-check": "cd .github/ci/vitest && npm install && npm outdated",
|
|
49
|
+
"vitest-outdated-check-major-release": "cd .github/ci/vitest && npm install && npm outdated",
|
|
50
|
+
"vitest-npm-update": "cd .github/ci/vitest && npm update",
|
|
51
|
+
"root-outdated-check": "npm install && npm outdated",
|
|
52
|
+
"root-outdated-check-major-release": "npm install && npm outdated",
|
|
53
|
+
"root-and-suggested-outdated-check": "cd .github/ci/root-and-suggested && npm install && npm outdated",
|
|
54
|
+
"root-and-suggested-outdated-check-major-release": "cd .github/ci/root-and-suggested && npm install && npm outdated",
|
|
55
|
+
"root-and-suggested-npm-update": "cd .github/ci/root-and-suggested && npm update"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"eslint": ">=9"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export class EslintInfo {
|
|
10
|
+
static readonly VERSION = '26.0.0' as const;
|
|
11
|
+
static readonly VERSION_BUILD_DATE_TIME = 'August 2 2026 20:32:26 MST' as const;
|
|
12
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Rule } from 'eslint';
|
|
10
|
+
|
|
11
|
+
import { EslintInvalidPackageNameException } from '../Throwable/Exception/EslintInvalidPackageNameException.ts';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The header body, one entry per line, with `{package}` where the package identifier goes.
|
|
15
|
+
*
|
|
16
|
+
* COPYRIGHT_HEADER.md in the `.github` repository holds the same text, and it maps every
|
|
17
|
+
* repository to its own identifier. An empty entry renders as a bare ` *` line.
|
|
18
|
+
*/
|
|
19
|
+
const LINES = [
|
|
20
|
+
'This file is part of the {package} package.',
|
|
21
|
+
'',
|
|
22
|
+
'Copyright (c) 2016-present Melech Mizrachi',
|
|
23
|
+
'',
|
|
24
|
+
'Released under the MIT License. See LICENSE.md for details.',
|
|
25
|
+
] as const;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The sentence that opens the header.
|
|
29
|
+
*
|
|
30
|
+
* A caller that passes a whole assembled header where a package identifier belongs builds
|
|
31
|
+
* `This file is part of the ⟨whole header⟩ package.`, so the factory rejects a name that
|
|
32
|
+
* carries this sentence. See `validatePackageName`.
|
|
33
|
+
*/
|
|
34
|
+
const OPENING_SENTENCE = 'This file is part of the';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Builds the copyright header, and the ESLint rule that enforces it.
|
|
38
|
+
*
|
|
39
|
+
* Every Valkyrja TypeScript repository takes its header from this factory and supplies only its
|
|
40
|
+
* own package identifier, so the text lives in one place.
|
|
41
|
+
*/
|
|
42
|
+
export class CopyrightHeaderFactory {
|
|
43
|
+
/**
|
|
44
|
+
* Gets the text that sits between the two block comment delimiters.
|
|
45
|
+
*
|
|
46
|
+
* The rule compares the first comment of a file against this, so a file whose header body is
|
|
47
|
+
* wrong fails too, and not only a file that carries no header at all.
|
|
48
|
+
*/
|
|
49
|
+
static getComment(packageName: string): string {
|
|
50
|
+
CopyrightHeaderFactory.validatePackageName(packageName);
|
|
51
|
+
|
|
52
|
+
const body = LINES.map((line) => (line === '' ? ' *' : ` * ${line.replace('{package}', packageName)}`)).join(
|
|
53
|
+
'\n',
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return `\n${body}\n `;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gets the full header block, and the empty line that separates it from the code below it.
|
|
61
|
+
*/
|
|
62
|
+
static getHeader(packageName: string): string {
|
|
63
|
+
return `/*${CopyrightHeaderFactory.getComment(packageName)}*/\n\n`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gets the ESLint rule that requires the header at the top of each linted file.
|
|
68
|
+
*/
|
|
69
|
+
static getRule(packageName: string): Rule.RuleModule {
|
|
70
|
+
const header = CopyrightHeaderFactory.getHeader(packageName);
|
|
71
|
+
const comment = CopyrightHeaderFactory.getComment(packageName);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
meta: {
|
|
75
|
+
type: 'layout',
|
|
76
|
+
fixable: 'code',
|
|
77
|
+
schema: [],
|
|
78
|
+
messages: {
|
|
79
|
+
missing: 'Missing copyright header. Add the standard block comment at the top of the file.',
|
|
80
|
+
incorrect: 'Incorrect copyright header. The block comment must match the standard header exactly.',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
create(context: Rule.RuleContext): Rule.RuleListener {
|
|
84
|
+
return {
|
|
85
|
+
Program(node): void {
|
|
86
|
+
// `getAllComments` returns the comments in source order, so the first block
|
|
87
|
+
// comment is the one that a header occupies.
|
|
88
|
+
const first = context.sourceCode.getAllComments().find((c) => c.type === 'Block');
|
|
89
|
+
const loc = first?.loc;
|
|
90
|
+
|
|
91
|
+
if (first === undefined || loc == null || loc.start.line !== 1) {
|
|
92
|
+
context.report({
|
|
93
|
+
node,
|
|
94
|
+
messageId: 'missing',
|
|
95
|
+
fix: (fixer) => fixer.insertTextBefore(node, header),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (first.value === comment) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// The file carries a header whose text differs. Replace that comment. An
|
|
106
|
+
// insert would put a second header above the first one.
|
|
107
|
+
context.report({
|
|
108
|
+
loc,
|
|
109
|
+
messageId: 'incorrect',
|
|
110
|
+
fix: (fixer) => fixer.replaceText(first, header.trimEnd()),
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Rejects a value that names no package.
|
|
120
|
+
*
|
|
121
|
+
* Warning: the rule rewrites the header of every file it reads, and it then reports the file
|
|
122
|
+
* as correct, because the file and the configuration agree. A wrong package name therefore
|
|
123
|
+
* corrupts a repository behind a green gate, so this guard runs before any text is built.
|
|
124
|
+
* The same defect landed in the PHP port, where a caller passed the assembled header to an
|
|
125
|
+
* argument that had become the package name.
|
|
126
|
+
*/
|
|
127
|
+
private static validatePackageName(packageName: string): void {
|
|
128
|
+
if (packageName.includes('\n') || packageName.includes('\r')) {
|
|
129
|
+
throw new EslintInvalidPackageNameException(
|
|
130
|
+
`A package name is one line. Got ${JSON.stringify(packageName)}.`,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (packageName.includes(OPENING_SENTENCE)) {
|
|
135
|
+
throw new EslintInvalidPackageNameException(
|
|
136
|
+
`A package name is an identifier such as 'Valkyrja Framework', not a built header. ` +
|
|
137
|
+
`Got ${JSON.stringify(packageName)}.`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (packageName.trim() === '') {
|
|
142
|
+
throw new EslintInvalidPackageNameException('A package name holds at least one character.');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The base for every exception this package throws for a bad argument.
|
|
11
|
+
*
|
|
12
|
+
* The chain roots in the native `Error` rather than in `ValkyrjaInvalidArgumentException`. An
|
|
13
|
+
* ESLint configuration is plain JavaScript that Node loads directly, so this package cannot
|
|
14
|
+
* depend on `@valkyrjaio/valkyrja`, which ships TypeScript source that Node does not compile.
|
|
15
|
+
*/
|
|
16
|
+
export abstract class EslintInvalidArgumentException extends Error {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { EslintInvalidArgumentException } from './Abstract/EslintInvalidArgumentException.ts';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The package name that a caller gave does not name a package.
|
|
13
|
+
*/
|
|
14
|
+
export class EslintInvalidPackageNameException extends EslintInvalidArgumentException {
|
|
15
|
+
constructor(message: string) {
|
|
16
|
+
super(message);
|
|
17
|
+
|
|
18
|
+
this.name = 'EslintInvalidPackageNameException';
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Valkyrja ESLint package.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2016-present Melech Mizrachi
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT License. See LICENSE.md for details.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { EslintInfo } from './Eslint/Constant/EslintInfo.ts';
|
|
10
|
+
export { CopyrightHeaderFactory } from './Eslint/Factory/CopyrightHeaderFactory.ts';
|
|
11
|
+
export { EslintInvalidArgumentException } from './Eslint/Throwable/Exception/Abstract/EslintInvalidArgumentException.ts';
|
|
12
|
+
export { EslintInvalidPackageNameException } from './Eslint/Throwable/Exception/EslintInvalidPackageNameException.ts';
|