@skapxd/eslint-opinionated 0.16.0 → 0.17.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 +79 -0
- package/dist/astro/index.mjs +2 -2
- package/dist/{chunk-LSLLVT64.mjs → chunk-3GEFHNU7.mjs} +2 -2
- package/dist/{chunk-YRWX3POD.mjs → chunk-54EOEKYS.mjs} +2 -2
- package/dist/{chunk-7OIMY5TI.mjs → chunk-GSQWHSHV.mjs} +2 -2
- package/dist/{chunk-X2DU5BAB.mjs → chunk-PD77UDUY.mjs} +222 -5
- package/dist/chunk-PD77UDUY.mjs.map +1 -0
- package/dist/{chunk-4FQ7SFU4.mjs → chunk-QDQUU6QK.mjs} +21 -5
- package/dist/chunk-QDQUU6QK.mjs.map +1 -0
- package/dist/cli.js +17 -5
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +17 -5
- package/dist/cli.mjs.map +1 -1
- package/dist/index.js +246 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -7
- package/dist/index.mjs.map +1 -1
- package/dist/nest/index.d.mts +3 -1
- package/dist/nest/index.d.ts +3 -1
- package/dist/nest/index.js +7 -2
- 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 +41 -2
- package/dist/shared/index.d.ts +41 -2
- package/dist/shared/index.js +241 -8
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +2 -2
- package/package.json +41 -16
- package/dist/chunk-4FQ7SFU4.mjs.map +0 -1
- package/dist/chunk-X2DU5BAB.mjs.map +0 -1
- /package/dist/{chunk-LSLLVT64.mjs.map → chunk-3GEFHNU7.mjs.map} +0 -0
- /package/dist/{chunk-YRWX3POD.mjs.map → chunk-54EOEKYS.mjs.map} +0 -0
- /package/dist/{chunk-7OIMY5TI.mjs.map → chunk-GSQWHSHV.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -748,6 +748,19 @@ export default [
|
|
|
748
748
|
];
|
|
749
749
|
```
|
|
750
750
|
|
|
751
|
+
Para librerías npm escritas en TypeScript (tsup o equivalente). Trae las
|
|
752
|
+
bases completas + el set type-driven (tipado, con `projectService`) +
|
|
753
|
+
`await-requires-result` + el contrato de empaquetado:
|
|
754
|
+
|
|
755
|
+
- `skapxd/package-requires-typed-exports` — los `exports` del package.json
|
|
756
|
+
cablean los tipos **por condición** (`import` → `.d.mts`, `require` →
|
|
757
|
+
`.d.ts`); el `types` único por subpath es el bug "FalseCJS".
|
|
758
|
+
- `skapxd/untrusted-module-requires-adapter` — inerte hasta que declares tu
|
|
759
|
+
inventario de paquetes con tipos mentirosos (ver su sección).
|
|
760
|
+
|
|
761
|
+
**Este mismo repo se lintea con este preset** — dogfood: la regla de exports
|
|
762
|
+
nos obligó a corregir nuestro propio package.json al nacer.
|
|
763
|
+
|
|
751
764
|
### Strict (sin escape via `eslint-disable`)
|
|
752
765
|
|
|
753
766
|
Un prompt o un agente puede saltarse cualquier regla con
|
|
@@ -831,7 +844,9 @@ de cada regla):
|
|
|
831
844
|
| `no-runtime-state-guard` | `allowFilePatterns` (globs) |
|
|
832
845
|
| `no-tunnel-props` | `allowFilePatterns` (globs), `allowPropPatterns` (regex) |
|
|
833
846
|
| `prefer-abort-signal` | `allowFilePatterns` (globs), `effectNames` (default `["useEffect", "useLayoutEffect"]`) |
|
|
847
|
+
| `package-requires-typed-exports` | `allowFilePatterns` (globs), `anchorFilePatterns` (default `src/index.ts(x)`, `src/main.ts`) |
|
|
834
848
|
| `prefer-tagged-union-state` | `allowFilePatterns` (globs), `loadingPatterns` (regex, en minúsculas), `errorPatterns` (regex, en minúsculas) |
|
|
849
|
+
| `untrusted-module-requires-adapter` | `modules` (default `[]` — inerte), `adapterFilePatterns` (globs), `allowFilePatterns` (globs) |
|
|
835
850
|
| `requires-strict-tsconfig` | `allowFilePatterns` (globs), `anchorFilePatterns` (globs), `requiredCompilerOptions` |
|
|
836
851
|
| `result-error-requires-handling` | `allowFilePatterns` (globs) |
|
|
837
852
|
|
|
@@ -883,6 +898,8 @@ matchea en cualquier carpeta). Las 7 reglas restantes no tienen opciones: su
|
|
|
883
898
|
| `skapxd/no-try-catch` | Prohíbe `try/catch`; usa `trySafe` de `@skapxd/result`. |
|
|
884
899
|
| `skapxd/no-promise-chain` | Prohíbe `.then/.catch/.finally`; usa `await` (+ `trySafe`). |
|
|
885
900
|
| `skapxd/prefer-ts-pattern` | Prohíbe `switch` y ternarios anidados; usa `match()` de ts-pattern. |
|
|
901
|
+
| `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`. |
|
|
902
|
+
| `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`. |
|
|
886
903
|
| `skapxd/no-jsx-ternary-null` | Prefiere `cond && <El />` sobre `cond ? <El /> : null` en JSX. |
|
|
887
904
|
|
|
888
905
|
### `skapxd/one-root-function-per-file`
|
|
@@ -2229,6 +2246,68 @@ no puede traer `signal`.
|
|
|
2229
2246
|
`effectNames` permite cubrir wrappers propios (`["useEffect",
|
|
2230
2247
|
"useLayoutEffect", "useIsomorphicEffect"]`).
|
|
2231
2248
|
|
|
2249
|
+
### `skapxd/package-requires-typed-exports`
|
|
2250
|
+
|
|
2251
|
+
El contrato de empaquetado de una librería TypeScript dual (ESM + CJS): cada
|
|
2252
|
+
condición del mapa `exports` declara **sus propios tipos**, del sabor
|
|
2253
|
+
correcto.
|
|
2254
|
+
|
|
2255
|
+
```jsonc
|
|
2256
|
+
"exports": {
|
|
2257
|
+
".": {
|
|
2258
|
+
"import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" },
|
|
2259
|
+
"require": { "types": "./dist/index.d.ts", "default": "./dist/index.js" }
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
```
|
|
2263
|
+
|
|
2264
|
+
El antipatrón que mata es el **"FalseCJS"** (el hallazgo #1 de
|
|
2265
|
+
[arethetypeswrong](https://arethetypeswrong.github.io)): un `types` único por
|
|
2266
|
+
subpath apuntando al `.d.ts` — los consumidores ESM con
|
|
2267
|
+
`moduleResolution: node16` reciben tipos CJS y el contrato miente en la
|
|
2268
|
+
frontera más pública que tiene una librería. tsup con `dts: true` ya genera
|
|
2269
|
+
los dos sabores (`.d.mts` y `.d.ts`); esta regla verifica que el package.json
|
|
2270
|
+
de verdad los cablee y que los archivos existan en disco. Anclada al
|
|
2271
|
+
entrypoint (`src/index.ts` por defecto): un reporte por paquete.
|
|
2272
|
+
|
|
2273
|
+
Dogfood: esta regla nació reportando a este mismo repo — nuestros `exports`
|
|
2274
|
+
tenían el bug y el lint no volvió a verde hasta corregirlos.
|
|
2275
|
+
|
|
2276
|
+
### `skapxd/untrusted-module-requires-adapter`
|
|
2277
|
+
|
|
2278
|
+
¿Qué pasa cuando los tipos de un paquete de terceros **mienten**? El clásico:
|
|
2279
|
+
un paquete escrito en JS cuyos tipos viven aparte (`@types/...`) y van
|
|
2280
|
+
desfasados del runtime real, o índices que juran nunca devolver `undefined`.
|
|
2281
|
+
Todo el sistema de este paquete descansa en que el tipo dice la verdad
|
|
2282
|
+
(`no-impossible-branch` le cree ciegamente) — un tipo mentiroso envenena cada
|
|
2283
|
+
regla type-aware que lo toque.
|
|
2284
|
+
|
|
2285
|
+
El playbook, en orden:
|
|
2286
|
+
|
|
2287
|
+
1. **Armadura de tsconfig primero**: `noUncheckedIndexedAccess` corrige de
|
|
2288
|
+
raíz la clase más común de mentira (index signatures optimistas) sin
|
|
2289
|
+
tocar al tercero — `requires-strict-tsconfig` ya lo exige.
|
|
2290
|
+
2. **Frontera anticorrupción** (lo que esta regla impone): declara el módulo
|
|
2291
|
+
como no confiable y enciérralo tras UN adaptador. El adaptador importa el
|
|
2292
|
+
paquete, re-declara los tipos honestos (lo que el runtime de verdad
|
|
2293
|
+
devuelve) y exporta esa versión. El resto del código importa el adaptador
|
|
2294
|
+
y razona con tipos veraces — la mentira queda en un archivo auditable.
|
|
2295
|
+
3. **`@ts-expect-error` con descripción** dentro del adaptador si hace falta
|
|
2296
|
+
forzar la corrección — es la puerta que `no-silenced-compiler` deja
|
|
2297
|
+
abierta, declarada y con porqué.
|
|
2298
|
+
4. **Arregla el upstream**: PR a DefinitelyTyped. Mientras llega, los pasos
|
|
2299
|
+
1-3 te protegen.
|
|
2300
|
+
|
|
2301
|
+
```js
|
|
2302
|
+
"skapxd/untrusted-module-requires-adapter": ["error", {
|
|
2303
|
+
adapterFilePatterns: ["src/lib/xlsx-adapter.ts"],
|
|
2304
|
+
modules: ["xlsx"],
|
|
2305
|
+
}]
|
|
2306
|
+
```
|
|
2307
|
+
|
|
2308
|
+
Sin `modules` declarados la regla es inerte: el inventario de sospechosos es
|
|
2309
|
+
una decisión del proyecto, no una adivinanza del linter (axioma A5).
|
|
2310
|
+
|
|
2232
2311
|
### `skapxd/no-jsx-ternary-null`
|
|
2233
2312
|
|
|
2234
2313
|
Cuando renderizas JSX condicional y una rama del ternario es `null`, prefiere la
|
package/dist/astro/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
baseRules,
|
|
3
3
|
createTypedLanguageOptions,
|
|
4
4
|
typeDrivenRules
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QDQUU6QK.mjs";
|
|
6
6
|
|
|
7
7
|
// src/constants/nest-entrypoint-file-patterns.ts
|
|
8
8
|
var nestEntrypointFilePatterns = [
|
|
@@ -130,4 +130,4 @@ function createNestConfigs(pluginReference) {
|
|
|
130
130
|
export {
|
|
131
131
|
createNestConfigs
|
|
132
132
|
};
|
|
133
|
-
//# sourceMappingURL=chunk-
|
|
133
|
+
//# sourceMappingURL=chunk-3GEFHNU7.mjs.map
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
baseRules,
|
|
7
7
|
createBaseLanguageOptions,
|
|
8
8
|
createTypedLanguageOptions
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QDQUU6QK.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-54EOEKYS.mjs.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
baseRules,
|
|
3
3
|
createBaseLanguageOptions,
|
|
4
4
|
createTypedLanguageOptions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QDQUU6QK.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-GSQWHSHV.mjs.map
|
|
@@ -2761,8 +2761,14 @@ var noEmoji = {
|
|
|
2761
2761
|
|
|
2762
2762
|
// src/utils/wrap-tseslint-rule.ts
|
|
2763
2763
|
import tseslint from "typescript-eslint";
|
|
2764
|
+
var upstreamRules = tseslint.plugin.rules;
|
|
2764
2765
|
function wrapTseslintRule(upstreamRuleName, { description, messages }) {
|
|
2765
|
-
const original =
|
|
2766
|
+
const original = upstreamRules[upstreamRuleName];
|
|
2767
|
+
if (!original) {
|
|
2768
|
+
throw new Error(
|
|
2769
|
+
`wrapTseslintRule: la regla "${upstreamRuleName}" no existe en typescript-eslint.`
|
|
2770
|
+
);
|
|
2771
|
+
}
|
|
2766
2772
|
return {
|
|
2767
2773
|
...original,
|
|
2768
2774
|
meta: {
|
|
@@ -2856,7 +2862,10 @@ function getNoTunnelPropsOptions(options = {}) {
|
|
|
2856
2862
|
|
|
2857
2863
|
// src/utils/get-object-pattern-prop-names.ts
|
|
2858
2864
|
function getObjectPatternPropNames(pattern) {
|
|
2859
|
-
const result = {
|
|
2865
|
+
const result = {
|
|
2866
|
+
propNames: [],
|
|
2867
|
+
restName: null
|
|
2868
|
+
};
|
|
2860
2869
|
if (pattern?.type !== "ObjectPattern") {
|
|
2861
2870
|
return result;
|
|
2862
2871
|
}
|
|
@@ -3494,7 +3503,7 @@ function readResolvedTsconfig(tsconfigPath) {
|
|
|
3494
3503
|
if (!parsed.ok || !parsed.value) {
|
|
3495
3504
|
return null;
|
|
3496
3505
|
}
|
|
3497
|
-
return parsed.value.options
|
|
3506
|
+
return parsed.value.options;
|
|
3498
3507
|
}
|
|
3499
3508
|
|
|
3500
3509
|
// src/rules/requires-strict-tsconfig.ts
|
|
@@ -3841,6 +3850,212 @@ var noRuntimeStateGuard = {
|
|
|
3841
3850
|
}
|
|
3842
3851
|
};
|
|
3843
3852
|
|
|
3853
|
+
// src/rules/package-requires-typed-exports.ts
|
|
3854
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
3855
|
+
import { dirname as dirname6, resolve as resolve3 } from "path";
|
|
3856
|
+
import { trySafe as trySafe4 } from "@skapxd/result";
|
|
3857
|
+
|
|
3858
|
+
// src/utils/get-typed-exports-options.ts
|
|
3859
|
+
function getTypedExportsOptions(options = {}) {
|
|
3860
|
+
return {
|
|
3861
|
+
allowFilePatterns: options.allowFilePatterns ?? [],
|
|
3862
|
+
// Anclada al entrypoint de la libreria: un reporte por paquete.
|
|
3863
|
+
anchorFilePatterns: options.anchorFilePatterns ?? [
|
|
3864
|
+
"src/index.ts",
|
|
3865
|
+
"src/index.tsx",
|
|
3866
|
+
"src/main.ts"
|
|
3867
|
+
]
|
|
3868
|
+
};
|
|
3869
|
+
}
|
|
3870
|
+
|
|
3871
|
+
// src/utils/get-untyped-export-conditions.ts
|
|
3872
|
+
import { existsSync as existsSync3 } from "fs";
|
|
3873
|
+
import { join as join3 } from "path";
|
|
3874
|
+
function getUntypedExportConditions(exportsField, packageDir) {
|
|
3875
|
+
const violations = [];
|
|
3876
|
+
const entries = "import" in exportsField || "require" in exportsField ? [[".", exportsField]] : Object.entries(exportsField);
|
|
3877
|
+
for (const [subpath, value] of entries) {
|
|
3878
|
+
if (subpath === "./package.json") {
|
|
3879
|
+
continue;
|
|
3880
|
+
}
|
|
3881
|
+
if (typeof value === "string") {
|
|
3882
|
+
violations.push({ kind: "untyped", condition: "todas", subpath });
|
|
3883
|
+
continue;
|
|
3884
|
+
}
|
|
3885
|
+
for (const condition of ["import", "require"]) {
|
|
3886
|
+
if (!(condition in value)) {
|
|
3887
|
+
continue;
|
|
3888
|
+
}
|
|
3889
|
+
const target = value[condition];
|
|
3890
|
+
if (typeof target !== "object" || typeof target.types !== "string") {
|
|
3891
|
+
violations.push({ kind: "untyped", condition, subpath });
|
|
3892
|
+
continue;
|
|
3893
|
+
}
|
|
3894
|
+
const expectsEsmTypes = condition === "import";
|
|
3895
|
+
const flavorOk = expectsEsmTypes ? target.types.endsWith(".d.mts") : target.types.endsWith(".d.ts") || target.types.endsWith(".d.cts");
|
|
3896
|
+
if (!flavorOk) {
|
|
3897
|
+
violations.push({ kind: "wrong-flavor", condition, subpath });
|
|
3898
|
+
continue;
|
|
3899
|
+
}
|
|
3900
|
+
if (!existsSync3(join3(packageDir, target.types))) {
|
|
3901
|
+
violations.push({ kind: "missing-file", condition, subpath });
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
return violations;
|
|
3906
|
+
}
|
|
3907
|
+
|
|
3908
|
+
// src/rules/package-requires-typed-exports.ts
|
|
3909
|
+
var kindMessages = {
|
|
3910
|
+
"missing-file": "missingTypesFile",
|
|
3911
|
+
untyped: "untypedCondition",
|
|
3912
|
+
"wrong-flavor": "wrongTypesFlavor"
|
|
3913
|
+
};
|
|
3914
|
+
var packageRequiresTypedExports = {
|
|
3915
|
+
meta: {
|
|
3916
|
+
type: "problem",
|
|
3917
|
+
docs: {
|
|
3918
|
+
description: "El package.json de una libreria debe cablear los tipos POR CONDICION en exports: import \u2192 .d.mts, require \u2192 .d.ts. Un types unico es el bug FalseCJS."
|
|
3919
|
+
},
|
|
3920
|
+
messages: {
|
|
3921
|
+
missingExports: "El package.json no tiene campo `exports`. Sin el, Node y TypeScript resuelven por heuristicas viejas y los consumidores ESM/CJS pueden recibir artefactos cruzados. Declara el mapa de exports con `types` por condicion.",
|
|
3922
|
+
missingTypesFile: 'En exports["{{subpath}}"].{{condition}}, el archivo de `types` declarado no existe en disco. El contrato apunta a un fantasma: o falta el build (dts) o la ruta esta mal escrita.',
|
|
3923
|
+
unreadablePackageJson: "No encontre un package.json legible subiendo desde este archivo. Esta regla valida el contrato de tipos de la libreria y necesita leerlo.",
|
|
3924
|
+
untypedCondition: 'exports["{{subpath}}"] \u2192 `{{condition}}` no declara su propio `types`. Un `types` unico a nivel del subpath es el bug "FalseCJS": el consumidor ESM con moduleResolution node16 recibe los tipos CJS. Cada condicion declara los suyos \u2014 `import` como objeto con `types: ./dist/x.d.mts` y `default: ./dist/x.mjs`; `require` como objeto con `types: ./dist/x.d.ts` y `default: ./dist/x.js`.',
|
|
3925
|
+
wrongTypesFlavor: 'exports["{{subpath}}"].{{condition}} apunta a tipos del formato equivocado: `import` exige `.d.mts` (tipos ESM) y `require` exige `.d.ts`/`.d.cts` (tipos CJS). tsup con dts: true ya genera ambos sabores.'
|
|
3926
|
+
},
|
|
3927
|
+
schema: [
|
|
3928
|
+
{
|
|
3929
|
+
additionalProperties: false,
|
|
3930
|
+
properties: {
|
|
3931
|
+
allowFilePatterns: {
|
|
3932
|
+
items: { type: "string" },
|
|
3933
|
+
type: "array"
|
|
3934
|
+
},
|
|
3935
|
+
anchorFilePatterns: {
|
|
3936
|
+
items: { type: "string" },
|
|
3937
|
+
type: "array"
|
|
3938
|
+
}
|
|
3939
|
+
},
|
|
3940
|
+
type: "object"
|
|
3941
|
+
}
|
|
3942
|
+
]
|
|
3943
|
+
},
|
|
3944
|
+
create(context) {
|
|
3945
|
+
const options = getTypedExportsOptions(context.options[0]);
|
|
3946
|
+
const filename = context.filename ?? context.getFilename();
|
|
3947
|
+
if (matchesAnyGlob(filename, options.allowFilePatterns) || !matchesAnyGlob(filename, options.anchorFilePatterns)) {
|
|
3948
|
+
return {};
|
|
3949
|
+
}
|
|
3950
|
+
return {
|
|
3951
|
+
Program(node) {
|
|
3952
|
+
const absoluteFilename = resolve3(context.cwd ?? process.cwd(), filename);
|
|
3953
|
+
const packageJsonPath = findProjectFile(
|
|
3954
|
+
dirname6(absoluteFilename),
|
|
3955
|
+
"package.json"
|
|
3956
|
+
);
|
|
3957
|
+
const parsed = packageJsonPath ? trySafe4(() => JSON.parse(readFileSync2(packageJsonPath, "utf8"))) : null;
|
|
3958
|
+
if (!parsed || !parsed.ok) {
|
|
3959
|
+
context.report({ messageId: "unreadablePackageJson", node });
|
|
3960
|
+
return;
|
|
3961
|
+
}
|
|
3962
|
+
const exportsField = parsed.value.exports;
|
|
3963
|
+
if (!exportsField || typeof exportsField !== "object") {
|
|
3964
|
+
context.report({ messageId: "missingExports", node });
|
|
3965
|
+
return;
|
|
3966
|
+
}
|
|
3967
|
+
const violations = getUntypedExportConditions(
|
|
3968
|
+
exportsField,
|
|
3969
|
+
dirname6(packageJsonPath)
|
|
3970
|
+
);
|
|
3971
|
+
for (const violation of violations) {
|
|
3972
|
+
context.report({
|
|
3973
|
+
data: {
|
|
3974
|
+
condition: violation.condition,
|
|
3975
|
+
subpath: violation.subpath
|
|
3976
|
+
},
|
|
3977
|
+
messageId: kindMessages[violation.kind],
|
|
3978
|
+
node
|
|
3979
|
+
});
|
|
3980
|
+
}
|
|
3981
|
+
}
|
|
3982
|
+
};
|
|
3983
|
+
}
|
|
3984
|
+
};
|
|
3985
|
+
|
|
3986
|
+
// src/utils/get-untrusted-module-options.ts
|
|
3987
|
+
function getUntrustedModuleOptions(options = {}) {
|
|
3988
|
+
return {
|
|
3989
|
+
// Globs de los archivos adaptador: el UNICO lugar desde donde se permite
|
|
3990
|
+
// importar los modulos declarados como no confiables.
|
|
3991
|
+
adapterFilePatterns: options.adapterFilePatterns ?? [],
|
|
3992
|
+
allowFilePatterns: options.allowFilePatterns ?? [],
|
|
3993
|
+
// Inventario de paquetes cuyos tipos mienten (p. ej. @types desfasados).
|
|
3994
|
+
// Vacio por defecto: la regla es inerte hasta que el proyecto declara
|
|
3995
|
+
// sus sospechosos.
|
|
3996
|
+
modules: options.modules ?? []
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
|
|
4000
|
+
// src/rules/untrusted-module-requires-adapter.ts
|
|
4001
|
+
var untrustedModuleRequiresAdapter = {
|
|
4002
|
+
meta: {
|
|
4003
|
+
type: "problem",
|
|
4004
|
+
docs: {
|
|
4005
|
+
description: "Los modulos declarados como no confiables (tipos que mienten) solo se importan desde su adaptador: la mentira vive en un archivo, no en todos."
|
|
4006
|
+
},
|
|
4007
|
+
messages: {
|
|
4008
|
+
untrustedImport: "`{{moduleSource}}` esta declarado como modulo de tipos NO confiables: importalo solo desde su adaptador ({{adapters}}). El adaptador es la frontera anticorrupcion: re-declara ahi los tipos honestos (lo que el runtime de verdad devuelve) y exporta esa version; el resto del codigo importa el adaptador y razona con tipos veraces. Asi la mentira de terceros vive en UN archivo auditable, no regada por el proyecto."
|
|
4009
|
+
},
|
|
4010
|
+
schema: [
|
|
4011
|
+
{
|
|
4012
|
+
additionalProperties: false,
|
|
4013
|
+
properties: {
|
|
4014
|
+
adapterFilePatterns: {
|
|
4015
|
+
items: { type: "string" },
|
|
4016
|
+
type: "array"
|
|
4017
|
+
},
|
|
4018
|
+
allowFilePatterns: {
|
|
4019
|
+
items: { type: "string" },
|
|
4020
|
+
type: "array"
|
|
4021
|
+
},
|
|
4022
|
+
modules: {
|
|
4023
|
+
items: { type: "string" },
|
|
4024
|
+
type: "array"
|
|
4025
|
+
}
|
|
4026
|
+
},
|
|
4027
|
+
type: "object"
|
|
4028
|
+
}
|
|
4029
|
+
]
|
|
4030
|
+
},
|
|
4031
|
+
create(context) {
|
|
4032
|
+
const options = getUntrustedModuleOptions(context.options[0]);
|
|
4033
|
+
const filename = context.filename ?? context.getFilename();
|
|
4034
|
+
if (options.modules.length === 0 || matchesAnyGlob(filename, options.allowFilePatterns) || matchesAnyGlob(filename, options.adapterFilePatterns)) {
|
|
4035
|
+
return {};
|
|
4036
|
+
}
|
|
4037
|
+
return {
|
|
4038
|
+
ImportDeclaration(node) {
|
|
4039
|
+
const source = node.source.value;
|
|
4040
|
+
const isUntrusted = options.modules.some(
|
|
4041
|
+
(moduleName) => source === moduleName || source.startsWith(`${moduleName}/`)
|
|
4042
|
+
);
|
|
4043
|
+
if (!isUntrusted) {
|
|
4044
|
+
return;
|
|
4045
|
+
}
|
|
4046
|
+
context.report({
|
|
4047
|
+
data: {
|
|
4048
|
+
adapters: options.adapterFilePatterns.join(", ") || "sin definir",
|
|
4049
|
+
moduleSource: source
|
|
4050
|
+
},
|
|
4051
|
+
messageId: "untrustedImport",
|
|
4052
|
+
node
|
|
4053
|
+
});
|
|
4054
|
+
}
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
};
|
|
4058
|
+
|
|
3844
4059
|
// src/shared/rules.ts
|
|
3845
4060
|
var rules = {
|
|
3846
4061
|
"class-properties-require-readonly": classPropertiesRequireReadonly,
|
|
@@ -3893,10 +4108,12 @@ var rules = {
|
|
|
3893
4108
|
"no-jsx-ternary-null": noJsxTernaryNull,
|
|
3894
4109
|
"no-nested-if": noNestedIf,
|
|
3895
4110
|
"no-promise-chain": noPromiseChain,
|
|
3896
|
-
"no-runtime-state-guard": noRuntimeStateGuard
|
|
4111
|
+
"no-runtime-state-guard": noRuntimeStateGuard,
|
|
4112
|
+
"package-requires-typed-exports": packageRequiresTypedExports,
|
|
4113
|
+
"untrusted-module-requires-adapter": untrustedModuleRequiresAdapter
|
|
3897
4114
|
};
|
|
3898
4115
|
|
|
3899
4116
|
export {
|
|
3900
4117
|
rules
|
|
3901
4118
|
};
|
|
3902
|
-
//# sourceMappingURL=chunk-
|
|
4119
|
+
//# sourceMappingURL=chunk-PD77UDUY.mjs.map
|