@mouse_484/oxc-config 0.4.2 → 0.5.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mouse_484/oxc-config",
3
3
  "type": "module",
4
- "version": "0.4.2",
4
+ "version": "0.5.1",
5
5
  "author": "mouse_484",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/mouse484/config/tree/main/packages/oxc",
@@ -19,11 +19,11 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@stylistic/eslint-plugin": "^5.10.0",
22
- "defu": "^6.1.7",
23
22
  "eslint-plugin-antfu": "^3.2.3",
24
23
  "eslint-plugin-better-tailwindcss": "^4.7.0",
25
24
  "eslint-plugin-perfectionist": "^5.10.1",
26
- "oxlint": "^1.78.0",
25
+ "local-pkg": "^1.2.1",
26
+ "oxlint": "^1.79.0",
27
27
  "oxlint-tsgolint": "^7.0.2001"
28
28
  },
29
29
  "publishConfig": {
@@ -34,7 +34,7 @@ function getConfigLiteral(/** @type {string} */ importedName) {
34
34
  return {}
35
35
  }
36
36
  return {
37
- defaultEnabled: literal.getProperty('defaultEnabled')
37
+ enable: literal.getProperty('enable')
38
38
  ?.asKind(ts.SyntaxKind.PropertyAssignment)
39
39
  ?.getInitializer()
40
40
  ?.getText(),
@@ -62,9 +62,15 @@ dtsFile.addInterface({
62
62
  const options = node.getProperty('options')
63
63
  ?.getTypeAtLocation(variable)
64
64
  .getConstraint()
65
- const { defaultEnabled, options: defaultOptions } = getConfigLiteral(name)
65
+ const { enable, options: defaultOptions } = getConfigLiteral(name)
66
+ let defaultText = 'auto'
67
+ if (enable === undefined) {
68
+ defaultText = 'true'
69
+ } else if (enable === 'true' || enable === 'false') {
70
+ defaultText = enable
71
+ }
66
72
  const tags = [
67
- { tagName: 'default', text: defaultEnabled ?? 'true' },
73
+ { tagName: 'default', text: defaultText },
68
74
  ]
69
75
  if (defaultOptions !== undefined) {
70
76
  tags.push({ tagName: 'options', text: defaultOptions })
@@ -2,8 +2,10 @@ import { createConfigs } from '../lib/factory.js'
2
2
 
3
3
  export default createConfigs({
4
4
  name: 'eslint',
5
+ enable: true,
5
6
  configs: [
6
7
  {
8
+ plugins: ['eslint'],
7
9
  rules: {
8
10
  'eslint/id-length': 'off',
9
11
  'eslint/func-style': ['error', 'declaration', { allowArrowFunctions: true }],
@@ -13,11 +15,7 @@ export default createConfigs({
13
15
  'eslint/no-nested-ternary': 'error',
14
16
  'eslint/no-unneeded-ternary': 'error',
15
17
  'eslint/no-void': ['error', { allowAsStatement: true }],
16
- /**
17
- * Prefer `perfectionist` plugin for sorting
18
- */
19
- 'eslint/sort-imports': 'off',
20
- 'eslint/sort-keys': 'off',
18
+ 'eslint/one-var': 'off',
21
19
  },
22
20
  },
23
21
  ],
@@ -2,7 +2,8 @@ import perfectionist from 'eslint-plugin-perfectionist'
2
2
  import { createConfigs } from '../lib/factory.js'
3
3
 
4
4
  export default createConfigs({
5
- name: 'perfectionist',
5
+ name: 'import',
6
+ enable: true,
6
7
  configs: [
7
8
  {
8
9
  jsPlugins: ['eslint-plugin-perfectionist'],
@@ -10,5 +11,11 @@ export default createConfigs({
10
11
  ...perfectionist.configs['recommended-natural'].rules,
11
12
  },
12
13
  },
14
+ {
15
+ rules: {
16
+ 'eslint/sort-imports': 'off',
17
+ 'eslint/sort-keys': 'off',
18
+ },
19
+ },
13
20
  ],
14
21
  })
@@ -1,4 +1,6 @@
1
- export declare function buildConfigs(options: Options): OxlintConfig[]
1
+ import type { OxlintConfig } from 'oxlint'
2
+
3
+ export default function buildConfigs(options: Options): OxlintConfig[]
2
4
 
3
5
  export interface Options {
4
6
  /**
@@ -17,10 +19,10 @@ export interface Options {
17
19
  */
18
20
  oxc?: boolean
19
21
  /**
20
- * `perfectionist` option
22
+ * `import` option
21
23
  * @default true
22
24
  */
23
- perfectionist?: boolean
25
+ import?: boolean
24
26
  /**
25
27
  * `stylistic` option
26
28
  * @default true
@@ -28,25 +30,48 @@ export interface Options {
28
30
  stylistic?: boolean
29
31
  /**
30
32
  * `tailwind` option
31
- * @default false
33
+ * @default auto
32
34
  * @options {
33
35
  * entryPoint: 'src/global.css',
34
36
  * }
35
37
  */
36
38
  tailwind?: boolean | { entryPoint: string } | undefined
37
39
  /**
38
- * `tanstackRouter` option
39
- * @default false
40
+ * `tanstack` option
41
+ * @default true
42
+ */
43
+ tanstack?: boolean
44
+ /**
45
+ * `typescript` option
46
+ * @default auto
47
+ * @options {
48
+ * typeAware: true,
49
+ * }
50
+ */
51
+ typescript?: boolean | { typeAware: boolean } | undefined
52
+ /**
53
+ * `react` option
54
+ * @default auto
55
+ */
56
+ react?: boolean
57
+ /**
58
+ * `vitest` option
59
+ * @default auto
40
60
  */
41
- tanstackRouter?: boolean
61
+ vitest?: boolean
42
62
  /**
43
- * `typeAware` option
63
+ * `node` option
64
+ * @default auto
65
+ */
66
+ node?: boolean
67
+ /**
68
+ * `javascript` option
44
69
  * @default true
45
70
  */
46
- typeAware?: boolean
71
+ javascript?: boolean
47
72
  /**
48
- * `typescript` option
73
+ * `unicorn` option
49
74
  * @default true
50
75
  */
51
- typescript?: boolean
76
+ unicorn?: boolean
52
77
  }
@@ -1,37 +1,52 @@
1
- import defu from 'defu'
1
+ import { isPackageExists } from 'local-pkg'
2
2
  import eslint from './eslint.js'
3
+ import importConfig from './import.js'
4
+ import javascript from './javascript.js'
5
+ import node from './node.js'
3
6
  import opinionated from './opinionated.js'
4
7
  import oxc from './oxc.js'
5
- import perfectionist from './perfectionist.js'
8
+ import react from './react.js'
6
9
  import stylistic from './stylistic.js'
7
10
  import tailwind from './tailwind.js'
8
- import tanstackRouter from './tanstack-router.js'
9
- import typeAware from './type-aware.js'
11
+ import tanstack from './tanstack.js'
10
12
  import typescript from './typescript.js'
13
+ import unicorn from './unicorn.js'
14
+ import vitest from './vitest.js'
11
15
 
12
16
  const CONFIGS = /** @type {const} */[
13
17
  eslint,
14
18
  opinionated,
15
19
  oxc,
16
- perfectionist,
20
+ importConfig,
17
21
  stylistic,
18
22
  tailwind,
19
- tanstackRouter,
20
- typeAware,
23
+ tanstack,
21
24
  typescript,
25
+ react,
26
+ vitest,
27
+ node,
28
+ javascript,
29
+ unicorn,
22
30
  ]
23
31
 
24
- /** @type {import(".").buildConfigs} */
32
+ /**
33
+ @param {import(".").Options} options
34
+ @returns {import("oxlint").OxlintConfig[]} Generated configs for the enabled options
35
+ */
25
36
  export default function buildConfigs(options) {
26
- const configs = CONFIGS.flatMap(({ name, build, defaultEnabled, options: defaultOptions }) => {
37
+ const context = { isPackageExists, options }
38
+ return CONFIGS.flatMap(({ name, build, enable = true }) => {
27
39
  const option = options[name]
28
- if (option === false || (option === undefined && defaultEnabled === false)) {
40
+ if (option === false) {
29
41
  return []
30
42
  }
43
+ if (option === undefined) {
44
+ const isEnabled = typeof enable === 'function' ? enable(context) : enable
45
+ if (!isEnabled) {
46
+ return []
47
+ }
48
+ }
31
49
  // @ts-expect-error - build configs with options
32
- // eslint-disable-next-line unicorn/prefer-minimal-ternary
33
- return typeof option === 'object' ? build(defu(option, defaultOptions)) : build(defaultOptions)
50
+ return build(context, typeof option === 'object' ? option : undefined)
34
51
  })
35
-
36
- return configs
37
52
  }
@@ -0,0 +1,11 @@
1
+ import { createConfigs } from '../lib/factory.js'
2
+
3
+ export default createConfigs({
4
+ name: 'javascript',
5
+ enable: true,
6
+ configs: [
7
+ {
8
+ plugins: ['jsdoc', 'promise'],
9
+ },
10
+ ],
11
+ })
@@ -0,0 +1,11 @@
1
+ import { createConfigs } from '../lib/factory.js'
2
+
3
+ export default createConfigs({
4
+ name: 'node',
5
+ enable: ({ isPackageExists }) => isPackageExists('@types/node'),
6
+ configs: [
7
+ {
8
+ plugins: ['node'],
9
+ },
10
+ ],
11
+ })
@@ -2,6 +2,7 @@ import { createConfigs } from '../lib/factory.js'
2
2
 
3
3
  export default createConfigs({
4
4
  name: 'opinionated',
5
+ enable: true,
5
6
  configs: [
6
7
  {
7
8
  jsPlugins: ['eslint-plugin-antfu'],
@@ -2,8 +2,10 @@ import { createConfigs } from '../lib/factory.js'
2
2
 
3
3
  export default createConfigs({
4
4
  name: 'oxc',
5
+ enable: true,
5
6
  configs: [
6
7
  {
8
+ plugins: ['oxc'],
7
9
  rules: {
8
10
  'oxc/no-async-await': 'off',
9
11
  'oxc/no-rest-spread-properties': 'off',
@@ -0,0 +1,20 @@
1
+ import { createConfigs } from '../lib/factory.js'
2
+
3
+ export default createConfigs({
4
+ name: 'react',
5
+ enable: ({ isPackageExists }) => isPackageExists('react'),
6
+ configs: [
7
+ {
8
+ plugins: ['react'],
9
+ rules: {
10
+ 'react/react-in-jsx-scope': 'off',
11
+ 'react/jsx-props-no-spreading': 'off',
12
+ 'react/jsx-max-depth': ['error', { max: 5 }],
13
+ 'react/jsx-filename-extension': ['error', { extensions: ['.jsx', '.tsx'] }],
14
+ },
15
+ },
16
+ {
17
+ plugins: ['jsx-a11y'],
18
+ },
19
+ ],
20
+ })
@@ -10,6 +10,7 @@ const { rules } = stylistic.configs.customize({
10
10
 
11
11
  export default createConfigs ({
12
12
  name: 'stylistic',
13
+ enable: true,
13
14
  configs: [
14
15
  {
15
16
  jsPlugins: ['@stylistic/eslint-plugin'],
@@ -3,12 +3,12 @@ import { createConfigs } from '../lib/factory.js'
3
3
 
4
4
  export default createConfigs({
5
5
  name: 'tailwind',
6
- defaultEnabled: false,
6
+ enable: ({ isPackageExists }) => isPackageExists('tailwindcss'),
7
7
  options: {
8
8
  entryPoint: 'src/global.css',
9
9
  },
10
- configs: ({ entryPoint }) => ([
11
- {
10
+ configs: [
11
+ ({ options: { entryPoint } }) => ({
12
12
  jsPlugins: [
13
13
  'eslint-plugin-better-tailwindcss',
14
14
  ],
@@ -23,6 +23,6 @@ export default createConfigs({
23
23
  entryPoint,
24
24
  },
25
25
  },
26
- },
27
- ]),
26
+ }),
27
+ ],
28
28
  })
@@ -0,0 +1,22 @@
1
+ import { createConfigs } from '../lib/factory.js'
2
+
3
+ export default createConfigs({
4
+ name: 'tanstack',
5
+ enable: true,
6
+ configs: [
7
+ ({ isPackageExists }) => isPackageExists('@tanstack/react-router')
8
+ ? {
9
+ ignorePatterns: ['**/src/routeTree.gen.ts'],
10
+ overrides: [
11
+ {
12
+ files: ['src/routes/**/*.tsx'],
13
+ rules: {
14
+ 'eslint/no-use-before-define': 'off',
15
+ 'react/only-export-components': ['error', { customHOCs: ['createRootRoute', 'createFileRoute'] }],
16
+ },
17
+ },
18
+ ],
19
+ }
20
+ : undefined,
21
+ ],
22
+ })
@@ -2,12 +2,29 @@ import { createConfigs } from '../lib/factory.js'
2
2
 
3
3
  export default createConfigs({
4
4
  name: 'typescript',
5
+ enable: ({ isPackageExists }) => isPackageExists('typescript'),
6
+ options: {
7
+ typeAware: true,
8
+ },
5
9
  configs: [
6
10
  {
11
+ plugins: ['typescript'],
7
12
  rules: {
8
13
  'typescript/explicit-function-return-type': 'off',
9
14
  'typescript/explicit-module-boundary-types': 'off',
15
+ 'eslint/no-undef': 'off',
10
16
  },
11
17
  },
18
+ ({ options: { typeAware } }) => typeAware
19
+ ? {
20
+ options: {
21
+ typeAware: true,
22
+ typeCheck: true,
23
+ },
24
+ rules: {
25
+ 'typescript/prefer-readonly-parameter-types': 'off',
26
+ },
27
+ }
28
+ : undefined,
12
29
  ],
13
30
  })
@@ -0,0 +1,11 @@
1
+ import { createConfigs } from '../lib/factory.js'
2
+
3
+ export default createConfigs({
4
+ name: 'unicorn',
5
+ enable: true,
6
+ configs: [
7
+ {
8
+ plugins: ['unicorn'],
9
+ },
10
+ ],
11
+ })
@@ -0,0 +1,11 @@
1
+ import { createConfigs } from '../lib/factory.js'
2
+
3
+ export default createConfigs({
4
+ name: 'vitest',
5
+ enable: ({ isPackageExists }) => isPackageExists('vitest'),
6
+ configs: [
7
+ {
8
+ plugins: ['vitest'],
9
+ },
10
+ ],
11
+ })
package/src/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { OxlintConfig } from 'oxlint'
2
2
  import type { Options } from './configs'
3
3
 
4
- declare function lint(options?: Options, config?: OxlintConfig): OxlintConfig
4
+ declare function lint(options: Options, config?: OxlintConfig): OxlintConfig
5
5
 
6
6
  export { lint }
7
7
  export { type Options } from './configs'
package/src/index.js CHANGED
@@ -1,24 +1,62 @@
1
- import defu from 'defu'
2
1
  import buildConfigs from './configs/index.js'
3
2
 
4
- /** @type {import('.').lint} */
3
+ const DEFAULT_CATEGORIES = {
4
+ correctness: 'error',
5
+ suspicious: 'warn',
6
+ pedantic: 'warn',
7
+ perf: 'warn',
8
+ style: 'warn',
9
+ restriction: 'warn',
10
+ nursery: 'warn',
11
+ }
12
+
13
+ const OBJECT_KEYS = ['settings', 'env', 'globals', 'options']
14
+ const ARRAY_KEYS = ['ignorePatterns']
15
+ const HOISTED_KEYS = [...OBJECT_KEYS, ...ARRAY_KEYS, 'categories']
16
+
17
+ /**
18
+ @type {import('.').lint}
19
+ */
5
20
  export function lint(options, config = {}) {
6
- // @ts-expect-error - deep merge config with default config
7
- return defu(
8
- config,
9
- {
10
- categories: {
11
- correctness: 'error',
12
- suspicious: 'warn',
13
- pedantic: 'warn',
14
- perf: 'warn',
15
- style: 'warn',
16
- restriction: 'warn',
17
- nursery: 'warn',
18
- },
19
- },
20
- // @ts-expect-error - buildConfigs returns a Config[]
21
- // eslint-disable-next-line ts/no-unsafe-argument
22
- ...buildConfigs(options),
23
- )
21
+ const all = [...buildConfigs(options), config]
22
+
23
+ /** @type {Record<string, any>} */
24
+ const root = {
25
+ categories: { ...DEFAULT_CATEGORIES, ...config.categories },
26
+ }
27
+
28
+ for (const item of all) {
29
+ for (const key of OBJECT_KEYS) {
30
+ // @ts-expect-error - hoisted keys are not part of the OxlintConfig index signature
31
+ // eslint-disable-next-line ts/no-unsafe-assignment
32
+ const value = item[key]
33
+ if (value !== undefined) {
34
+ // eslint-disable-next-line ts/no-unsafe-assignment
35
+ root[key] = { ...root[key], ...value }
36
+ }
37
+ }
38
+ for (const key of ARRAY_KEYS) {
39
+ // @ts-expect-error - hoisted keys are not part of the OxlintConfig index signature
40
+ // eslint-disable-next-line ts/no-unsafe-assignment
41
+ const value = item[key]
42
+ if (value !== undefined) {
43
+ // eslint-disable-next-line ts/no-unsafe-assignment
44
+ root[key] = [...new Set([...(root[key] ?? []), ...value])]
45
+ }
46
+ }
47
+ }
48
+
49
+ return {
50
+ ...root,
51
+ extends: all
52
+ .map((item) => {
53
+ const rest = { ...item }
54
+ for (const key of HOISTED_KEYS) {
55
+ // @ts-expect-error - delete hoisted keys
56
+ delete rest[key]
57
+ }
58
+ return rest
59
+ })
60
+ .filter(item => Object.keys(item).length > 0),
61
+ }
24
62
  }
@@ -1,4 +1,14 @@
1
1
  import type { OxlintConfig } from 'oxlint'
2
+ import type { Options } from '../configs'
3
+
4
+ interface EnableContext<TOptions = Options> {
5
+ isPackageExists: (name: string) => boolean
6
+ options: TOptions
7
+ }
8
+
9
+ type Enable = boolean | ((context: EnableContext) => boolean)
10
+
11
+ type ConfigItem<TOptions> = OxlintConfig | undefined | ((context: EnableContext<TOptions>) => OxlintConfig | undefined)
2
12
 
3
13
  declare function createConfigs<
4
14
  TName extends string,
@@ -6,14 +16,15 @@ declare function createConfigs<
6
16
  >(
7
17
  parameters: {
8
18
  name: TName
9
- defaultEnabled?: boolean
19
+ enable?: Enable
10
20
  options?: TOptions
11
- configs: OxlintConfig[] | ((options: TOptions) => OxlintConfig[])
21
+ configs: ConfigItem<TOptions>[]
12
22
  }): {
13
23
  name: TName
14
- defaultEnabled?: boolean
24
+ enable?: Enable
15
25
  options?: TOptions
16
- build: (options?: TOptions) => OxlintConfig[]
26
+ build: (context: EnableContext, options?: TOptions) => OxlintConfig[]
17
27
  }
18
28
 
19
29
  export { createConfigs }
30
+ export type { ConfigItem, Enable, EnableContext }
@@ -1,18 +1,17 @@
1
- /** @type {import('./factory').createConfigs} */
2
- export function createConfigs({ name, defaultEnabled, options, configs }) {
1
+ /**
2
+ @type {import('./factory').createConfigs}
3
+ */
4
+ export function createConfigs({ name, enable = true, options, configs }) {
3
5
  return {
4
6
  name,
5
- defaultEnabled,
7
+ enable,
6
8
  options,
7
- build: (overriddenOptions) => {
8
- if (typeof configs === 'function') {
9
- // @ts-expect-error - build configs
10
- return configs({
11
- ...options,
12
- ...overriddenOptions,
13
- })
14
- }
15
- return configs
9
+ build: (context, overriddenOptions) => {
10
+ const local = { ...context, options: { ...options, ...overriddenOptions } }
11
+ return configs.flatMap((item) => {
12
+ const config = typeof item === 'function' ? item(local) : item
13
+ return config ? [config] : []
14
+ })
16
15
  },
17
16
  }
18
17
  }
@@ -1,19 +0,0 @@
1
- import { createConfigs } from '../lib/factory.js'
2
-
3
- export default createConfigs({
4
- defaultEnabled: false,
5
- name: 'tanstackRouter',
6
- configs: [
7
- {
8
- ignorePatterns: ['**/src/routeTree.gen.ts'],
9
- overrides: [
10
- {
11
- files: ['src/routes/**/*.tsx'],
12
- rules: {
13
- 'eslint/no-use-before-define': 'off',
14
- },
15
- },
16
- ],
17
- },
18
- ],
19
- })
@@ -1,16 +0,0 @@
1
- import { createConfigs } from '../lib/factory.js'
2
-
3
- export default createConfigs({
4
- name: 'typeAware',
5
- configs: [
6
- {
7
- options: {
8
- typeAware: true,
9
- typeCheck: true,
10
- },
11
- rules: {
12
- 'typescript/prefer-readonly-parameter-types': 'off',
13
- },
14
- },
15
- ],
16
- })