@skapxd/eslint-opinionated 0.5.0 → 0.7.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 +192 -5
- package/dist/astro/index.d.mts +2 -0
- package/dist/astro/index.d.ts +2 -0
- package/dist/astro/index.js +1 -0
- package/dist/astro/index.js.map +1 -1
- package/dist/astro/index.mjs +2 -2
- package/dist/{chunk-QJQ2E2NG.mjs → chunk-72XIHMY7.mjs} +19 -3
- package/dist/chunk-72XIHMY7.mjs.map +1 -0
- package/dist/{chunk-QNSHGNVQ.mjs → chunk-G6TJUBFT.mjs} +133 -32
- package/dist/chunk-G6TJUBFT.mjs.map +1 -0
- package/dist/chunk-HB755SJQ.mjs +32 -0
- package/dist/chunk-HB755SJQ.mjs.map +1 -0
- package/dist/{chunk-RWQGOTVZ.mjs → chunk-LDAR6XT6.mjs} +2 -1
- package/dist/chunk-LDAR6XT6.mjs.map +1 -0
- package/dist/{chunk-7H7DRTP2.mjs → chunk-OVPAO7Q3.mjs} +2 -2
- package/dist/index.js +169 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -5
- package/dist/index.mjs.map +1 -1
- package/dist/next/index.d.mts +8 -0
- package/dist/next/index.d.ts +8 -0
- package/dist/next/index.js +41 -1
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +3 -2
- package/dist/shared/index.d.mts +3 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +128 -4
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +3 -2
- package/package.json +3 -2
- package/dist/chunk-QJQ2E2NG.mjs.map +0 -1
- package/dist/chunk-QNSHGNVQ.mjs.map +0 -1
- package/dist/chunk-RWQGOTVZ.mjs.map +0 -1
- /package/dist/{chunk-7H7DRTP2.mjs.map → chunk-OVPAO7Q3.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -510,6 +510,50 @@ export default [
|
|
|
510
510
|
Si necesitas una excepción puntual (p. ej. archivos generados), añade después un
|
|
511
511
|
bloque con `linterOptions: { noInlineConfig: false }` para esos globs.
|
|
512
512
|
|
|
513
|
+
## Configurar y sobrescribir reglas
|
|
514
|
+
|
|
515
|
+
Los presets son flat configs normales de ESLint: **el último config que
|
|
516
|
+
matchea un archivo gana**. Para ajustar una regla encima de un preset, esparce
|
|
517
|
+
sus `rules` y sobrescribe la entrada:
|
|
518
|
+
|
|
519
|
+
```js
|
|
520
|
+
export default [
|
|
521
|
+
{
|
|
522
|
+
files: ["src/**/*.{ts,tsx}"],
|
|
523
|
+
...skapxd.configs.shared.frontend,
|
|
524
|
+
rules: {
|
|
525
|
+
...skapxd.configs.shared.frontend.rules,
|
|
526
|
+
// mismo id, nuevas opciones: esta entrada reemplaza a la del preset
|
|
527
|
+
"skapxd/no-deep-relative-imports": ["error", { maxDepth: 1 }],
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
];
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
> Las opciones de una regla **se reemplazan completas**, no se mergean: si el
|
|
534
|
+
> preset pasaba opciones y tú la redeclaras, incluye también las que quieras
|
|
535
|
+
> conservar. (Excepción: los patrones *integrados* de `no-default-export` —
|
|
536
|
+
> configs y stories — viven dentro de la regla y nunca se pierden; tus
|
|
537
|
+
> `allowFilePatterns` se suman a ellos.)
|
|
538
|
+
|
|
539
|
+
Referencia rápida de qué se puede configurar (detalle y defaults en la sección
|
|
540
|
+
de cada regla):
|
|
541
|
+
|
|
542
|
+
| Regla | Opciones |
|
|
543
|
+
| --- | --- |
|
|
544
|
+
| `async-functions-return-result` | `allowFilePatterns` (globs), `allowNamePatterns` (regex), `checkMissingReturnType`, `checkMissingReturnTypeWhenCallNames`, `requireCallNames`, `promiseTypeNames`, `resultTypeNames` |
|
|
545
|
+
| `await-requires-result` | `allowFilePatterns` (globs), `trySafeCallNames` |
|
|
546
|
+
| `max-hook-size` | `maxLines`, `maxUseState` |
|
|
547
|
+
| `no-deep-relative-imports` | `maxDepth` |
|
|
548
|
+
| `no-default-export` | `allowFilePatterns` (globs, aditivos a los integrados) |
|
|
549
|
+
| `no-functions-inside-components` | `allowJsxCallbacks`, `allowArrayMapCallbacks` (ambas `true` por defecto) |
|
|
550
|
+
| `no-promise-chain` | `methods` |
|
|
551
|
+
|
|
552
|
+
Los `allowFilePatterns` de todas las reglas son **globs** (`*` un segmento,
|
|
553
|
+
`**` cualquier profundidad, `{a,b}` alternativas; un patrón sin prefijo
|
|
554
|
+
matchea en cualquier carpeta). Las 7 reglas restantes no tienen opciones: su
|
|
555
|
+
única configuración es activarlas, apagarlas o cambiar la severidad.
|
|
556
|
+
|
|
513
557
|
## Reglas
|
|
514
558
|
|
|
515
559
|
| Regla | Qué protege |
|
|
@@ -522,6 +566,7 @@ bloque con `linterOptions: { noInlineConfig: false }` para esos globs.
|
|
|
522
566
|
| `skapxd/max-hook-size` | Marca hooks grandes o con demasiados `useState`. |
|
|
523
567
|
| `skapxd/jsx-return-name-pascal-case` | Funciones que retornan JSX deben nombrarse como componentes. |
|
|
524
568
|
| `skapxd/no-deep-relative-imports` | Limita la profundidad de los imports relativos (`../`). |
|
|
569
|
+
| `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. |
|
|
525
570
|
| `skapxd/no-functions-inside-components` | Prohíbe definir funciones dentro de componentes React. |
|
|
526
571
|
| `skapxd/no-try-catch` | Prohíbe `try/catch`; usa `trySafe` de `@skapxd/result`. |
|
|
527
572
|
| `skapxd/no-promise-chain` | Prohíbe `.then/.catch/.finally`; usa `await` (+ `trySafe`). |
|
|
@@ -610,6 +655,20 @@ async function no(): Promise<Result<number, Error>> {} // se reporta
|
|
|
610
655
|
> Sin información de tipos cae a una comprobación por nombre (`resultTypeNames`),
|
|
611
656
|
> menos estricta.
|
|
612
657
|
|
|
658
|
+
Todas las opciones, con sus defaults:
|
|
659
|
+
|
|
660
|
+
```js
|
|
661
|
+
"skapxd/async-functions-return-result": ["error", {
|
|
662
|
+
allowFilePatterns: [], // globs de archivos exentos, p. ej. ["src/legacy/**"]
|
|
663
|
+
allowNamePatterns: [], // regex de nombres exentos, p. ej. ["^(GET|POST)$"]
|
|
664
|
+
checkMissingReturnType: true, // reportar también funciones SIN anotación de retorno
|
|
665
|
+
checkMissingReturnTypeWhenCallNames: [], // ...o solo si el cuerpo llama a estos nombres
|
|
666
|
+
requireCallNames: [], // acotar la regla a funciones que llamen a estos nombres
|
|
667
|
+
promiseTypeNames: ["Promise"], // wrappers de promesa aceptados (fallback sin tipos)
|
|
668
|
+
resultTypeNames: ["Result"], // nombres de Result aceptados (fallback sin tipos)
|
|
669
|
+
}]
|
|
670
|
+
```
|
|
671
|
+
|
|
613
672
|
### `skapxd/result-error-requires-cause`
|
|
614
673
|
|
|
615
674
|
Evita perder el error original al transformar un `Result` fallido:
|
|
@@ -698,6 +757,30 @@ Sirve para código de pegamento, pero deja el error sin modelar (`Result<T,
|
|
|
698
757
|
unknown>`). Cuando la misma operación se repite o el error importa, el mensaje
|
|
699
758
|
de la regla empuja hacia el camino 1.
|
|
700
759
|
|
|
760
|
+
### `skapxd/no-ad-hoc-ok-result`
|
|
761
|
+
|
|
762
|
+
Prohíbe que una función async **exportada** retorne objetos literales con la
|
|
763
|
+
forma `{ ok: ... }` armados a mano. Un contrato casero fragmenta el sistema:
|
|
764
|
+
cada módulo inventa su variante, la exención type-aware de
|
|
765
|
+
`await-requires-result` no lo reconoce, y `match()` pierde la exhaustividad.
|
|
766
|
+
|
|
767
|
+
```ts
|
|
768
|
+
export async function getUser(id: string) {
|
|
769
|
+
return { ok: false, message: "falló" }; // ❌ contrato inventado
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
export async function getUser(id: string): Promise<Result<User, UserError>> {
|
|
773
|
+
return Result.err({ // ✅ el Result real
|
|
774
|
+
cause: error,
|
|
775
|
+
message: "No pude cargar el usuario.",
|
|
776
|
+
type: "USER_FETCH_FAILED",
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
Solo mira funciones async exportadas: un helper interno con un objeto `ok`
|
|
782
|
+
cualquiera no es un contrato público y no se reporta.
|
|
783
|
+
|
|
701
784
|
### `skapxd/max-hook-size`
|
|
702
785
|
|
|
703
786
|
Marca hooks que crecen demasiado o acumulan muchos `useState`.
|
|
@@ -705,6 +788,35 @@ Marca hooks que crecen demasiado o acumulan muchos `useState`.
|
|
|
705
788
|
La intención es empujar el diseño hacia `useReducer`, hooks más pequeños o
|
|
706
789
|
módulos de transición de estado.
|
|
707
790
|
|
|
791
|
+
Opciones (los presets `frontend` y `next` usan `maxLines: 120`, `maxUseState: 1`):
|
|
792
|
+
|
|
793
|
+
```js
|
|
794
|
+
"skapxd/max-hook-size": ["error", {
|
|
795
|
+
maxLines: 120, // líneas máximas del cuerpo del hook
|
|
796
|
+
maxUseState: 1, // useState propios permitidos antes de exigir useReducer
|
|
797
|
+
}]
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
### `skapxd/jsx-return-name-pascal-case`
|
|
801
|
+
|
|
802
|
+
Si una función devuelve JSX, es un componente, y debe llamarse como tal:
|
|
803
|
+
PascalCase. El mensaje sugiere el rename concreto.
|
|
804
|
+
|
|
805
|
+
```tsx
|
|
806
|
+
function renderUserCard(user: User) { // ❌ "render*" devuelve JSX → es un componente
|
|
807
|
+
return <article>{user.name}</article>;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function UserCard({ user }: { user: User }) { // ✅ nombre de componente + props
|
|
811
|
+
return <article>{user.name}</article>;
|
|
812
|
+
}
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
Esta regla es la que mantiene honesto al resto del sistema React: las reglas
|
|
816
|
+
de componentes detectan "componente" por nombre PascalCase, así que una
|
|
817
|
+
función `renderX` que devuelve JSX escaparía de ellas. Esta la captura y
|
|
818
|
+
fuerza el rename — y con el nombre corregido, las demás ya la ven.
|
|
819
|
+
|
|
708
820
|
### `skapxd/no-deep-relative-imports`
|
|
709
821
|
|
|
710
822
|
Limita cuántos niveles puede subir un import relativo. Por defecto **prohíbe
|
|
@@ -730,20 +842,73 @@ Revisa imports estáticos (`import`), re-exports (`export ... from`) e imports
|
|
|
730
842
|
dinámicos (`import(...)`). El remedio habitual es un alias de ruta (`@/...`) o
|
|
731
843
|
acercar el módulo a quien lo usa.
|
|
732
844
|
|
|
845
|
+
### `skapxd/no-default-export`
|
|
846
|
+
|
|
847
|
+
Prohíbe `export default` (incluida la forma `export { x as default }`). Con
|
|
848
|
+
exports nombrados, el nombre del símbolo es el contrato del módulo: renombrar
|
|
849
|
+
con el IDE actualiza todos los usos, `grep` encuentra definición y consumo, y
|
|
850
|
+
los autoimports no inventan nombres distintos por archivo.
|
|
851
|
+
|
|
852
|
+
```ts
|
|
853
|
+
export default function getUser() {} // ❌ cada import puede llamarlo distinto
|
|
854
|
+
export function getUser() {} // ✅ un solo nombre canónico
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
**Dónde sí se permite el default.** Hay entrypoints donde el ecosistema lo
|
|
858
|
+
exige, y la regla los reconoce en capas:
|
|
859
|
+
|
|
860
|
+
1. **Integrados (siempre activos):** configs de tooling (`*.config.{js,mjs,cjs,ts}`:
|
|
861
|
+
`next.config`, `tailwind.config`, `vitest.config`, `eslint.config`, ...) y
|
|
862
|
+
stories de Storybook (`*.stories.*`).
|
|
863
|
+
2. **Preset `next` (automático):** los entrypoints del App Router donde Next
|
|
864
|
+
exige el default — `page`, `layout`, `template`, `error`, `loading`,
|
|
865
|
+
`not-found`, `sitemap`, `robots`, `manifest`, `icon`, `opengraph-image`,
|
|
866
|
+
etc. No hay que configurar nada.
|
|
867
|
+
3. **`allowFilePatterns` (extensible):** si usas un framework o tool que la
|
|
868
|
+
regla aún no contempla, agrega su glob. Los patrones propios se **suman**
|
|
869
|
+
a los integrados, no los reemplazan. Son globs legibles (`*` un segmento,
|
|
870
|
+
`**` cualquier profundidad, `{a,b}` alternativas) y un patrón sin prefijo
|
|
871
|
+
matchea en cualquier carpeta:
|
|
872
|
+
|
|
873
|
+
```js
|
|
874
|
+
"skapxd/no-default-export": ["error", {
|
|
875
|
+
// p. ej. SvelteKit exige default en +page.ts / +layout.ts
|
|
876
|
+
allowFilePatterns: ["+page.ts", "+layout.ts"],
|
|
877
|
+
}]
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
Detalle útil con `React.lazy` (que espera `{ default }`): no hace falta volver
|
|
881
|
+
al default export, basta mapear el named en el import dinámico:
|
|
882
|
+
|
|
883
|
+
```ts
|
|
884
|
+
const Card = lazy(() => import("./card").then((m) => ({ default: m.Card })));
|
|
885
|
+
```
|
|
886
|
+
|
|
733
887
|
### `skapxd/no-functions-inside-components`
|
|
734
888
|
|
|
735
|
-
Prohíbe **
|
|
736
|
-
con nombre PascalCase)
|
|
737
|
-
re-renders
|
|
889
|
+
Prohíbe definir funciones **con peso propio** dentro de un componente React
|
|
890
|
+
(una función con nombre PascalCase): handlers con nombre, helpers, callbacks de
|
|
891
|
+
`useEffect`. Cada render las recrea, dispara re-renders en hijos memoizados y
|
|
892
|
+
mezcla lógica con composición.
|
|
738
893
|
|
|
739
894
|
```tsx
|
|
740
895
|
function Card() {
|
|
741
|
-
const onClick = () => save(); // ❌
|
|
896
|
+
const onClick = () => save(); // ❌ handler con nombre en el cuerpo
|
|
742
897
|
useEffect(() => subscribe(), []); // ❌ callback dentro del componente
|
|
743
|
-
return
|
|
898
|
+
return (
|
|
899
|
+
<ul>
|
|
900
|
+
{items.map((i) => <Li key={i} />)} {/* ✅ React idiomático */}
|
|
901
|
+
<button onClick={() => save()}>Guardar</button> {/* ✅ React idiomático */}
|
|
902
|
+
</ul>
|
|
903
|
+
);
|
|
744
904
|
}
|
|
745
905
|
```
|
|
746
906
|
|
|
907
|
+
Los dos patrones idiomáticos de React están **permitidos por defecto**: el
|
|
908
|
+
callback anónimo como valor directo de una prop JSX y el callback anónimo de
|
|
909
|
+
`.map(...)` en el render. Forzarlos a salir del componente produce workarounds
|
|
910
|
+
peores que el problema (`.bind(null, ...)`, adapters artificiales).
|
|
911
|
+
|
|
747
912
|
El cuerpo del componente queda como composición declarativa; **toda** función
|
|
748
913
|
—handlers, efectos, memos, mapeos— vive fuera:
|
|
749
914
|
|
|
@@ -764,6 +929,28 @@ function Card() {
|
|
|
764
929
|
helper en minúscula **sí** pueden tener funciones dentro — ahí es donde se mueve
|
|
765
930
|
la lógica.
|
|
766
931
|
|
|
932
|
+
**Opciones.** Las exenciones aplican solo a **flechas de expresión** (sin
|
|
933
|
+
cuerpo `{ }`) en esa posición exacta: el valor directo de una prop JSX, o el
|
|
934
|
+
primer argumento de `.map(...)`. La distinción importa: una flecha de expresión
|
|
935
|
+
solo puede contener una expresión — es declarativa por construcción —, mientras
|
|
936
|
+
que un bloque da pie a `if`s, variables y llamadas que pertenecen fuera:
|
|
937
|
+
|
|
938
|
+
```tsx
|
|
939
|
+
{items.map((i) => <li key={i} />)} // ✅ flecha de expresión
|
|
940
|
+
{items.map((i) => { return <li key={i} />; })} // ❌ bloque: invita a meter lógica
|
|
941
|
+
```
|
|
942
|
+
|
|
943
|
+
Un handler con nombre en el cuerpo (`const onClick = () => ...`), un callback
|
|
944
|
+
de `useEffect` o un `.forEach` siguen reportándose. Para el modo ultraestricto
|
|
945
|
+
(ninguna función inline, como en v0.6.0 y anteriores), apágalas explícitamente:
|
|
946
|
+
|
|
947
|
+
```js
|
|
948
|
+
"skapxd/no-functions-inside-components": ["error", {
|
|
949
|
+
allowJsxCallbacks: false, // también reporta onClick={() => ...}
|
|
950
|
+
allowArrayMapCallbacks: false, // también reporta items.map((i) => ...)
|
|
951
|
+
}]
|
|
952
|
+
```
|
|
953
|
+
|
|
767
954
|
### `skapxd/no-try-catch`
|
|
768
955
|
|
|
769
956
|
Prohíbe `try/catch`. La intención es que los errores se modelen como `Result` en
|
package/dist/astro/index.d.mts
CHANGED
|
@@ -12,6 +12,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
12
12
|
rules: {
|
|
13
13
|
"skapxd/no-ad-hoc-ok-result": string;
|
|
14
14
|
"skapxd/no-deep-relative-imports": string;
|
|
15
|
+
"skapxd/no-default-export": string;
|
|
15
16
|
"skapxd/no-promise-chain": string;
|
|
16
17
|
"skapxd/no-try-catch": string;
|
|
17
18
|
"skapxd/one-root-function-per-file": string;
|
|
@@ -27,6 +28,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
27
28
|
rules: {
|
|
28
29
|
"skapxd/no-ad-hoc-ok-result": string;
|
|
29
30
|
"skapxd/no-deep-relative-imports": string;
|
|
31
|
+
"skapxd/no-default-export": string;
|
|
30
32
|
"skapxd/no-promise-chain": string;
|
|
31
33
|
"skapxd/no-try-catch": string;
|
|
32
34
|
"skapxd/one-root-function-per-file": string;
|
package/dist/astro/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
12
12
|
rules: {
|
|
13
13
|
"skapxd/no-ad-hoc-ok-result": string;
|
|
14
14
|
"skapxd/no-deep-relative-imports": string;
|
|
15
|
+
"skapxd/no-default-export": string;
|
|
15
16
|
"skapxd/no-promise-chain": string;
|
|
16
17
|
"skapxd/no-try-catch": string;
|
|
17
18
|
"skapxd/one-root-function-per-file": string;
|
|
@@ -27,6 +28,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
27
28
|
rules: {
|
|
28
29
|
"skapxd/no-ad-hoc-ok-result": string;
|
|
29
30
|
"skapxd/no-deep-relative-imports": string;
|
|
31
|
+
"skapxd/no-default-export": string;
|
|
30
32
|
"skapxd/no-promise-chain": string;
|
|
31
33
|
"skapxd/no-try-catch": string;
|
|
32
34
|
"skapxd/one-root-function-per-file": string;
|
package/dist/astro/index.js
CHANGED
|
@@ -38,6 +38,7 @@ module.exports = __toCommonJS(astro_exports);
|
|
|
38
38
|
var baseRules = {
|
|
39
39
|
"skapxd/no-ad-hoc-ok-result": "error",
|
|
40
40
|
"skapxd/no-deep-relative-imports": "error",
|
|
41
|
+
"skapxd/no-default-export": "error",
|
|
41
42
|
"skapxd/no-promise-chain": "error",
|
|
42
43
|
"skapxd/no-try-catch": "error",
|
|
43
44
|
"skapxd/one-root-function-per-file": "error",
|
package/dist/astro/index.js.map
CHANGED
|
@@ -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/no-ad-hoc-ok-result\": \"error\",\n \"skapxd/no-deep-relative-imports\": \"error\",\n \"skapxd/no-promise-chain\": \"error\",\n \"skapxd/no-try-catch\": \"error\",\n \"skapxd/one-root-function-per-file\": \"error\",\n \"skapxd/prefer-ts-pattern\": \"error\",\n \"skapxd/result-error-requires-cause\": \"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 },\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAY;AAAA,EACvB,8BAA8B;AAAA,EAC9B,mCAAmC;AAAA,EACnC,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,4BAA4B;AAAA,EAC5B,sCAAsC;AACxC;;;
|
|
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/no-ad-hoc-ok-result\": \"error\",\n \"skapxd/no-deep-relative-imports\": \"error\",\n \"skapxd/no-default-export\": \"error\",\n \"skapxd/no-promise-chain\": \"error\",\n \"skapxd/no-try-catch\": \"error\",\n \"skapxd/one-root-function-per-file\": \"error\",\n \"skapxd/prefer-ts-pattern\": \"error\",\n \"skapxd/result-error-requires-cause\": \"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 },\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAY;AAAA,EACvB,8BAA8B;AAAA,EAC9B,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,4BAA4B;AAAA,EAC5B,sCAAsC;AACxC;;;ACTA,+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,MACxC;AAAA,IACF;AAAA,EACF;AACF;","names":["tseslint","import_typescript_eslint","tseslint"]}
|
package/dist/astro/index.mjs
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
nextAppMetadataFileStems,
|
|
3
|
+
nextAppRouteSegmentFileStems
|
|
4
|
+
} from "./chunk-HB755SJQ.mjs";
|
|
1
5
|
import {
|
|
2
6
|
baseRules,
|
|
3
7
|
createBaseLanguageOptions,
|
|
4
8
|
createTypedLanguageOptions
|
|
5
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LDAR6XT6.mjs";
|
|
6
10
|
|
|
7
11
|
// src/next/configs.ts
|
|
12
|
+
var nextDefaultExportFileGlob = `{${[
|
|
13
|
+
...nextAppRouteSegmentFileStems,
|
|
14
|
+
...nextAppMetadataFileStems
|
|
15
|
+
].join(",")}}.{js,jsx,ts,tsx}`;
|
|
8
16
|
function createNextConfigs(pluginReference) {
|
|
9
17
|
const baseLanguageOptions = createBaseLanguageOptions();
|
|
10
18
|
const typedLanguageOptions = createTypedLanguageOptions();
|
|
@@ -13,7 +21,15 @@ function createNextConfigs(pluginReference) {
|
|
|
13
21
|
languageOptions: baseLanguageOptions,
|
|
14
22
|
name: "skapxd/next/base",
|
|
15
23
|
plugins: { skapxd: pluginReference },
|
|
16
|
-
rules:
|
|
24
|
+
rules: {
|
|
25
|
+
...baseRules,
|
|
26
|
+
"skapxd/no-default-export": [
|
|
27
|
+
"error",
|
|
28
|
+
{
|
|
29
|
+
allowFilePatterns: [nextDefaultExportFileGlob]
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
17
33
|
},
|
|
18
34
|
{
|
|
19
35
|
files: ["src/app/api/**/*.{ts,tsx}", "src/server/**/*.{ts,tsx}"],
|
|
@@ -53,4 +69,4 @@ function createNextConfigs(pluginReference) {
|
|
|
53
69
|
export {
|
|
54
70
|
createNextConfigs
|
|
55
71
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
72
|
+
//# sourceMappingURL=chunk-72XIHMY7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/next/configs.ts"],"sourcesContent":["import { nextAppMetadataFileStems } from \"#/constants/next-app-metadata-file-stems\";\nimport { nextAppRouteSegmentFileStems } from \"#/constants/next-app-route-segment-file-stems\";\nimport {\n baseRules,\n createBaseLanguageOptions,\n createTypedLanguageOptions,\n} from \"#/shared/configs\";\n\n// Entrypoints donde Next exige `export default` (page, layout, sitemap, ...):\n// la regla no-default-export los exime automáticamente en este preset.\nconst nextDefaultExportFileGlob = `{${[\n ...nextAppRouteSegmentFileStems,\n ...nextAppMetadataFileStems,\n].join(\",\")}}.{js,jsx,ts,tsx}`;\n\nexport function createNextConfigs(pluginReference: unknown) {\n const baseLanguageOptions = createBaseLanguageOptions();\n const typedLanguageOptions = createTypedLanguageOptions();\n\n return [\n {\n languageOptions: baseLanguageOptions,\n name: \"skapxd/next/base\",\n plugins: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n \"skapxd/no-default-export\": [\n \"error\",\n {\n allowFilePatterns: [nextDefaultExportFileGlob],\n },\n ],\n },\n },\n {\n files: [\"src/app/api/**/*.{ts,tsx}\", \"src/server/**/*.{ts,tsx}\"],\n languageOptions: typedLanguageOptions,\n name: \"skapxd/next/server\",\n plugins: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n // Obligatoria: todo await resuelve en Result. A diferencia de\n // async-functions-return-result (apagada por defecto), no necesita\n // excepciones para los entrypoints de Next: envolver un await en\n // trySafe es compatible con cualquier firma que imponga el framework.\n \"skapxd/await-requires-result\": \"error\",\n },\n },\n {\n files: [\"**/*.tsx\"],\n languageOptions: baseLanguageOptions,\n name: \"skapxd/next/react\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/jsx-return-name-pascal-case\": \"error\",\n \"skapxd/no-functions-inside-components\": \"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 ];\n}\n"],"mappings":";;;;;;;;;;;AAUA,IAAM,4BAA4B,IAAI;AAAA,EACpC,GAAG;AAAA,EACH,GAAG;AACL,EAAE,KAAK,GAAG,CAAC;AAEJ,SAAS,kBAAkB,iBAA0B;AAC1D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL;AAAA,MACE,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,GAAG;AAAA,QACH,4BAA4B;AAAA,UAC1B;AAAA,UACA;AAAA,YACE,mBAAmB,CAAC,yBAAyB;AAAA,UAC/C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,OAAO,CAAC,6BAA6B,0BAA0B;AAAA,MAC/D,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA,QAKH,gCAAgC;AAAA,MAClC;AAAA,IACF;AAAA,IACA;AAAA,MACE,OAAO,CAAC,UAAU;AAAA,MAClB,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,sCAAsC;AAAA,QACtC,yCAAyC;AAAA,QACzC,8BAA8B;AAAA,QAC9B,wBAAwB;AAAA,UACtB;AAAA,UACA;AAAA,YACE,UAAU;AAAA,YACV,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
nextAppMetadataFileStems,
|
|
3
|
+
nextAppRouteSegmentFileStems
|
|
4
|
+
} from "./chunk-HB755SJQ.mjs";
|
|
5
|
+
|
|
1
6
|
// src/utils/get-file-name.ts
|
|
2
7
|
function getFileName(filename) {
|
|
3
8
|
return filename.split(/[\\/]/).at(-1) ?? filename;
|
|
@@ -47,33 +52,6 @@ function isInsideAppDirectory(filename) {
|
|
|
47
52
|
return getPathParts(filename).includes("app");
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
// src/constants/next-app-metadata-file-stems.ts
|
|
51
|
-
var nextAppMetadataFileStems = [
|
|
52
|
-
"apple-icon",
|
|
53
|
-
"icon",
|
|
54
|
-
"manifest",
|
|
55
|
-
"opengraph-image",
|
|
56
|
-
"robots",
|
|
57
|
-
"sitemap",
|
|
58
|
-
"twitter-image"
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
// src/constants/next-app-route-segment-file-stems.ts
|
|
62
|
-
var nextAppRouteSegmentFileStems = [
|
|
63
|
-
"default",
|
|
64
|
-
"error",
|
|
65
|
-
"forbidden",
|
|
66
|
-
"global-error",
|
|
67
|
-
"global-not-found",
|
|
68
|
-
"layout",
|
|
69
|
-
"loading",
|
|
70
|
-
"not-found",
|
|
71
|
-
"page",
|
|
72
|
-
"route",
|
|
73
|
-
"template",
|
|
74
|
-
"unauthorized"
|
|
75
|
-
];
|
|
76
|
-
|
|
77
55
|
// src/constants/next-project-root-file-stems.ts
|
|
78
56
|
var nextProjectRootFileStems = [
|
|
79
57
|
"instrumentation",
|
|
@@ -580,6 +558,16 @@ function isSkapxdResultOrPromiseResultType(type, typeContext) {
|
|
|
580
558
|
return Boolean(promisedType && isSkapxdResultType(promisedType, typeContext));
|
|
581
559
|
}
|
|
582
560
|
|
|
561
|
+
// src/utils/matches-any-glob.ts
|
|
562
|
+
import picomatch from "picomatch";
|
|
563
|
+
function matchesAnyGlob(filePath, globs) {
|
|
564
|
+
const normalized = filePath.replaceAll("\\", "/");
|
|
565
|
+
return globs.some((glob) => {
|
|
566
|
+
const anchored = glob.startsWith("/") || glob.startsWith("**") ? glob : `**/${glob}`;
|
|
567
|
+
return picomatch(anchored)(normalized);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
583
571
|
// src/utils/matches-any-pattern.ts
|
|
584
572
|
function matchesAnyPattern(value, patterns) {
|
|
585
573
|
return patterns.some((pattern) => new RegExp(pattern).test(value));
|
|
@@ -642,7 +630,7 @@ var asyncFunctionsReturnResult = {
|
|
|
642
630
|
return isPromiseOfResultType(annotation, options);
|
|
643
631
|
}
|
|
644
632
|
function reportIfInvalidAsyncReturn(node, name, reportNode = node) {
|
|
645
|
-
if (!node.async ||
|
|
633
|
+
if (!node.async || matchesAnyGlob(filename, options.allowFilePatterns)) {
|
|
646
634
|
return;
|
|
647
635
|
}
|
|
648
636
|
const functionName = name ?? "anonymous";
|
|
@@ -939,7 +927,7 @@ var awaitRequiresResult = {
|
|
|
939
927
|
}
|
|
940
928
|
return {
|
|
941
929
|
AwaitExpression(node) {
|
|
942
|
-
if (
|
|
930
|
+
if (matchesAnyGlob(filename, options.allowFilePatterns)) {
|
|
943
931
|
return;
|
|
944
932
|
}
|
|
945
933
|
if (typeContext && isSkapxdResultOrPromiseResultExpression(node.argument, typeContext)) {
|
|
@@ -1337,6 +1325,96 @@ var noDeepRelativeImports = {
|
|
|
1337
1325
|
}
|
|
1338
1326
|
};
|
|
1339
1327
|
|
|
1328
|
+
// src/constants/default-export-allowed-file-patterns.ts
|
|
1329
|
+
var defaultExportAllowedFilePatterns = [
|
|
1330
|
+
"*.config.*",
|
|
1331
|
+
"*.stories.*"
|
|
1332
|
+
];
|
|
1333
|
+
|
|
1334
|
+
// src/utils/get-no-default-export-options.ts
|
|
1335
|
+
function getNoDefaultExportOptions(options = {}) {
|
|
1336
|
+
return {
|
|
1337
|
+
allowFilePatterns: [
|
|
1338
|
+
...defaultExportAllowedFilePatterns,
|
|
1339
|
+
...options.allowFilePatterns ?? []
|
|
1340
|
+
]
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// src/rules/no-default-export.ts
|
|
1345
|
+
var noDefaultExport = {
|
|
1346
|
+
meta: {
|
|
1347
|
+
type: "suggestion",
|
|
1348
|
+
docs: {
|
|
1349
|
+
description: "Prohibe export default; un export nombrado hace del nombre el contrato del modulo."
|
|
1350
|
+
},
|
|
1351
|
+
messages: {
|
|
1352
|
+
noDefaultExport: 'No uses `export default`: un export nombrado hace el simbolo renombrable con el IDE, grepeable y estable en autoimports. Si este archivo es un entrypoint donde un framework o tool exige el default, agrega su glob en `allowFilePatterns` de skapxd/no-default-export (p. ej. "+page.ts").'
|
|
1353
|
+
},
|
|
1354
|
+
schema: [
|
|
1355
|
+
{
|
|
1356
|
+
additionalProperties: false,
|
|
1357
|
+
properties: {
|
|
1358
|
+
allowFilePatterns: {
|
|
1359
|
+
items: { type: "string" },
|
|
1360
|
+
type: "array"
|
|
1361
|
+
}
|
|
1362
|
+
},
|
|
1363
|
+
type: "object"
|
|
1364
|
+
}
|
|
1365
|
+
]
|
|
1366
|
+
},
|
|
1367
|
+
create(context) {
|
|
1368
|
+
const options = getNoDefaultExportOptions(context.options[0]);
|
|
1369
|
+
const filename = context.filename ?? context.getFilename();
|
|
1370
|
+
if (matchesAnyGlob(filename, options.allowFilePatterns)) {
|
|
1371
|
+
return {};
|
|
1372
|
+
}
|
|
1373
|
+
return {
|
|
1374
|
+
ExportDefaultDeclaration(node) {
|
|
1375
|
+
context.report({ messageId: "noDefaultExport", node });
|
|
1376
|
+
},
|
|
1377
|
+
// Cubre la forma indirecta: `export { algo as default }`.
|
|
1378
|
+
ExportNamedDeclaration(node) {
|
|
1379
|
+
for (const specifier of node.specifiers ?? []) {
|
|
1380
|
+
const exportedName = specifier.exported?.name ?? specifier.exported?.value;
|
|
1381
|
+
if (exportedName === "default") {
|
|
1382
|
+
context.report({ messageId: "noDefaultExport", node: specifier });
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
|
|
1390
|
+
// src/utils/get-no-functions-inside-components-options.ts
|
|
1391
|
+
function getNoFunctionsInsideComponentsOptions(options = {}) {
|
|
1392
|
+
return {
|
|
1393
|
+
allowArrayMapCallbacks: options.allowArrayMapCallbacks ?? true,
|
|
1394
|
+
allowJsxCallbacks: options.allowJsxCallbacks ?? true
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
// src/utils/is-array-map-callback.ts
|
|
1399
|
+
function isArrayMapCallback(node) {
|
|
1400
|
+
const parent = node.parent;
|
|
1401
|
+
if (parent?.type !== "CallExpression" || parent.arguments[0] !== node) {
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
const callee = parent.callee;
|
|
1405
|
+
return callee?.type === "MemberExpression" && !callee.computed && callee.property?.type === "Identifier" && callee.property.name === "map";
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
// src/utils/is-expression-arrow-function.ts
|
|
1409
|
+
function isExpressionArrowFunction(node) {
|
|
1410
|
+
return node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement";
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
// src/utils/is-jsx-attribute-callback.ts
|
|
1414
|
+
function isJsxAttributeCallback(node) {
|
|
1415
|
+
return node.parent?.type === "JSXExpressionContainer" && node.parent.parent?.type === "JSXAttribute";
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1340
1418
|
// src/rules/no-functions-inside-components.ts
|
|
1341
1419
|
var noFunctionsInsideComponents = {
|
|
1342
1420
|
meta: {
|
|
@@ -1345,19 +1423,41 @@ var noFunctionsInsideComponents = {
|
|
|
1345
1423
|
description: "Prohibe definir funciones dentro de componentes React; se recrean en cada render."
|
|
1346
1424
|
},
|
|
1347
1425
|
messages: {
|
|
1348
|
-
functionInsideComponent: "No definas funciones dentro del componente `{{component}}`: se recrean en cada render. Muevela a un hook (`useX`) o a un helper fuera del componente."
|
|
1426
|
+
functionInsideComponent: "No definas funciones dentro del componente `{{component}}`: se recrean en cada render. Muevela a un hook (`useX`) o a un helper fuera del componente. Los callbacks inline de JSX y .map solo se permiten como flecha de expresion (sin cuerpo `{ }`): un bloque ya da pie a ifs y logica que pertenece fuera."
|
|
1349
1427
|
},
|
|
1350
|
-
schema: [
|
|
1428
|
+
schema: [
|
|
1429
|
+
{
|
|
1430
|
+
additionalProperties: false,
|
|
1431
|
+
properties: {
|
|
1432
|
+
allowArrayMapCallbacks: { type: "boolean" },
|
|
1433
|
+
allowJsxCallbacks: { type: "boolean" }
|
|
1434
|
+
},
|
|
1435
|
+
type: "object"
|
|
1436
|
+
}
|
|
1437
|
+
]
|
|
1351
1438
|
},
|
|
1352
1439
|
create(context) {
|
|
1440
|
+
const options = getNoFunctionsInsideComponentsOptions(context.options[0]);
|
|
1353
1441
|
function isComponentFunction(node) {
|
|
1354
1442
|
return isFunctionNode(node) && isPascalCaseName(getFunctionName(node));
|
|
1355
1443
|
}
|
|
1444
|
+
function isAllowedInlineCallback(node) {
|
|
1445
|
+
if (!isExpressionArrowFunction(node)) {
|
|
1446
|
+
return false;
|
|
1447
|
+
}
|
|
1448
|
+
if (options.allowJsxCallbacks && isJsxAttributeCallback(node)) {
|
|
1449
|
+
return true;
|
|
1450
|
+
}
|
|
1451
|
+
return options.allowArrayMapCallbacks && isArrayMapCallback(node);
|
|
1452
|
+
}
|
|
1356
1453
|
function reportIfInsideComponent(node) {
|
|
1357
1454
|
const enclosingFunction = getContainingFunction(node);
|
|
1358
1455
|
if (!enclosingFunction || !isComponentFunction(enclosingFunction)) {
|
|
1359
1456
|
return;
|
|
1360
1457
|
}
|
|
1458
|
+
if (isAllowedInlineCallback(node)) {
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1361
1461
|
context.report({
|
|
1362
1462
|
data: {
|
|
1363
1463
|
component: getFunctionName(enclosingFunction)
|
|
@@ -1546,6 +1646,7 @@ var rules = {
|
|
|
1546
1646
|
"result-error-requires-cause": resultErrorRequiresCause,
|
|
1547
1647
|
"max-hook-size": maxHookSize,
|
|
1548
1648
|
"no-deep-relative-imports": noDeepRelativeImports,
|
|
1649
|
+
"no-default-export": noDefaultExport,
|
|
1549
1650
|
"no-functions-inside-components": noFunctionsInsideComponents,
|
|
1550
1651
|
"no-try-catch": noTryCatch,
|
|
1551
1652
|
"prefer-ts-pattern": preferTsPattern,
|
|
@@ -1556,4 +1657,4 @@ var rules = {
|
|
|
1556
1657
|
export {
|
|
1557
1658
|
rules
|
|
1558
1659
|
};
|
|
1559
|
-
//# sourceMappingURL=chunk-
|
|
1660
|
+
//# sourceMappingURL=chunk-G6TJUBFT.mjs.map
|