@ivanmaxlogiudice/eslint-config 3.0.0-beta.4 → 3.0.0-beta.6

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/dist/index.js CHANGED
@@ -85,7 +85,10 @@ import { spawn } from "node:child_process";
85
85
  import fs from "node:fs";
86
86
  import path from "node:path";
87
87
  import process from "node:process";
88
- var cachePkg;
88
+ import { fileURLToPath } from "node:url";
89
+ import { isPackageExists } from "local-pkg";
90
+ var scopeUrl = fileURLToPath(new URL(".", import.meta.url));
91
+ var isCwdInScope = isPackageExists("@ivanmaxlogiudice/eslint-config");
89
92
  async function combine(...configs) {
90
93
  const resolved = await Promise.all(configs);
91
94
  return resolved.flat();
@@ -101,11 +104,11 @@ function renameRules(rules, from, to) {
101
104
  }
102
105
  return renamed;
103
106
  }
104
- function clearPackageCache() {
105
- cachePkg = void 0;
106
- }
107
107
  function hasSomePackage(names) {
108
- return names.some((name) => packageExists(name));
108
+ return names.some((name) => isPackageInScope(name));
109
+ }
110
+ function isPackageInScope(name) {
111
+ return isPackageExists(name, { paths: [scopeUrl] });
109
112
  }
110
113
  function findUp(file, cwd = process.cwd(), depth = 3) {
111
114
  let currentPath = cwd;
@@ -118,21 +121,10 @@ function findUp(file, cwd = process.cwd(), depth = 3) {
118
121
  }
119
122
  return null;
120
123
  }
