@skapxd/eslint-opinionated 1.0.0 → 2.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/README.md CHANGED
@@ -350,6 +350,11 @@ tocar contratos. Es la ola que más enseña por repetición:
350
350
  - `skapxd/no-nested-if` y `skapxd/no-else` — guard clauses. El refactor más
351
351
  formativo que existe para un junior: aplana la lógica o confiesa que la
352
352
  función hace demasiado.
353
+ - `skapxd/no-anonymous-condition` — la pareja de las anteriores y **la más
354
+ cara de todo el catálogo** (cientos de hallazgos en un backend típico):
355
+ cada condición-cómputo recibe un nombre con criterio. Vale la pena ir por
356
+ carpetas y SIN prisa — es la que más enseña por hallazgo, y la última de
357
+ esta ola.
353
358
  - `skapxd/one-root-function-per-file` y `skapxd/no-default-export` — el árbol
354
359
  de archivos empieza a contar la historia.
355
360
  - `skapxd/no-accessors`, `skapxd/max-public-methods` — clases con una
@@ -880,7 +885,7 @@ matchea en cualquier carpeta). Las 7 reglas restantes no tienen opciones: su
880
885
  | `skapxd/nest-no-swagger-in-controllers` | Los controllers no se llenan de decoradores de swagger; el plugin introspecciona los DTOs. Preset `nest`. |
881
886
  | `skapxd/nest-requires-swagger-plugin` | `nest-cli.json` debe tener el plugin `@nestjs/swagger`: la premisa de las reglas de swagger, verificada. Preset `nest`. |
882
887
  | `skapxd/nest-validation-pipe-config` | Todo `new ValidationPipe` configura `transform` y `whitelist`: la premisa de las reglas de DTOs. Preset `nest`. |
883
- | `skapxd/no-anonymous-condition` | El `if` solo acepta condiciones ya nombradas; todo cómputo (llamada, comparación, `&&`/`||`) se extrae a una `const` con nombre semántico. **Opt-in: no está en ningún preset.** |
888
+ | `skapxd/no-anonymous-condition` | El `if` solo acepta condiciones ya nombradas; todo cómputo (llamada, comparación, `&&`/`||`) se extrae a una `const` con nombre semántico. |
884
889
  | `skapxd/no-deep-relative-imports` | Limita la profundidad de los imports relativos (`../`). |
885
890
  | `skapxd/no-default-export` | Prohíbe `export default`; el nombre del símbolo es el contrato. Exime configs/stories y, en el preset `next`, los entrypoints del App Router. |
886
891
  | `skapxd/no-else` | Prohíbe `else`/`else if`: el else es el estado sin nombre. Retorno anticipado, ternario simple o `match()`. |
