js-style-kit 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -39,13 +39,22 @@ interface EslintConfigObject<Rules extends Linter.RulesRecord = Linter.RulesReco
39
39
  }
40
40
  type FilenameCase = "camelCase" | "kebabCase" | "pascalCase" | "snakeCase";
41
41
  type FunctionStyle = "arrow" | "declaration" | "expression";
42
+ type ReactFramework = "next" | "none" | "react-router" | "remix" | "vite";
42
43
 
43
44
  interface TestingConfig {
44
45
  filenamePattern?: "spec" | "test";
45
46
  files?: string[];
46
47
  formattingRules?: boolean;
47
48
  framework?: "bun" | "jest" | "node" | "vitest";
49
+ /**
50
+ * Whether to enforce imports from the correct testing framework.
51
+ * Uses the built-in ESLint `no-restricted-imports` rule.
52
+ *
53
+ * @default true
54
+ */
55
+ importRestrictions?: boolean;
48
56
  itOrTest?: "it" | "test";
57
+ typescript?: boolean;
49
58
  }
50
59
 
51
60
  interface EslintConfigOptions {
@@ -58,7 +67,7 @@ interface EslintConfigOptions {
58
67
  };
59
68
  query?: boolean;
60
69
  react?: boolean | {
61
- framework?: "next" | "none" | "react-router" | "remix" | "vite";
70
+ framework?: ReactFramework;
62
71
  reactCompiler?: boolean;
63
72
  reactRefresh?: boolean;
64
73
  };
@@ -93,8 +102,9 @@ interface EslintConfigOptions {
93
102
  * @param options.testing - An object with the following properties:
94
103
  * - `filenamePattern`: One of "spec" or "test" to determine which filename pattern to use.
95
104
  * - `files`: Array of file patterns to include in the configuration.
96
- * - `framework`: One of "vitest" or "jest" to determine which testing library to use.
105
+ * - `framework`: One of "vitest" or "jest" or "bun" or "node" to determine which testing library to use.
97
106
  * - `formattingRules`: Whether to include formatting rules like padding around blocks.
107
+ * - `importRestrictions`: Whether to enforce imports from the correct testing framework.
98
108
  * - `itOrTest`: One of "it" or "test" to determine which test function to use.
99
109
  * @param options.typescript - Whether to include TypeScript rules. Can be a boolean or a string with path to tsconfig.
100
110
  * @param options.turbo - Whether to include Turborepo rules. Defaults to false.
@@ -137,4 +147,4 @@ interface PrettierConfigWithPlugins extends Config, SortJsonOptions, PluginOptio
137
147
  */
138
148
  declare const prettierConfig: (options?: PrettierConfigOptions) => PrettierConfigWithPlugins;
139
149
 
140
- export { type EslintConfigObject, type EslintConfigOptions, type EslintRuleConfig, type EslintSeverity, type FilenameCase, type FunctionStyle, type PrettierConfigOptions, type PrettierConfigWithPlugins, eslintConfig, prettierConfig };
150
+ export { type EslintConfigObject, type EslintConfigOptions, type EslintRuleConfig, type EslintSeverity, type FilenameCase, type FunctionStyle, type PrettierConfigOptions, type PrettierConfigWithPlugins, type ReactFramework, eslintConfig, prettierConfig };
package/dist/index.js CHANGED
@@ -492,9 +492,8 @@ import { createRequire } from "module";
492
492
  // src/eslint/convex/rules.ts
493
493
  var convexRules = {
494
494
  "@convex-dev/import-wrong-runtime": "warn",
495
- "@convex-dev/no-args-without-validator": "warn",
496
- "@convex-dev/no-missing-args-validator": "warn",
497
- "@convex-dev/no-old-registered-function-syntax": "warn"
495
+ "@convex-dev/no-old-registered-function-syntax": "warn",
496
+ "@convex-dev/require-args-validator": "warn"
498
497
  };
499
498
 
500
499
  // src/eslint/convex/config.ts
@@ -514,13 +513,14 @@ var convexConfig = (customRules) => ({
514
513
 
515
514
  // src/eslint/ignores.ts
516
515
  var ignoresConfig = ({
517
- next = false,
518
- storybook = false,
519
- userIgnores = []
520
- } = {}) => ({
516
+ reactFramework,
517
+ storybook,
518
+ userIgnores
519
+ }) => ({
521
520
  ignores: [
522
521
  "**/dist/",
523
- ...next ? [".next"] : [],
522
+ ...reactFramework === "next" ? [".next"] : [],
523
+ ...reactFramework === "react-router" ? [".react-router"] : [],
524
524
  ...storybook ? ["!.storybook"] : [],
525
525
  ...userIgnores
526
526
  ],
@@ -1158,6 +1158,56 @@ var storybookConfig = (customRules) => [
1158
1158
  import jest from "eslint-plugin-jest";
1159
1159
  import vitest from "eslint-plugin-vitest";
1160
1160
 
1161
+ // src/eslint/testing/get-import-restrictions.ts
1162
+ var commonTestImports = [
1163
+ "describe",
1164
+ "it",
1165
+ "test",
1166
+ "expect",
1167
+ "beforeAll",
1168
+ "beforeEach",
1169
+ "afterAll",
1170
+ "afterEach",
1171
+ "vi",
1172
+ "mock",
1173
+ "spyOn"
1174
+ ];
1175
+ var frameworkConfig = {
1176
+ bun: {
1177
+ allowed: "'bun:test'",
1178
+ restricted: ["vitest", "jest", "@jest/globals", "node:test"]
1179
+ },
1180
+ jest: {
1181
+ allowed: "'jest' or '@jest/globals'",
1182
+ restricted: ["vitest", "bun:test", "node:test"]
1183
+ },
1184
+ node: {
1185
+ allowed: "'node:test'",
1186
+ restricted: ["vitest", "jest", "@jest/globals", "bun:test"]
1187
+ },
1188
+ vitest: {
1189
+ allowed: "'vitest'",
1190
+ restricted: ["jest", "@jest/globals", "bun:test", "node:test"]
1191
+ }
1192
+ };
1193
+ var getRestrictionMessage = (allowedFramework) => `This project is setup to use ${allowedFramework} for testing. Importing from other testing frameworks is not allowed. Change this setting in eslint.config.js under testing.framework`;
1194
+ var getImportRestrictions = (framework) => {
1195
+ const config = frameworkConfig[framework];
1196
+ const message = getRestrictionMessage(config.allowed);
1197
+ return {
1198
+ "no-restricted-imports": [
1199
+ "warn",
1200
+ {
1201
+ paths: config.restricted.map((name) => ({
1202
+ importNames: commonTestImports,
1203
+ message,
1204
+ name
1205
+ }))
1206
+ }
1207
+ ]
1208
+ };
1209
+ };
1210
+
1161
1211
  // src/eslint/testing/jest-rules.ts
1162
1212
  var jestRules = (itOrTest = "test") => ({
1163
1213
  "jest/consistent-test-it": [
@@ -1248,17 +1298,14 @@ var vitestRules = (itOrTest = "test") => ({
1248
1298
 
1249
1299
  // src/eslint/testing/config.ts
1250
1300
  var testingConfig = ({
1251
- filenamePattern,
1301
+ filenamePattern = "test",
1252
1302
  files,
1253
- formattingRules,
1254
- framework,
1255
- itOrTest
1256
- } = {
1257
- filenamePattern: "test",
1258
- formattingRules: true,
1259
- framework: "vitest",
1260
- itOrTest: "test"
1261
- }, customRules) => ({
1303
+ formattingRules = true,
1304
+ framework = "vitest",
1305
+ importRestrictions = true,
1306
+ itOrTest = "test",
1307
+ typescript = true
1308
+ } = {}, customRules) => ({
1262
1309
  files: files ?? ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
1263
1310
  languageOptions: {
1264
1311
  globals: framework === "vitest" ? { ...vitest.environments.env.globals } : jest.environments.globals.globals
@@ -1269,8 +1316,8 @@ var testingConfig = ({
1269
1316
  vitest
1270
1317
  },
1271
1318
  rules: {
1319
+ ...typescript ? { "@typescript-eslint/unbound-method": "off" } : {},
1272
1320
  // jest doesn't have a file name rule, so we'll use this one for both
1273
- "@typescript-eslint/unbound-method": "off",
1274
1321
  "vitest/consistent-test-filename": [
1275
1322
  "warn",
1276
1323
  {
@@ -1288,6 +1335,7 @@ var testingConfig = ({
1288
1335
  "jest/padding-around-expect-groups": "warn",
1289
1336
  "jest/padding-around-test-blocks": "warn"
1290
1337
  } : {},
1338
+ ...importRestrictions ? getImportRestrictions(framework) : {},
1291
1339
  ...customRules ?? {}
1292
1340
  },
1293
1341
  ...framework !== "jest" && framework !== "vitest" ? {
@@ -1576,13 +1624,6 @@ var unicornConfig = ({
1576
1624
  });
1577
1625
 
1578
1626
  // src/eslint/index.ts
1579
- var defaultTestingConfig = {
1580
- filenamePattern: "test",
1581
- files: ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
1582
- formattingRules: true,
1583
- framework: "vitest",
1584
- itOrTest: "it"
1585
- };
1586
1627
  var eslintConfig = ({
1587
1628
  convex = false,
1588
1629
  functionStyle = "arrow",
@@ -1594,16 +1635,15 @@ var eslintConfig = ({
1594
1635
  rules: rules2,
1595
1636
  sorting = true,
1596
1637
  storybook = false,
1597
- testing = defaultTestingConfig,
1638
+ testing,
1598
1639
  turbo: turbo2 = false,
1599
1640
  typescript = true,
1600
1641
  unicorn: unicorn2 = { filenameCase: "kebabCase" }
1601
1642
  } = {}, ...additionalConfigs) => {
1602
1643
  const categorizedRules = rules2 === void 0 ? {} : processCustomRules(rules2);
1603
- const usingNextjs = isObject(react2) && react2.framework === "next";
1604
1644
  const configs = [
1605
1645
  ignoresConfig({
1606
- next: usingNextjs,
1646
+ reactFramework: isObject(react2) && react2.framework ? react2.framework : "none",
1607
1647
  storybook,
1608
1648
  userIgnores: ignores
1609
1649
  }),
@@ -1654,7 +1694,7 @@ var eslintConfig = ({
1654
1694
  typescript: Boolean(typescript)
1655
1695
  })
1656
1696
  );
1657
- if (usingNextjs) {
1697
+ if (isObject(react2) && react2.framework === "next") {
1658
1698
  configs.push(nextjsConfig(categorizedRules[configNames.nextjs]));
1659
1699
  }
1660
1700
  }
@@ -1665,8 +1705,23 @@ var eslintConfig = ({
1665
1705
  configs.push(convexConfig(categorizedRules[configNames.convex]));
1666
1706
  }
1667
1707
  if (testing !== false) {
1708
+ const defaultTestingConfig = {
1709
+ filenamePattern: "test",
1710
+ files: ["**/*.{test,spec}.{ts,tsx,js,jsx}"],
1711
+ formattingRules: true,
1712
+ framework: "vitest",
1713
+ importRestrictions: true,
1714
+ itOrTest: "it"
1715
+ };
1668
1716
  const mergedTestingConfig = isObject(testing) ? { ...defaultTestingConfig, ...testing } : defaultTestingConfig;
1669
- const { filenamePattern, files, formattingRules, framework, itOrTest } = mergedTestingConfig;
1717
+ const {
1718
+ filenamePattern,
1719
+ files,
1720
+ formattingRules,
1721
+ framework,
1722
+ importRestrictions,
1723
+ itOrTest
1724
+ } = mergedTestingConfig;
1670
1725
  configs.push(
1671
1726
  testingConfig(
1672
1727
  {
@@ -1674,7 +1729,9 @@ var eslintConfig = ({
1674
1729
  files,
1675
1730
  formattingRules,
1676
1731
  framework,
1677
- itOrTest
1732
+ importRestrictions,
1733
+ itOrTest,
1734
+ typescript: Boolean(typescript)
1678
1735
  },
1679
1736
  categorizedRules[configNames.testing]
1680
1737
  )