121
- function packageExists(name) {
122
- if (!cachePkg) {
123
- const pkgPath = findUp("package.json");
124
- if (!pkgPath) {
125
- throw new Error('Can not found "package.json".');
126
- }
127
- const pkgContent = fs.readFileSync(pkgPath, "utf-8");
128
- cachePkg = JSON.parse(pkgContent);
129
- }
130
- return cachePkg?.dependencies?.[name] !== void 0 || cachePkg?.devDependencies?.[name] !== void 0;
131
- }
132
124
  async function ensurePackages(packages) {
133
- if (process.env.CI || process.stdout.isTTY === false)
125
+ if (process.env.CI || process.stdout.isTTY === false || isCwdInScope === false)
134
126
  return;
135
- const missingPackages = packages.filter((i) => i && !packageExists(i));
127
+ const missingPackages = packages.filter((i) => i && !isPackageInScope(i));
136
128
  if (missingPackages.length === 0)
137
129
  return;
138
130
  console.log(`
@@ -148,7 +140,14 @@ async function interopDefault(m) {
148
140
  return resolved.default || resolved;
149
141
  }
150
142
  function isInEditorEnv() {
151
- return !!((process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM) && !process.env.CI);
143
+ if (process.env.CI)
144
+ return false;
145
+ if (isInGitHooksOrLintStaged())
146
+ return false;
147
+ return !!(process.env.VSCODE_PID || process.env.VSCODE_CWD || process.env.JETBRAINS_IDE || process.env.VIM || process.env.NVIM);
148
+ }
149
+ function isInGitHooksOrLintStaged() {
150
+ return !!(process.env.GIT_PARAMS || process.env.VSCODE_GIT_COMMAND || process.env.npm_lifecycle_script?.startsWith("lint-staged"));
152
151
  }
153
152
  async function spawnAsync(command, args, options) {
154
153
  return new Promise((resolve, reject) => {
@@ -474,7 +473,7 @@ function jsdoc() {
474
473
 
475
474
  // src/configs/jsonc.ts
476
475
  import plugin4 from "eslint-plugin-jsonc";
477
- import parser from "jsonc-eslint-parser";
476
+ import * as parser from "jsonc-eslint-parser";
478
477
  function jsonc(options = {}) {
479
478
  const {
480
479
  files = [GLOB_JSON, GLOB_JSON5, GLOB_JSONC],
@@ -545,12 +544,12 @@ async function markdown(options = {}) {
545
544
  overrides = {}
546
545
  } = options;
547
546
  await ensurePackages(["eslint-plugin-markdown"]);
548
- const plugin10 = await interopDefault(import("eslint-plugin-markdown"));
547
+ const plugin9 = await interopDefault(import("eslint-plugin-markdown"));
549
548
  return [
550
549
  {
551
550
  name: "ivanmaxlogiudice/markdown/setup",
552
551
  plugins: {
553
- markdown: plugin10
552
+ markdown: plugin9
554
553
  }
555
554
  },
556
555
  {
@@ -668,15 +667,15 @@ async function regexp(options = {}) {
668
667
  overrides = {}
669
668
  } = options;
670
669
  await ensurePackages(["eslint-plugin-regexp"]);
671
- const plugin10 = await interopDefault(import("eslint-plugin-regexp"));
670
+ const plugin9 = await interopDefault(import("eslint-plugin-regexp"));
672
671
  return [
673
672
  {
674
673
  name: "ivanmaxlogiudice/regexp/rules",
675
674
  plugins: {
676
- regexp: plugin10
675
+ regexp: plugin9
677
676
  },
678
677
  rules: {
679
- ...plugin10.configs["flat/recommended"].rules,
678
+ ...plugin9.configs["flat/recommended"].rules,
680
679
  ...overrides
681
680
  }
682
681
  }
@@ -971,41 +970,93 @@ async function test(options = {}) {
971
970
  }
972
971
 
973
972
  // src/configs/typescript.ts
974
- import plugin8 from "@typescript-eslint/eslint-plugin";
975
- import parser2 from "@typescript-eslint/parser";
976
- function typescript(options = {}) {
973
+ import process2 from "node:process";
974
+ async function typescript(options = {}) {
977
975
  const {
978
976
  componentExts = [],
979
977
  overrides = {},
978
+ overridesTypeAware = {},
979
+ parserOptions = {},
980
980
  type = "app"
981
981
  } = options;
982
982
  const files = options.files ?? [GLOB_TS, ...componentExts.map((ext) => `**/*.${ext}`)];
983
- return [
984
- {
985
- name: "ivanmaxlogiudice/typescript/setup",
986
- plugins: {
987
- ts: plugin8
988
- }
989
- },
990
- {
991
- name: "ivanmaxlogiudice/typescript/parser",
992
- files,
983
+ const filesTypeAware = options.filesTypeAware ?? [GLOB_TS];
984
+ const ignoresTypeAware = options.ignoresTypeAware ?? [`${GLOB_MARKDOWN}/**`];
985
+ const tsconfigPath = options?.tsconfigPath ? options.tsconfigPath : void 0;
986
+ const isTypeAware = !!tsconfigPath;
987
+ const typeAwareRules = {
988
+ "dot-notation": "off",
989
+ "no-implied-eval": "off",
990
+ "ts/await-thenable": "error",
991
+ "ts/dot-notation": ["error", { allowKeywords: true }],
992
+ "ts/no-floating-promises": "error",
993
+ "ts/no-for-in-array": "error",
994
+ "ts/no-implied-eval": "error",
995
+ "ts/no-misused-promises": "error",
996
+ "ts/no-unnecessary-type-assertion": "error",
997
+ "ts/no-unsafe-argument": "error",
998
+ "ts/no-unsafe-assignment": "error",
999
+ "ts/no-unsafe-call": "error",
1000
+ "ts/no-unsafe-member-access": "error",
1001
+ "ts/no-unsafe-return": "error",
1002
+ "ts/promise-function-async": "error",
1003
+ "ts/restrict-plus-operands": "error",
1004
+ "ts/restrict-template-expressions": "error",
1005
+ "ts/return-await": ["error", "in-try-catch"],
1006
+ "ts/strict-boolean-expressions": ["error", { allowNullableBoolean: true, allowNullableObject: true }],
1007
+ "ts/switch-exhaustiveness-check": "error",
1008
+ "ts/unbound-method": "error"
1009
+ };
1010
+ const [plugin9, parser2] = await Promise.all([
1011
+ interopDefault(import("@typescript-eslint/eslint-plugin")),
1012
+ interopDefault(import("@typescript-eslint/parser"))
1013
+ ]);
1014
+ function makeParser(typeAware, files2, ignores2) {
1015
+ return {
1016
+ files: files2,
1017
+ ...ignores2 ? { ignores: ignores2 } : {},
1018
+ name: `ivanmaxlogiudice/typescript/${typeAware ? "type-aware-parser" : "parser"}`,
993
1019
  languageOptions: {
994
1020
  parser: parser2,
995
1021
  parserOptions: {
996
1022
  extraFileExtensions: componentExts.map((ext) => `.${ext}`),
997
- sourceType: "module"
1023
+ sourceType: "module",
1024
+ ...typeAware ? {
1025
+ projectService: {
1026
+ allowDefaultProject: ["./*.js"],
1027
+ defaultProject: tsconfigPath
1028
+ },
1029
+ tsconfigRootDir: process2.cwd()
1030
+ } : {},
1031
+ ...parserOptions
998
1032
  }
999
1033
  }
1034
+ };
1035
+ }
1036
+ return [
1037
+ {
1038
+ // Install the plugins without globs, so they can be configured separately.
1039
+ name: "ivanmaxlogiudice/typescript/setup",
1040
+ plugins: {
1041
+ ts: plugin9
1042
+ }
1000
1043
  },
1044
+ // assign type-aware parser for type-aware files and type-unaware parser for the rest
1045
+ ...isTypeAware ? [
1046
+ makeParser(false, files),
1047
+ makeParser(true, filesTypeAware, ignoresTypeAware)
1048
+ ] : [
1049
+ makeParser(false, files)
1050
+ ],
1001
1051
  {
1002
1052
  name: "ivanmaxlogiudice/typescript/rules",
1003
1053
  files,
1004
1054
  rules: {
1005
1055
  // Disable eslint rules which are already handled by TypeScript.
1006
- ...renameRules(plugin8.configs["eslint-recommended"].overrides[0].rules, "@typescript-eslint", "ts"),
1007
- ...renameRules(plugin8.configs.strict.rules, "@typescript-eslint", "ts"),
1056
+ ...renameRules(plugin9.configs["eslint-recommended"].overrides[0].rules, "@typescript-eslint", "ts"),
1057
+ ...renameRules(plugin9.configs.strict.rules, "@typescript-eslint", "ts"),
1008
1058
  "no-dupe-class-members": "off",
1059
+ "no-loss-of-precision": "off",
1009
1060
  "no-redeclare": "off",
1010
1061
  "no-use-before-define": "off",
1011
1062
  "no-useless-constructor": "off",
@@ -1043,6 +1094,15 @@ function typescript(options = {}) {
1043
1094
  ...overrides
1044
1095
  }
1045
1096
  },
1097
+ ...isTypeAware ? [{
1098
+ name: "ivanmaxlogiudice/typescript/rules-type-aware",
1099
+ files: filesTypeAware,
1100
+ ignores: ignoresTypeAware,
1101
+ rules: {
1102
+ ...typeAwareRules,
1103
+ ...overridesTypeAware
1104
+ }
1105
+ }] : [],
1046
1106
  {
1047
1107
  name: "ivanmaxlogiudice/typescript/disables/dts",
1048
1108
  files: ["**/*.d.?([cm])ts"],
@@ -1064,20 +1124,21 @@ function typescript(options = {}) {
1064
1124
  name: "ivanmaxlogiudice/typescript/disables/cjs",
1065
1125
  files: ["**/*.js", "**/*.cjs"],
1066
1126
  rules: {
1067
- "ts/no-require-imports": "off"
1127
+ "ts/no-require-imports": "off",
1128
+ "ts/no-var-requires": "off"
1068
1129
  }
1069
1130
  }
1070
1131
  ];
1071
1132
  }