@@ -1701,18 +1706,15 @@ Lo que **sí dispara**: llamadas, comparaciones (`a.length <= b.max`,
1701
1706
  (`if (total % 2)`). La extracción directa a `const` conserva el narrowing
1702
1707
  (TS 4.4+, aliased conditions).
1703
1708
 
1704
- **Opt-in deliberado: no está en ningún preset.** La calibración contra 4
1705
- proyectos reales (2026-06-12) midió 473/95/308 hallazgos en tres backends
1706
- NestJS en producción y 44 en un front pequeño — señal genuina en la muestra
1707
- revisada, pero un orden de magnitud más invasiva que cualquier regla de las
1708
- bases. Actívala por proyecto (o por carpeta, estilo ola 3 del playbook de
1709
- adopción):
1710
-
1711
- ```js
1712
- rules: {
1713
- "skapxd/no-anonymous-condition": "error",
1714
- }
1715
- ```
1709
+ **Está en las reglas base** y es la más invasiva del catálogo: la
1710
+ calibración contra 4 proyectos reales (2026-06-12) midió 473/95/308
1711
+ hallazgos en tres backends NestJS en producción y 44 en un front pequeño
1712
+ (señal genuina en la muestra revisada a mano). En un proyecto existente,
1713
+ trátala con el playbook de adopción: entra apagada en la lista de
1714
+ pendientes y se enciende por carpetas, nombrando con criterio — el valor de
1715
+ la regla son los nombres, y un nombre autogenerado la traiciona. Este mismo
1716
+ repo la tiene en su lista de pendientes (245 condiciones heredadas) — la
1717
+ regla nació subiendo la vara que su propio código aún está alcanzando.
1716
1718
 
1717
1719
  ### `skapxd/no-deep-relative-imports`
1718
1720
 
@@ -14,6 +14,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
14
14
  "skapxd/max-public-methods": string;
15
15
  "skapxd/no-accessors": string;
16
16
  "skapxd/no-ad-hoc-ok-result": string;
17
+ "skapxd/no-anonymous-condition": string;
17
18
  "skapxd/no-deep-relative-imports": string;
18
19
  "skapxd/no-default-export": string;
19
20
  "skapxd/no-else": string;
@@ -40,6 +41,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
40
41
  "skapxd/max-public-methods": string;
41
42
  "skapxd/no-accessors": string;
42
43
  "skapxd/no-ad-hoc-ok-result": string;
44
+ "skapxd/no-anonymous-condition": string;
43
45
  "skapxd/no-deep-relative-imports": string;
44
46
  "skapxd/no-default-export": string;
45
47
  "skapxd/no-else": string;
@@ -14,6 +14,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
14
14
  "skapxd/max-public-methods": string;
15
15
  "skapxd/no-accessors": string;
16
16
  "skapxd/no-ad-hoc-ok-result": string;
17
+ "skapxd/no-anonymous-condition": string;
17
18
  "skapxd/no-deep-relative-imports": string;
18
19
  "skapxd/no-default-export": string;
19
20
  "skapxd/no-else": string;
@@ -40,6 +41,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
40
41
  "skapxd/max-public-methods": string;
41
42
  "skapxd/no-accessors": string;
42
43
  "skapxd/no-ad-hoc-ok-result": string;
44
+ "skapxd/no-anonymous-condition": string;
43
45
  "skapxd/no-deep-relative-imports": string;
44
46
  "skapxd/no-default-export": string;
45
47
  "skapxd/no-else": string;
@@ -40,6 +40,10 @@ var baseRules = {
40
40
  "skapxd/max-public-methods": "error",
41
41
  "skapxd/no-accessors": "error",
42
42
  "skapxd/no-ad-hoc-ok-result": "error",
43
+ // En las bases por decisión del dueño (issue #2): con poca adopción
44
+ // todavía, es el momento de subir la vara; los legacy la apagan en su
45
+ // lista de pendientes (playbook de adopción del README).
46
+ "skapxd/no-anonymous-condition": "error",
43
47
  "skapxd/no-deep-relative-imports": "error",
44
48
  "skapxd/no-default-export": "error",
45
49
  "skapxd/no-else": "error",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/astro/index.ts","../../src/shared/configs/base-rules.ts","../../src/shared/configs/create-base-language-options.ts","../../src/shared/configs/create-typed-language-options.ts","../../src/astro/configs.ts"],"sourcesContent":["export { createAstroConfigs } from \"./configs\";\n","export const baseRules = {\n \"skapxd/class-properties-require-readonly\": \"error\",\n \"skapxd/max-public-methods\": \"error\",\n \"skapxd/no-accessors\": \"error\",\n \"skapxd/no-ad-hoc-ok-result\": \"error\",\n \"skapxd/no-deep-relative-imports\": \"error\",\n \"skapxd/no-default-export\": \"error\",\n \"skapxd/no-else\": \"error\",\n \"skapxd/no-emoji\": \"error\",\n \"skapxd/no-nested-if\": \"error\",\n \"skapxd/no-runtime-state-guard\": \"error\",\n \"skapxd/no-promise-chain\": \"error\",\n \"skapxd/no-try-catch\": \"error\",\n \"skapxd/one-root-function-per-file\": \"error\",\n \"skapxd/prefer-tagged-union-state\": \"error\",\n \"skapxd/requires-strict-tsconfig\": \"error\",\n \"skapxd/prefer-ts-pattern\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n};\n","import tseslint from \"typescript-eslint\";\n\n// Variante sin type-checking: solo el parser, para presets que aplican a TS\n// pero no necesitan projectService (base, package, next/base, next/react).\nexport function createBaseLanguageOptions() {\n return {\n parser: tseslint.parser,\n };\n}\n","import tseslint from \"typescript-eslint\";\n\nexport function createTypedLanguageOptions() {\n return {\n // Sin el parser explícito, un consumidor que use solo estos presets\n // obtiene \"Parsing error\" en cada archivo TS (espree no parsea TS).\n parser: tseslint.parser,\n parserOptions: {\n projectService: true,\n },\n };\n}\n","import {\n baseRules,\n createBaseLanguageOptions,\n createTypedLanguageOptions,\n} from \"#/shared/configs\";\n\nexport function createAstroConfigs(pluginReference: unknown) {\n const baseLanguageOptions = createBaseLanguageOptions();\n const typedLanguageOptions = createTypedLanguageOptions();\n\n return [\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: baseLanguageOptions,\n name: \"skapxd/astro/base\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n // Los .astro no llevan parser propio: lo aporta eslint-plugin-astro,\n // que el consumidor debe tener configurado.\n {\n files: [\"src/**/*.astro\"],\n name: \"skapxd/astro/astro-files\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: typedLanguageOptions,\n name: \"skapxd/astro/typescript\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/await-requires-result\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n },\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAY;AAAA,EACvB,4CAA4C;AAAA,EAC5C,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,8BAA8B;AAAA,EAC9B,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,iCAAiC;AAAA,EACjC,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,oCAAoC;AAAA,EACpC,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,sCAAsC;AAAA,EACtC,yCAAyC;AAC3C;;;ACnBA,+BAAqB;AAId,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL,QAAQ,yBAAAA,QAAS;AAAA,EACnB;AACF;;;ACRA,IAAAC,4BAAqB;AAEd,SAAS,6BAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA,IAGL,QAAQ,0BAAAC,QAAS;AAAA,IACjB,eAAe;AAAA,MACb,gBAAgB;AAAA,IAClB;AAAA,EACF;AACF;;;ACLO,SAAS,mBAAmB,iBAA0B;AAC3D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA;AAAA;AAAA,IAGA;AAAA,MACE,OAAO,CAAC,gBAAgB;AAAA,MACxB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,gCAAgC;AAAA,QAChC,sCAAsC;AAAA,QACtC,yCAAyC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;","names":["tseslint","import_typescript_eslint","tseslint"]}
1
+ {"version":3,"sources":["../../src/astro/index.ts","../../src/shared/configs/base-rules.ts","../../src/shared/configs/create-base-language-options.ts","../../src/shared/configs/create-typed-language-options.ts","../../src/astro/configs.ts"],"sourcesContent":["export { createAstroConfigs } from \"./configs\";\n","export const baseRules = {\n \"skapxd/class-properties-require-readonly\": \"error\",\n \"skapxd/max-public-methods\": \"error\",\n \"skapxd/no-accessors\": \"error\",\n \"skapxd/no-ad-hoc-ok-result\": \"error\",\n // En las bases por decisión del dueño (issue #2): con poca adopción\n // todavía, es el momento de subir la vara; los legacy la apagan en su\n // lista de pendientes (playbook de adopción del README).\n \"skapxd/no-anonymous-condition\": \"error\",\n \"skapxd/no-deep-relative-imports\": \"error\",\n \"skapxd/no-default-export\": \"error\",\n \"skapxd/no-else\": \"error\",\n \"skapxd/no-emoji\": \"error\",\n \"skapxd/no-nested-if\": \"error\",\n \"skapxd/no-runtime-state-guard\": \"error\",\n \"skapxd/no-promise-chain\": \"error\",\n \"skapxd/no-try-catch\": \"error\",\n \"skapxd/one-root-function-per-file\": \"error\",\n \"skapxd/prefer-tagged-union-state\": \"error\",\n \"skapxd/requires-strict-tsconfig\": \"error\",\n \"skapxd/prefer-ts-pattern\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n};\n","import tseslint from \"typescript-eslint\";\n\n// Variante sin type-checking: solo el parser, para presets que aplican a TS\n// pero no necesitan projectService (base, package, next/base, next/react).\nexport function createBaseLanguageOptions() {\n return {\n parser: tseslint.parser,\n };\n}\n","import tseslint from \"typescript-eslint\";\n\nexport function createTypedLanguageOptions() {\n return {\n // Sin el parser explícito, un consumidor que use solo estos presets\n // obtiene \"Parsing error\" en cada archivo TS (espree no parsea TS).\n parser: tseslint.parser,\n parserOptions: {\n projectService: true,\n },\n };\n}\n","import {\n baseRules,\n createBaseLanguageOptions,\n createTypedLanguageOptions,\n} from \"#/shared/configs\";\n\nexport function createAstroConfigs(pluginReference: unknown) {\n const baseLanguageOptions = createBaseLanguageOptions();\n const typedLanguageOptions = createTypedLanguageOptions();\n\n return [\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: baseLanguageOptions,\n name: \"skapxd/astro/base\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n // Los .astro no llevan parser propio: lo aporta eslint-plugin-astro,\n // que el consumidor debe tener configurado.\n {\n files: [\"src/**/*.astro\"],\n name: \"skapxd/astro/astro-files\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: typedLanguageOptions,\n name: \"skapxd/astro/typescript\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/await-requires-result\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n },\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAY;AAAA,EACvB,4CAA4C;AAAA,EAC5C,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,8BAA8B;AAAA;AAAA;AAAA;AAAA,EAI9B,iCAAiC;AAAA,EACjC,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,iCAAiC;AAAA,EACjC,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,oCAAoC;AAAA,EACpC,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,sCAAsC;AAAA,EACtC,yCAAyC;AAC3C;;;ACvBA,+BAAqB;AAId,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL,QAAQ,yBAAAA,QAAS;AAAA,EACnB;AACF;;;ACRA,IAAAC,4BAAqB;AAEd,SAAS,6BAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA,IAGL,QAAQ,0BAAAC,QAAS;AAAA,IACjB,eAAe;AAAA,MACb,gBAAgB;AAAA,IAClB;AAAA,EACF;AACF;;;ACLO,SAAS,mBAAmB,iBAA0B;AAC3D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA;AAAA;AAAA,IAGA;AAAA,MACE,OAAO,CAAC,gBAAgB;AAAA,MACxB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,gCAAgC;AAAA,QAChC,sCAAsC;AAAA,QACtC,yCAAyC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;","names":["tseslint","import_typescript_eslint","tseslint"]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createAstroConfigs
3
- } from "../chunk-GSQWHSHV.mjs";
4
- import "../chunk-QDQUU6QK.mjs";
3
+ } from "../chunk-3LQ4KQP5.mjs";
4
+ import "../chunk-TFVTEI2T.mjs";
5
5
  export {
6
6
  createAstroConfigs
7
7
  };
@@ -2,7 +2,7 @@ import {
2
2
  baseRules,
3
3
  createTypedLanguageOptions,
4
4
  typeDrivenRules
5
- } from "./chunk-QDQUU6QK.mjs";
5
+ } from "./chunk-TFVTEI2T.mjs";
6
6
 
