@mionjs/devtools 0.8.0-alpha.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/LICENSE +21 -0
- package/build/eslint/cjs/index.cjs +41 -0
- package/build/eslint/cjs/index.cjs.map +1 -0
- package/build/eslint/cjs/package.json +1 -0
- package/build/eslint/cjs/src/eslint/index.cjs +13 -0
- package/build/eslint/cjs/src/eslint/index.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/index.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/enforce-type-imports.cjs +121 -0
- package/build/eslint/cjs/src/eslint/rules/enforce-type-imports.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/enforce-type-imports.d.ts +7 -0
- package/build/eslint/cjs/src/eslint/rules/formatTypeNames.cjs +71 -0
- package/build/eslint/cjs/src/eslint/rules/formatTypeNames.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/formatTypeNames.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-mixed-union-properties.cjs +220 -0
- package/build/eslint/cjs/src/eslint/rules/no-mixed-union-properties.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-mixed-union-properties.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-type-imports.cjs +251 -0
- package/build/eslint/cjs/src/eslint/rules/no-type-imports.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-type-imports.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-typeof-runtype.cjs +72 -0
- package/build/eslint/cjs/src/eslint/rules/no-typeof-runtype.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-typeof-runtype.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-unreachable-union-types.cjs +220 -0
- package/build/eslint/cjs/src/eslint/rules/no-unreachable-union-types.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-unreachable-union-types.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-vite-client.cjs +71 -0
- package/build/eslint/cjs/src/eslint/rules/no-vite-client.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-vite-client.d.ts +4 -0
- package/build/eslint/cjs/src/eslint/rules/pure-functions.cjs +346 -0
- package/build/eslint/cjs/src/eslint/rules/pure-functions.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/pure-functions.d.ts +4 -0
- package/build/eslint/cjs/src/eslint/rules/strong-typed-routes.cjs +328 -0
- package/build/eslint/cjs/src/eslint/rules/strong-typed-routes.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/strong-typed-routes.d.ts +4 -0
- package/build/eslint/cjs/src/eslint/rules/type-formats-imports.cjs +52 -0
- package/build/eslint/cjs/src/eslint/rules/type-formats-imports.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/type-formats-imports.d.ts +3 -0
- package/build/eslint/cjs/src/pureFns/purityRules.cjs +67 -0
- package/build/eslint/cjs/src/pureFns/purityRules.cjs.map +1 -0
- package/build/eslint/cjs/src/pureFns/purityRules.d.ts +4 -0
- package/build/eslint/esm/index.js +42 -0
- package/build/eslint/esm/index.js.map +1 -0
- package/build/eslint/esm/src/eslint/index.d.ts +3 -0
- package/build/eslint/esm/src/eslint/index.js +14 -0
- package/build/eslint/esm/src/eslint/index.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/enforce-type-imports.d.ts +7 -0
- package/build/eslint/esm/src/eslint/rules/enforce-type-imports.js +122 -0
- package/build/eslint/esm/src/eslint/rules/enforce-type-imports.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/formatTypeNames.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/formatTypeNames.js +71 -0
- package/build/eslint/esm/src/eslint/rules/formatTypeNames.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-mixed-union-properties.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-mixed-union-properties.js +221 -0
- package/build/eslint/esm/src/eslint/rules/no-mixed-union-properties.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-type-imports.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-type-imports.js +252 -0
- package/build/eslint/esm/src/eslint/rules/no-type-imports.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-typeof-runtype.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-typeof-runtype.js +73 -0
- package/build/eslint/esm/src/eslint/rules/no-typeof-runtype.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-unreachable-union-types.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-unreachable-union-types.js +221 -0
- package/build/eslint/esm/src/eslint/rules/no-unreachable-union-types.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-vite-client.d.ts +4 -0
- package/build/eslint/esm/src/eslint/rules/no-vite-client.js +72 -0
- package/build/eslint/esm/src/eslint/rules/no-vite-client.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/pure-functions.d.ts +4 -0
- package/build/eslint/esm/src/eslint/rules/pure-functions.js +347 -0
- package/build/eslint/esm/src/eslint/rules/pure-functions.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/strong-typed-routes.d.ts +4 -0
- package/build/eslint/esm/src/eslint/rules/strong-typed-routes.js +329 -0
- package/build/eslint/esm/src/eslint/rules/strong-typed-routes.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/type-formats-imports.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/type-formats-imports.js +53 -0
- package/build/eslint/esm/src/eslint/rules/type-formats-imports.js.map +1 -0
- package/build/eslint/esm/src/pureFns/purityRules.d.ts +4 -0
- package/build/eslint/esm/src/pureFns/purityRules.js +67 -0
- package/build/eslint/esm/src/pureFns/purityRules.js.map +1 -0
- package/build/vite-plugin/cjs/index.cjs +14 -0
- package/build/vite-plugin/cjs/index.cjs.map +1 -0
- package/build/vite-plugin/cjs/package.json +1 -0
- package/build/vite-plugin/cjs/src/pureFns/purityRules.cjs +65 -0
- package/build/vite-plugin/cjs/src/pureFns/purityRules.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/pureFns/purityRules.d.ts +4 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotCacheGenerator.cjs +235 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotCacheGenerator.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotCacheGenerator.d.ts +23 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotDiskCache.cjs +134 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotDiskCache.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotDiskCache.d.ts +6 -0
- package/build/vite-plugin/cjs/src/vite-plugin/cjsPackageJsonPlugin.cjs +15 -0
- package/build/vite-plugin/cjs/src/vite-plugin/cjsPackageJsonPlugin.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/cjsPackageJsonPlugin.d.ts +2 -0
- package/build/vite-plugin/cjs/src/vite-plugin/constants.cjs +25 -0
- package/build/vite-plugin/cjs/src/vite-plugin/constants.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/constants.d.ts +10 -0
- package/build/vite-plugin/cjs/src/vite-plugin/extractPureFn.cjs +628 -0
- package/build/vite-plugin/cjs/src/vite-plugin/extractPureFn.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/extractPureFn.d.ts +13 -0
- package/build/vite-plugin/cjs/src/vite-plugin/index.cjs +14 -0
- package/build/vite-plugin/cjs/src/vite-plugin/index.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/index.d.ts +5 -0
- package/build/vite-plugin/cjs/src/vite-plugin/mionVitePlugin.cjs +404 -0
- package/build/vite-plugin/cjs/src/vite-plugin/mionVitePlugin.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/mionVitePlugin.d.ts +36 -0
- package/build/vite-plugin/cjs/src/vite-plugin/resolveModule.cjs +55 -0
- package/build/vite-plugin/cjs/src/vite-plugin/resolveModule.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/resolveModule.d.ts +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/transformers.cjs +165 -0
- package/build/vite-plugin/cjs/src/vite-plugin/transformers.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/transformers.d.ts +10 -0
- package/build/vite-plugin/cjs/src/vite-plugin/types.cjs +2 -0
- package/build/vite-plugin/cjs/src/vite-plugin/types.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/types.d.ts +57 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtual-modules.d.cjs +2 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtual-modules.d.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtualModule.cjs +68 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtualModule.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtualModule.d.ts +2 -0
- package/build/vite-plugin/esm/index.js +14 -0
- package/build/vite-plugin/esm/index.js.map +1 -0
- package/build/vite-plugin/esm/src/pureFns/purityRules.d.ts +4 -0
- package/build/vite-plugin/esm/src/pureFns/purityRules.js +65 -0
- package/build/vite-plugin/esm/src/pureFns/purityRules.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotCacheGenerator.d.ts +23 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotCacheGenerator.js +235 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotCacheGenerator.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotDiskCache.d.ts +6 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotDiskCache.js +133 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotDiskCache.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/cjsPackageJsonPlugin.d.ts +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/cjsPackageJsonPlugin.js +15 -0
- package/build/vite-plugin/esm/src/vite-plugin/cjsPackageJsonPlugin.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/constants.d.ts +10 -0
- package/build/vite-plugin/esm/src/vite-plugin/constants.js +25 -0
- package/build/vite-plugin/esm/src/vite-plugin/constants.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/extractPureFn.d.ts +13 -0
- package/build/vite-plugin/esm/src/vite-plugin/extractPureFn.js +611 -0
- package/build/vite-plugin/esm/src/vite-plugin/extractPureFn.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/index.d.ts +5 -0
- package/build/vite-plugin/esm/src/vite-plugin/index.js +14 -0
- package/build/vite-plugin/esm/src/vite-plugin/index.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/mionVitePlugin.d.ts +36 -0
- package/build/vite-plugin/esm/src/vite-plugin/mionVitePlugin.js +387 -0
- package/build/vite-plugin/esm/src/vite-plugin/mionVitePlugin.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/resolveModule.d.ts +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/resolveModule.js +33 -0
- package/build/vite-plugin/esm/src/vite-plugin/resolveModule.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/transformers.d.ts +10 -0
- package/build/vite-plugin/esm/src/vite-plugin/transformers.js +148 -0
- package/build/vite-plugin/esm/src/vite-plugin/transformers.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/types.d.ts +57 -0
- package/build/vite-plugin/esm/src/vite-plugin/types.js +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/types.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtual-modules.d.js +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtual-modules.d.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtualModule.d.ts +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtualModule.js +68 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtualModule.js.map +1 -0
- package/package.json +94 -0
- package/src/vite-plugin/virtual-modules.d.ts +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Mion
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const src_eslint_rules_noTypeofRuntype = require("./src/eslint/rules/no-typeof-runtype.cjs");
|
|
3
|
+
const src_eslint_rules_strongTypedRoutes = require("./src/eslint/rules/strong-typed-routes.cjs");
|
|
4
|
+
const src_eslint_rules_noUnreachableUnionTypes = require("./src/eslint/rules/no-unreachable-union-types.cjs");
|
|
5
|
+
const src_eslint_rules_noMixedUnionProperties = require("./src/eslint/rules/no-mixed-union-properties.cjs");
|
|
6
|
+
const src_eslint_rules_noTypeImports = require("./src/eslint/rules/no-type-imports.cjs");
|
|
7
|
+
const src_eslint_rules_pureFunctions = require("./src/eslint/rules/pure-functions.cjs");
|
|
8
|
+
const src_eslint_rules_noViteClient = require("./src/eslint/rules/no-vite-client.cjs");
|
|
9
|
+
const src_eslint_rules_typeFormatsImports = require("./src/eslint/rules/type-formats-imports.cjs");
|
|
10
|
+
const src_eslint_rules_enforceTypeImports = require("./src/eslint/rules/enforce-type-imports.cjs");
|
|
11
|
+
const plugin = {
|
|
12
|
+
rules: {
|
|
13
|
+
"no-typeof-runtype": src_eslint_rules_noTypeofRuntype,
|
|
14
|
+
"strong-typed-routes": src_eslint_rules_strongTypedRoutes,
|
|
15
|
+
"no-unreachable-union-types": src_eslint_rules_noUnreachableUnionTypes,
|
|
16
|
+
"no-mixed-union-properties": src_eslint_rules_noMixedUnionProperties,
|
|
17
|
+
"no-type-imports": src_eslint_rules_noTypeImports,
|
|
18
|
+
"pure-functions": src_eslint_rules_pureFunctions,
|
|
19
|
+
"no-vite-client": src_eslint_rules_noViteClient,
|
|
20
|
+
"type-formats-imports": src_eslint_rules_typeFormatsImports,
|
|
21
|
+
"enforce-type-imports": src_eslint_rules_enforceTypeImports
|
|
22
|
+
},
|
|
23
|
+
configs: {}
|
|
24
|
+
};
|
|
25
|
+
plugin.configs.recommended = {
|
|
26
|
+
plugins: {
|
|
27
|
+
"@mionjs": plugin
|
|
28
|
+
},
|
|
29
|
+
rules: {
|
|
30
|
+
"@mionjs/no-typeof-runtype": "error",
|
|
31
|
+
"@mionjs/strong-typed-routes": "error",
|
|
32
|
+
"@mionjs/no-unreachable-union-types": "error",
|
|
33
|
+
"@mionjs/no-type-imports": "error",
|
|
34
|
+
"@mionjs/pure-functions": "error",
|
|
35
|
+
"@mionjs/type-formats-imports": "error"
|
|
36
|
+
// disabled as seems is not too useful and overlaps with some ts rules
|
|
37
|
+
// '@mionjs/no-mixed-union-properties': 'warn',
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
module.exports = plugin;
|
|
41
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/eslint/index.ts"],"sourcesContent":["/* ########\n * 2024 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport type {ESLint, Linter} from 'eslint';\nimport noTypeofRunType from './rules/no-typeof-runtype.ts';\nimport strongTypedRoutes from './rules/strong-typed-routes.ts';\nimport noUnreachableUnionTypes from './rules/no-unreachable-union-types.ts';\nimport noMixedUnionProperties from './rules/no-mixed-union-properties.ts';\nimport noTypeImports from './rules/no-type-imports.ts';\nimport pureFunctions from './rules/pure-functions.ts';\nimport noViteClient from './rules/no-vite-client.ts';\nimport typeFormatsImports from './rules/type-formats-imports.ts';\nimport enforceTypeImports from './rules/enforce-type-imports.ts';\n\n// configs is set outside the initial object due to circular reference: recommended config references the plugin itself.\nconst plugin: ESLint.Plugin = {\n rules: {\n 'no-typeof-runtype': noTypeofRunType,\n 'strong-typed-routes': strongTypedRoutes,\n 'no-unreachable-union-types': noUnreachableUnionTypes,\n 'no-mixed-union-properties': noMixedUnionProperties,\n 'no-type-imports': noTypeImports,\n 'pure-functions': pureFunctions,\n 'no-vite-client': noViteClient,\n 'type-formats-imports': typeFormatsImports,\n 'enforce-type-imports': enforceTypeImports,\n } as unknown as ESLint.Plugin['rules'],\n configs: {},\n};\n\n// Flat config preset: self-contained with plugin registration and recommended rules.\n// Usage: import mionPlugin from '@mionjs/devtools/eslint'; ... mionPlugin.configs.recommended\nplugin.configs!.recommended = {\n plugins: {\n '@mionjs': plugin,\n },\n rules: {\n '@mionjs/no-typeof-runtype': 'error',\n '@mionjs/strong-typed-routes': 'error',\n '@mionjs/no-unreachable-union-types': 'error',\n '@mionjs/no-type-imports': 'error',\n '@mionjs/pure-functions': 'error',\n '@mionjs/type-formats-imports': 'error',\n // disabled as seems is not too useful and overlaps with some ts rules\n // '@mionjs/no-mixed-union-properties': 'warn',\n },\n} satisfies Linter.Config;\n\nexport default plugin;\n"],"names":["noTypeofRunType","strongTypedRoutes","noUnreachableUnionTypes","noMixedUnionProperties","noTypeImports","pureFunctions","noViteClient","typeFormatsImports","enforceTypeImports"],"mappings":";;;;;;;;;;AAmBA,MAAM,SAAwB;AAAA,EAC1B,OAAO;AAAA,IACH,qBAAqBA;AAAAA,IACrB,uBAAuBC;AAAAA,IACvB,8BAA8BC;AAAAA,IAC9B,6BAA6BC;AAAAA,IAC7B,mBAAmBC;AAAAA,IACnB,kBAAkBC;AAAAA,IAClB,kBAAkBC;AAAAA,IAClB,wBAAwBC;AAAAA,IACxB,wBAAwBC;AAAAA,EAAA;AAAA,EAE5B,SAAS,CAAA;AACb;AAIA,OAAO,QAAS,cAAc;AAAA,EAC1B,SAAS;AAAA,IACL,WAAW;AAAA,EAAA;AAAA,EAEf,OAAO;AAAA,IACH,6BAA6B;AAAA,IAC7B,+BAA+B;AAAA,IAC/B,sCAAsC;AAAA,IACtC,2BAA2B;AAAA,IAC3B,0BAA0B;AAAA,IAC1B,gCAAgC;AAAA;AAAA;AAAA,EAAA;AAIxC;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
require("./rules/no-typeof-runtype.cjs");
|
|
3
|
+
require("./rules/strong-typed-routes.cjs");
|
|
4
|
+
require("./rules/no-unreachable-union-types.cjs");
|
|
5
|
+
require("./rules/no-mixed-union-properties.cjs");
|
|
6
|
+
require("./rules/no-type-imports.cjs");
|
|
7
|
+
require("./rules/pure-functions.cjs");
|
|
8
|
+
require("./rules/no-vite-client.cjs");
|
|
9
|
+
require("./rules/type-formats-imports.cjs");
|
|
10
|
+
require("./rules/enforce-type-imports.cjs");
|
|
11
|
+
const index = require("../../index.cjs");
|
|
12
|
+
module.exports = index;
|
|
13
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const utils = require("@typescript-eslint/utils");
|
|
3
|
+
const rule = {
|
|
4
|
+
meta: {
|
|
5
|
+
type: "suggestion",
|
|
6
|
+
fixable: "code",
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Enforce type-only imports from backend code paths to prevent bundling server code into the frontend."
|
|
9
|
+
},
|
|
10
|
+
messages: {
|
|
11
|
+
enforceTypeImport: 'Import from "{{source}}" must use "import type" to avoid importing backend code into the frontend bundle.',
|
|
12
|
+
enforceTypeExport: 'Re-export from "{{source}}" must use "export type" to avoid importing backend code into the frontend bundle.',
|
|
13
|
+
sideEffectImport: 'Side-effect import from "{{source}}" imports backend code into the frontend bundle. Remove this import or use "import type".'
|
|
14
|
+
},
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
backendSources: {
|
|
20
|
+
type: "array",
|
|
21
|
+
items: { type: "string" },
|
|
22
|
+
minItems: 1,
|
|
23
|
+
description: "Array of regex patterns matching import sources that should use type-only imports."
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
required: ["backendSources"],
|
|
27
|
+
additionalProperties: false
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
defaultOptions: [{ backendSources: [] }],
|
|
32
|
+
create(context) {
|
|
33
|
+
const options = context.options[0];
|
|
34
|
+
if (!options || !options.backendSources.length) return {};
|
|
35
|
+
const patterns = options.backendSources.map((p) => new RegExp(p));
|
|
36
|
+
function matchesBackend(source) {
|
|
37
|
+
return patterns.some((p) => p.test(source));
|
|
38
|
+
}
|
|
39
|
+
function hasAllValueSpecifiers(specifiers) {
|
|
40
|
+
return specifiers.every((s) => {
|
|
41
|
+
if (s.type === utils.AST_NODE_TYPES.ImportSpecifier) return s.importKind !== "type";
|
|
42
|
+
return true;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function fixImport(fixer, node) {
|
|
46
|
+
const sourceCode = context.sourceCode;
|
|
47
|
+
if (hasAllValueSpecifiers(node.specifiers)) {
|
|
48
|
+
const importToken = sourceCode.getFirstToken(node);
|
|
49
|
+
return fixer.insertTextAfter(importToken, " type");
|
|
50
|
+
}
|
|
51
|
+
const fixes = [];
|
|
52
|
+
for (const specifier of node.specifiers) {
|
|
53
|
+
if (specifier.type === utils.AST_NODE_TYPES.ImportSpecifier && specifier.importKind !== "type") {
|
|
54
|
+
fixes.push(fixer.insertTextBefore(specifier, "type "));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return fixes;
|
|
58
|
+
}
|
|
59
|
+
function fixExport(fixer, node) {
|
|
60
|
+
const sourceCode = context.sourceCode;
|
|
61
|
+
const allValue = node.specifiers.every((s) => s.exportKind !== "type");
|
|
62
|
+
if (allValue) {
|
|
63
|
+
const exportToken = sourceCode.getFirstToken(node);
|
|
64
|
+
return fixer.insertTextAfter(exportToken, " type");
|
|
65
|
+
}
|
|
66
|
+
const fixes = [];
|
|
67
|
+
for (const specifier of node.specifiers) {
|
|
68
|
+
if (specifier.exportKind !== "type") {
|
|
69
|
+
fixes.push(fixer.insertTextBefore(specifier, "type "));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return fixes;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
ImportDeclaration(node) {
|
|
76
|
+
const source = node.source.value;
|
|
77
|
+
if (!matchesBackend(source)) return;
|
|
78
|
+
if (node.importKind === "type") return;
|
|
79
|
+
if (node.specifiers.length === 0) {
|
|
80
|
+
context.report({
|
|
81
|
+
node,
|
|
82
|
+
messageId: "sideEffectImport",
|
|
83
|
+
data: { source }
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const hasValueSpecifier = node.specifiers.some((s) => {
|
|
88
|
+
if (s.type === utils.AST_NODE_TYPES.ImportSpecifier) return s.importKind !== "type";
|
|
89
|
+
return true;
|
|
90
|
+
});
|
|
91
|
+
if (!hasValueSpecifier) return;
|
|
92
|
+
context.report({
|
|
93
|
+
node,
|
|
94
|
+
messageId: "enforceTypeImport",
|
|
95
|
+
data: { source },
|
|
96
|
+
fix(fixer) {
|
|
97
|
+
return fixImport(fixer, node);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
ExportNamedDeclaration(node) {
|
|
102
|
+
if (!node.source) return;
|
|
103
|
+
const source = node.source.value;
|
|
104
|
+
if (!matchesBackend(source)) return;
|
|
105
|
+
if (node.exportKind === "type") return;
|
|
106
|
+
const hasValueSpecifier = node.specifiers.some((s) => s.exportKind !== "type");
|
|
107
|
+
if (!hasValueSpecifier) return;
|
|
108
|
+
context.report({
|
|
109
|
+
node,
|
|
110
|
+
messageId: "enforceTypeExport",
|
|
111
|
+
data: { source },
|
|
112
|
+
fix(fixer) {
|
|
113
|
+
return fixExport(fixer, node);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
module.exports = rule;
|
|
121
|
+
//# sourceMappingURL=enforce-type-imports.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce-type-imports.cjs","sources":["../../../../../../src/eslint/rules/enforce-type-imports.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {TSESTree, TSESLint, AST_NODE_TYPES} from '@typescript-eslint/utils';\n\nexport interface Options {\n backendSources: string[];\n}\n\ntype MessageIds = 'enforceTypeImport' | 'enforceTypeExport' | 'sideEffectImport';\n\n/** Enforce type-only imports from backend code to prevent bundling server code into the frontend. */\nconst rule: TSESLint.RuleModule<MessageIds, [Options]> = {\n meta: {\n type: 'suggestion',\n fixable: 'code',\n docs: {\n description: 'Enforce type-only imports from backend code paths to prevent bundling server code into the frontend.',\n },\n messages: {\n enforceTypeImport:\n 'Import from \"{{source}}\" must use \"import type\" to avoid importing backend code into the frontend bundle.',\n enforceTypeExport:\n 'Re-export from \"{{source}}\" must use \"export type\" to avoid importing backend code into the frontend bundle.',\n sideEffectImport:\n 'Side-effect import from \"{{source}}\" imports backend code into the frontend bundle. Remove this import or use \"import type\".',\n },\n schema: [\n {\n type: 'object',\n properties: {\n backendSources: {\n type: 'array',\n items: {type: 'string'},\n minItems: 1,\n description: 'Array of regex patterns matching import sources that should use type-only imports.',\n },\n },\n required: ['backendSources'],\n additionalProperties: false,\n },\n ],\n },\n defaultOptions: [{backendSources: []}],\n create(context) {\n const options = context.options[0];\n if (!options || !options.backendSources.length) return {};\n\n const patterns = options.backendSources.map((p) => new RegExp(p));\n\n function matchesBackend(source: string): boolean {\n return patterns.some((p) => p.test(source));\n }\n\n function hasAllValueSpecifiers(specifiers: TSESTree.ImportClause[]): boolean {\n return specifiers.every((s) => {\n if (s.type === AST_NODE_TYPES.ImportSpecifier) return s.importKind !== 'type';\n return true; // default and namespace imports are always value\n });\n }\n\n function fixImport(fixer: TSESLint.RuleFixer, node: TSESTree.ImportDeclaration): TSESLint.RuleFix | TSESLint.RuleFix[] {\n const sourceCode = context.sourceCode;\n if (hasAllValueSpecifiers(node.specifiers)) {\n // convert entire declaration: insert 'type ' after 'import'\n const importToken = sourceCode.getFirstToken(node)!;\n return fixer.insertTextAfter(importToken, ' type');\n }\n // mixed: add 'type' to each value specifier\n const fixes: TSESLint.RuleFix[] = [];\n for (const specifier of node.specifiers) {\n if (specifier.type === AST_NODE_TYPES.ImportSpecifier && specifier.importKind !== 'type') {\n fixes.push(fixer.insertTextBefore(specifier, 'type '));\n }\n }\n return fixes;\n }\n\n function fixExport(\n fixer: TSESLint.RuleFixer,\n node: TSESTree.ExportNamedDeclaration\n ): TSESLint.RuleFix | TSESLint.RuleFix[] {\n const sourceCode = context.sourceCode;\n const allValue = node.specifiers.every((s) => s.exportKind !== 'type');\n if (allValue) {\n const exportToken = sourceCode.getFirstToken(node)!;\n return fixer.insertTextAfter(exportToken, ' type');\n }\n const fixes: TSESLint.RuleFix[] = [];\n for (const specifier of node.specifiers) {\n if (specifier.exportKind !== 'type') {\n fixes.push(fixer.insertTextBefore(specifier, 'type '));\n }\n }\n return fixes;\n }\n\n return {\n ImportDeclaration(node: TSESTree.ImportDeclaration) {\n const source = node.source.value;\n if (!matchesBackend(source)) return;\n if (node.importKind === 'type') return;\n\n // side-effect import (no specifiers)\n if (node.specifiers.length === 0) {\n context.report({\n node,\n messageId: 'sideEffectImport',\n data: {source},\n });\n return;\n }\n\n // check if all specifiers are already type-only\n const hasValueSpecifier = node.specifiers.some((s) => {\n if (s.type === AST_NODE_TYPES.ImportSpecifier) return s.importKind !== 'type';\n return true;\n });\n if (!hasValueSpecifier) return;\n\n context.report({\n node,\n messageId: 'enforceTypeImport',\n data: {source},\n fix(fixer) {\n return fixImport(fixer, node);\n },\n });\n },\n\n ExportNamedDeclaration(node: TSESTree.ExportNamedDeclaration) {\n if (!node.source) return;\n const source = node.source.value;\n if (!matchesBackend(source)) return;\n if (node.exportKind === 'type') return;\n\n const hasValueSpecifier = node.specifiers.some((s) => s.exportKind !== 'type');\n if (!hasValueSpecifier) return;\n\n context.report({\n node,\n messageId: 'enforceTypeExport',\n data: {source},\n fix(fixer) {\n return fixExport(fixer, node);\n },\n });\n },\n };\n },\n};\n\nexport default rule;\n"],"names":["AST_NODE_TYPES"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TSESLint } from '@typescript-eslint/utils';
|
|
2
|
+
export interface Options {
|
|
3
|
+
backendSources: string[];
|
|
4
|
+
}
|
|
5
|
+
type MessageIds = 'enforceTypeImport' | 'enforceTypeExport' | 'sideEffectImport';
|
|
6
|
+
declare const rule: TSESLint.RuleModule<MessageIds, [Options]>;
|
|
7
|
+
export default rule;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const RUN_TYPES_FORMAT_TYPES = /* @__PURE__ */ new Set(["TypeFormat"]);
|
|
4
|
+
const TYPE_FORMATS_FORMAT_TYPES = /* @__PURE__ */ new Set([
|
|
5
|
+
// Number formats (numberFormat.runtype.ts + defaultNumberFormats.ts)
|
|
6
|
+
"FormatNumber",
|
|
7
|
+
"FormatInteger",
|
|
8
|
+
"FormatFloat",
|
|
9
|
+
"FormatPositive",
|
|
10
|
+
"FormatNegative",
|
|
11
|
+
"FormatPositiveInt",
|
|
12
|
+
"FormatNegativeInt",
|
|
13
|
+
"FormatInt8",
|
|
14
|
+
"FormatInt16",
|
|
15
|
+
"FormatInt32",
|
|
16
|
+
"FormatUInt8",
|
|
17
|
+
"FormatUInt16",
|
|
18
|
+
"FormatUInt32",
|
|
19
|
+
// BigInt formats (bigIntFormat.runtype.ts + defaultBigNumberFormats.ts)
|
|
20
|
+
"FormatBigInt",
|
|
21
|
+
"FormatBigPositive",
|
|
22
|
+
"FormatBigNegative",
|
|
23
|
+
"FormatBigPositiveInt",
|
|
24
|
+
"FormatBigNegativeInt",
|
|
25
|
+
"FormatBigInt64",
|
|
26
|
+
"FormatBigUInt64",
|
|
27
|
+
// String format base (stringFormat.runtype.ts)
|
|
28
|
+
"FormatString",
|
|
29
|
+
// Date/Time formats (date.runtype.ts, time.runtype.ts, dateTime.runtype.ts)
|
|
30
|
+
"FormatStringDate",
|
|
31
|
+
"FormatStringTime",
|
|
32
|
+
"FormatStringDateTime",
|
|
33
|
+
// Email formats (email.runtype.ts)
|
|
34
|
+
"FormatEmail",
|
|
35
|
+
"FormatEmailStrict",
|
|
36
|
+
"FormatEmailPattern",
|
|
37
|
+
"FormatEmailPunycode",
|
|
38
|
+
// Domain formats (domain.runtype.ts)
|
|
39
|
+
"FormatDomain",
|
|
40
|
+
"FormatDomainStrict",
|
|
41
|
+
// URL formats (url.runtype.ts)
|
|
42
|
+
"FormatUrl",
|
|
43
|
+
"FormatUrlFile",
|
|
44
|
+
"FormatUrlHttp",
|
|
45
|
+
"FormatUrlSocialMedia",
|
|
46
|
+
// IP formats (ip.runtype.ts)
|
|
47
|
+
"FormatIP",
|
|
48
|
+
"FormatIPv4",
|
|
49
|
+
"FormatIPv6",
|
|
50
|
+
"FormatIPWithPort",
|
|
51
|
+
"FormatIPv4WithPort",
|
|
52
|
+
"FormatIPv6WithPort",
|
|
53
|
+
// UUID formats (uuid.runtype.ts)
|
|
54
|
+
"FormatUUIDv4",
|
|
55
|
+
"FormatUUIDv7",
|
|
56
|
+
// Default string formats (defaultStringFormats.runtype.ts)
|
|
57
|
+
"FormatAlphaNumeric",
|
|
58
|
+
"FormatAlpha",
|
|
59
|
+
"FormatNumeric",
|
|
60
|
+
"FormatLowercase",
|
|
61
|
+
"FormatUppercase",
|
|
62
|
+
"FormatCapitalize"
|
|
63
|
+
]);
|
|
64
|
+
const FORMAT_TYPES_BY_PACKAGE = /* @__PURE__ */ new Map([
|
|
65
|
+
["@mionjs/run-types", RUN_TYPES_FORMAT_TYPES],
|
|
66
|
+
["@mionjs/type-formats", TYPE_FORMATS_FORMAT_TYPES]
|
|
67
|
+
]);
|
|
68
|
+
exports.FORMAT_TYPES_BY_PACKAGE = FORMAT_TYPES_BY_PACKAGE;
|
|
69
|
+
exports.RUN_TYPES_FORMAT_TYPES = RUN_TYPES_FORMAT_TYPES;
|
|
70
|
+
exports.TYPE_FORMATS_FORMAT_TYPES = TYPE_FORMATS_FORMAT_TYPES;
|
|
71
|
+
//# sourceMappingURL=formatTypeNames.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatTypeNames.cjs","sources":["../../../../../../src/eslint/rules/formatTypeNames.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\n/**\n * Single source of truth for all TypeFormat type names that must NOT use `import type`.\n * Deepkit's type compiler needs actual imports to preserve type metadata for runtime reflection.\n * When new format types are added to @mionjs/type-formats or @mionjs/run-types, update this file.\n */\n\n/** Format type names from @mionjs/run-types that must not use `import type` */\nexport const RUN_TYPES_FORMAT_TYPES = new Set(['TypeFormat']);\n\n/** Format type names from @mionjs/type-formats that must not use `import type` */\nexport const TYPE_FORMATS_FORMAT_TYPES = new Set([\n // Number formats (numberFormat.runtype.ts + defaultNumberFormats.ts)\n 'FormatNumber',\n 'FormatInteger',\n 'FormatFloat',\n 'FormatPositive',\n 'FormatNegative',\n 'FormatPositiveInt',\n 'FormatNegativeInt',\n 'FormatInt8',\n 'FormatInt16',\n 'FormatInt32',\n 'FormatUInt8',\n 'FormatUInt16',\n 'FormatUInt32',\n\n // BigInt formats (bigIntFormat.runtype.ts + defaultBigNumberFormats.ts)\n 'FormatBigInt',\n 'FormatBigPositive',\n 'FormatBigNegative',\n 'FormatBigPositiveInt',\n 'FormatBigNegativeInt',\n 'FormatBigInt64',\n 'FormatBigUInt64',\n\n // String format base (stringFormat.runtype.ts)\n 'FormatString',\n\n // Date/Time formats (date.runtype.ts, time.runtype.ts, dateTime.runtype.ts)\n 'FormatStringDate',\n 'FormatStringTime',\n 'FormatStringDateTime',\n\n // Email formats (email.runtype.ts)\n 'FormatEmail',\n 'FormatEmailStrict',\n 'FormatEmailPattern',\n 'FormatEmailPunycode',\n\n // Domain formats (domain.runtype.ts)\n 'FormatDomain',\n 'FormatDomainStrict',\n\n // URL formats (url.runtype.ts)\n 'FormatUrl',\n 'FormatUrlFile',\n 'FormatUrlHttp',\n 'FormatUrlSocialMedia',\n\n // IP formats (ip.runtype.ts)\n 'FormatIP',\n 'FormatIPv4',\n 'FormatIPv6',\n 'FormatIPWithPort',\n 'FormatIPv4WithPort',\n 'FormatIPv6WithPort',\n\n // UUID formats (uuid.runtype.ts)\n 'FormatUUIDv4',\n 'FormatUUIDv7',\n\n // Default string formats (defaultStringFormats.runtype.ts)\n 'FormatAlphaNumeric',\n 'FormatAlpha',\n 'FormatNumeric',\n 'FormatLowercase',\n 'FormatUppercase',\n 'FormatCapitalize',\n]);\n\n/** Maps a source package prefix to the set of format type names from that package */\nexport const FORMAT_TYPES_BY_PACKAGE = new Map<string, Set<string>>([\n ['@mionjs/run-types', RUN_TYPES_FORMAT_TYPES],\n ['@mionjs/type-formats', TYPE_FORMATS_FORMAT_TYPES],\n]);\n"],"names":[],"mappings":";;AAcO,MAAM,yBAAyB,oBAAI,IAAI,CAAC,YAAY,CAAC;AAGrD,MAAM,gDAAgC,IAAI;AAAA;AAAA,EAE7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAGM,MAAM,8CAA8B,IAAyB;AAAA,EAChE,CAAC,qBAAqB,sBAAsB;AAAA,EAC5C,CAAC,wBAAwB,yBAAyB;AACtD,CAAC;;;;"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const utils = require("@typescript-eslint/utils");
|
|
3
|
+
function getObjectTypeProperties(node) {
|
|
4
|
+
if (node.type === utils.AST_NODE_TYPES.TSTypeLiteral) {
|
|
5
|
+
const props = [];
|
|
6
|
+
for (const member of node.members) {
|
|
7
|
+
if (member.type === utils.AST_NODE_TYPES.TSPropertySignature && member.key.type === utils.AST_NODE_TYPES.Identifier) {
|
|
8
|
+
props.push({ name: member.key.name, isOptional: !!member.optional });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return props;
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
function getUnionObjectTypes(unionNode) {
|
|
16
|
+
const types = [];
|
|
17
|
+
for (const typeNode of unionNode.types) {
|
|
18
|
+
const props = getObjectTypeProperties(typeNode);
|
|
19
|
+
if (props && props.length > 0) {
|
|
20
|
+
types.push({ node: typeNode, properties: props });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return types;
|
|
24
|
+
}
|
|
25
|
+
function getObjectLiteralPropertyNames(node) {
|
|
26
|
+
const names = [];
|
|
27
|
+
for (const prop of node.properties) {
|
|
28
|
+
if (prop.type === utils.AST_NODE_TYPES.Property && prop.key.type === utils.AST_NODE_TYPES.Identifier) {
|
|
29
|
+
names.push(prop.key.name);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return names;
|
|
33
|
+
}
|
|
34
|
+
function getMatchingUnionTypes(objectProps, unionTypes) {
|
|
35
|
+
const matchingIndices = [];
|
|
36
|
+
for (let i = 0; i < unionTypes.length; i++) {
|
|
37
|
+
const unionPropNames = new Set(unionTypes[i].properties.map((p) => p.name));
|
|
38
|
+
if (objectProps.some((prop) => unionPropNames.has(prop))) {
|
|
39
|
+
matchingIndices.push(i);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return matchingIndices;
|
|
43
|
+
}
|
|
44
|
+
function getUniquePropertiesPerType(unionTypes) {
|
|
45
|
+
const allProps = /* @__PURE__ */ new Map();
|
|
46
|
+
for (let i = 0; i < unionTypes.length; i++) {
|
|
47
|
+
for (const prop of unionTypes[i].properties) {
|
|
48
|
+
const existing = allProps.get(prop.name) || [];
|
|
49
|
+
existing.push(i);
|
|
50
|
+
allProps.set(prop.name, existing);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const uniqueProps = /* @__PURE__ */ new Map();
|
|
54
|
+
for (let i = 0; i < unionTypes.length; i++) {
|
|
55
|
+
const unique = /* @__PURE__ */ new Set();
|
|
56
|
+
for (const prop of unionTypes[i].properties) {
|
|
57
|
+
if ((allProps.get(prop.name) || []).length === 1) {
|
|
58
|
+
unique.add(prop.name);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
uniqueProps.set(i, unique);
|
|
62
|
+
}
|
|
63
|
+
return uniqueProps;
|
|
64
|
+
}
|
|
65
|
+
function resolveTypeReference(node, context) {
|
|
66
|
+
if (node.type !== utils.AST_NODE_TYPES.TSTypeReference) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
if (node.typeName.type !== utils.AST_NODE_TYPES.Identifier) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const typeName = node.typeName.name;
|
|
73
|
+
const sourceCode = context.sourceCode;
|
|
74
|
+
const program = sourceCode.ast;
|
|
75
|
+
for (const statement of program.body) {
|
|
76
|
+
if (statement.type === utils.AST_NODE_TYPES.TSTypeAliasDeclaration) {
|
|
77
|
+
if (statement.id.name === typeName && statement.typeAnnotation.type === utils.AST_NODE_TYPES.TSUnionType) {
|
|
78
|
+
return statement.typeAnnotation;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function getReturnTypeAnnotation(func, context) {
|
|
85
|
+
const returnType = func.returnType?.typeAnnotation;
|
|
86
|
+
if (!returnType) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (returnType.type === utils.AST_NODE_TYPES.TSUnionType) {
|
|
90
|
+
return returnType;
|
|
91
|
+
}
|
|
92
|
+
if (returnType.type === utils.AST_NODE_TYPES.TSTypeReference) {
|
|
93
|
+
return resolveTypeReference(returnType, context);
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function findReturnStatements(func) {
|
|
98
|
+
const returns = [];
|
|
99
|
+
if (func.type === utils.AST_NODE_TYPES.ArrowFunctionExpression && func.expression && func.body.type !== utils.AST_NODE_TYPES.BlockStatement) {
|
|
100
|
+
returns.push(func.body);
|
|
101
|
+
return returns;
|
|
102
|
+
}
|
|
103
|
+
if (func.body.type === utils.AST_NODE_TYPES.BlockStatement) {
|
|
104
|
+
findReturnsInBlock(func.body, returns);
|
|
105
|
+
}
|
|
106
|
+
return returns;
|
|
107
|
+
}
|
|
108
|
+
function findReturnsInBlock(block, returns) {
|
|
109
|
+
for (const statement of block.body) {
|
|
110
|
+
if (statement.type === utils.AST_NODE_TYPES.ReturnStatement && statement.argument) {
|
|
111
|
+
returns.push(statement.argument);
|
|
112
|
+
} else if (statement.type === utils.AST_NODE_TYPES.IfStatement) {
|
|
113
|
+
if (statement.consequent.type === utils.AST_NODE_TYPES.BlockStatement) {
|
|
114
|
+
findReturnsInBlock(statement.consequent, returns);
|
|
115
|
+
} else if (statement.consequent.type === utils.AST_NODE_TYPES.ReturnStatement && statement.consequent.argument) {
|
|
116
|
+
returns.push(statement.consequent.argument);
|
|
117
|
+
}
|
|
118
|
+
if (statement.alternate?.type === utils.AST_NODE_TYPES.BlockStatement) {
|
|
119
|
+
findReturnsInBlock(statement.alternate, returns);
|
|
120
|
+
} else if (statement.alternate?.type === utils.AST_NODE_TYPES.ReturnStatement && statement.alternate.argument) {
|
|
121
|
+
returns.push(statement.alternate.argument);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function getConflictDescription(objectProps, unionTypes, matchingIndices) {
|
|
127
|
+
const uniqueProps = getUniquePropertiesPerType(unionTypes);
|
|
128
|
+
const conflicts = [];
|
|
129
|
+
for (const idx of matchingIndices) {
|
|
130
|
+
const unique = uniqueProps.get(idx) || /* @__PURE__ */ new Set();
|
|
131
|
+
const matchingProps = objectProps.filter((p) => unique.has(p));
|
|
132
|
+
if (matchingProps.length > 0) {
|
|
133
|
+
conflicts.push(`'${matchingProps.join("', '")}' from type ${idx + 1}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return conflicts.join(" and ");
|
|
137
|
+
}
|
|
138
|
+
function isRouterFunction(node, context) {
|
|
139
|
+
let current = node;
|
|
140
|
+
while (current) {
|
|
141
|
+
if (current.type === utils.AST_NODE_TYPES.CallExpression) {
|
|
142
|
+
return isRouterFunctionCall(current, context);
|
|
143
|
+
}
|
|
144
|
+
current = current.parent;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
function isRouterFunctionCall(node, context) {
|
|
149
|
+
const routerFunctions = ["route", "middleFn", "headersFn"];
|
|
150
|
+
if (node.callee.type !== utils.AST_NODE_TYPES.Identifier || !routerFunctions.includes(node.callee.name)) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
return isImportedFromMionRouter(node.callee.name, context);
|
|
154
|
+
}
|
|
155
|
+
function isImportedFromMionRouter(name, context) {
|
|
156
|
+
const sourceCode = context.sourceCode;
|
|
157
|
+
const program = sourceCode.ast;
|
|
158
|
+
for (const statement of program.body) {
|
|
159
|
+
if (statement.type === utils.AST_NODE_TYPES.ImportDeclaration) {
|
|
160
|
+
const source = statement.source.value;
|
|
161
|
+
if (source === "@mionjs/router" || source === "@mionjs/router/") {
|
|
162
|
+
for (const specifier of statement.specifiers) {
|
|
163
|
+
if (specifier.type === utils.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === utils.AST_NODE_TYPES.Identifier && specifier.imported.name === name) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
function checkFunction(func, context) {
|
|
173
|
+
if (!isRouterFunction(func, context)) return;
|
|
174
|
+
const unionType = getReturnTypeAnnotation(func, context);
|
|
175
|
+
if (!unionType) return;
|
|
176
|
+
const unionTypes = getUnionObjectTypes(unionType);
|
|
177
|
+
if (unionTypes.length < 2) return;
|
|
178
|
+
const returnStatements = findReturnStatements(func);
|
|
179
|
+
for (const returnNode of returnStatements) {
|
|
180
|
+
if (returnNode.type !== utils.AST_NODE_TYPES.ObjectExpression) continue;
|
|
181
|
+
const objectProps = getObjectLiteralPropertyNames(returnNode);
|
|
182
|
+
if (objectProps.length === 0) continue;
|
|
183
|
+
const matchingIndices = getMatchingUnionTypes(objectProps, unionTypes);
|
|
184
|
+
const uniqueProps = getUniquePropertiesPerType(unionTypes);
|
|
185
|
+
const typesWithUniqueMatches = matchingIndices.filter((idx) => {
|
|
186
|
+
const unique = uniqueProps.get(idx) || /* @__PURE__ */ new Set();
|
|
187
|
+
return objectProps.some((prop) => unique.has(prop));
|
|
188
|
+
});
|
|
189
|
+
if (typesWithUniqueMatches.length > 1) {
|
|
190
|
+
const conflicts = getConflictDescription(objectProps, unionTypes, typesWithUniqueMatches);
|
|
191
|
+
context.report({ node: returnNode, messageId: "mixedUnionProperties", data: { conflicts } });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const rule = {
|
|
196
|
+
meta: {
|
|
197
|
+
type: "problem",
|
|
198
|
+
docs: { description: "Detect object literals with properties from multiple union types in router handlers" },
|
|
199
|
+
messages: {
|
|
200
|
+
mixedUnionProperties: "Object literal has properties from multiple union types: {{conflicts}}. With loose union matching, only the first matching type will be used for serialization."
|
|
201
|
+
},
|
|
202
|
+
schema: []
|
|
203
|
+
},
|
|
204
|
+
defaultOptions: [],
|
|
205
|
+
create(context) {
|
|
206
|
+
return {
|
|
207
|
+
ArrowFunctionExpression(node) {
|
|
208
|
+
checkFunction(node, context);
|
|
209
|
+
},
|
|
210
|
+
FunctionExpression(node) {
|
|
211
|
+
checkFunction(node, context);
|
|
212
|
+
},
|
|
213
|
+
FunctionDeclaration(node) {
|
|
214
|
+
checkFunction(node, context);
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
module.exports = rule;
|
|
220
|
+
//# sourceMappingURL=no-mixed-union-properties.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-mixed-union-properties.cjs","sources":["../../../../../../src/eslint/rules/no-mixed-union-properties.ts"],"sourcesContent":["/* ########\n * 2024 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {TSESTree, TSESLint, AST_NODE_TYPES} from '@typescript-eslint/utils';\n\ntype PropertyInfo = {name: string; isOptional: boolean};\ntype UnionTypeInfo = {node: TSESTree.TypeNode; properties: PropertyInfo[]};\n\nfunction getObjectTypeProperties(node: TSESTree.TypeNode): PropertyInfo[] | null {\n if (node.type === AST_NODE_TYPES.TSTypeLiteral) {\n const props: PropertyInfo[] = [];\n for (const member of node.members) {\n if (member.type === AST_NODE_TYPES.TSPropertySignature && member.key.type === AST_NODE_TYPES.Identifier) {\n props.push({name: member.key.name, isOptional: !!member.optional});\n }\n }\n return props;\n }\n return null;\n}\n\nfunction getUnionObjectTypes(unionNode: TSESTree.TSUnionType): UnionTypeInfo[] {\n const types: UnionTypeInfo[] = [];\n for (const typeNode of unionNode.types) {\n const props = getObjectTypeProperties(typeNode);\n if (props && props.length > 0) {\n types.push({node: typeNode, properties: props});\n }\n }\n return types;\n}\n\nfunction getObjectLiteralPropertyNames(node: TSESTree.ObjectExpression): string[] {\n const names: string[] = [];\n for (const prop of node.properties) {\n if (prop.type === AST_NODE_TYPES.Property && prop.key.type === AST_NODE_TYPES.Identifier) {\n names.push(prop.key.name);\n }\n }\n return names;\n}\n\nfunction getMatchingUnionTypes(objectProps: string[], unionTypes: UnionTypeInfo[]): number[] {\n const matchingIndices: number[] = [];\n for (let i = 0; i < unionTypes.length; i++) {\n const unionPropNames = new Set(unionTypes[i].properties.map((p) => p.name));\n if (objectProps.some((prop) => unionPropNames.has(prop))) {\n matchingIndices.push(i);\n }\n }\n return matchingIndices;\n}\n\nfunction getUniquePropertiesPerType(unionTypes: UnionTypeInfo[]): Map<number, Set<string>> {\n const allProps = new Map<string, number[]>();\n for (let i = 0; i < unionTypes.length; i++) {\n for (const prop of unionTypes[i].properties) {\n const existing = allProps.get(prop.name) || [];\n existing.push(i);\n allProps.set(prop.name, existing);\n }\n }\n const uniqueProps = new Map<number, Set<string>>();\n for (let i = 0; i < unionTypes.length; i++) {\n const unique = new Set<string>();\n for (const prop of unionTypes[i].properties) {\n if ((allProps.get(prop.name) || []).length === 1) {\n unique.add(prop.name);\n }\n }\n uniqueProps.set(i, unique);\n }\n return uniqueProps;\n}\n\n/**\n * Resolves a type reference to its actual union type definition\n */\nfunction resolveTypeReference(node: TSESTree.TypeNode, context: TSESLint.RuleContext<any, any>): TSESTree.TSUnionType | null {\n if (node.type !== AST_NODE_TYPES.TSTypeReference) {\n return null;\n }\n\n // Get the type name\n if (node.typeName.type !== AST_NODE_TYPES.Identifier) {\n return null;\n }\n\n const typeName = node.typeName.name;\n const sourceCode = context.sourceCode;\n const program = sourceCode.ast;\n\n // Find the type alias declaration\n for (const statement of program.body) {\n if (statement.type === AST_NODE_TYPES.TSTypeAliasDeclaration) {\n if (statement.id.name === typeName && statement.typeAnnotation.type === AST_NODE_TYPES.TSUnionType) {\n return statement.typeAnnotation;\n }\n }\n }\n\n return null;\n}\n\nfunction getReturnTypeAnnotation(\n func: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | TSESTree.FunctionDeclaration,\n context: TSESLint.RuleContext<any, any>\n): TSESTree.TSUnionType | null {\n const returnType = func.returnType?.typeAnnotation;\n if (!returnType) {\n return null;\n }\n\n // Direct union type\n if (returnType.type === AST_NODE_TYPES.TSUnionType) {\n return returnType;\n }\n\n // Type reference that might resolve to a union type\n if (returnType.type === AST_NODE_TYPES.TSTypeReference) {\n return resolveTypeReference(returnType, context);\n }\n\n return null;\n}\n\nfunction findReturnStatements(\n func: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | TSESTree.FunctionDeclaration\n): TSESTree.Node[] {\n const returns: TSESTree.Node[] = [];\n if (\n func.type === AST_NODE_TYPES.ArrowFunctionExpression &&\n func.expression &&\n func.body.type !== AST_NODE_TYPES.BlockStatement\n ) {\n returns.push(func.body);\n return returns;\n }\n if (func.body.type === AST_NODE_TYPES.BlockStatement) {\n findReturnsInBlock(func.body, returns);\n }\n return returns;\n}\n\nfunction findReturnsInBlock(block: TSESTree.BlockStatement, returns: TSESTree.Node[]): void {\n for (const statement of block.body) {\n if (statement.type === AST_NODE_TYPES.ReturnStatement && statement.argument) {\n returns.push(statement.argument);\n } else if (statement.type === AST_NODE_TYPES.IfStatement) {\n if (statement.consequent.type === AST_NODE_TYPES.BlockStatement) {\n findReturnsInBlock(statement.consequent, returns);\n } else if (statement.consequent.type === AST_NODE_TYPES.ReturnStatement && statement.consequent.argument) {\n returns.push(statement.consequent.argument);\n }\n if (statement.alternate?.type === AST_NODE_TYPES.BlockStatement) {\n findReturnsInBlock(statement.alternate, returns);\n } else if (statement.alternate?.type === AST_NODE_TYPES.ReturnStatement && statement.alternate.argument) {\n returns.push(statement.alternate.argument);\n }\n }\n }\n}\n\nfunction getConflictDescription(objectProps: string[], unionTypes: UnionTypeInfo[], matchingIndices: number[]): string {\n const uniqueProps = getUniquePropertiesPerType(unionTypes);\n const conflicts: string[] = [];\n for (const idx of matchingIndices) {\n const unique = uniqueProps.get(idx) || new Set();\n const matchingProps = objectProps.filter((p) => unique.has(p));\n if (matchingProps.length > 0) {\n conflicts.push(`'${matchingProps.join(\"', '\")}' from type ${idx + 1}`);\n }\n }\n return conflicts.join(' and ');\n}\n\nfunction isRouterFunction(node: TSESTree.Node, context: TSESLint.RuleContext<any, any>): boolean {\n let current: TSESTree.Node | undefined = node;\n while (current) {\n if (current.type === AST_NODE_TYPES.CallExpression) {\n return isRouterFunctionCall(current, context);\n }\n current = current.parent;\n }\n return false;\n}\n\nfunction isRouterFunctionCall(node: TSESTree.CallExpression, context: TSESLint.RuleContext<any, any>): boolean {\n const routerFunctions = ['route', 'middleFn', 'headersFn'];\n if (node.callee.type !== AST_NODE_TYPES.Identifier || !routerFunctions.includes(node.callee.name)) {\n return false;\n }\n return isImportedFromMionRouter(node.callee.name, context);\n}\n\nfunction isImportedFromMionRouter(name: string, context: TSESLint.RuleContext<any, any>): boolean {\n const sourceCode = context.sourceCode;\n const program = sourceCode.ast;\n for (const statement of program.body) {\n if (statement.type === AST_NODE_TYPES.ImportDeclaration) {\n const source = statement.source.value;\n if (source === '@mionjs/router' || source === '@mionjs/router/') {\n for (const specifier of statement.specifiers) {\n if (\n specifier.type === AST_NODE_TYPES.ImportSpecifier &&\n specifier.imported.type === AST_NODE_TYPES.Identifier &&\n specifier.imported.name === name\n ) {\n return true;\n }\n }\n }\n }\n }\n return false;\n}\n\nfunction checkFunction(\n func: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | TSESTree.FunctionDeclaration,\n context: TSESLint.RuleContext<'mixedUnionProperties', []>\n) {\n if (!isRouterFunction(func, context)) return;\n const unionType = getReturnTypeAnnotation(func, context);\n if (!unionType) return;\n const unionTypes = getUnionObjectTypes(unionType);\n if (unionTypes.length < 2) return;\n const returnStatements = findReturnStatements(func);\n for (const returnNode of returnStatements) {\n if (returnNode.type !== AST_NODE_TYPES.ObjectExpression) continue;\n const objectProps = getObjectLiteralPropertyNames(returnNode);\n if (objectProps.length === 0) continue;\n const matchingIndices = getMatchingUnionTypes(objectProps, unionTypes);\n const uniqueProps = getUniquePropertiesPerType(unionTypes);\n const typesWithUniqueMatches = matchingIndices.filter((idx) => {\n const unique = uniqueProps.get(idx) || new Set();\n return objectProps.some((prop) => unique.has(prop));\n });\n if (typesWithUniqueMatches.length > 1) {\n const conflicts = getConflictDescription(objectProps, unionTypes, typesWithUniqueMatches);\n context.report({node: returnNode, messageId: 'mixedUnionProperties', data: {conflicts}});\n }\n }\n}\n\nconst rule: TSESLint.RuleModule<'mixedUnionProperties', []> = {\n meta: {\n type: 'problem',\n docs: {description: 'Detect object literals with properties from multiple union types in router handlers'},\n messages: {\n mixedUnionProperties:\n 'Object literal has properties from multiple union types: {{conflicts}}. ' +\n 'With loose union matching, only the first matching type will be used for serialization.',\n },\n schema: [],\n },\n defaultOptions: [],\n create(context) {\n return {\n ArrowFunctionExpression(node: TSESTree.ArrowFunctionExpression) {\n checkFunction(node, context);\n },\n FunctionExpression(node: TSESTree.FunctionExpression) {\n checkFunction(node, context);\n },\n FunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n checkFunction(node, context);\n },\n };\n },\n};\n\nexport default rule;\n"],"names":["AST_NODE_TYPES"],"mappings":"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"}
|