@skapxd/eslint-opinionated 0.11.0 → 0.12.1
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 +57 -0
- package/dist/astro/index.d.mts +3 -0
- package/dist/astro/index.d.ts +3 -0
- package/dist/astro/index.js +4 -2
- package/dist/astro/index.js.map +1 -1
- package/dist/astro/index.mjs +2 -2
- package/dist/{chunk-Z2MYYOIS.mjs → chunk-DJXM5PMG.mjs} +2 -2
- package/dist/{chunk-3NM7FEIN.mjs → chunk-JA2ZO3KQ.mjs} +4 -3
- package/dist/{chunk-3NM7FEIN.mjs.map → chunk-JA2ZO3KQ.mjs.map} +1 -1
- package/dist/{chunk-J472YWOD.mjs → chunk-QADXO5IL.mjs} +3 -2
- package/dist/chunk-QADXO5IL.mjs.map +1 -0
- package/dist/{chunk-EXMF54EM.mjs → chunk-WZERKXPJ.mjs} +131 -12
- package/dist/chunk-WZERKXPJ.mjs.map +1 -0
- package/dist/index.js +135 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/dist/next/index.d.mts +2 -0
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +2 -1
- package/dist/next/index.js.map +1 -1
- package/dist/next/index.mjs +2 -2
- package/dist/shared/index.d.mts +3 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +132 -12
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-EXMF54EM.mjs.map +0 -1
- package/dist/chunk-J472YWOD.mjs.map +0 -1
- /package/dist/{chunk-Z2MYYOIS.mjs.map → chunk-DJXM5PMG.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -552,6 +552,7 @@ de cada regla):
|
|
|
552
552
|
| `no-promise-chain` | `methods` |
|
|
553
553
|
| `no-tunnel-props` | `allowFilePatterns` (globs), `allowPropPatterns` (regex) |
|
|
554
554
|
| `prefer-abort-signal` | `allowFilePatterns` (globs), `effectNames` (default `["useEffect", "useLayoutEffect"]`) |
|
|
555
|
+
| `result-error-requires-handling` | `allowFilePatterns` (globs) |
|
|
555
556
|
|
|
556
557
|
Los `allowFilePatterns` de todas las reglas son **globs** (`*` un segmento,
|
|
557
558
|
`**` cualquier profundidad, `{a,b}` alternativas; un patrón sin prefijo
|
|
@@ -565,6 +566,7 @@ matchea en cualquier carpeta). Las 7 reglas restantes no tienen opciones: su
|
|
|
565
566
|
| `skapxd/one-root-function-per-file` | Un archivo, una función top-level semántica. |
|
|
566
567
|
| `skapxd/async-functions-return-result` | Funciones async de dominio deben retornar `Promise<Result<...>>`. **Apagada por defecto; opt-in** (ver motivos en su sección). |
|
|
567
568
|
| `skapxd/result-error-requires-cause` | Un `Result.err` derivado debe preservar `cause: result.error`. |
|
|
569
|
+
| `skapxd/result-error-requires-handling` | Prohíbe descartar en silencio un Result fallido: el error se transforma o se entrega, nunca se ignora. |
|
|
568
570
|
| `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.** |
|
|
569
571
|
| `skapxd/no-ad-hoc-ok-result` | Evita contratos `{ ok: ... }` hechos a mano en async exports. |
|
|
570
572
|
| `skapxd/max-hook-size` | Marca hooks grandes o con demasiados `useState`. |
|
|
@@ -705,6 +707,61 @@ aliases, re-exports y tipos inferidos, sin depender solo del nombre importado en
|
|
|
705
707
|
el archivo. Su punto ciego histórico —el `Result.err` escondido en un `if`
|
|
706
708
|
anidado— lo elimina `skapxd/no-nested-if` de raíz.
|
|
707
709
|
|
|
710
|
+
### `skapxd/result-error-requires-handling`
|
|
711
|
+
|
|
712
|
+
La hermana de la anterior cierra la última puerta de evasión: el **descarte
|
|
713
|
+
silencioso**. Detectar el fallo y botarlo sin tocarlo es legal para
|
|
714
|
+
`result-error-requires-cause` (no hay transformación que vigilar), pero deja
|
|
715
|
+
morir información valiosa sin que nadie lo decidiera conscientemente:
|
|
716
|
+
|
|
717
|
+
```ts
|
|
718
|
+
const result = await copyTextToClipboard(text);
|
|
719
|
+
if (!result.ok) return; // ❌ el error muere aquí, en silencio
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
El contrato: dentro de un guard de Result fallido, `result.error` (o el
|
|
723
|
+
result completo) debe **fluir a alguna parte**. Dos salidas:
|
|
724
|
+
|
|
725
|
+
```ts
|
|
726
|
+
// 1. Transformarlo (y result-error-requires-cause vigila el cause)
|
|
727
|
+
if (!result.ok) {
|
|
728
|
+
return Result.err({ cause: result.error, message: "...", type: "COPY_FAILED" });
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// 2. Entregárselo a alguien: telemetría, estado de error, log de dominio
|
|
732
|
+
if (!result.ok) {
|
|
733
|
+
trackClipboardFailure(result.error);
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// (propagar el result completo también vale: `if (!result.ok) return result;`)
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
**No hay tercera salida.** `void result.error` no cuenta como manejo, y
|
|
741
|
+
manejar sin tocar el error (`setFailed(true)`) tampoco — el detalle se perdió
|
|
742
|
+
igual. Esto es deliberado: si darle seguimiento a un error es crítico o no,
|
|
743
|
+
no puede depender de la interpretación de quien escribe; el camino por
|
|
744
|
+
defecto nunca es ignorarlo.
|
|
745
|
+
|
|
746
|
+
**El alias tampoco es escape.** Asignar no es consumir: la regla sigue los
|
|
747
|
+
alias (y los encadenados, y el destructuring) hasta verificar que alguno se
|
|
748
|
+
consume de verdad:
|
|
749
|
+
|
|
750
|
+
```ts
|
|
751
|
+
if (!result.ok) {
|
|
752
|
+
const e = result.error; // ❌ transferencia sin destino: se reporta
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
if (!result.ok) {
|
|
757
|
+
const cause = result.error;
|
|
758
|
+
return Result.err({ cause, message: "..." }); // ✅ el alias se consumió
|
|
759
|
+
}
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
Type-aware como su hermana: solo aplica a Results reales de `@skapxd/result`,
|
|
763
|
+
con las mismas cinco formas de guard.
|
|
764
|
+
|
|
708
765
|
### `skapxd/await-requires-result`
|
|
709
766
|
|
|
710
767
|
> **Es la regla obligatoria del sistema de errores**: la activan todos los
|
package/dist/astro/index.d.mts
CHANGED
|
@@ -20,6 +20,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
20
20
|
"skapxd/one-root-function-per-file": string;
|
|
21
21
|
"skapxd/prefer-ts-pattern": string;
|
|
22
22
|
"skapxd/result-error-requires-cause": string;
|
|
23
|
+
"skapxd/result-error-requires-handling": string;
|
|
23
24
|
};
|
|
24
25
|
} | {
|
|
25
26
|
files: string[];
|
|
@@ -38,6 +39,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
38
39
|
"skapxd/one-root-function-per-file": string;
|
|
39
40
|
"skapxd/prefer-ts-pattern": string;
|
|
40
41
|
"skapxd/result-error-requires-cause": string;
|
|
42
|
+
"skapxd/result-error-requires-handling": string;
|
|
41
43
|
};
|
|
42
44
|
languageOptions?: undefined;
|
|
43
45
|
} | {
|
|
@@ -55,6 +57,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
55
57
|
rules: {
|
|
56
58
|
"skapxd/await-requires-result": string;
|
|
57
59
|
"skapxd/result-error-requires-cause": string;
|
|
60
|
+
"skapxd/result-error-requires-handling": string;
|
|
58
61
|
};
|
|
59
62
|
})[];
|
|
60
63
|
|
package/dist/astro/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
20
20
|
"skapxd/one-root-function-per-file": string;
|
|
21
21
|
"skapxd/prefer-ts-pattern": string;
|
|
22
22
|
"skapxd/result-error-requires-cause": string;
|
|
23
|
+
"skapxd/result-error-requires-handling": string;
|
|
23
24
|
};
|
|
24
25
|
} | {
|
|
25
26
|
files: string[];
|
|
@@ -38,6 +39,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
38
39
|
"skapxd/one-root-function-per-file": string;
|
|
39
40
|
"skapxd/prefer-ts-pattern": string;
|
|
40
41
|
"skapxd/result-error-requires-cause": string;
|
|
42
|
+
"skapxd/result-error-requires-handling": string;
|
|
41
43
|
};
|
|
42
44
|
languageOptions?: undefined;
|
|
43
45
|
} | {
|
|
@@ -55,6 +57,7 @@ declare function createAstroConfigs(pluginReference: unknown): ({
|
|
|
55
57
|
rules: {
|
|
56
58
|
"skapxd/await-requires-result": string;
|
|
57
59
|
"skapxd/result-error-requires-cause": string;
|
|
60
|
+
"skapxd/result-error-requires-handling": string;
|
|
58
61
|
};
|
|
59
62
|
})[];
|
|
60
63
|
|
package/dist/astro/index.js
CHANGED
|
@@ -45,7 +45,8 @@ var baseRules = {
|
|
|
45
45
|
"skapxd/no-try-catch": "error",
|
|
46
46
|
"skapxd/one-root-function-per-file": "error",
|
|
47
47
|
"skapxd/prefer-ts-pattern": "error",
|
|
48
|
-
"skapxd/result-error-requires-cause": "error"
|
|
48
|
+
"skapxd/result-error-requires-cause": "error",
|
|
49
|
+
"skapxd/result-error-requires-handling": "error"
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
// src/shared/configs/create-base-language-options.ts
|
|
@@ -96,7 +97,8 @@ function createAstroConfigs(pluginReference) {
|
|
|
96
97
|
plugins: { skapxd: pluginReference },
|
|
97
98
|
rules: {
|
|
98
99
|
"skapxd/await-requires-result": "error",
|
|
99
|
-
"skapxd/result-error-requires-cause": "error"
|
|
100
|
+
"skapxd/result-error-requires-cause": "error",
|
|
101
|
+
"skapxd/result-error-requires-handling": "error"
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
];
|
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-default-export\": \"error\",\n \"skapxd/no-emoji\": \"error\",\n \"skapxd/no-nested-if\": \"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,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,4BAA4B;AAAA,EAC5B,sCAAsC;
|
|
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-emoji\": \"error\",\n \"skapxd/no-nested-if\": \"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 \"skapxd/result-error-requires-handling\": \"error\",\n};\n","import tseslint from \"typescript-eslint\";\n\n// Variante sin type-checking: solo el parser, para presets que aplican a TS\n// pero no necesitan projectService (base, package, next/base, next/react).\nexport function createBaseLanguageOptions() {\n return {\n parser: tseslint.parser,\n };\n}\n","import tseslint from \"typescript-eslint\";\n\nexport function createTypedLanguageOptions() {\n return {\n // Sin el parser explícito, un consumidor que use solo estos presets\n // obtiene \"Parsing error\" en cada archivo TS (espree no parsea TS).\n parser: tseslint.parser,\n parserOptions: {\n projectService: true,\n },\n };\n}\n","import {\n baseRules,\n createBaseLanguageOptions,\n createTypedLanguageOptions,\n} from \"#/shared/configs\";\n\nexport function createAstroConfigs(pluginReference: unknown) {\n const baseLanguageOptions = createBaseLanguageOptions();\n const typedLanguageOptions = createTypedLanguageOptions();\n\n return [\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: baseLanguageOptions,\n name: \"skapxd/astro/base\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n // Los .astro no llevan parser propio: lo aporta eslint-plugin-astro,\n // que el consumidor debe tener configurado.\n {\n files: [\"src/**/*.astro\"],\n name: \"skapxd/astro/astro-files\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: typedLanguageOptions,\n name: \"skapxd/astro/typescript\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/await-requires-result\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n },\n },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,YAAY;AAAA,EACvB,8BAA8B;AAAA,EAC9B,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,4BAA4B;AAAA,EAC5B,sCAAsC;AAAA,EACtC,yCAAyC;AAC3C;;;ACZA,+BAAqB;AAId,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL,QAAQ,yBAAAA,QAAS;AAAA,EACnB;AACF;;;ACRA,IAAAC,4BAAqB;AAEd,SAAS,6BAA6B;AAC3C,SAAO;AAAA;AAAA;AAAA,IAGL,QAAQ,0BAAAC,QAAS;AAAA,IACjB,eAAe;AAAA,MACb,gBAAgB;AAAA,IAClB;AAAA,EACF;AACF;;;ACLO,SAAS,mBAAmB,iBAA0B;AAC3D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA;AAAA;AAAA,IAGA;AAAA,MACE,OAAO,CAAC,gBAAgB;AAAA,MACxB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,gCAAgC;AAAA,QAChC,sCAAsC;AAAA,QACtC,yCAAyC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;","names":["tseslint","import_typescript_eslint","tseslint"]}
|
package/dist/astro/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
baseRules,
|
|
7
7
|
createBaseLanguageOptions,
|
|
8
8
|
createTypedLanguageOptions
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QADXO5IL.mjs";
|
|
10
10
|
|
|
11
11
|
// src/next/configs.ts
|
|
12
12
|
var nextDefaultExportFileGlob = `{${[
|
|
@@ -71,4 +71,4 @@ function createNextConfigs(pluginReference) {
|
|
|
71
71
|
export {
|
|
72
72
|
createNextConfigs
|
|
73
73
|
};
|
|
74
|
-
//# sourceMappingURL=chunk-
|
|
74
|
+
//# sourceMappingURL=chunk-DJXM5PMG.mjs.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
baseRules,
|
|
3
3
|
createBaseLanguageOptions,
|
|
4
4
|
createTypedLanguageOptions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QADXO5IL.mjs";
|
|
6
6
|
|
|
7
7
|
// src/astro/configs.ts
|
|
8
8
|
function createAstroConfigs(pluginReference) {
|
|
@@ -31,7 +31,8 @@ function createAstroConfigs(pluginReference) {
|
|
|
31
31
|
plugins: { skapxd: pluginReference },
|
|
32
32
|
rules: {
|
|
33
33
|
"skapxd/await-requires-result": "error",
|
|
34
|
-
"skapxd/result-error-requires-cause": "error"
|
|
34
|
+
"skapxd/result-error-requires-cause": "error",
|
|
35
|
+
"skapxd/result-error-requires-handling": "error"
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
];
|
|
@@ -40,4 +41,4 @@ function createAstroConfigs(pluginReference) {
|
|
|
40
41
|
export {
|
|
41
42
|
createAstroConfigs
|
|
42
43
|
};
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-JA2ZO3KQ.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/astro/configs.ts"],"sourcesContent":["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":";;;;;;;AAMO,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,
|
|
1
|
+
{"version":3,"sources":["../src/astro/configs.ts"],"sourcesContent":["import {\n baseRules,\n createBaseLanguageOptions,\n createTypedLanguageOptions,\n} from \"#/shared/configs\";\n\nexport function createAstroConfigs(pluginReference: unknown) {\n const baseLanguageOptions = createBaseLanguageOptions();\n const typedLanguageOptions = createTypedLanguageOptions();\n\n return [\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: baseLanguageOptions,\n name: \"skapxd/astro/base\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n // Los .astro no llevan parser propio: lo aporta eslint-plugin-astro,\n // que el consumidor debe tener configurado.\n {\n files: [\"src/**/*.astro\"],\n name: \"skapxd/astro/astro-files\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n {\n files: [\"src/**/*.{ts,tsx}\"],\n languageOptions: typedLanguageOptions,\n name: \"skapxd/astro/typescript\",\n plugins: { skapxd: pluginReference },\n rules: {\n \"skapxd/await-requires-result\": \"error\",\n \"skapxd/result-error-requires-cause\": \"error\",\n \"skapxd/result-error-requires-handling\": \"error\",\n },\n },\n ];\n}\n"],"mappings":";;;;;;;AAMO,SAAS,mBAAmB,iBAA0B;AAC3D,QAAM,sBAAsB,0BAA0B;AACtD,QAAM,uBAAuB,2BAA2B;AAExD,SAAO;AAAA,IACL;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA;AAAA;AAAA,IAGA;AAAA,MACE,OAAO,CAAC,gBAAgB;AAAA,MACxB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,OAAO,CAAC,mBAAmB;AAAA,MAC3B,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,gCAAgC;AAAA,QAChC,sCAAsC;AAAA,QACtC,yCAAyC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -22,7 +22,8 @@ var baseRules = {
|
|
|
22
22
|
"skapxd/no-try-catch": "error",
|
|
23
23
|
"skapxd/one-root-function-per-file": "error",
|
|
24
24
|
"skapxd/prefer-ts-pattern": "error",
|
|
25
|
-
"skapxd/result-error-requires-cause": "error"
|
|
25
|
+
"skapxd/result-error-requires-cause": "error",
|
|
26
|
+
"skapxd/result-error-requires-handling": "error"
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
// src/shared/configs/create-base-language-options.ts
|
|
@@ -115,4 +116,4 @@ export {
|
|
|
115
116
|
createSharedConfigs,
|
|
116
117
|
strictConfig
|
|
117
118
|
};
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
119
|
+
//# sourceMappingURL=chunk-QADXO5IL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/configs/create-typed-language-options.ts","../src/shared/configs/base-rules.ts","../src/shared/configs/create-base-language-options.ts","../src/shared/configs/create-shared-configs.ts","../src/shared/configs/strict-config.ts"],"sourcesContent":["import tseslint from \"typescript-eslint\";\n\nexport function createTypedLanguageOptions() {\n return {\n // Sin el parser explícito, un consumidor que use solo estos presets\n // obtiene \"Parsing error\" en cada archivo TS (espree no parsea TS).\n parser: tseslint.parser,\n parserOptions: {\n projectService: true,\n },\n };\n}\n","export const baseRules = {\n \"skapxd/no-ad-hoc-ok-result\": \"error\",\n \"skapxd/no-deep-relative-imports\": \"error\",\n \"skapxd/no-default-export\": \"error\",\n \"skapxd/no-emoji\": \"error\",\n \"skapxd/no-nested-if\": \"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 \"skapxd/result-error-requires-handling\": \"error\",\n};\n","import tseslint from \"typescript-eslint\";\n\n// Variante sin type-checking: solo el parser, para presets que aplican a TS\n// pero no necesitan projectService (base, package, next/base, next/react).\nexport function createBaseLanguageOptions() {\n return {\n parser: tseslint.parser,\n };\n}\n","import { baseRules } from \"./base-rules\";\nimport { createBaseLanguageOptions } from \"./create-base-language-options\";\nimport { createTypedLanguageOptions } from \"./create-typed-language-options\";\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: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n // La regla obligatoria del sistema de errores es await-requires-result\n // (todo await resuelve en Result). async-functions-return-result queda\n // apagada por defecto: exigir la firma por decreto choca con los bordes\n // del framework y bloquea la adopción incremental; la presión sobre los\n // awaits produce el mismo estado final. Ver \"¿Por qué está apagada por\n // defecto?\" en el README.\n \"skapxd/await-requires-result\": \"error\",\n },\n },\n base: {\n languageOptions: baseLanguageOptions,\n name: \"skapxd/shared/base\",\n plugins: { skapxd: pluginReference },\n rules: baseRules,\n },\n frontend: {\n languageOptions: typedLanguageOptions,\n name: \"skapxd/shared/frontend\",\n plugins: { skapxd: pluginReference },\n rules: {\n ...baseRules,\n // 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","// 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;;;ACXO,IAAM,YAAY;AAAA,EACvB,8BAA8B;AAAA,EAC9B,mCAAmC;AAAA,EACnC,4BAA4B;AAAA,EAC5B,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,qCAAqC;AAAA,EACrC,4BAA4B;AAAA,EAC5B,sCAAsC;AAAA,EACtC,yCAAyC;AAC3C;;;ACZA,OAAOA,eAAc;AAId,SAAS,4BAA4B;AAC1C,SAAO;AAAA,IACL,QAAQA,UAAS;AAAA,EACnB;AACF;;;ACJO,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,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,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,EAAE,QAAQ,gBAAgB;AAAA,MACnC,OAAO;AAAA,QACL,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;;;AClEO,IAAM,eAAe;AAAA,EAC1B,eAAe;AAAA,IACb,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM;AACR;","names":["tseslint"]}
|
|
@@ -1151,6 +1151,135 @@ var resultErrorRequiresCause = {
|
|
|
1151
1151
|
}
|
|
1152
1152
|
};
|
|
1153
1153
|
|
|
1154
|
+
// src/utils/collect-identifiers-named.ts
|
|
1155
|
+
function collectIdentifiersNamed(node, name, results = []) {
|
|
1156
|
+
if (node?.type === "Identifier" && node.name === name) {
|
|
1157
|
+
results.push(node);
|
|
1158
|
+
}
|
|
1159
|
+
for (const child of getNodeChildren(node)) {
|
|
1160
|
+
collectIdentifiersNamed(child, name, results);
|
|
1161
|
+
}
|
|
1162
|
+
return results;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// src/utils/get-result-error-requires-handling-options.ts
|
|
1166
|
+
function getResultErrorRequiresHandlingOptions(options = {}) {
|
|
1167
|
+
return {
|
|
1168
|
+
allowFilePatterns: options.allowFilePatterns ?? []
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// src/utils/get-declared-alias-names.ts
|
|
1173
|
+
function getDeclaredAliasNames(id) {
|
|
1174
|
+
if (id.type === "Identifier") {
|
|
1175
|
+
return [id.name];
|
|
1176
|
+
}
|
|
1177
|
+
if (id.type !== "ObjectPattern") {
|
|
1178
|
+
return [];
|
|
1179
|
+
}
|
|
1180
|
+
return id.properties.flatMap((property) => {
|
|
1181
|
+
if (property.type === "RestElement" && property.argument.type === "Identifier") {
|
|
1182
|
+
return [property.argument.name];
|
|
1183
|
+
}
|
|
1184
|
+
if (property.type === "Property" && property.value.type === "Identifier") {
|
|
1185
|
+
return [property.value.name];
|
|
1186
|
+
}
|
|
1187
|
+
return [];
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// src/utils/is-inside-node.ts
|
|
1192
|
+
function isInsideNode(node, ancestor) {
|
|
1193
|
+
let current = node;
|
|
1194
|
+
while (current) {
|
|
1195
|
+
if (current === ancestor) {
|
|
1196
|
+
return true;
|
|
1197
|
+
}
|
|
1198
|
+
current = current.parent;
|
|
1199
|
+
}
|
|
1200
|
+
return false;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// src/utils/is-consumed-result-reference.ts
|
|
1204
|
+
function isConsumedResultReference(identifier, searchRoot, visited = /* @__PURE__ */ new Set()) {
|
|
1205
|
+
const member = identifier.parent?.type === "MemberExpression" && identifier.parent.object === identifier ? identifier.parent : null;
|
|
1206
|
+
const reference = member ?? identifier;
|
|
1207
|
+
const parent = reference.parent;
|
|
1208
|
+
if (parent?.type === "UnaryExpression" && parent.operator === "void") {
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
if (parent?.type === "ExpressionStatement") {
|
|
1212
|
+
return false;
|
|
1213
|
+
}
|
|
1214
|
+
if (parent?.type !== "VariableDeclarator" || parent.init !== reference) {
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
1217
|
+
const aliasNames = getDeclaredAliasNames(parent.id).filter(
|
|
1218
|
+
(name) => !visited.has(name)
|
|
1219
|
+
);
|
|
1220
|
+
return aliasNames.some((aliasName) => {
|
|
1221
|
+
visited.add(aliasName);
|
|
1222
|
+
return collectIdentifiersNamed(searchRoot, aliasName).filter((aliasReference) => !isInsideNode(aliasReference, parent.id)).some(
|
|
1223
|
+
(aliasReference) => isConsumedResultReference(aliasReference, searchRoot, visited)
|
|
1224
|
+
);
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// src/rules/result-error-requires-handling.ts
|
|
1229
|
+
var resultErrorRequiresHandling = {
|
|
1230
|
+
meta: {
|
|
1231
|
+
type: "problem",
|
|
1232
|
+
docs: {
|
|
1233
|
+
description: "Prohibe descartar en silencio un Result fallido: el error se transforma o se entrega, nunca se ignora."
|
|
1234
|
+
},
|
|
1235
|
+
messages: {
|
|
1236
|
+
unhandledResultError: "El guard detecta que `{{name}}` fallo, pero `{{name}}.error` muere aqui sin seguimiento. Transformalo (`Result.err({ cause: {{name}}.error, ... })`), entregaselo a alguien (telemetria, estado de error, log de dominio) o propaga el result completo. Si darle seguimiento es critico o no, no es una interpretacion: todo error fluye a alguna parte."
|
|
1237
|
+
},
|
|
1238
|
+
schema: [
|
|
1239
|
+
{
|
|
1240
|
+
additionalProperties: false,
|
|
1241
|
+
properties: {
|
|
1242
|
+
allowFilePatterns: {
|
|
1243
|
+
items: { type: "string" },
|
|
1244
|
+
type: "array"
|
|
1245
|
+
}
|
|
1246
|
+
},
|
|
1247
|
+
type: "object"
|
|
1248
|
+
}
|
|
1249
|
+
]
|
|
1250
|
+
},
|
|
1251
|
+
create(context) {
|
|
1252
|
+
const options = getResultErrorRequiresHandlingOptions(context.options[0]);
|
|
1253
|
+
const filename = context.filename ?? context.getFilename();
|
|
1254
|
+
const typeContext = getTypeContext(context);
|
|
1255
|
+
if (matchesAnyGlob(filename, options.allowFilePatterns)) {
|
|
1256
|
+
return {};
|
|
1257
|
+
}
|
|
1258
|
+
return {
|
|
1259
|
+
IfStatement(node) {
|
|
1260
|
+
const resultGuard = getFailedResultGuard(node.test);
|
|
1261
|
+
if (!typeContext || !resultGuard || !isSkapxdResultExpression(resultGuard.node, typeContext)) {
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
const references = collectIdentifiersNamed(
|
|
1265
|
+
node.consequent,
|
|
1266
|
+
resultGuard.name
|
|
1267
|
+
);
|
|
1268
|
+
if (references.some(
|
|
1269
|
+
(reference) => isConsumedResultReference(reference, node.consequent)
|
|
1270
|
+
)) {
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
context.report({
|
|
1274
|
+
data: { name: resultGuard.name },
|
|
1275
|
+
messageId: "unhandledResultError",
|
|
1276
|
+
node: node.test
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1154
1283
|
// src/utils/count-own-use-state-calls-in-node.ts
|
|
1155
1284
|
function countOwnUseStateCallsInNode(node) {
|
|
1156
1285
|
if (!isAstNode(node)) {
|
|
@@ -1461,17 +1590,6 @@ var noEmoji = {
|
|
|
1461
1590
|
}
|
|
1462
1591
|
};
|
|
1463
1592
|
|
|
1464
|
-
// src/utils/collect-identifiers-named.ts
|
|
1465
|
-
function collectIdentifiersNamed(node, name, results = []) {
|
|
1466
|
-
if (node?.type === "Identifier" && node.name === name) {
|
|
1467
|
-
results.push(node);
|
|
1468
|
-
}
|
|
1469
|
-
for (const child of getNodeChildren(node)) {
|
|
1470
|
-
collectIdentifiersNamed(child, name, results);
|
|
1471
|
-
}
|
|
1472
|
-
return results;
|
|
1473
|
-
}
|
|
1474
|
-
|
|
1475
1593
|
// src/utils/get-no-tunnel-props-options.ts
|
|
1476
1594
|
function getNoTunnelPropsOptions(options = {}) {
|
|
1477
1595
|
return {
|
|
@@ -2045,6 +2163,7 @@ var rules = {
|
|
|
2045
2163
|
}
|
|
2046
2164
|
},
|
|
2047
2165
|
"result-error-requires-cause": resultErrorRequiresCause,
|
|
2166
|
+
"result-error-requires-handling": resultErrorRequiresHandling,
|
|
2048
2167
|
"max-hook-size": maxHookSize,
|
|
2049
2168
|
"no-deep-relative-imports": noDeepRelativeImports,
|
|
2050
2169
|
"no-default-export": noDefaultExport,
|
|
@@ -2062,4 +2181,4 @@ var rules = {
|
|
|
2062
2181
|
export {
|
|
2063
2182
|
rules
|
|
2064
2183
|
};
|
|
2065
|
-
//# sourceMappingURL=chunk-
|
|
2184
|
+
//# sourceMappingURL=chunk-WZERKXPJ.mjs.map
|