@skapxd/eslint-opinionated 0.14.0 → 0.15.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 +190 -9
- package/dist/astro/index.mjs +2 -2
- package/dist/{chunk-C5JP4FQN.mjs → chunk-DJDXQWCP.mjs} +2 -2
- package/dist/{chunk-QR35MHTW.mjs → chunk-F6GJW5A4.mjs} +4 -2
- package/dist/{chunk-QR35MHTW.mjs.map → chunk-F6GJW5A4.mjs.map} +1 -1
- package/dist/{chunk-YUKVSZZ4.mjs → chunk-MLFXSEY7.mjs} +74 -6
- package/dist/chunk-MLFXSEY7.mjs.map +1 -0
- package/dist/{chunk-NBEAEKXG.mjs → chunk-O5BXMSNR.mjs} +2 -2
- package/dist/{chunk-TZ5XPZGL.mjs → chunk-OVC5GQV3.mjs} +2 -2
- package/dist/index.js +78 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/dist/nest/index.d.mts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +3 -1
- package/dist/nest/index.js.map +1 -1
- package/dist/nest/index.mjs +2 -2
- package/dist/next/index.mjs +2 -2
- package/dist/shared/index.d.mts +2 -2
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js +77 -7
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-YUKVSZZ4.mjs.map +0 -1
- /package/dist/{chunk-C5JP4FQN.mjs.map → chunk-DJDXQWCP.mjs.map} +0 -0
- /package/dist/{chunk-NBEAEKXG.mjs.map → chunk-O5BXMSNR.mjs.map} +0 -0
- /package/dist/{chunk-TZ5XPZGL.mjs.map → chunk-OVC5GQV3.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ la que defiende el axioma más fundamental (el orden es jerárquico).
|
|
|
98
98
|
|
|
99
99
|
| # | Axioma | Reglas que lo ejecutan |
|
|
100
100
|
| --- | --- | --- |
|
|
101
|
-
| A1 | **Los estados imposibles son irrepresentables.** El tipo modela exactamente los estados válidos; lo inválido no compila. | `prefer-tagged-union-state`, `no-runtime-state-guard`, `requires-strict-tsconfig`,
|
|
101
|
+
| A1 | **Los estados imposibles son irrepresentables.** El tipo modela exactamente los estados válidos; lo inválido no compila. | `prefer-tagged-union-state`, `no-runtime-state-guard`, `requires-strict-tsconfig`, `no-impossible-branch`, `no-explicit-any`, `consistent-type-definitions` |
|
|
102
102
|
| A2 | **Ningún efecto es invisible al tipo.** Si una operación puede fallar, su firma lo confiesa — no una convención oral ni un `throw` sorpresa. | `await-requires-result`, `no-try-catch`, `no-promise-chain`, `no-ad-hoc-ok-result`, `@typescript-eslint/no-floating-promises` |
|
|
103
103
|
| A3 | **La información no se destruye.** Un error que se transforma conserva su `cause`; uno que se detecta llega a alguien. Nadie decide "esto no importa" en silencio. | `result-error-requires-cause`, `result-error-requires-handling` |
|
|
104
104
|
| A4 | **Una unidad, una responsabilidad, un nombre semántico.** El árbol de archivos cuenta una historia; una clase expone una intención. | `one-root-function-per-file`, `max-public-methods`, `no-default-export`, `jsx-return-name-pascal-case`, `max-hook-size` |
|
|
@@ -274,6 +274,149 @@ hay errores, sale con código `1` (apto para CI). Como acota por **archivo
|
|
|
274
274
|
completo**, también dispara las reglas estructurales (p. ej.
|
|
275
275
|
`one-root-function-per-file`), que un filtrado por línea se perdería.
|
|
276
276
|
|
|
277
|
+
## Adopción en proyectos legacy: de `off` a `error`, por olas
|
|
278
|
+
|
|
279
|
+
El CLI de arriba acota **qué archivos** se juzgan. Este apartado acota **qué
|
|
280
|
+
reglas** — el camino para meter el preset completo en un proyecto legacy
|
|
281
|
+
escrito por humanos, sin que el primer `pnpm lint` escupa 2.000 errores y el
|
|
282
|
+
equipo apague el linter para siempre.
|
|
283
|
+
|
|
284
|
+
### Las reglas del juego
|
|
285
|
+
|
|
286
|
+
1. **`off` o `error`, nunca `warn`.** Un warn se ignora desde el día dos y
|
|
287
|
+
solo entrena al equipo a ignorar amarillo. Una regla está adoptada
|
|
288
|
+
(`error`) o todavía no (`off`) — no hay estado intermedio.
|
|
289
|
+
2. **Una regla a la vez, y a cero.** Se activa una regla, se arreglan TODOS
|
|
290
|
+
sus hallazgos, se mergea en verde. Nunca actives una regla con pendientes:
|
|
291
|
+
el CI rojo permanente es la ventana rota que normaliza ignorar el linter.
|
|
292
|
+
3. **Ratchet: lo que se enciende no se apaga.** El bloque de `off` solo puede
|
|
293
|
+
encoger. El diff de ese bloque ES la métrica de progreso del equipo.
|
|
294
|
+
4. **Mide antes de activar.** En una rama, borra el `off` de una regla y corre
|
|
295
|
+
el lint: el número de hallazgos es el precio. **Activa siempre la más
|
|
296
|
+
barata pendiente** — el momentum importa más que el orden perfecto.
|
|
297
|
+
5. **Deja que el mensaje enseñe.** Los mensajes de error de estas reglas
|
|
298
|
+
explican el porqué y el cómo (qué patrón usar, cómo se llama, dónde va).
|
|
299
|
+
Para un equipo sin seniors, el linter es el code review que nadie tiene
|
|
300
|
+
tiempo de hacer: no resumas las reglas en un documento aparte — el
|
|
301
|
+
documento es el error en pantalla.
|
|
302
|
+
|
|
303
|
+
### El mecanismo: la lista de pendientes
|
|
304
|
+
|
|
305
|
+
El preset completo es la meta; un bloque posterior apaga lo que el equipo aún
|
|
306
|
+
no cumple. **Adoptar una regla = borrar su línea y arreglar lo que aflore:**
|
|
307
|
+
|
|
308
|
+
```js
|
|
309
|
+
// eslint.config.js
|
|
310
|
+
import skapxd from "@skapxd/eslint-opinionated";
|
|
311
|
+
|
|
312
|
+
export default [
|
|
313
|
+
...skapxd.configs.nest, // la meta: el preset completo, desde el día uno
|
|
314
|
+
|
|
315
|
+
// ─── Lista de pendientes ───────────────────────────────────────────
|
|
316
|
+
// Todo lo que el proyecto aún no cumple, apagado y a la vista.
|
|
317
|
+
// Este bloque SOLO ENCOGE: se borra una línea, se arregla, se mergea.
|
|
318
|
+
{
|
|
319
|
+
rules: {
|
|
320
|
+
"skapxd/await-requires-result": "off",
|
|
321
|
+
"skapxd/no-try-catch": "off",
|
|
322
|
+
// ...
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
];
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### El orden de las olas
|
|
329
|
+
|
|
330
|
+
El orden no es arbitrario: va de "cada hallazgo es un bug que ya tienes" hacia
|
|
331
|
+
"esto exige rediseñar tipos", y cada ola deja el suelo que la siguiente pisa.
|
|
332
|
+
|
|
333
|
+
**Ola 1 — bugs gratis y fixes únicos.** Señal pura, arreglo puntual, cero
|
|
334
|
+
rediseño. Aquí el equipo aprende que el linter encuentra cosas reales:
|
|
335
|
+
|
|
336
|
+
- `@typescript-eslint/no-floating-promises` — cada hallazgo es un error que
|
|
337
|
+
hoy muere sin que nadie lo vea (en un backend real en producción: 12).
|
|
338
|
+
- `skapxd/nest-requires-swagger-plugin` y `skapxd/nest-validation-pipe-config`
|
|
339
|
+
— un hallazgo por proyecto, un fix de configuración, y quedan vigiladas las
|
|
340
|
+
premisas de las olas siguientes.
|
|
341
|
+
- `skapxd/requires-strict-tsconfig` con la exigencia mínima:
|
|
342
|
+
`{ requiredCompilerOptions: ["strict"] }`. Es el trinquete del tsconfig —
|
|
343
|
+
cada ola le sube un flag (ver abajo).
|
|
344
|
+
- `skapxd/no-emoji`, `skapxd/no-deep-relative-imports` — fixes mecánicos.
|
|
345
|
+
- `skapxd/prefer-abort-signal` (front) — cada hallazgo es un leak.
|
|
346
|
+
|
|
347
|
+
**Ola 2 — la forma del código.** Refactors locales, archivo por archivo, sin
|
|
348
|
+
tocar contratos. Es la ola que más enseña por repetición:
|
|
349
|
+
|
|
350
|
+
- `skapxd/no-nested-if` y `skapxd/no-else` — guard clauses. El refactor más
|
|
351
|
+
formativo que existe para un junior: aplana la lógica o confiesa que la
|
|
352
|
+
función hace demasiado.
|
|
353
|
+
- `skapxd/one-root-function-per-file` y `skapxd/no-default-export` — el árbol
|
|
354
|
+
de archivos empieza a contar la historia.
|
|
355
|
+
- `skapxd/no-accessors`, `skapxd/max-public-methods` — clases con una
|
|
356
|
+
intención (partir un god-object es la cirugía mayor de esta ola: déjala de
|
|
357
|
+
última).
|
|
358
|
+
- Front: `skapxd/jsx-return-name-pascal-case`, `skapxd/max-hook-size`,
|
|
359
|
+
`skapxd/no-functions-inside-components`, `skapxd/no-jsx-ternary-null`,
|
|
360
|
+
`skapxd/no-tunnel-props`.
|
|
361
|
+
- Nest: `skapxd/nest-no-swagger-in-controllers`,
|
|
362
|
+
`skapxd/nest-dto-requires-api-property`,
|
|
363
|
+
`skapxd/nest-dto-requires-validation`,
|
|
364
|
+
`skapxd/nest-no-inline-query-params`,
|
|
365
|
+
`skapxd/nest-no-direct-instantiation` — mover decoradores y dependencias a
|
|
366
|
+
donde pertenecen.
|
|
367
|
+
|
|
368
|
+
**Ola 3 — el contrato de errores.** La migración de paradigma
|
|
369
|
+
(`@skapxd/result` + `ts-pattern`; ver "Cómo encaja todo" abajo). Aquí NO se va
|
|
370
|
+
regla por regla sino **módulo por módulo**: las seis reglas entran juntas
|
|
371
|
+
(son un solo sistema) pero acotadas por carpeta, y el primer módulo migrado se
|
|
372
|
+
vuelve el ejemplo canónico que el resto copia:
|
|
373
|
+
|
|
374
|
+
```js
|
|
375
|
+
// Ola 3: el pipeline de Result entra carpeta por carpeta.
|
|
376
|
+
{
|
|
377
|
+
files: ["src/modules/payments/**"],
|
|
378
|
+
rules: {
|
|
379
|
+
"skapxd/await-requires-result": "error",
|
|
380
|
+
"skapxd/no-try-catch": "error",
|
|
381
|
+
"skapxd/no-promise-chain": "error",
|
|
382
|
+
"skapxd/no-ad-hoc-ok-result": "error",
|
|
383
|
+
"skapxd/prefer-ts-pattern": "error",
|
|
384
|
+
"skapxd/result-error-requires-cause": "error",
|
|
385
|
+
"skapxd/result-error-requires-handling": "error",
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
(En Nest, suma `skapxd/nest-no-result-response` al grupo: el controller del
|
|
391
|
+
módulo migrado traduce el Result, no lo serializa.) Cuando todos los módulos
|
|
392
|
+
migraron, las líneas salen del bloque por-carpeta y entran globales: se borran
|
|
393
|
+
de la lista de pendientes.
|
|
394
|
+
|
|
395
|
+
**Ola 4 — el modelado de estados.** Lo más profundo: exige criterio de
|
|
396
|
+
diseño, no solo disciplina. Para cuando el equipo ya vio el patrón en la ola 3:
|
|
397
|
+
|
|
398
|
+
- `requires-strict-tsconfig` al máximo: `["strict", "noImplicitReturns",
|
|
399
|
+
"noUncheckedIndexedAccess"]`. Sube un flag a la vez — cada uno aflora
|
|
400
|
+
errores de compilación que son bugs latentes, no burocracia.
|
|
401
|
+
- `@typescript-eslint/no-explicit-any`, `no-non-null-assertion` y
|
|
402
|
+
`ban-ts-comment` — se cierran las tres puertas de escape del compilador.
|
|
403
|
+
- `skapxd/class-properties-require-readonly` — el cambio se modela con
|
|
404
|
+
instancias nuevas.
|
|
405
|
+
- `skapxd/prefer-tagged-union-state` y `skapxd/no-runtime-state-guard` — los
|
|
406
|
+
booleanos co-dependientes se vuelven uniones etiquetadas.
|
|
407
|
+
- `skapxd/no-impossible-branch` — **la última de todas**: solo es sólida
|
|
408
|
+
cuando el tsconfig ya está al máximo (sin `noUncheckedIndexedAccess`,
|
|
409
|
+
acusaría guards necesarios).
|
|
410
|
+
|
|
411
|
+
### Los dos ejes se combinan
|
|
412
|
+
|
|
413
|
+
Mientras la lista de pendientes encoge, `skapxd-lint-changed` aplica lo ya
|
|
414
|
+
activado solo a los archivos tocados: el código nuevo nace cumpliendo y el
|
|
415
|
+
legacy se corrige cuando alguien lo visita (regla del boy scout), no en un
|
|
416
|
+
big-bang. Un proyecto mediano recorre las cuatro olas en semanas, no en
|
|
417
|
+
trimestres — y cada semana el lint encuentra menos, porque el equipo ya
|
|
418
|
+
escribe distinto.
|
|
419
|
+
|
|
277
420
|
## Cómo encaja todo: `@skapxd/result` + `ts-pattern`
|
|
278
421
|
|
|
279
422
|
Este plugin no es una colección de reglas sueltas: es el guardián de un
|
|
@@ -676,6 +819,7 @@ de cada regla):
|
|
|
676
819
|
| `no-default-export` | `allowFilePatterns` (globs, aditivos a los integrados) |
|
|
677
820
|
| `no-else` | `allowFilePatterns` (globs) |
|
|
678
821
|
| `no-emoji` | `allowFilePatterns` (globs) |
|
|
822
|
+
| `no-impossible-branch` | las de la regla original de typescript-eslint (`allowConstantLoopConditions`, ...) |
|
|
679
823
|
| `no-functions-inside-components` | `allowJsxCallbacks`, `allowArrayMapCallbacks` (ambas `true` por defecto) |
|
|
680
824
|
| `no-nested-if` | `allowFilePatterns` (globs) |
|
|
681
825
|
| `no-promise-chain` | `methods` |
|
|
@@ -719,6 +863,7 @@ matchea en cualquier carpeta). Las 7 reglas restantes no tienen opciones: su
|
|
|
719
863
|
| `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. |
|
|
720
864
|
| `skapxd/no-else` | Prohíbe `else`/`else if`: el else es el estado sin nombre. Retorno anticipado, ternario simple o `match()`. |
|
|
721
865
|
| `skapxd/no-emoji` | Prohíbe emojis en strings y JSX; cada sistema los renderiza distinto. Usa un icono SVG. |
|
|
866
|
+
| `skapxd/no-impossible-branch` | Condiciones que el type-checker demuestra constantes: la pregunta ya tiene respuesta. Es `@typescript-eslint/no-unnecessary-condition` con nombre semántico y mensajes que enseñan el fix. |
|
|
722
867
|
| `skapxd/no-nested-if` | Prohíbe `if` anidados: retorno anticipado o `match()`. Menos carga cognitiva y sin puntos ciegos para las demás reglas. |
|
|
723
868
|
| `skapxd/no-runtime-state-guard` | Prohíbe `if (this.x) throw` en métodos: el estado inválido se hace irrepresentable en el tipo, no se vigila en runtime. |
|
|
724
869
|
| `skapxd/no-tunnel-props` | Ninguna prop viaja más de un nivel: quien la recibe no puede reenviarla a otro componente. Mata el prop drilling. |
|
|
@@ -831,8 +976,12 @@ Todas las opciones, con sus defaults:
|
|
|
831
976
|
Todo el sistema descansa en que el compilador pueda hacer irrepresentables
|
|
832
977
|
los estados inválidos — y eso exige un `tsconfig` implacable. Esta regla lee
|
|
833
978
|
el `tsconfig.json` **real** del proyecto (con la API de TypeScript: soporta
|
|
834
|
-
JSONC y resuelve la cadena de `extends`) y exige los flags,
|
|
835
|
-
|
|
979
|
+
JSONC y resuelve la cadena de `extends`) y exige los flags, reportando una
|
|
980
|
+
vez por proyecto: si existe un archivo ancla (`anchorFilePatterns`, default
|
|
981
|
+
`src/main.ts(x)`/`src/index.ts(x)`), el reporte le pertenece a ese archivo;
|
|
982
|
+
si el proyecto no tiene entrypoint clásico (Astro, librerías), reporta sobre
|
|
983
|
+
el primer archivo del run y los demás callan — un proyecto sin ancla no se
|
|
984
|
+
queda sin guardián:
|
|
836
985
|
|
|
837
986
|
- `strict` — sin él, el sistema de tipos está apagado a medias.
|
|
838
987
|
- `noImplicitReturns` — una rama que sale sin valor deja de ser silenciosa
|
|
@@ -862,12 +1011,14 @@ Además, los **presets tipados activan reglas curadas de typescript-eslint**
|
|
|
862
1011
|
que tú" dicho al compilador. Si no puede ser nulo, que lo diga el tipo.
|
|
863
1012
|
(En `nest/tests` queda apagada: el `!` sobre un fixture cuya existencia el
|
|
864
1013
|
propio test garantiza es el arrange, no una mentira.)
|
|
865
|
-
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1014
|
+
- `skapxd/no-impossible-branch` — la generalización type-aware de
|
|
1015
|
+
`no-runtime-state-guard`: si el tipo dice que un estado es imposible, el
|
|
1016
|
+
guard defensivo sobra; si el guard hace falta, lo que está mal es el tipo.
|
|
1017
|
+
Es `@typescript-eslint/no-unnecessary-condition` **re-registrada bajo
|
|
1018
|
+
nuestro namespace** (ver su sección): mismo motor, nombre que dice lo que
|
|
1019
|
+
defiende y mensajes que enseñan el fix. Por eso esta regla y
|
|
1020
|
+
`requires-strict-tsconfig` van juntas: sin `noUncheckedIndexedAccess`,
|
|
1021
|
+
`array[i]` miente y la regla acusaría guards necesarios.
|
|
871
1022
|
- `@typescript-eslint/ban-ts-comment` — un error de tipos se arregla
|
|
872
1023
|
modelando mejor, no silenciando la alarma: `@ts-ignore` y `@ts-nocheck`
|
|
873
1024
|
prohibidos. `@ts-expect-error` **con descripción** queda permitido: es la
|
|
@@ -1726,6 +1877,36 @@ en un `<input>` es la frontera con el DOM). Para wrappers legítimos de un
|
|
|
1726
1877
|
design system, exime props por nombre (`allowPropPatterns: ["^className$"]`)
|
|
1727
1878
|
o archivos completos (`allowFilePatterns`).
|
|
1728
1879
|
|
|
1880
|
+
### `skapxd/no-impossible-branch`
|
|
1881
|
+
|
|
1882
|
+
La rama imposible: una condición que el type-checker demuestra constante. Si
|
|
1883
|
+
el tipo dice que un valor siempre es truthy, ese `if` no decide nada; si un
|
|
1884
|
+
`?.` cuelga de algo que nunca es nullish, finge una duda que el modelo ya
|
|
1885
|
+
resolvió. La pregunta ya tiene respuesta — y un `if` que no pregunta es
|
|
1886
|
+
código muerto disfrazado de prudencia.
|
|
1887
|
+
|
|
1888
|
+
```ts
|
|
1889
|
+
const sheet = workbook.Sheets[name]; // tipo: WorkSheet (¿seguro?)
|
|
1890
|
+
if (!sheet) continue; // ❌ "always falsy"... ¿o el tipo miente?
|
|
1891
|
+
```
|
|
1892
|
+
|
|
1893
|
+
El mensaje de error enseña la lección completa: **si la comprobación hace
|
|
1894
|
+
falta en runtime, lo que está mal es el tipo**. El caso clásico es el acceso
|
|
1895
|
+
por índice sin `noUncheckedIndexedAccess` — `array[i]` y `obj[key]` juran que
|
|
1896
|
+
nunca son `undefined`, y esta regla, creyéndoles, acusaría guards necesarios.
|
|
1897
|
+
Por eso va de la mano de `skapxd/requires-strict-tsconfig`, que exige ese
|
|
1898
|
+
flag: primero el tsconfig dice la verdad, después esta regla opina.
|
|
1899
|
+
|
|
1900
|
+
Bajo el capó es `@typescript-eslint/no-unnecessary-condition`
|
|
1901
|
+
([doc original](https://typescript-eslint.io/rules/no-unnecessary-condition/))
|
|
1902
|
+
**re-registrada bajo nuestro namespace**: mismo motor y mismas opciones, pero
|
|
1903
|
+
con un nombre que dice lo que defiende (axioma A1: los estados imposibles son
|
|
1904
|
+
irrepresentables — es la generalización type-aware de
|
|
1905
|
+
`no-runtime-state-guard`) y mensajes en español que explican el fix en vez
|
|
1906
|
+
del críptico "Unnecessary conditional". Los presets tipados activan este
|
|
1907
|
+
nombre y **no** el original: una sola fuente de verdad para configurarla,
|
|
1908
|
+
silenciarla o buscarla.
|
|
1909
|
+
|
|
1729
1910
|
### `skapxd/no-functions-inside-components`
|
|
1730
1911
|
|
|
1731
1912
|
Prohíbe definir funciones **con peso propio** dentro de un componente React
|
package/dist/astro/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
baseRules,
|
|
3
3
|
createBaseLanguageOptions,
|
|
4
4
|
createTypedLanguageOptions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-F6GJW5A4.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-
|
|
44
|
+
//# sourceMappingURL=chunk-DJDXQWCP.mjs.map
|
|
@@ -78,7 +78,9 @@ var typeDrivenRules = {
|
|
|
78
78
|
// hace falta, lo que está mal es el tipo. Requiere el tsconfig de
|
|
79
79
|
// requires-strict-tsconfig para ser sólida: sin noUncheckedIndexedAccess,
|
|
80
80
|
// `array[i]` miente y esta regla acusaría guards necesarios.
|
|
81
|
-
|
|
81
|
+
// Es @typescript-eslint/no-unnecessary-condition re-registrada bajo un
|
|
82
|
+
// nombre que dice lo que defiende, con mensajes que enseñan el fix.
|
|
83
|
+
"skapxd/no-impossible-branch": "error"
|
|
82
84
|
};
|
|
83
85
|
|
|
84
86
|
// src/shared/configs/create-shared-configs.ts
|
|
@@ -172,4 +174,4 @@ export {
|
|
|
172
174
|
createSharedConfigs,
|
|
173
175
|
strictConfig
|
|
174
176
|
};
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
177
|
+
//# sourceMappingURL=chunk-F6GJW5A4.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/configs/create-typed-language-options.ts","../src/shared/configs/create-shared-configs.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/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","import tseslint from \"typescript-eslint\";\nimport { 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 plugins: {\n \"@typescript-eslint\": tseslint.plugin,\n skapxd: pluginReference,\n },\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: {\n \"@typescript-eslint\": tseslint.plugin,\n skapxd: pluginReference,\n },\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 package: {\n languageOptions: baseLanguageOptions,\n name: \"skapxd/shared/package\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/one-root-function-per-file\": \"error\",\n },\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 \"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 y que no\n// tiene sentido reimplementar — typescript-eslint ya es peer dependency.\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 // 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.\n \"@typescript-eslint/ban-ts-comment\": [\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 \"@typescript-eslint/consistent-type-definitions\": [\"error\", \"type\"],\n // `any` apaga el sistema de tipos: todo el esfuerzo de modelar estados\n // irrepresentables muere donde aparece uno.\n \"@typescript-eslint/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. Esta\n // regla obliga a awaitear (y ahí entra el pipeline de Result). El operador\n // `void promesa` queda como única salida: fire-and-forget declarado y\n // greppeable, no interpretado.\n \"@typescript-eslint/no-floating-promises\": \"error\",\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 \"@typescript-eslint/no-non-null-assertion\": \"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 \"@typescript-eslint/no-unnecessary-condition\": \"error\",\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":";AAAA,OAAO,cAAc;AAEd,SAAS,6BAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA,IAGL,QAAQ,SAAS;AAAA,IACjB,eAAe;AAAA,MACb,gBAAgB;AAAA,IAClB;AAAA,EACF;AACF;;;ACXA,OAAOA,eAAc;;;ACAd,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,OAAOC,eAAc;AAId,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL,QAAQA,UAAS;AAAA,EACnB;AACF;;;ACSO,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,qCAAqC;AAAA,IACnC;AAAA,IACA;AAAA,MACE,mBAAmB;AAAA,MACnB,aAAa;AAAA,MACb,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,kDAAkD,CAAC,SAAS,MAAM;AAAA;AAAA;AAAA,EAGlE,sCAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtC,2CAA2C;AAAA;AAAA;AAAA,EAG3C,4CAA4C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5C,+CAA+C;AACjD;;;AH7CO,SAAS,oBAAoB,iBAA0B;AAC5D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL,SAAS;AAAA,MACP,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,sBAAsBC,UAAS;AAAA,QAC/B,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOH,gCAAgC;AAAA,MAClC;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA,UAAU;AAAA,MACR,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,sBAAsBA,UAAS;AAAA,QAC/B,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA,QAKH,gCAAgC;AAAA,QAChC,sCAAsC;AAAA;AAAA;AAAA;AAAA,QAItC,yCAAyC;AAAA,QACzC,0BAA0B;AAAA;AAAA;AAAA,QAG1B,8BAA8B;AAAA,QAC9B,8BAA8B;AAAA,QAC9B,wBAAwB;AAAA,UACtB;AAAA,UACA;AAAA,YACE,UAAU;AAAA,YACV,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,qCAAqC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACF;;;AI5EO,IAAM,eAAe;AAAA,EAC1B,eAAe;AAAA,IACb,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM;AACR;","names":["tseslint","tseslint","tseslint"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/configs/create-typed-language-options.ts","../src/shared/configs/create-shared-configs.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/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","import tseslint from \"typescript-eslint\";\nimport { 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 plugins: {\n \"@typescript-eslint\": tseslint.plugin,\n skapxd: pluginReference,\n },\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: {\n \"@typescript-eslint\": tseslint.plugin,\n skapxd: pluginReference,\n },\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 package: {\n languageOptions: baseLanguageOptions,\n name: \"skapxd/shared/package\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/one-root-function-per-file\": \"error\",\n },\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 \"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 y que no\n// tiene sentido reimplementar — typescript-eslint ya es peer dependency.\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 // 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.\n \"@typescript-eslint/ban-ts-comment\": [\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 \"@typescript-eslint/consistent-type-definitions\": [\"error\", \"type\"],\n // `any` apaga el sistema de tipos: todo el esfuerzo de modelar estados\n // irrepresentables muere donde aparece uno.\n \"@typescript-eslint/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. Esta\n // regla obliga a awaitear (y ahí entra el pipeline de Result). El operador\n // `void promesa` queda como única salida: fire-and-forget declarado y\n // greppeable, no interpretado.\n \"@typescript-eslint/no-floating-promises\": \"error\",\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 \"@typescript-eslint/no-non-null-assertion\": \"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 // Es @typescript-eslint/no-unnecessary-condition re-registrada bajo un\n // nombre que dice lo que defiende, con mensajes que enseñan el fix.\n \"skapxd/no-impossible-branch\": \"error\",\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":";AAAA,OAAO,cAAc;AAEd,SAAS,6BAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA,IAGL,QAAQ,SAAS;AAAA,IACjB,eAAe;AAAA,MACb,gBAAgB;AAAA,IAClB;AAAA,EACF;AACF;;;ACXA,OAAOA,eAAc;;;ACAd,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,OAAOC,eAAc;AAId,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL,QAAQA,UAAS;AAAA,EACnB;AACF;;;ACSO,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,qCAAqC;AAAA,IACnC;AAAA,IACA;AAAA,MACE,mBAAmB;AAAA,MACnB,aAAa;AAAA,MACb,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA,EAGA,kDAAkD,CAAC,SAAS,MAAM;AAAA;AAAA;AAAA,EAGlE,sCAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtC,2CAA2C;AAAA;AAAA;AAAA,EAG3C,4CAA4C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ5C,+BAA+B;AACjC;;;AH/CO,SAAS,oBAAoB,iBAA0B;AAC5D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL,SAAS;AAAA,MACP,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,sBAAsBC,UAAS;AAAA,QAC/B,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOH,gCAAgC;AAAA,MAClC;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA,UAAU;AAAA,MACR,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,sBAAsBA,UAAS;AAAA,QAC/B,QAAQ;AAAA,MACV;AAAA,MACA,OAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA,QAKH,gCAAgC;AAAA,QAChC,sCAAsC;AAAA;AAAA;AAAA;AAAA,QAItC,yCAAyC;AAAA,QACzC,0BAA0B;AAAA;AAAA;AAAA,QAG1B,8BAA8B;AAAA,QAC9B,8BAA8B;AAAA,QAC9B,wBAAwB;AAAA,UACtB;AAAA,UACA;AAAA,YACE,UAAU;AAAA,YACV,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,qCAAqC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACF;;;AI5EO,IAAM,eAAe;AAAA,EAC1B,eAAe;AAAA,IACb,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM;AACR;","names":["tseslint","tseslint","tseslint"]}
|
|
@@ -2759,6 +2759,33 @@ var noEmoji = {
|
|
|
2759
2759
|
}
|
|
2760
2760
|
};
|
|
2761
2761
|
|
|
2762
|
+
// src/rules/no-impossible-branch.ts
|
|
2763
|
+
import tseslint from "typescript-eslint";
|
|
2764
|
+
var original = tseslint.plugin.rules["no-unnecessary-condition"];
|
|
2765
|
+
var elTipoMiente = " Si la comprobacion hace falta en runtime, el tipo esta mintiendo: arregla el tipo, no borres el guard a ciegas (acceso por indice tipo `array[i]` u `obj[key]`? te falta `noUncheckedIndexedAccess` en el tsconfig \u2014 `skapxd/requires-strict-tsconfig` lo exige).";
|
|
2766
|
+
var noImpossibleBranch = {
|
|
2767
|
+
...original,
|
|
2768
|
+
meta: {
|
|
2769
|
+
...original.meta,
|
|
2770
|
+
docs: {
|
|
2771
|
+
...original.meta.docs,
|
|
2772
|
+
description: "La rama imposible: condiciones que el type-checker demuestra constantes. Si el tipo dice que no puede pasar, la rama sobra; si la rama hace falta, lo que esta mal es el tipo."
|
|
2773
|
+
},
|
|
2774
|
+
messages: {
|
|
2775
|
+
...original.meta.messages,
|
|
2776
|
+
alwaysFalsy: "Rama imposible: el tipo dice que este valor SIEMPRE es falsy \u2014 el camino positivo de esta condicion es codigo muerto." + elTipoMiente,
|
|
2777
|
+
alwaysNullish: "Rama imposible: el tipo dice que el lado izquierdo del `??` SIEMPRE es null/undefined \u2014 la expresion es solo su fallback." + elTipoMiente,
|
|
2778
|
+
alwaysTruthy: "Pregunta ya respondida: el tipo dice que este valor SIEMPRE es truthy \u2014 la condicion solo tiene un camino posible." + elTipoMiente,
|
|
2779
|
+
comparisonBetweenLiteralTypes: "Comparacion constante: `{{left}} {{operator}} {{right}}` siempre es {{trueOrFalse}} segun los tipos \u2014 esta decision no decide nada." + elTipoMiente,
|
|
2780
|
+
never: "Rama imposible: este valor es de tipo `never` \u2014 segun el modelo, este punto del codigo es inalcanzable." + elTipoMiente,
|
|
2781
|
+
neverNullish: "El `??` no aporta: el tipo dice que el lado izquierdo NUNCA es null/undefined \u2014 el fallback es codigo muerto." + elTipoMiente,
|
|
2782
|
+
neverOptionalChain: "El `?.` sobra: el tipo dice que este valor nunca es nullish \u2014 el encadenamiento opcional finge una duda que el modelo ya resolvio." + elTipoMiente,
|
|
2783
|
+
noOverlapBooleanExpression: "Comparacion imposible: los tipos de ambos lados no se solapan, asi que el resultado siempre es el mismo (ej. comparar con `null` un valor cuyo tipo nunca incluye `null`)." + elTipoMiente,
|
|
2784
|
+
noStrictNullCheck: "Esta regla necesita `strictNullChecks` (viene con `strict: true`): sin el, los tipos mienten sobre null/undefined y la regla acusaria guards necesarios. `skapxd/requires-strict-tsconfig` vigila esa premisa."
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
};
|
|
2788
|
+
|
|
2762
2789
|
// src/utils/get-no-tunnel-props-options.ts
|
|
2763
2790
|
function getNoTunnelPropsOptions(options = {}) {
|
|
2764
2791
|
return {
|
|
@@ -3323,7 +3350,7 @@ var preferTaggedUnionState = {
|
|
|
3323
3350
|
};
|
|
3324
3351
|
|
|
3325
3352
|
// src/rules/requires-strict-tsconfig.ts
|
|
3326
|
-
import { dirname as
|
|
3353
|
+
import { dirname as dirname5, resolve as resolve2 } from "path";
|
|
3327
3354
|
|
|
3328
3355
|
// src/utils/get-strict-tsconfig-options.ts
|
|
3329
3356
|
function getStrictTsconfigOptions(options = {}) {
|
|
@@ -3349,8 +3376,38 @@ function getStrictTsconfigOptions(options = {}) {
|
|
|
3349
3376
|
};
|
|
3350
3377
|
}
|
|
3351
3378
|
|
|
3352
|
-
// src/utils/
|
|
3379
|
+
// src/utils/is-anchorless-check-redundant.ts
|
|
3353
3380
|
import { dirname as dirname3 } from "path";
|
|
3381
|
+
|
|
3382
|
+
// src/utils/anchor-file-exists.ts
|
|
3383
|
+
import { existsSync as existsSync2 } from "fs";
|
|
3384
|
+
import { join as join2 } from "path";
|
|
3385
|
+
function anchorFileExists(rootDir, anchorFilePatterns) {
|
|
3386
|
+
return anchorFilePatterns.some((pattern) => {
|
|
3387
|
+
const literal = pattern.replace(/^\*\*\//, "");
|
|
3388
|
+
if (literal.includes("*") || literal.includes("{")) {
|
|
3389
|
+
return false;
|
|
3390
|
+
}
|
|
3391
|
+
return existsSync2(join2(rootDir, literal));
|
|
3392
|
+
});
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
// src/utils/is-anchorless-check-redundant.ts
|
|
3396
|
+
var checkedRoots = /* @__PURE__ */ new Set();
|
|
3397
|
+
function isAnchorlessCheckRedundant(tsconfigPath, fallbackRootKey, anchorFilePatterns) {
|
|
3398
|
+
const rootKey = tsconfigPath ?? fallbackRootKey;
|
|
3399
|
+
if (checkedRoots.has(rootKey)) {
|
|
3400
|
+
return true;
|
|
3401
|
+
}
|
|
3402
|
+
checkedRoots.add(rootKey);
|
|
3403
|
+
if (!tsconfigPath) {
|
|
3404
|
+
return false;
|
|
3405
|
+
}
|
|
3406
|
+
return anchorFileExists(dirname3(tsconfigPath), anchorFilePatterns);
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3409
|
+
// src/utils/read-resolved-tsconfig.ts
|
|
3410
|
+
import { dirname as dirname4 } from "path";
|
|
3354
3411
|
import ts3 from "typescript";
|
|
3355
3412
|
import { trySafe as trySafe3 } from "@skapxd/result";
|
|
3356
3413
|
function readResolvedTsconfig(tsconfigPath) {
|
|
@@ -3362,7 +3419,7 @@ function readResolvedTsconfig(tsconfigPath) {
|
|
|
3362
3419
|
return ts3.parseJsonConfigFileContent(
|
|
3363
3420
|
raw.config,
|
|
3364
3421
|
ts3.sys,
|
|
3365
|
-
|
|
3422
|
+
dirname4(tsconfigPath)
|
|
3366
3423
|
);
|
|
3367
3424
|
});
|
|
3368
3425
|
if (!parsed.ok || !parsed.value) {
|
|
@@ -3406,16 +3463,24 @@ var requiresStrictTsconfig = {
|
|
|
3406
3463
|
create(context) {
|
|
3407
3464
|
const options = getStrictTsconfigOptions(context.options[0]);
|
|
3408
3465
|
const filename = context.filename ?? context.getFilename();
|
|
3409
|
-
if (matchesAnyGlob(filename, options.allowFilePatterns)
|
|
3466
|
+
if (matchesAnyGlob(filename, options.allowFilePatterns)) {
|
|
3410
3467
|
return {};
|
|
3411
3468
|
}
|
|
3469
|
+
const isAnchor = matchesAnyGlob(filename, options.anchorFilePatterns);
|
|
3412
3470
|
return {
|
|
3413
3471
|
Program(node) {
|
|
3414
3472
|
const absoluteFilename = resolve2(context.cwd ?? process.cwd(), filename);
|
|
3415
3473
|
const tsconfigPath = findProjectFile(
|
|
3416
|
-
|
|
3474
|
+
dirname5(absoluteFilename),
|
|
3417
3475
|
"tsconfig.json"
|
|
3418
3476
|
);
|
|
3477
|
+
if (!isAnchor && isAnchorlessCheckRedundant(
|
|
3478
|
+
tsconfigPath,
|
|
3479
|
+
context.cwd ?? process.cwd(),
|
|
3480
|
+
options.anchorFilePatterns
|
|
3481
|
+
)) {
|
|
3482
|
+
return;
|
|
3483
|
+
}
|
|
3419
3484
|
const compilerOptions = tsconfigPath ? readResolvedTsconfig(tsconfigPath) : null;
|
|
3420
3485
|
if (!compilerOptions) {
|
|
3421
3486
|
context.report({ messageId: "missingTsconfig", node });
|
|
@@ -3741,6 +3806,9 @@ var rules = {
|
|
|
3741
3806
|
"no-default-export": noDefaultExport,
|
|
3742
3807
|
"no-else": noElse,
|
|
3743
3808
|
"no-emoji": noEmoji,
|
|
3809
|
+
// Re-registro de @typescript-eslint/no-unnecessary-condition con nombre
|
|
3810
|
+
// semántico y mensajes propios (ver src/rules/no-impossible-branch.ts).
|
|
3811
|
+
"no-impossible-branch": noImpossibleBranch,
|
|
3744
3812
|
"no-tunnel-props": noTunnelProps,
|
|
3745
3813
|
"no-functions-inside-components": noFunctionsInsideComponents,
|
|
3746
3814
|
"no-try-catch": noTryCatch,
|
|
@@ -3757,4 +3825,4 @@ var rules = {
|
|
|
3757
3825
|
export {
|
|
3758
3826
|
rules
|
|
3759
3827
|
};
|
|
3760
|
-
//# sourceMappingURL=chunk-
|
|
3828
|
+
//# sourceMappingURL=chunk-MLFXSEY7.mjs.map
|