@skapxd/eslint-opinionated
v8.6.0
Published
Reusable ESLint architectural rules for TypeScript, React, backend, frontend, and package projects
Maintainers
Readme
@skapxd/eslint-opinionated
Reglas de ESLint para que los agentes no negocien la arquitectura de tu proyecto.
Este paquete convierte opiniones de arquitectura en guardrails ejecutables: archivos pequenos, nombres semanticos, errores modelados con Result, causas preservadas y fronteras explicitas. El README queda como puerta de entrada; el detalle vive en docs/ para que npm no entierre lo importante en 2.400 lineas.
Skill para agentes
Instala la skill skapxd-lint en tu agente con un comando compatible con skills.sh y 20+ agentes como Claude Code, Cursor y Copilot:
npx skills add skapxd/eslint-opinionatedLuego pide al agente que la use:
- "Audita este proyecto con skapxd-lint y muestrame los hallazgos."
- "Adopta las reglas skapxd de forma incremental (10%) en este repo legacy."
- "Verifica el lote de adopcion skapxd con la seed que acaba de generar el CLI."
La skill esta indexada en skills.sh, invoca el CLI publicado @skapxd/eslint-opinionated@6 con npm provenance y no modifica el proyecto medido: la evaluacion es efimera y solo lectura salvo que pidas aplicar fixes.
Si no usas la skill, puedes invocar el CLI directo:
npx @skapxd/eslint-opinionated@6 <path> --yes --format toonUso rapido
pnpm add -D @skapxd/eslint-opinionated eslint typescript typescript-eslintimport skapxd from "@skapxd/eslint-opinionated";
export default [
skapxd.configs.shared.base,
];Luego ejecutalo como cualquier regla de ESLint:
pnpm eslint
pnpm eslint src
pnpm eslint --max-warnings=0Documentacion
Los enlaces apuntan a GitHub de forma absoluta para que funcionen tambien desde npmjs.com.
| Tema | Contenido | | --- | --- | | Axiomas y motivacion | Por que existe el paquete, que protege y por que las alternativas no bastan. | | Presets y estructura | Shared, backend, frontend, Next.js, NestJS, Astro, package y strict. | | Adopcion incremental y legacy | Lint sobre cambios, olas de adopcion, overrides y propuestas de reglas. | | Pipeline Result | Como encajan @skapxd/result, ts-pattern y el trace global. | | Notas type-aware | Supuestos, limites conocidos y notas de reglas que dependen del checker. | | Indice de reglas | Las 64 fichas individuales en docs/reglas/. |
Reglas
| Regla | Que protege |
| --- | --- |
| skapxd/one-root-function-per-file | Un archivo, una función top-level semántica. |
| skapxd/filename-matches-root-function | El nombre del archivo es la versión kebab de su función raíz exportada. |
| skapxd/dense-function-requires-comment | Funciones exportadas densas en líneas, literales y ramas declaran su motivación en un comentario de bloque. |
| skapxd/async-functions-return-result | Funciones async de dominio deben retornar Promise<Result<...>>. Apagada por defecto; opt-in (ver motivos en su sección). |
| skapxd/requires-strict-tsconfig | El tsconfig debe ser implacable (strict, noImplicitReturns, noUncheckedIndexedAccess): sin ellos, el compilador no puede hacer irrepresentable lo inválido. |
| skapxd/result-error-requires-cause | Un Result.err derivado debe preservar cause: result.error. |
| skapxd/result-error-requires-handling | Prohíbe descartar en silencio un Result fallido: el error se transforma o se entrega, nunca se ignora. |
| skapxd/result-error-requires-modeling | Una frontera no puede devolver Result<_, unknown>: el canal de error debe modelarse como un error de dominio (tagged union), no quedar opaco. |
| skapxd/await-requires-result | Todo await debe resolver en un Result: o la función llamada retorna Promise<Result<...>> (preferido) o se envuelve en trySafe. Obligatoria en todos los presets tipados. |
| skapxd/no-rethrow-result-error | Prohíbe re-lanzar el error crudo de un Result: el flujo no vuelve de trySafe a excepción cruda. |
| skapxd/trysafe-only-at-boundary | Exige que trySafe capture en la frontera runtime/paquete, no una capa arriba sobre código del proyecto. En las bases (agnóstica de framework); detección conservadora para acotar falsos positivos. |
| skapxd/no-ad-hoc-ok-result | Evita contratos { ok: ... } hechos a mano en async exports. |
| skapxd/max-hook-size | Marca hooks grandes o con demasiados useState. |
| skapxd/class-properties-require-readonly | Toda propiedad de clase es readonly: el cambio se modela con instancias nuevas, no con mutación. |
| skapxd/max-public-methods | Una clase, una responsabilidad: máximo N métodos públicos (default 1). Agnóstica al framework, en las reglas base; el preset nest le inyecta sus hooks. |
| skapxd/no-exported-function-bag | Prohíbe exportar objetos que publican varias funciones: una bolsa de funciones es una clase o namespace disfrazado. En las bases. |
| skapxd/no-accessors | Prohíbe get/set: un método explícito dice la verdad; el accessor esconde computación (y métodos disfrazados). |
| skapxd/jsx-return-name-pascal-case | Funciones que retornan JSX deben nombrarse como componentes. |
| skapxd/nest-controller-injects-use-case | Controllers y gateways inyectan casos de uso con @UseCase, no services/repositories directos. Preset nest. |
| skapxd/nest-controller-returns-dto | Los métodos de ruta de un @Controller retornan una clase extends Dto() con brand "dto" de @skapxd/nest para que Swagger genere el response schema sin exponer interfaces ni schemas de DB. Preset nest. |
| skapxd/nest-dto-no-inline-object | Los objetos anidados de un DTO se modelan como clases DTO, no como tipos inline ni type: Object. Preset nest. |
| skapxd/nest-dto-requires-api-property | Toda propiedad pública de un *.dto.ts lleva @ApiProperty: el contrato HTTP se documenta en el DTO. Preset nest. |
| skapxd/nest-dto-requires-validation | Todo DTO valida en runtime: class-validator en cada propiedad, @IsOptional si hay ?, @Type junto a @ValidateNested; zod/valibot para uniones. Preset nest. |
| skapxd/nest-no-direct-instantiation | Prohíbe new sobre imports internos en services: las dependencias entran por el constructor (DI). Preset nest. |
| skapxd/nest-no-inline-query-params | Dos o más @Query('x')/@ApiQuery individuales son un DTO disfrazado: consolida en @Query() filters: Dto. Preset nest. |
| skapxd/nest-no-result-response | Los métodos de un @Controller no retornan Result: el envelope se serializaría al cliente. La activa el preset nest. |
| skapxd/nest-no-swagger-in-controllers | Los controllers no se llenan de decoradores de swagger; el plugin introspecciona los DTOs. Preset nest. |
| skapxd/nest-requires-swagger-plugin | nest-cli.json debe tener el plugin @nestjs/swagger: la premisa de las reglas de swagger, verificada. Preset nest. |
| skapxd/nest-use-case-no-result-response | Los métodos públicos de un @UseCase real consumen Result y lanzan excepciones, no propagan el envelope al controller. Preset nest. |
| skapxd/nest-validation-pipe-config | Todo new ValidationPipe configura transform y whitelist: la premisa de las reglas de DTOs. Preset nest. |
| skapxd/nested-function-requires-capture | Una funcion anidada nombrada debe capturar scope local; si no, es un helper extraible. Preset shared, en error. |
| 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. |
| skapxd/no-deep-relative-imports | Limita la profundidad de los imports relativos (../). |
| 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. |
| skapxd/no-else | Prohíbe else/else if: el else es el estado sin nombre. Retorno anticipado, ternario simple o match(). |
| skapxd/no-emoji | Prohíbe emojis en strings y JSX; cada sistema los renderiza distinto. Usa un icono SVG. |
| skapxd/no-explicit-any | Prohíbe any: apaga el sistema de tipos donde más se necesita. unknown para lo desconocido, el tipo real para lo demás. Wrapper de typescript-eslint. |
| skapxd/no-floating-promises | Promesas sin await ni void: el rechazo muere sin pasar por trySafe. El mensaje corrige el consejo upstream (.then/.catch aquí están prohibidos). Wrapper de typescript-eslint. |
| skapxd/no-magic-numbers | Prohíbe números mágicos: un literal numérico significativo debe extraerse a una const con nombre de dominio. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-argument | Impide pasar un any invisible como argumento: la frontera debe declararse unknown y estrecharse con schema o predicate. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-assignment | Impide asignar un any invisible a variables o propiedades: la frontera debe declararse unknown y validarse. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-call | Impide invocar valores any: antes de llamar hay que probar el tipo real con evidencia runtime. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-member-access | Impide leer propiedades sobre any: JSON.parse()/response.json() pasan por unknown + schema/predicate antes de tocar campos. Wrapper de typescript-eslint. |
| skapxd/no-unsafe-return | Impide retornar any desde una funcion tipada: el dato externo se estrecha antes de salir de la frontera. Wrapper de typescript-eslint. |
| skapxd/no-unverified-cast | Prohíbe casts as que estrechan sin evidencia: schema, type predicate honesto o tipo de origen mejor modelado. Wrapper de typescript-eslint. |
| skapxd/prefer-schema-validation | Detecta validadores artesanales con muchos checks estructurales sobre el mismo unknown/any: eso ya es un schema, decláralo. |
| 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. |
| skapxd/no-nested-if | Prohíbe if anidados: retorno anticipado o match(). Menos carga cognitiva y sin puntos ciegos para las demás reglas. |
| skapxd/no-non-null-assertion | Prohíbe el !: es "cállate, yo sé más que tú" dicho al compilador. Modela el tipo o maneja la duda. Wrapper de typescript-eslint. |
| 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. |
| skapxd/no-silenced-compiler | Prohíbe @ts-ignore/@ts-nocheck: silenciar la alarma no arregla el incendio. @ts-expect-error con descripción queda para tests de tipos. Wrapper de ban-ts-comment. |
| 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. |
| skapxd/prefer-abort-signal | Listeners en efectos se limpian con AbortController ({ signal } + abort()), no con removeEventListener. |
| skapxd/prefer-node-protocol-for-builtins | Builtins de Node siempre con protocolo node:: separa runtime de npm y evita ambigüedad cross-runtime. |
| skapxd/prefer-tagged-union-state | Prohíbe estados inconsistentes representables: flag de loading + campo de error independientes → unión etiquetada. |
| skapxd/prefer-type-over-interface | Las uniones discriminadas son types; un type no crece en silencio por declaration merging. Wrapper de consistent-type-definitions. |
| skapxd/no-functions-inside-components | Prohíbe definir funciones dentro de componentes React. |
| skapxd/no-try-catch | Prohíbe try/catch; usa trySafe de @skapxd/result. |
| skapxd/no-promise-chain | Prohíbe .then/.catch/.finally; usa await (+ trySafe). |
| skapxd/prefer-ts-pattern | Prohíbe switch y ternarios anidados; usa match() de ts-pattern. |
| skapxd/package-requires-typed-exports | Los exports del package.json declaran types por condición (import → .d.mts, require → .d.ts): mata el bug FalseCJS. Preset package. |
| skapxd/untrusted-module-requires-adapter | Los paquetes con tipos mentirosos (@types desfasados) solo se importan desde su adaptador: la mentira vive en UN archivo. Preset package. |
| skapxd/no-jsx-ternary-null | Prefiere cond && <El /> sobre cond ? <El /> : null en JSX. |
| skapxd/repeated-jsx-requires-component | Detecta patrones JSX repetidos tres veces que ya son un componente sin nombre. Activa como error en frontend, next/react y astro/react. |
Licencia
MIT