1072
1133
 
1073
1134
  // src/configs/unicorn.ts
1074
- import plugin9 from "eslint-plugin-unicorn";
1135
+ import plugin8 from "eslint-plugin-unicorn";
1075
1136
  function unicorn() {
1076
1137
  return [
1077
1138
  {
1078
1139
  name: "ivanmaxlogiudice/unicorn/rules",
1079
1140
  plugins: {
1080
- unicorn: plugin9
1141
+ unicorn: plugin8
1081
1142
  },
1082
1143
  rules: {
1083
1144
  // Pass error message when throwing errors
@@ -1119,14 +1180,14 @@ async function unocss(options = {}) {
1119
1180
  strict = false
1120
1181
  } = options;
1121
1182
  await ensurePackages(["@unocss/eslint-plugin"]);
1122
- const [plugin10] = await Promise.all([
1183
+ const [plugin9] = await Promise.all([
1123
1184
  interopDefault(import("@unocss/eslint-plugin"))
1124
1185
  ]);
1125
1186
  return [
1126
1187
  {
1127
1188
  name: "ivanmaxlogiudice/unocss/rules",
1128
1189
  plugins: {
1129
- unocss: plugin10
1190
+ unocss: plugin9
1130
1191
  },
1131
1192
  rules: {
1132
1193
  "unocss/order": "warn",
@@ -1145,7 +1206,7 @@ async function vue(options = {}) {
1145
1206
  overrides = {}
1146
1207
  } = options;
1147
1208
  await ensurePackages(["eslint-plugin-vue", "vue-eslint-parser"]);
1148
- const [plugin10, parser3] = await Promise.all([
1209
+ const [plugin9, parser2] = await Promise.all([
1149
1210
  // @ts-expect-error missing types
1150
1211
  interopDefault(import("eslint-plugin-vue")),
1151
1212
  interopDefault(import("vue-eslint-parser"))
@@ -1154,7 +1215,7 @@ async function vue(options = {}) {
1154
1215
  {
1155
1216
  name: "ivanmaxlogiudice/vue/setup",
1156
1217
  plugins: {
1157
- vue: plugin10
1218
+ vue: plugin9
1158
1219
  },
1159
1220
  // This allows Vue plugin to work with auto imports
1160
1221
  // https://github.com/vuejs/eslint-plugin-vue/pull/2422
@@ -1181,7 +1242,7 @@ async function vue(options = {}) {
1181
1242
  name: "ivanmaxlogiudice/vue/rules",
1182
1243
  files,
1183
1244
  languageOptions: {
1184
- parser: parser3,
1245
+ parser: parser2,
1185
1246
  parserOptions: {
1186
1247
  ecmaFeatures: {
1187
1248
  jsx: true
@@ -1191,12 +1252,12 @@ async function vue(options = {}) {
1191
1252
  sourceType: "module"
1192
1253
  }
1193
1254
  },
1194
- processor: plugin10.processors[".vue"],
1255
+ processor: plugin9.processors[".vue"],
1195
1256
  rules: {
1196
- ...plugin10.configs.base.rules,
1197
- ...plugin10.configs["vue3-essential"].rules,
1198
- ...plugin10.configs["vue3-strongly-recommended"].rules,
1199
- ...plugin10.configs["vue3-recommended"].rules,
1257
+ ...plugin9.configs.base.rules,
1258
+ ...plugin9.configs["vue3-essential"].rules,
1259
+ ...plugin9.configs["vue3-strongly-recommended"].rules,
1260
+ ...plugin9.configs["vue3-recommended"].rules,
1200
1261
  "node/prefer-global/process": "off",
1201
1262
  "vue/block-order": ["error", {
1202
1263
  order: ["template", "script", "style"]
@@ -1285,7 +1346,7 @@ async function yaml(options = {}) {
1285
1346
  overrides = {}
1286
1347
  } = options;
1287
1348
  await ensurePackages(["eslint-plugin-yml", "yaml-eslint-parser"]);
1288
- const [plugin10, parser3] = await Promise.all([
1349
+ const [plugin9, parser2] = await Promise.all([
1289
1350
  interopDefault(import("eslint-plugin-yml")),
1290
1351
  interopDefault(import("yaml-eslint-parser"))
1291
1352
  ]);
@@ -1293,14 +1354,14 @@ async function yaml(options = {}) {
1293
1354
  {
1294
1355
  name: "ivanmaxlogiudice/yaml/setup",
1295
1356
  plugins: {
1296
- yaml: plugin10
1357
+ yaml: plugin9
1297
1358
  }
1298
1359
  },
1299
1360
  {
1300
1361
  name: "ivanmaxlogiudice/yaml/rules",
1301
1362
  files,
1302
1363
  languageOptions: {
1303
- parser: parser3
1364
+ parser: parser2
1304
1365
  },
1305
1366
  rules: {
1306
1367
  // TODO: Check rules (https://github.com/ota-meshi/eslint-plugin-yml)
@@ -1332,15 +1393,20 @@ async function yaml(options = {}) {
1332
1393
 
1333
1394
  // src/factory.ts
1334
1395
  async function config2(options = {}, ...userConfigs) {
1335
- clearPackageCache();
1336
1396
  const {
1337
1397
  componentExts = [],
1338
- isInEditor = isInEditorEnv(),
1339
1398
  regexp: enableRegexp = false,
1340
- typescript: enableTypeScript = packageExists("typescript"),
1399
+ typescript: enableTypeScript = isPackageInScope("typescript"),
1341
1400
  unocss: enableUnoCSS = hasSomePackage(["unocss", "@unocss/nuxt"]),
1342
1401
  vue: enableVue = hasSomePackage(["vue", "nuxt", "vitepress", "@slidev/cli"])
1343
1402
  } = options;
1403
+ let isInEditor = options.isInEditor;
1404
+ if (isInEditor == null) {
1405
+ isInEditor = isInEditorEnv();
1406
+ if (isInEditor) {
1407
+ console.log("[@ivanmaxlogiudice/eslint-config] Detected running in editor, some rules are disabled.");
1408
+ }
1409
+ }
1344
1410
  const configs = [
1345
1411
  comments(),
1346
1412
  ignores(),
@@ -1368,6 +1434,7 @@ async function config2(options = {}, ...userConfigs) {
1368
1434
  }
1369
1435
  if (enableTypeScript) {
1370
1436
  configs.push(typescript({
1437
+ ...resolveSubOptions(options, "typescript"),
1371
1438
  componentExts,
1372
1439
  overrides: getOverrides(options, "typescript"),
1373
1440
  type: options.type
@@ -1421,7 +1488,6 @@ function resolveSubOptions(options, key) {
1421
1488
  function getOverrides(options, key) {
1422
1489
  const sub = resolveSubOptions(options, key);
1423
1490
  return {
1424
- ...options.overrides?.[key],
1425
1491
  ..."overrides" in sub ? sub.overrides : {}
1426
1492
  };
1427
1493
  }
@@ -1443,7 +1509,6 @@ export {
1443
1509
  GLOB_TS,
1444
1510
  GLOB_VUE,
1445
1511
  GLOB_YAML,
1446
- clearPackageCache,
1447
1512
  combine,
1448
1513
  comments,
1449
1514
  config2 as config,
@@ -1456,12 +1521,13 @@ export {
1456
1521
  imports,
1457
1522
  interopDefault,
1458
1523
  isInEditorEnv,
1524
+ isInGitHooksOrLintStaged,
1525
+ isPackageInScope,
1459
1526
  javascript,
1460
1527
  jsdoc,
1461
1528
  jsonc,
1462
1529
  markdown,
1463
1530
  node,
1464
- packageExists,
1465
1531
  perfectionist,
1466
1532
  regexp,
1467
1533
  renameRules,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ivanmaxlogiudice/eslint-config",
3
- "version": "3.0.0-beta.4",
4
- "packageManager": "bun@1.1.24",
3
+ "version": "3.0.0-beta.6",
4
+ "packageManager": "bun@1.1.25",
5
5
  "description": "Personal ESLint config",
6
6
  "type": "module",
7
7
  "keywords": ["eslint-config"],
@@ -32,7 +32,7 @@
32
32
  "dev": "config-inspector --config eslint.config.ts",
33
33
  "build": "bun run typegen && tsup --format esm --clean --dts",
34
34
  "test": "vitest",
35
- "lint": "eslint . --fix",
35
+ "lint": "eslint --flag unstable_ts_config --fix .",
36
36
  "typegen": "bun scripts/typegen.ts",
37
37
  "prepack": "bun run build",
38
38
  "release": "bumpp && npm publish",
@@ -73,47 +73,55 @@
73
73
  },
74
74
  "dependencies": {
75
75
  "@clack/prompts": "^0.7.0",
76
- "@eslint-community/eslint-plugin-eslint-comments": "^4.3.0",
76
+ "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0",
77
77
  "@ivanmaxlogiudice/gitignore": "^0.0.2",
78
- "@stylistic/eslint-plugin": "^2.6.2",
79
- "@typescript-eslint/eslint-plugin": "^8.1.0",
80
- "@typescript-eslint/parser": "^8.1.0",
81
- "@vitest/eslint-plugin": "^1.0.2",
82
- "eslint-plugin-antfu": "^2.3.5",
78
+ "@stylistic/eslint-plugin": "^2.6.4",
79
+ "@typescript-eslint/eslint-plugin": "^8.2.0",
80
+ "@typescript-eslint/parser": "^8.2.0",
81
+ "@vitest/eslint-plugin": "^1.0.3",
82
+ "eslint-plugin-antfu": "^2.3.6",
83
83
  "eslint-plugin-import-x": "^3.1.0",
84
84
  "eslint-plugin-jsdoc": "^50.2.2",
85
85
  "eslint-plugin-jsonc": "^2.16.0",
86
86
  "eslint-plugin-n": "^17.10.2",
87
- "eslint-plugin-no-only-tests": "^3.1.0",
88
- "eslint-plugin-perfectionist": "^3.1.3",
87
+ "eslint-plugin-no-only-tests": "^3.3.0",
88
+ "eslint-plugin-perfectionist": "^3.2.0",
89
89
  "eslint-plugin-unicorn": "^55.0.0",
90
90
  "eslint-plugin-unused-imports": "^4.1.3",
91
91
  "globals": "^15.9.0",
92
92
  "jsonc-eslint-parser": "^2.4.0",
93
+ "local-pkg": "^0.5.0",
93
94
  "picocolors": "^1.0.1",
94
95
  "yargs": "^17.7.2"
95
96
  },
96
97
  "devDependencies": {
97
- "@eslint/config-inspector": "^0.5.2",
98
- "@stylistic/eslint-plugin-migrate": "^2.6.2",
98
+ "@eslint/config-inspector": "^0.5.4",
99
+ "@stylistic/eslint-plugin-migrate": "^2.6.4",
99
100
  "@types/eslint": "^9.6.0",
100
- "@types/node": "^22.3.0",
101
+ "@types/node": "^22.5.0",
101
102
  "@types/yargs": "^17.0.33",
102
- "@unocss/eslint-plugin": "^0.62.1",
103
- "bumpp": "^9.5.1",
104
- "bun-types": "^1.1.24",
105
- "bundle-require": "^5.0.0",
103
+ "@unocss/eslint-plugin": "^0.62.2",
104
+ "bumpp": "^9.5.2",
105
+ "bun-types": "^1.1.25",
106
106
  "eslint": "^9.9.0",
107
107
  "eslint-plugin-markdown": "^5.1.0",
108
108
  "eslint-plugin-regexp": "^2.6.0",
109
109
  "eslint-plugin-vue": "^9.27.0",
110
110
  "eslint-plugin-yml": "^1.14.0",
111
- "eslint-typegen": "^0.3.0",
111
+ "eslint-typegen": "^0.3.1",
112
+ "lint-staged": "^15.2.9",
113
+ "simple-git-hooks": "^2.11.1",
112
114
  "tsup": "^8.2.4",
113
115
  "typescript": "^5.5.4",
114
116
  "unbuild": "^2.0.0",
115
117
  "vitest": "^2.0.5",
116
118
  "vue-eslint-parser": "^9.4.3",
117
119
  "yaml-eslint-parser": "^1.2.3"
120
+ },
121
+ "simple-git-hooks": {
122
+ "pre-commit": "bunx lint-staged"
123
+ },
124
+ "lint-staged": {
125
+ "*": "eslint --flag unstable_ts_config --fix"
118
126
  }
119
127
  }