7
7
  // src/constants/nest-entrypoint-file-patterns.ts
8
8
  var nestEntrypointFilePatterns = [
@@ -130,4 +130,4 @@ function createNestConfigs(pluginReference) {
130
130
  export {
131
131
  createNestConfigs
132
132
  };
133
- //# sourceMappingURL=chunk-3GEFHNU7.mjs.map
133
+ //# sourceMappingURL=chunk-33N6EMC2.mjs.map
@@ -2,7 +2,7 @@ import {
2
2
  baseRules,
3
3
  createBaseLanguageOptions,
4
4
  createTypedLanguageOptions
5
- } from "./chunk-QDQUU6QK.mjs";
5
+ } from "./chunk-TFVTEI2T.mjs";
6
6
 
7
7
  // src/astro/configs.ts
8
8
  function createAstroConfigs(pluginReference) {
@@ -41,4 +41,4 @@ function createAstroConfigs(pluginReference) {
41
41
  export {
42
42
  createAstroConfigs
43
43
  };
44
- //# sourceMappingURL=chunk-GSQWHSHV.mjs.map
44
+ //# sourceMappingURL=chunk-3LQ4KQP5.mjs.map
@@ -6,7 +6,7 @@ import {
6
6
  baseRules,
7
7
  createBaseLanguageOptions,
8
8
  createTypedLanguageOptions
9
- } from "./chunk-QDQUU6QK.mjs";
9
+ } from "./chunk-TFVTEI2T.mjs";
10
10
 
11
11
  // src/next/configs.ts
12
12
  var nextDefaultExportFileGlob = `{${[
@@ -71,4 +71,4 @@ function createNextConfigs(pluginReference) {
71
71
  export {
72
72
  createNextConfigs
73
73
  };
74
- //# sourceMappingURL=chunk-54EOEKYS.mjs.map
74
+ //# sourceMappingURL=chunk-FTSYXBE4.mjs.map
@@ -17,6 +17,10 @@ var baseRules = {
17
17
  "skapxd/max-public-methods": "error",
18
18
  "skapxd/no-accessors": "error",
19
19
  "skapxd/no-ad-hoc-ok-result": "error",
20
+ // En las bases por decisión del dueño (issue #2): con poca adopción
21
+ // todavía, es el momento de subir la vara; los legacy la apagan en su
22
+ // lista de pendientes (playbook de adopción del README).
23
+ "skapxd/no-anonymous-condition": "error",
20
24
  "skapxd/no-deep-relative-imports": "error",
21
25
  "skapxd/no-default-export": "error",
22
26
  "skapxd/no-else": "error",
@@ -186,4 +190,4 @@ export {
186
190
  createSharedConfigs,
187
191
  strictConfig
188
192
  };
189
- //# sourceMappingURL=chunk-QDQUU6QK.mjs.map
193
+ //# sourceMappingURL=chunk-TFVTEI2T.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/configs/create-typed-language-options.ts","../src/shared/configs/base-rules.ts","../src/shared/configs/create-base-language-options.ts","../src/shared/configs/type-driven-rules.ts","../src/shared/configs/create-shared-configs.ts","../src/shared/configs/strict-config.ts"],"sourcesContent":["import tseslint from \"typescript-eslint\";\n\nexport function createTypedLanguageOptions() {\n return {\n // Sin el parser explícito, un consumidor que use solo estos presets\n // obtiene \"Parsing error\" en cada archivo TS (espree no parsea TS).\n parser: tseslint.parser,\n parserOptions: {\n projectService: true,\n },\n };\n}\n","export const baseRules = {\n \"skapxd/class-properties-require-readonly\": \"error\",\n \"skapxd/max-public-methods\": \"error\",\n \"skapxd/no-accessors\": \"error\",\n \"skapxd/no-ad-hoc-ok-result\": \"error\",\n // En las bases por decisión del dueño (issue #2): con poca adopción\n // todavía, es el momento de subir la vara; los legacy la apagan en su\n // lista de pendientes (playbook de adopción del README).\n \"skapxd/no-anonymous-condition\": \"error\",\n \"skapxd/no-deep-relative-imports\": \"error\",\n \"skapxd/no-default-export\": \"error\",\n \"skapxd/no-else\": \"error\",\n \"skapxd/no-emoji\": \"error\",\n \"skapxd/no-nested-if\": \"error\",\n \"skapxd/no-runtime-state-guard\": \"error\",\n \"skapxd/no-promise-chain\": \"error\",\n \"skapxd/no-try-catch\": \"error\",\n \"skapxd/one-root-function-per-file\": \"error\",\n \"skapxd/prefer-tagged-union-state\": \"error\",\n \"skapxd/requires-strict-tsconfig\": \"error\",\n \"skapxd/prefer-ts-pattern\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n};\n","import tseslint from \"typescript-eslint\";\n\n// Variante sin type-checking: solo el parser, para presets que aplican a TS\n// pero no necesitan projectService (base, package, next/base, next/react).\nexport function createBaseLanguageOptions() {\n return {\n parser: tseslint.parser,\n };\n}\n","// Reglas de typescript-eslint que el diseño guiado por tipos exige, todas\n// re-registradas bajo el namespace skapxd (ver src/utils/wrap-tseslint-rule.ts):\n// mismo motor, cero reimplementación, pero con nombres que dicen lo que\n// defienden y mensajes que enseñan el fix — un solo namespace en toda la\n// lista de pendientes del consumidor.\n//\n// Ausencias deliberadas (no son olvidos):\n// - switch-exhaustiveness-check: prefer-ts-pattern prohíbe el switch entero;\n// match().exhaustive() da la misma garantía sin él.\n// - prefer-readonly: superada por class-properties-require-readonly, que\n// exige readonly en la declaración (no solo en privados nunca reasignados).\n// - strict-boolean-expressions: castiga narrowing legítimo por cientos\n// (560 hallazgos en un backend real) sin hacer irrepresentable ningún\n// estado nuevo. Ruido, no señal.\n// - explicit-module-boundary-types: los contratos que importan ya están\n// gobernados (Result en await-requires-result, respuestas de controller en\n// nest-no-result-response); anotar todo lo demás es ceremonia (198\n// hallazgos) que la inferencia resuelve sin perder garantías.\n// - prefer-readonly-parameter-types: impracticable con cualquier parámetro\n// que venga de una librería externa.\nexport const typeDrivenRules = {\n // `any` apaga el sistema de tipos: todo el esfuerzo de modelar estados\n // irrepresentables muere donde aparece uno. (Era no-explicit-any.)\n \"skapxd/no-explicit-any\": \"error\",\n // El hueco que await-requires-result no ve: una llamada async SIN await no\n // produce AwaitExpression — el rechazo muere sin pasar por trySafe. La\n // única salida sin await es `void promesa()`: fire-and-forget declarado.\n // (Era no-floating-promises; el mensaje upstream recomendaba .then/.catch,\n // que no-promise-chain prohíbe — el nuestro corrige el consejo.)\n \"skapxd/no-floating-promises\": \"error\",\n // La generalización type-aware de no-runtime-state-guard: si el tipo dice\n // que un estado es imposible, el guard defensivo sobra — y si el guard\n // hace falta, lo que está mal es el tipo. Requiere el tsconfig de\n // requires-strict-tsconfig para ser sólida: sin noUncheckedIndexedAccess,\n // `array[i]` miente y esta regla acusaría guards necesarios.\n // (Era no-unnecessary-condition.) El literal `true` en bucles queda\n // permitido: `while (true)` con returns internos es un bucle infinito\n // DECLARADO (axioma A5), no un guard mentiroso.\n \"skapxd/no-impossible-branch\": [\n \"error\",\n { allowConstantLoopConditions: \"only-allowed-literals\" },\n ],\n // `!` es \"cállate, yo sé más que tú\" dicho al compilador. Si el valor no\n // puede ser nulo, que lo diga el tipo; si puede serlo, hay que modelarlo.\n \"skapxd/no-non-null-assertion\": \"error\",\n // Silenciar la alarma no arregla el incendio: un error de tipos se\n // resuelve modelando mejor, no apagando el compilador. @ts-expect-error\n // queda permitido CON descripción: es la forma legítima de testear que un\n // estado inválido de verdad no compila. (Era ban-ts-comment.)\n \"skapxd/no-silenced-compiler\": [\n \"error\",\n {\n \"ts-expect-error\": \"allow-with-description\",\n \"ts-ignore\": true,\n \"ts-nocheck\": true,\n },\n ],\n // `type` en vez de `interface`: las uniones discriminadas son types, y la\n // homogeneidad evita el \"¿esto se puede extender por declaration merging?\"\n // (Era consistent-type-definitions, cuyo default upstream es `interface` —\n // por eso la opción explícita.)\n \"skapxd/prefer-type-over-interface\": [\"error\", \"type\"],\n};\n","import { baseRules } from \"./base-rules\";\nimport { createBaseLanguageOptions } from \"./create-base-language-options\";\nimport { createTypedLanguageOptions } from \"./create-typed-language-options\";\nimport { typeDrivenRules } from \"./type-driven-rules\";\n\nexport function createSharedConfigs(pluginReference: unknown) {\n const baseLanguageOptions = createBaseLanguageOptions();\n const typedLanguageOptions = createTypedLanguageOptions();\n\n return {\n backend: {\n languageOptions: typedLanguageOptions,\n name: \"skapxd/shared/backend\",\n // Solo el plugin skapxd: las reglas de typescript-eslint entran\n // re-registradas bajo nuestro namespace (typeDrivenRules), así el\n // consumidor puede registrar su propia instancia de tseslint sin\n // chocar con \"Cannot redefine plugin\".\n plugins: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n ...typeDrivenRules,\n // La regla obligatoria del sistema de errores es await-requires-result\n // (todo await resuelve en Result). async-functions-return-result queda\n // apagada por defecto: exigir la firma por decreto choca con los bordes\n // del framework y bloquea la adopción incremental; la presión sobre los\n // awaits produce el mismo estado final. Ver \"¿Por qué está apagada por\n // defecto?\" en el README.\n \"skapxd/await-requires-result\": \"error\",\n },\n },\n base: {\n languageOptions: baseLanguageOptions,\n name: \"skapxd/shared/base\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n frontend: {\n languageOptions: typedLanguageOptions,\n name: \"skapxd/shared/frontend\",\n plugins: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n ...typeDrivenRules,\n // En el front no se obliga a retornar Result, pero todo await debe\n // resolver en uno: o la función llamada ya retorna Promise<Result>\n // (camino preferido: errores modelados en el dominio) o se envuelve\n // en trySafe en el sitio.\n \"skapxd/await-requires-result\": \"error\",\n \"skapxd/jsx-return-name-pascal-case\": \"error\",\n // Anti prop-drilling: ninguna prop viaja más de un nivel. Quien la\n // crea puede pasarla a UN hijo; quien la recibe no la reenvía —\n // estado y acciones a un store global o custom hook.\n \"skapxd/no-functions-inside-components\": \"error\",\n \"skapxd/no-tunnel-props\": \"error\",\n // Listeners en efectos: un AbortController por efecto, cleanup con\n // un solo abort() en vez de removeEventListener por listener.\n \"skapxd/prefer-abort-signal\": \"error\",\n \"skapxd/no-jsx-ternary-null\": \"error\",\n \"skapxd/max-hook-size\": [\n \"error\",\n {\n maxLines: 120,\n maxUseState: 1,\n },\n ],\n },\n },\n // Para librerias npm en TypeScript (tsup o equivalente): las bases\n // completas + el set type-driven + el contrato de empaquetado. Este\n // mismo repo se lintea con este preset (dogfood).\n package: {\n languageOptions: typedLanguageOptions,\n name: \"skapxd/shared/package\",\n plugins: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n ...typeDrivenRules,\n \"skapxd/await-requires-result\": \"error\",\n // El contrato de tipos duales en exports: import → .d.mts,\n // require → .d.ts. Sin esto, FalseCJS (attw lo confirma).\n \"skapxd/package-requires-typed-exports\": \"error\",\n // Inerte hasta declarar modulos sospechosos: el inventario de\n // paquetes cuyos @types mienten, encerrados tras su adaptador.\n \"skapxd/untrusted-module-requires-adapter\": \"error\",\n },\n },\n };\n}\n","// Config endurecida: ignora TODOS los comentarios `eslint-disable` (y demás\n// directivas inline) en los archivos que cubre. Así ni una persona ni un agente\n// pueden saltarse una regla con `// eslint-disable-next-line`.\nexport const strictConfig = {\n linterOptions: {\n noInlineConfig: true,\n },\n name: \"skapxd/strict\",\n};\n"],"mappings":"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","names":["tseslint"]}
package/dist/index.js CHANGED
@@ -42,6 +42,10 @@ var baseRules = {
42
42
  "skapxd/max-public-methods": "error",
43
43
  "skapxd/no-accessors": "error",
44
44
  "skapxd/no-ad-hoc-ok-result": "error",
45
+ // En las bases por decisión del dueño (issue #2): con poca adopción
46
+ // todavía, es el momento de subir la vara; los legacy la apagan en su
47
+ // lista de pendientes (playbook de adopción del README).
48
+ "skapxd/no-anonymous-condition": "error",
45
49
  "skapxd/no-deep-relative-imports": "error",
46
50
  "skapxd/no-default-export": "error",
47
51
  "skapxd/no-else": "error",
@@ -4724,7 +4728,7 @@ var plugin = {
4724
4728
  configs: {},
4725
4729
  meta: {
4726
4730
  name: "@skapxd/eslint-opinionated",
4727
- version: "1.0.0"
4731
+ version: "2.0.0"
4728
4732
  },
4729
4733
  rules
4730
4734
  };