@polariens/kitsune-lint 1.0.0-rc.3
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/README.md +233 -0
- package/bin/copy-prettierignore.mjs +30 -0
- package/eslint/configs/base.d.mts +10 -0
- package/eslint/configs/base.mjs +28 -0
- package/eslint/configs/clean-code.d.mts +20 -0
- package/eslint/configs/clean-code.mjs +77 -0
- package/eslint/configs/pinia.d.mts +10 -0
- package/eslint/configs/pinia.mjs +36 -0
- package/eslint/configs/security.d.mts +12 -0
- package/eslint/configs/security.mjs +46 -0
- package/eslint/configs/tests.d.mts +10 -0
- package/eslint/configs/tests.mjs +40 -0
- package/eslint/configs/typescript.d.mts +12 -0
- package/eslint/configs/typescript.mjs +184 -0
- package/eslint/configs/vitest.d.mts +20 -0
- package/eslint/configs/vitest.mjs +62 -0
- package/eslint/configs/vue.d.mts +25 -0
- package/eslint/configs/vue.mjs +71 -0
- package/eslint/index.d.mts +51 -0
- package/eslint/index.mjs +85 -0
- package/eslint/rules/no-null-in-types.mjs +117 -0
- package/eslint/utils.d.mts +7 -0
- package/eslint/utils.mjs +20 -0
- package/package.json +117 -0
- package/prettier/.prettierignore +12 -0
- package/prettier/index.d.mts +44 -0
- package/prettier/index.mjs +78 -0
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# @merieli/kitsune-lint đŠ
|
|
2
|
+
|
|
3
|
+
Opinionated ESLint & Prettier configs for high-quality Vue, TypeScript & Vitest projects.
|
|
4
|
+
|
|
5
|
+
> **Kitsune** (ç) Ă© a raposa mĂstica do folclore japonĂȘs â astuta, adaptĂĄvel e capaz de se transformar conforme o contexto. Assim como a kitsune, este pacote se molda ao seu projeto: vocĂȘ escolhe os mĂłdulos e as opçÔes, e ele compĂ”e as regras certas para cada cenĂĄrio. CĂłdigo limpo com a precisĂŁo de uma raposa.
|
|
6
|
+
|
|
7
|
+
## O que Ă©
|
|
8
|
+
|
|
9
|
+
Um pacote instalĂĄvel que padroniza regras de linting e formatação entre mĂșltiplos projetos. As configuraçÔes sĂŁo **modulares** â cada conjunto de regras (TypeScript, Vue, Pinia, segurança, etc.) Ă© independente e configurĂĄvel via opçÔes.
|
|
10
|
+
|
|
11
|
+
## Como usar
|
|
12
|
+
|
|
13
|
+
### Instalação
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install --save-dev @merieli/kitsune-lint
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
As peer dependencies devem ser instaladas no projeto consumidor:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install --save-dev eslint @eslint/js typescript-eslint globals
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Dependendo dos módulos habilitados, instale também:
|
|
26
|
+
|
|
27
|
+
| MĂłdulo | DependĂȘncias extras |
|
|
28
|
+
| ---------- | ------------------------------------------------ |
|
|
29
|
+
| `security` | `eslint-plugin-security` |
|
|
30
|
+
| `vue` | `eslint-plugin-vue vue-eslint-parser` |
|
|
31
|
+
| `pinia` | `eslint-plugin-pinia` |
|
|
32
|
+
| `vitest` | `@vitest/eslint-plugin` |
|
|
33
|
+
|
|
34
|
+
### ESLint â Factory function (recomendado)
|
|
35
|
+
|
|
36
|
+
A forma mais simples. O `createConfig` compÔe os módulos selecionados:
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
// eslint.config.js
|
|
40
|
+
import { createConfig } from '@merieli/kitsune-lint/eslint';
|
|
41
|
+
|
|
42
|
+
export default await createConfig({
|
|
43
|
+
vue: true,
|
|
44
|
+
pinia: true,
|
|
45
|
+
tests: true,
|
|
46
|
+
vitest: true,
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Por padrĂŁo, `base`, `typescript`, `security` e `cleanCode` jĂĄ vĂȘm habilitados. Passe `false` para desativar:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
export default await createConfig({
|
|
54
|
+
security: false,
|
|
55
|
+
vue: true,
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### ESLint â Customizando mĂłdulos
|
|
60
|
+
|
|
61
|
+
Cada módulo aceita um objeto de opçÔes no lugar de `true`:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
export default await createConfig({
|
|
65
|
+
base: { environment: 'node' },
|
|
66
|
+
cleanCode: { maxDepth: 3, maxParams: 3, complexity: 10, maxLines: 300 },
|
|
67
|
+
vue: { apiStyle: 'composition' },
|
|
68
|
+
pinia: true,
|
|
69
|
+
vitest: {
|
|
70
|
+
titlePattern: '^should .+',
|
|
71
|
+
titleMessage: 'Test title must start with "should"',
|
|
72
|
+
fn: 'it',
|
|
73
|
+
maxNestedDescribe: 2,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### ESLint â Imports granulares
|
|
79
|
+
|
|
80
|
+
Para controle total, importe cada mĂłdulo diretamente:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
// eslint.config.js
|
|
84
|
+
import { base } from '@merieli/kitsune-lint/eslint/base';
|
|
85
|
+
import { typescript } from '@merieli/kitsune-lint/eslint/typescript';
|
|
86
|
+
import { vue } from '@merieli/kitsune-lint/eslint/vue';
|
|
87
|
+
import { pinia } from '@merieli/kitsune-lint/eslint/pinia';
|
|
88
|
+
|
|
89
|
+
export default [
|
|
90
|
+
...base(),
|
|
91
|
+
...typescript(),
|
|
92
|
+
...vue(),
|
|
93
|
+
...(await pinia()),
|
|
94
|
+
];
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### ESLint â Estendendo com configs extras
|
|
98
|
+
|
|
99
|
+
Use `extend` para adicionar configs de plugins externos (ex: `eslint-config-prettier`):
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
import { createConfig } from '@merieli/kitsune-lint/eslint';
|
|
103
|
+
import eslintConfigPrettier from 'eslint-config-prettier';
|
|
104
|
+
import pluginVue from 'eslint-plugin-vue';
|
|
105
|
+
|
|
106
|
+
export default await createConfig({
|
|
107
|
+
vue: true,
|
|
108
|
+
pinia: true,
|
|
109
|
+
tests: true,
|
|
110
|
+
vitest: true,
|
|
111
|
+
extend: [
|
|
112
|
+
...pluginVue.configs['flat/recommended'],
|
|
113
|
+
eslintConfigPrettier,
|
|
114
|
+
],
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Prettier
|
|
119
|
+
|
|
120
|
+
Uso direto da config padrĂŁo:
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// prettier.config.mjs
|
|
124
|
+
import { prettierConfig } from '@merieli/kitsune-lint/prettier';
|
|
125
|
+
export default prettierConfig;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Com overrides:
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
import { createPrettierConfig } from '@merieli/kitsune-lint/prettier';
|
|
132
|
+
export default createPrettierConfig({ printWidth: 120 });
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## MĂłdulos
|
|
136
|
+
|
|
137
|
+
| Módulo | Default | Descrição |
|
|
138
|
+
| ------------ | ------- | ------------------------------------------------------------ |
|
|
139
|
+
| `base` | â
on | Globals do ambiente (browser/node) |
|
|
140
|
+
| `typescript` | â
on | Regras TS recomendadas + naming conventions |
|
|
141
|
+
| `security` | â
on | Prevenção de eval, XSS, injection + eslint-plugin-security |
|
|
142
|
+
| `cleanCode` | â
on | SRP, legibilidade, imutabilidade, organização |
|
|
143
|
+
| `vue` | â off | Vue 3 + script setup + type-based props/emits |
|
|
144
|
+
| `pinia` | â off | Stores Pinia â naming, organização, boas prĂĄticas |
|
|
145
|
+
| `tests` | â off | Relaxamentos para arquivos de teste (desliga regras rĂgidas) |
|
|
146
|
+
| `vitest` | â off | Regras do plugin Vitest (naming, hooks, describe) |
|
|
147
|
+
|
|
148
|
+
## OpçÔes dos módulos
|
|
149
|
+
|
|
150
|
+
### base
|
|
151
|
+
|
|
152
|
+
| Opção | Padrão | Descrição |
|
|
153
|
+
| ------------- | ----------- | ------------------------------------------------ |
|
|
154
|
+
| `environment` | `'browser'` | Globals: `browser`, `node`, `shared-node-browser`|
|
|
155
|
+
|
|
156
|
+
### typescript
|
|
157
|
+
|
|
158
|
+
| Opção | Padrão | Descrição |
|
|
159
|
+
| -------- | -------------- | ------------------ |
|
|
160
|
+
| `ignores`| configs + dist | Patterns a ignorar |
|
|
161
|
+
| `rules` | `{}` | Regras extras |
|
|
162
|
+
|
|
163
|
+
### security
|
|
164
|
+
|
|
165
|
+
| Opção | Padrão | Descrição |
|
|
166
|
+
| --------------- | ------ | ----------------------------- |
|
|
167
|
+
| `pluginEnabled` | `true` | Usar `eslint-plugin-security` |
|
|
168
|
+
| `rules` | `{}` | Regras extras |
|
|
169
|
+
|
|
170
|
+
### cleanCode
|
|
171
|
+
|
|
172
|
+
| Opção | Padrão | Descrição |
|
|
173
|
+
| --------------------- | ------ | ---------------------------------- |
|
|
174
|
+
| `maxDepth` | `4` | Profundidade mĂĄxima de aninhamento |
|
|
175
|
+
| `maxParams` | `4` | Parùmetros måximos por função |
|
|
176
|
+
| `complexity` | `14` | Complexidade ciclomĂĄtica mĂĄxima |
|
|
177
|
+
| `maxLines` | `400` | Linhas mĂĄximas por arquivo |
|
|
178
|
+
| `maxLinesPerFunction` | `80` | Linhas måximas por função |
|
|
179
|
+
| `rules` | `{}` | Regras extras |
|
|
180
|
+
|
|
181
|
+
### vue
|
|
182
|
+
|
|
183
|
+
| Opção | Padrão | Descrição |
|
|
184
|
+
| ---------- | ---------------- | ------------------- |
|
|
185
|
+
| `apiStyle` | `'script-setup'` | Estilo de API Vue |
|
|
186
|
+
| `rules` | `{}` | Regras extras |
|
|
187
|
+
|
|
188
|
+
### pinia
|
|
189
|
+
|
|
190
|
+
| Opção | Padrão | Descrição |
|
|
191
|
+
| ------- | ------------------------- | ------------------------------- |
|
|
192
|
+
| `files` | `['src/state/**/*.ts']` | Override dos file patterns |
|
|
193
|
+
| `rules` | `{}` | Regras extras |
|
|
194
|
+
|
|
195
|
+
### tests
|
|
196
|
+
|
|
197
|
+
Relaxamentos para arquivos de teste â desliga regras rĂgidas de produção como `complexity`, `max-lines`, `max-lines-per-function`, `no-explicit-any`, `naming-convention`, etc.
|
|
198
|
+
|
|
199
|
+
| Opção | Padrão | Descrição |
|
|
200
|
+
| ------- | ------------------------------- | -------------------------- |
|
|
201
|
+
| `files` | `['tests/**/*.{js,mjs,cjs,ts}']`| Override dos file patterns |
|
|
202
|
+
| `rules` | `{}` | Regras extras |
|
|
203
|
+
|
|
204
|
+
### vitest
|
|
205
|
+
|
|
206
|
+
| Opção | Padrão | Descrição |
|
|
207
|
+
| ------------------ | -------------- | -------------------------------- |
|
|
208
|
+
| `fn` | `'test'` | `test()` ou `it()` |
|
|
209
|
+
| `titlePattern` | Gherkin PT-BR | Regex do tĂtulo dos testes |
|
|
210
|
+
| `titleMessage` | mensagem PT-BR | Mensagem de erro |
|
|
211
|
+
| `maxNestedDescribe`| `3` | MĂĄximo de describe aninhados |
|
|
212
|
+
| `rules` | `{}` | Regras extras |
|
|
213
|
+
|
|
214
|
+
## Estrutura
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
@merieli/kitsune-lint/
|
|
218
|
+
âââ package.json
|
|
219
|
+
âââ eslint/
|
|
220
|
+
â âââ index.mjs # Factory createConfig + re-exports
|
|
221
|
+
â âââ utils.mjs # Patterns de arquivos compartilhados
|
|
222
|
+
â âââ configs/
|
|
223
|
+
â âââ base.mjs # Globals do ambiente (browser/node)
|
|
224
|
+
â âââ typescript.mjs # Regras TypeScript + naming conventions
|
|
225
|
+
â âââ security.mjs # Prevenção de eval, XSS, injection
|
|
226
|
+
â âââ clean-code.mjs # SRP, legibilidade, imutabilidade
|
|
227
|
+
â âââ vue.mjs # Vue 3 + script setup
|
|
228
|
+
â âââ pinia.mjs # Stores Pinia
|
|
229
|
+
â âââ tests.mjs # Relaxamentos para testes
|
|
230
|
+
â âââ vitest.mjs # Regras plugin Vitest
|
|
231
|
+
âââ prettier/
|
|
232
|
+
âââ index.mjs # Config Prettier exportĂĄvel
|
|
233
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { cpSync, existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const source = resolve(__dirname, '..', 'prettier', '.prettierignore');
|
|
9
|
+
const dest = resolve(process.cwd(), '.prettierignore');
|
|
10
|
+
|
|
11
|
+
const force = process.argv.includes('--force');
|
|
12
|
+
|
|
13
|
+
if (existsSync(dest) && !force) {
|
|
14
|
+
const existing = readFileSync(dest, 'utf-8');
|
|
15
|
+
const template = readFileSync(source, 'utf-8');
|
|
16
|
+
|
|
17
|
+
if (existing === template) {
|
|
18
|
+
console.info('[lint-config] .prettierignore jĂĄ estĂĄ atualizado.');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
console.error(
|
|
23
|
+
'[lint-config] .prettierignore jĂĄ existe e difere do template.\n' +
|
|
24
|
+
' Use --force para sobrescrever.'
|
|
25
|
+
);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
cpSync(source, dest);
|
|
30
|
+
console.info(`[lint-config] .prettierignore copiado para ${dest}`);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export interface BaseOptions {
|
|
4
|
+
/** File patterns override */
|
|
5
|
+
files?: string[];
|
|
6
|
+
/** Ambiente de globals a aplicar @default 'browser' */
|
|
7
|
+
environment?: 'browser' | 'node' | 'shared-node-browser' | 'worker' | 'serviceworker';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export declare function base(options?: BaseOptions): Linter.Config[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import globals from 'globals';
|
|
2
|
+
|
|
3
|
+
import { resolveFiles } from '../utils.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} BaseOptions
|
|
7
|
+
* @property {string[]} [files] - File patterns override
|
|
8
|
+
* @property {'browser' | 'node' | 'shared-node-browser'} [environment='browser'] - Ambiente global
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Configuração base com globals do ambiente.
|
|
13
|
+
* @param {BaseOptions} [options={}]
|
|
14
|
+
* @returns {import('eslint').Linter.Config[]}
|
|
15
|
+
*/
|
|
16
|
+
export function base(options = {}) {
|
|
17
|
+
const { files, environment = 'browser' } = options;
|
|
18
|
+
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
files: resolveFiles('all', files),
|
|
22
|
+
name: '@kitsune/base/globals',
|
|
23
|
+
languageOptions: {
|
|
24
|
+
globals: globals[environment],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export interface CleanCodeOptions {
|
|
4
|
+
/** File patterns override */
|
|
5
|
+
files?: string[];
|
|
6
|
+
/** Profundidade mĂĄxima de aninhamento @default 4 */
|
|
7
|
+
maxDepth?: number;
|
|
8
|
+
/** NĂșmero mĂĄximo de parĂąmetros por função @default 4 */
|
|
9
|
+
maxParams?: number;
|
|
10
|
+
/** Complexidade ciclomĂĄtica mĂĄxima @default 14 */
|
|
11
|
+
complexity?: number;
|
|
12
|
+
/** Linhas mĂĄximas por arquivo @default 400 */
|
|
13
|
+
maxLines?: number;
|
|
14
|
+
/** Linhas måximas por função @default 80 */
|
|
15
|
+
maxLinesPerFunction?: number;
|
|
16
|
+
/** Regras adicionais ou overrides */
|
|
17
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export declare function cleanCode(options?: CleanCodeOptions): Linter.Config[];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { resolveFiles } from '../utils.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} CleanCodeOptions
|
|
5
|
+
* @property {string[]} [files] - File patterns override
|
|
6
|
+
* @property {number} [maxDepth=4] - Profundidade mĂĄxima de aninhamento
|
|
7
|
+
* @property {number} [maxParams=4] - NĂșmero mĂĄximo de parĂąmetros
|
|
8
|
+
* @property {number} [complexity=14] - Complexidade ciclomĂĄtica mĂĄxima
|
|
9
|
+
* @property {number} [maxLines=400] - Linhas mĂĄximas por arquivo
|
|
10
|
+
* @property {number} [maxLinesPerFunction=80] - Linhas måximas por função
|
|
11
|
+
* @property {Record<string, unknown>} [rules] - Regras adicionais ou overrides
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Regras de clean code para legibilidade e manutenibilidade.
|
|
16
|
+
* @param {CleanCodeOptions} [options={}]
|
|
17
|
+
* @returns {import('eslint').Linter.Config[]}
|
|
18
|
+
*/
|
|
19
|
+
export function cleanCode(options = {}) {
|
|
20
|
+
const {
|
|
21
|
+
files,
|
|
22
|
+
maxDepth = 4,
|
|
23
|
+
maxParams = 4,
|
|
24
|
+
complexity: maxComplexity = 14,
|
|
25
|
+
maxLines = 400,
|
|
26
|
+
maxLinesPerFunction = 80,
|
|
27
|
+
rules: extraRules = {},
|
|
28
|
+
} = options;
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
files: resolveFiles('all', files),
|
|
33
|
+
name: '@kitsune/clean-code/rules',
|
|
34
|
+
rules: {
|
|
35
|
+
// --- Single Responsibility (SRP) ---
|
|
36
|
+
complexity: ['warn', maxComplexity],
|
|
37
|
+
'max-lines': ['warn', { max: maxLines, skipBlankLines: true, skipComments: true }],
|
|
38
|
+
'max-lines-per-function': ['warn', { max: maxLinesPerFunction, skipBlankLines: true, skipComments: true }],
|
|
39
|
+
'max-depth': ['error', maxDepth],
|
|
40
|
+
'max-params': ['error', maxParams],
|
|
41
|
+
|
|
42
|
+
// --- Readability & Expressiveness ---
|
|
43
|
+
'no-negated-condition': 'error',
|
|
44
|
+
'no-nested-ternary': 'error',
|
|
45
|
+
'no-unneeded-ternary': 'error',
|
|
46
|
+
'no-else-return': 'error',
|
|
47
|
+
'no-lonely-if': 'error',
|
|
48
|
+
'prefer-template': 'error',
|
|
49
|
+
'object-shorthand': 'error',
|
|
50
|
+
curly: ['error', 'all'],
|
|
51
|
+
'arrow-body-style': ['error', 'as-needed'],
|
|
52
|
+
'no-multi-assign': 'error',
|
|
53
|
+
'no-unreachable-loop': 'error',
|
|
54
|
+
'no-unused-labels': 'error',
|
|
55
|
+
|
|
56
|
+
// --- Immutability & Safety ---
|
|
57
|
+
'no-param-reassign': ['error', { props: false }],
|
|
58
|
+
'no-return-assign': ['error', 'always'],
|
|
59
|
+
'no-sequences': 'error',
|
|
60
|
+
'no-constructor-return': 'error',
|
|
61
|
+
'no-promise-executor-return': 'error',
|
|
62
|
+
// Evita modificação de built-ins
|
|
63
|
+
'no-extend-native': 'error',
|
|
64
|
+
|
|
65
|
+
// --- Code Organization ---
|
|
66
|
+
'default-case-last': 'error',
|
|
67
|
+
'grouped-accessor-pairs': ['error', 'getBeforeSet'],
|
|
68
|
+
|
|
69
|
+
// --- Bug Prevention ---
|
|
70
|
+
'no-template-curly-in-string': 'warn',
|
|
71
|
+
'no-useless-return': 'error',
|
|
72
|
+
|
|
73
|
+
...extraRules,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export interface PiniaOptions {
|
|
4
|
+
/** File patterns override @default ['src/state/**\/*.ts'] */
|
|
5
|
+
files?: string[];
|
|
6
|
+
/** Regras adicionais ou overrides */
|
|
7
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export declare function pinia(options?: PiniaOptions): Promise<Linter.Config[]>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { resolveFiles } from '../utils.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} PiniaOptions
|
|
5
|
+
* @property {string[]} [files] - File patterns override (default: src/state/**\/*.ts)
|
|
6
|
+
* @property {Record<string, unknown>} [rules] - Regras adicionais ou overrides
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Regras para stores Pinia â organização, naming e boas prĂĄticas.
|
|
11
|
+
* @param {PiniaOptions} [options={}]
|
|
12
|
+
* @returns {Promise<import('eslint').Linter.Config[]>}
|
|
13
|
+
*/
|
|
14
|
+
export async function pinia(options = {}) {
|
|
15
|
+
const { files, rules: extraRules = {} } = options;
|
|
16
|
+
|
|
17
|
+
const pluginPinia = await import('eslint-plugin-pinia').then((m) => m.default ?? m);
|
|
18
|
+
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
files: resolveFiles('pinia', files),
|
|
22
|
+
name: '@kitsune/pinia/rules',
|
|
23
|
+
plugins: { pinia: pluginPinia },
|
|
24
|
+
rules: {
|
|
25
|
+
'pinia/never-export-initialized-store': 'error',
|
|
26
|
+
'pinia/no-duplicate-store-ids': 'error',
|
|
27
|
+
'pinia/no-return-global-properties': 'error',
|
|
28
|
+
'pinia/no-store-to-refs-in-store': 'error',
|
|
29
|
+
'pinia/prefer-single-store-per-file': 'warn',
|
|
30
|
+
'pinia/prefer-use-store-naming-convention': 'warn',
|
|
31
|
+
'pinia/require-setup-store-properties-export': 'warn',
|
|
32
|
+
...extraRules,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export interface SecurityOptions {
|
|
4
|
+
/** File patterns override */
|
|
5
|
+
files?: string[];
|
|
6
|
+
/** Habilitar eslint-plugin-security @default true */
|
|
7
|
+
pluginEnabled?: boolean;
|
|
8
|
+
/** Regras adicionais ou overrides */
|
|
9
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export declare function security(options?: SecurityOptions): Linter.Config[];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import pluginSecurity from 'eslint-plugin-security';
|
|
2
|
+
|
|
3
|
+
import { resolveFiles } from '../utils.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} SecurityOptions
|
|
7
|
+
* @property {string[]} [files] - File patterns override
|
|
8
|
+
* @property {boolean} [pluginEnabled=true] - Habilitar eslint-plugin-security
|
|
9
|
+
* @property {Record<string, unknown>} [rules] - Regras adicionais ou overrides
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Regras de segurança para prevenir vulnerabilidades comuns.
|
|
14
|
+
* @param {SecurityOptions} [options={}]
|
|
15
|
+
* @returns {import('eslint').Linter.Config[]}
|
|
16
|
+
*/
|
|
17
|
+
export function security(options = {}) {
|
|
18
|
+
const { files, pluginEnabled = true, rules: extraRules = {} } = options;
|
|
19
|
+
const resolvedFiles = resolveFiles('all', files);
|
|
20
|
+
|
|
21
|
+
const configs = []
|
|
22
|
+
|
|
23
|
+
if (pluginEnabled) {
|
|
24
|
+
configs.push({
|
|
25
|
+
...pluginSecurity.configs.recommended,
|
|
26
|
+
files: resolvedFiles,
|
|
27
|
+
name: '@kitsune/security/plugin',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
configs.push({
|
|
32
|
+
files: resolvedFiles,
|
|
33
|
+
name: '@kitsune/security/rules',
|
|
34
|
+
rules: {
|
|
35
|
+
'no-alert': 'error',
|
|
36
|
+
'no-eval': 'error',
|
|
37
|
+
'no-debugger': 'error',
|
|
38
|
+
'no-new-func': 'error',
|
|
39
|
+
'no-script-url': 'error',
|
|
40
|
+
'no-implied-eval': 'error',
|
|
41
|
+
...extraRules,
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
return configs;
|
|
46
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export interface TestsOptions {
|
|
4
|
+
/** File patterns override */
|
|
5
|
+
files?: string[];
|
|
6
|
+
/** Regras adicionais ou overrides */
|
|
7
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export declare function tests(options?: TestsOptions): Linter.Config[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { resolveFiles } from '../utils.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} TestsOptions
|
|
5
|
+
* @property {string[]} [files] - File patterns override
|
|
6
|
+
* @property {Record<string, unknown>} [rules] - Regras adicionais ou overrides
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Relaxamentos para arquivos de teste â desliga regras rĂgidas de produção
|
|
11
|
+
* que atrapalham a escrita de testes (complexity, max-lines, naming, etc).
|
|
12
|
+
* @param {TestsOptions} [options={}]
|
|
13
|
+
* @returns {import('eslint').Linter.Config[]}
|
|
14
|
+
*/
|
|
15
|
+
export function tests(options = {}) {
|
|
16
|
+
const { files, rules: extraRules = {} } = options;
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
files: resolveFiles('tests', files),
|
|
21
|
+
name: '@kitsune/tests/relaxations',
|
|
22
|
+
rules: {
|
|
23
|
+
'max-lines-per-function': 'off',
|
|
24
|
+
'max-lines': 'off',
|
|
25
|
+
complexity: 'off',
|
|
26
|
+
'@typescript-eslint/no-shadow': 'off',
|
|
27
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
28
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
29
|
+
'@typescript-eslint/naming-convention': 'off',
|
|
30
|
+
'no-promise-executor-return': 'off',
|
|
31
|
+
'no-param-reassign': 'off',
|
|
32
|
+
'no-constructor-return': 'off',
|
|
33
|
+
'no-script-url': 'off',
|
|
34
|
+
'security/detect-object-injection': 'off',
|
|
35
|
+
'security/detect-unsafe-regex': 'off',
|
|
36
|
+
...extraRules,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
|
|
3
|
+
export interface TypescriptOptions {
|
|
4
|
+
/** File patterns override */
|
|
5
|
+
files?: string[];
|
|
6
|
+
/** Patterns a ignorar */
|
|
7
|
+
ignores?: string[];
|
|
8
|
+
/** Regras adicionais ou overrides */
|
|
9
|
+
rules?: Partial<Linter.RulesRecord>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export declare function typescript(options?: TypescriptOptions): Linter.Config[];
|