@todesktop/dev-config 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # dev-config
2
+
3
+ This package provides reusable development configuration files used across the
4
+ repository: ESLint, Prettier, and a base `tsconfig`.
5
+
6
+ ## ESLint
7
+
8
+ The ESLint configuration is based on
9
+ [eslint-config-airbnb-extended](https://github.com/NishargShah/eslint-config-airbnb-extended),
10
+ which modernizes and replaces parts of
11
+ [eslint-config-airbnb](https://github.com/airbnb/javascript) and
12
+ [eslint-config-airbnb-typescript](https://github.com/iamturns/eslint-config-airbnb-typescript).
13
+
14
+ All projects extend the root config at
15
+ [eslint.config.mjs](../../eslint.config.mjs). If a project needs a different
16
+ configuration, add or override rules in that project's `eslint.config.mjs` (for
17
+ example, [tdutils](../tdutils/eslint.config.mjs)).
18
+
19
+ A typical project config that reuses these shared configs looks like this:
20
+
21
+ ```js
22
+ import { configs, defineConfig } from '@todesktop/dev-config/eslint';
23
+
24
+ export default defineConfig(
25
+ configs.base,
26
+ configs.ts,
27
+ configs.prettier,
28
+ configs.react,
29
+ configs.nodeCommonJs,
30
+
31
+ {
32
+ rules: {
33
+ 'no-console': 'off',
34
+ },
35
+ },
36
+ );
37
+ ```
38
+
39
+ Predefined configs from this package are applied first, then any
40
+ project-specific rules are merged on top.
41
+
42
+ See `eslint/index.js` in this package for a list of available configs and short
43
+ descriptions.
44
+
45
+ Some configs come in multiple strictness levels. When you choose a strict
46
+ variant, also include the base config, since it's not inherited.
47
+
48
+ | Base | Strict | Description |
49
+ | ------------ | ----------- | ------------------------------------------------------------------- |
50
+ | base | strict | JavaScript rules |
51
+ | ts | tsStrict | TypeScript rules |
52
+ | react | reactStrict | React-specific rules |
53
+ | prettier | - | Loads Prettier-related rule adjustments |
54
+ | node | - | Best practices for Node.js |
55
+ | nodeCommonJs | - | For CommonJS `.js`/`.cjs` files (configs, scripts, not source code) |
56
+ | esm | - | ESM-specific rules |
57
+ | unicorn | - | Rules from `eslint-plugin-unicorn` |
58
+
59
+ ## Prettier
60
+
61
+ A shared Prettier configuration is provided and applied from the repository
62
+ root, so you usually do not need to add a separate Prettier config inside each
63
+ subpackage.
64
+
65
+ ## tsconfig
66
+
67
+ A shared TypeScript base config is available. To reuse it, extend it from your
68
+ package's `tsconfig.json`:
69
+
70
+ ```json
71
+ {
72
+ "extends": "@todesktop/dev-config/tsconfig.json",
73
+ "include": ["src/**/*.ts"]
74
+ }
75
+ ```
@@ -0,0 +1,69 @@
1
+ import airbnb from 'eslint-config-airbnb-extended';
2
+
3
+ /** @type {import('eslint').Linter.Config} */
4
+ export default {
5
+ name: '@todesktop/dev-config/eslint/base',
6
+
7
+ languageOptions: {
8
+ ecmaVersion: 'latest',
9
+ sourceType: 'module',
10
+ },
11
+
12
+ rules: {
13
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/errors.ts
14
+ ...airbnb.rules.base.errors.rules,
15
+
16
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/es6.ts
17
+ ...airbnb.rules.base.es6.rules,
18
+
19
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/strict.ts
20
+ ...airbnb.rules.base.strict.rules,
21
+
22
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/style.ts
23
+ ...airbnb.rules.base.style.rules,
24
+
25
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/variables.ts
26
+ ...airbnb.rules.base.variables.rules,
27
+
28
+ // Together with enabling for..of
29
+ // https://eslint.org/docs/latest/rules/no-restricted-syntax
30
+ 'no-continue': 'off',
31
+
32
+ // Re-enabled in strict
33
+ // https://eslint.org/docs/latest/rules/no-nested-ternary
34
+ 'no-nested-ternary': 'off',
35
+
36
+ // Re-enabled in strict, keep `Promise((r) => setTimeout(r, 10))` syntax
37
+ // https://eslint.org/docs/rules/no-promise-executor-return
38
+ 'no-promise-executor-return': 'off',
39
+
40
+ // Allow for..of
41
+ // https://eslint.org/docs/latest/rules/no-restricted-syntax
42
+ 'no-restricted-syntax': [
43
+ 'error',
44
+ {
45
+ message:
46
+ 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
47
+ selector: 'ForInStatement',
48
+ },
49
+ {
50
+ message:
51
+ 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
52
+ selector: 'LabeledStatement',
53
+ },
54
+ {
55
+ message:
56
+ '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
57
+ selector: 'WithStatement',
58
+ },
59
+ ],
60
+
61
+ // Using before definition allows placing the primary code on the top
62
+ // https://eslint.org/docs/latest/rules/no-use-before-define
63
+ 'no-use-before-define': 'off',
64
+
65
+ // We have a lot of code where it'd be less readable on applying
66
+ // https://eslint.org/docs/latest/rules/prefer-template
67
+ 'prefer-template': 'off',
68
+ },
69
+ };
@@ -0,0 +1,17 @@
1
+ /** @type {import('eslint').Linter.Config} */
2
+ export default {
3
+ name: '@todesktop/dev-config/eslint/esm',
4
+
5
+ files: ['**/*.js', '**/*.mjs'],
6
+
7
+ languageOptions: {
8
+ ecmaVersion: 2022,
9
+ sourceType: 'module',
10
+ },
11
+
12
+ rules: {
13
+ // ESM files couldn't use directory imports
14
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-useless-path-segments.md
15
+ 'import-x/no-useless-path-segments': 'off',
16
+ },
17
+ };
@@ -0,0 +1,39 @@
1
+ import airbnb from 'eslint-config-airbnb-extended';
2
+ import globals from 'globals';
3
+
4
+ /** @type {import('eslint').Linter.Config} */
5
+ export default {
6
+ name: '@todesktop/dev-config/eslint/node',
7
+
8
+ languageOptions: {
9
+ globals: {
10
+ ...globals.node,
11
+ },
12
+ },
13
+
14
+ plugins: {
15
+ ...airbnb.plugins.node.plugins,
16
+ },
17
+
18
+ rules: {
19
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/node/nodeBase.ts
20
+ ...airbnb.rules.node.base.rules,
21
+
22
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/node/nodeGlobals.ts
23
+ ...airbnb.rules.node.globals.rules,
24
+
25
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/node/nodeNoUnsupportedFeatures.ts
26
+ ...airbnb.rules.node.promises.rules,
27
+
28
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/node/nodePromises.ts
29
+ ...airbnb.rules.node.noUnsupportedFeatures.rules,
30
+
31
+ // Requires type information
32
+ // https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-sync.md
33
+ 'n/no-sync': 'off',
34
+
35
+ // Strict flag depends on sourceType
36
+ // https://eslint.org/docs/latest/rules/strict
37
+ 'strict': ['error', 'global'],
38
+ },
39
+ };
@@ -0,0 +1,22 @@
1
+ import globals from 'globals';
2
+
3
+ /** @type {import('eslint').Linter.Config} */
4
+ export default {
5
+ name: '@todesktop/dev-config/eslint/nodeCommonJs',
6
+
7
+ files: ['**/*.js', '**/*.cjs'],
8
+
9
+ languageOptions: {
10
+ ecmaVersion: 2022,
11
+ globals: {
12
+ ...globals.node,
13
+ },
14
+ sourceType: 'commonjs',
15
+ },
16
+
17
+ rules: {
18
+ // Require 'use strict' for commonJs files
19
+ // https://eslint.org/docs/latest/rules/strict
20
+ strict: ['error', 'global'],
21
+ },
22
+ };
@@ -0,0 +1,17 @@
1
+ import prettierConfig from 'eslint-config-prettier/flat';
2
+ import prettierPlugin from 'eslint-plugin-prettier';
3
+
4
+ /** @type {import('eslint').Linter.Config} */
5
+ export default {
6
+ name: '@todesktop/dev-config/eslint/prettier',
7
+
8
+ plugins: { prettier: prettierPlugin },
9
+
10
+ rules: {
11
+ // https://github.com/prettier/eslint-config-prettier/blob/main/index.js
12
+ ...prettierConfig.rules,
13
+
14
+ // https://github.com/prettier/eslint-plugin-prettier/blob/main/eslint-plugin-prettier.js
15
+ ...prettierPlugin.configs.recommended.rules,
16
+ },
17
+ };
@@ -0,0 +1,52 @@
1
+ import airbnb from 'eslint-config-airbnb-extended';
2
+
3
+ /** @type {import('eslint').Linter.Config} */
4
+ export default {
5
+ name: '@todesktop/dev-config/eslint/react',
6
+
7
+ languageOptions: {
8
+ ...airbnb.plugins.react.plugins.languageOptions,
9
+ },
10
+
11
+ plugins: {
12
+ ...airbnb.plugins.react.plugins,
13
+ ...airbnb.plugins.reactHooks.plugins,
14
+ },
15
+
16
+ rules: {
17
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/react/react.ts
18
+ ...airbnb.rules.react.base.rules,
19
+
20
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/react/reactHooks.ts
21
+ ...airbnb.rules.react.hooks.rules,
22
+
23
+ // Add tsx extension
24
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md
25
+ 'react/jsx-filename-extension': [
26
+ 'error',
27
+ {
28
+ extensions: ['.jsx', '.tsx'],
29
+ },
30
+ ],
31
+
32
+ // Re-enabled in reactStrict
33
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md
34
+ 'react/destructuring-assignment': 'off',
35
+
36
+ // There are a lot of existed cases that would look worse after applying
37
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-one-expression-per-line.md
38
+ 'react/jsx-one-expression-per-line': 'off',
39
+
40
+ // We already have a lot of components defined as arrow functions
41
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md
42
+ 'react/function-component-definition': 'off',
43
+
44
+ // I think only web-app doesn't use react-jsx runtime
45
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/react-in-jsx-scope.md
46
+ 'react/react-in-jsx-scope': 'off',
47
+
48
+ // It's better handled by TSC
49
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/prop-types.md
50
+ 'react/require-default-props': 'off',
51
+ },
52
+ };
@@ -0,0 +1,25 @@
1
+ import airbnb from 'eslint-config-airbnb-extended';
2
+
3
+ /** @type {import('eslint').Linter.Config} */
4
+ export default {
5
+ name: '@todesktop/dev-config/eslint/reactStrict',
6
+
7
+ rules: {
8
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/react/reactStrict.ts
9
+ ...airbnb.rules.react.strict.rules,
10
+
11
+ // Re-enabling
12
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/destructuring-assignment.md
13
+ 'react/destructuring-assignment': 'error',
14
+
15
+ // Re-enabling
16
+ // https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/function-component-definition.md
17
+ 'react/function-component-definition': [
18
+ 'error',
19
+ {
20
+ namedComponents: ['function-declaration', 'function-expression'],
21
+ unnamedComponents: 'function-expression',
22
+ },
23
+ ],
24
+ },
25
+ };
@@ -0,0 +1,157 @@
1
+ import airbnb from 'eslint-config-airbnb-extended';
2
+ import perfectionist from 'eslint-plugin-perfectionist';
3
+
4
+ /** @type {import('eslint').Linter.Config} */
5
+ export default {
6
+ name: '@todesktop/dev-config/eslint/strict',
7
+
8
+ /*
9
+ import-x replaces an old import plugin. It's much more powerful, but some
10
+ things work wired. If there are any issues with this plugin in the future,
11
+ it makes sense to completely remove it.
12
+ */
13
+ plugins: {
14
+ ...airbnb.plugins.importX.plugins,
15
+ perfectionist,
16
+ },
17
+
18
+ rules: {
19
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/best-practices.ts
20
+ ...airbnb.rules.base.bestPractices.rules,
21
+
22
+ // https://github.com/NishargShah/eslint-config-airbnb-extended/blob/master/packages/eslint-config-airbnb-extended/rules/imports.ts
23
+ ...airbnb.rules.base.imports.rules,
24
+
25
+ // It's too hard to configure it properly for different project types
26
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/extensions.md
27
+ 'import-x/extensions': 'off',
28
+
29
+ // Reports if a module's default export is unnamed
30
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-anonymous-default-export.md
31
+ 'import-x/no-anonymous-default-export': [
32
+ 'error',
33
+ {
34
+ allowArray: true,
35
+ allowObject: true,
36
+ },
37
+ ],
38
+
39
+ // It's often useful to rename default exports
40
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-rename-default.md
41
+ 'import-x/no-rename-default': 'off',
42
+
43
+ // It's too hard to configure it properly for different project types
44
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/no-unresolved.md
45
+ 'import-x/no-unresolved': 'off',
46
+
47
+ // perfectionist is used instead
48
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/order.md
49
+ 'import-x/order': 'off',
50
+
51
+ // That's not always useful
52
+ // https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/prefer-default-export.md
53
+ 'import-x/prefer-default-export': 'off',
54
+
55
+ // Re-enabling
56
+ // https://eslint.org/docs/latest/rules/no-nested-ternary
57
+ 'no-nested-ternary': 'error',
58
+
59
+ // Re-enabling
60
+ // https://eslint.org/docs/rules/no-promise-executor-return
61
+ 'no-promise-executor-return': 'error',
62
+
63
+ // https://perfectionist.dev/rules/sort-array-includes
64
+ 'perfectionist/sort-array-includes': [
65
+ 'error',
66
+ { order: 'asc', type: 'alphabetical' },
67
+ ],
68
+
69
+ // https://perfectionist.dev/rules/sort-enums
70
+ 'perfectionist/sort-enums': [
71
+ 'error',
72
+ { order: 'asc', type: 'alphabetical' },
73
+ ],
74
+
75
+ // https://perfectionist.dev/rules/sort-exports
76
+ 'perfectionist/sort-exports': [
77
+ 'error',
78
+ { order: 'asc', type: 'alphabetical' },
79
+ ],
80
+
81
+ // https://perfectionist.dev/rules/sort-imports
82
+ 'perfectionist/sort-imports': [
83
+ 'error',
84
+ {
85
+ groups: ['import', 'parent', 'sibling', 'unknown'],
86
+ newlinesBetween: 0,
87
+ order: 'asc',
88
+ type: 'alphabetical',
89
+ },
90
+ ],
91
+
92
+ // https://perfectionist.dev/rules/sort-interfaces
93
+ 'perfectionist/sort-interfaces': [
94
+ 'error',
95
+ { order: 'asc', type: 'alphabetical' },
96
+ ],
97
+
98
+ // https://perfectionist.dev/rules/sort-intersection-types
99
+ 'perfectionist/sort-intersection-types': [
100
+ 'error',
101
+ { order: 'asc', type: 'alphabetical' },
102
+ ],
103
+
104
+ // https://perfectionist.dev/rules/sort-jsx-props
105
+ 'perfectionist/sort-jsx-props': [
106
+ 'error',
107
+ { order: 'asc', type: 'alphabetical' },
108
+ ],
109
+
110
+ // https://perfectionist.dev/rules/sort-modules
111
+ 'perfectionist/sort-modules': [
112
+ 'error',
113
+ { order: 'asc', type: 'alphabetical' },
114
+ ],
115
+
116
+ // https://perfectionist.dev/rules/sort-named-exports
117
+ 'perfectionist/sort-named-exports': [
118
+ 'error',
119
+ { order: 'asc', type: 'alphabetical' },
120
+ ],
121
+
122
+ // https://perfectionist.dev/rules/sort-named-imports
123
+ 'perfectionist/sort-named-imports': [
124
+ 'error',
125
+ { order: 'asc', type: 'alphabetical' },
126
+ ],
127
+
128
+ // https://perfectionist.dev/rules/sort-object-types
129
+ 'perfectionist/sort-object-types': [
130
+ 'error',
131
+ { order: 'asc', type: 'alphabetical' },
132
+ ],
133
+
134
+ // https://perfectionist.dev/rules/sort-objects
135
+ 'perfectionist/sort-objects': [
136
+ 'error',
137
+ {
138
+ order: 'asc',
139
+ partitionByComment: true,
140
+ partitionByNewLine: true,
141
+ type: 'alphabetical',
142
+ },
143
+ ],
144
+
145
+ // https://perfectionist.dev/rules/sort-switch-case
146
+ 'perfectionist/sort-switch-case': [
147
+ 'error',
148
+ { order: 'asc', type: 'alphabetical' },
149
+ ],
150
+
151
+ // https://perfectionist.dev/rules/sort-union-types
152
+ 'perfectionist/sort-union-types': [
153
+ 'error',
154
+ { order: 'asc', type: 'alphabetical' },
155
+ ],
156
+ },
157
+ };
@@ -0,0 +1,21 @@
1
+ import ts from 'typescript-eslint';
2
+ import flatArrayConfig from '../utils/flatArrayConfig.js';
3
+
4
+ const recommendedConfig = flatArrayConfig(ts.configs.recommended);
5
+
6
+ /** @type {import('eslint').Linter.Config} */
7
+ export default {
8
+ ...recommendedConfig,
9
+ name: '@todesktop/dev-config/eslint/ts',
10
+
11
+ files: ['**/*.ts', '**/*.tsx'],
12
+
13
+ rules: {
14
+ // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/flat/recommended.ts
15
+ ...recommendedConfig.rules,
16
+
17
+ // Re-enabled in tsStrict
18
+ // https://typescript-eslint.io/rules/no-explicit-any/
19
+ '@typescript-eslint/no-explicit-any': 'off',
20
+ },
21
+ };
@@ -0,0 +1,21 @@
1
+ import ts from 'typescript-eslint';
2
+ import flatArrayConfig from '../utils/flatArrayConfig.js';
3
+
4
+ const strictConfig = flatArrayConfig(ts.configs.strict);
5
+
6
+ /** @type {import('eslint').Linter.Config} */
7
+ export default {
8
+ ...strictConfig,
9
+ name: '@todesktop/dev-config/eslint/tsStrict',
10
+
11
+ files: ['**/*.ts', '**/*.tsx'],
12
+
13
+ rules: {
14
+ // https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/flat/strict.ts
15
+ ...strictConfig.rules,
16
+
17
+ // Re-enabled after ts config
18
+ // https://typescript-eslint.io/rules/no-explicit-any/
19
+ '@typescript-eslint/no-explicit-any': 'error',
20
+ },
21
+ };
@@ -0,0 +1,46 @@
1
+ // I have no idea why import-x's parser has an error passing this lib
2
+ // eslint-disable-next-line
3
+ import unicorn from 'eslint-plugin-unicorn';
4
+
5
+ /** @type {import('eslint').Linter.Config} */
6
+ export default {
7
+ name: '@todesktop/dev-config/eslint/unicorn',
8
+
9
+ plugins: { unicorn },
10
+
11
+ rules: {
12
+ ...unicorn.configs.recommended.rules,
13
+
14
+ // Sometimes following the rule makes code less readable
15
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/consistent-function-scoping.md
16
+ 'unicorn/consistent-function-scoping': 'off',
17
+
18
+ // e as the name of a handled error is widely used
19
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/catch-error-name.md
20
+ 'unicorn/catch-error-name': 'off',
21
+
22
+ // We use camelCase for many files
23
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md
24
+ 'unicorn/filename-case': 'off',
25
+
26
+ // Ofter `return undefined` specifies the return type explicitly
27
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-useless-undefined.md
28
+ 'unicorn/no-useless-undefined': 'off',
29
+
30
+ // We allow abbreviations in identifiers
31
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prevent-abbreviations.md
32
+ 'unicorn/prevent-abbreviations': 'off',
33
+
34
+ // It's handled by other plugins
35
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-module.md
36
+ 'unicorn/prefer-module': 'off',
37
+
38
+ // Already handled by n/prefer-node-protocol
39
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md
40
+ 'unicorn/prefer-node-protocol': 'off',
41
+
42
+ // Since most projects are compiled to CommonJS, that's not possible now
43
+ // https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-top-level-await.md
44
+ 'unicorn/prefer-top-level-await': 'off',
45
+ },
46
+ };
@@ -0,0 +1,51 @@
1
+ import base from './configs/base.js';
2
+ import esm from './configs/esm.js';
3
+ import node from './configs/node.js';
4
+ import nodeCommonJs from './configs/nodeCommonJs.js';
5
+ import prettier from './configs/prettier.js';
6
+ import react from './configs/react.js';
7
+ import reactStrict from './configs/reactStrict.js';
8
+ import strict from './configs/strict.js';
9
+ import ts from './configs/ts.js';
10
+ import tsStrict from './configs/tsStrict.js';
11
+ import unicorn from './configs/unicorn.js';
12
+
13
+ // eslint-disable-next-line import-x/no-extraneous-dependencies
14
+ export { defineConfig } from 'eslint/config';
15
+
16
+ export const configs = {
17
+ // Mostly Airbnb base rules
18
+ base,
19
+
20
+ // ESM files, *.js, *.mjs only.
21
+ esm,
22
+
23
+ // Node.js best practices
24
+ node,
25
+
26
+ // CommonJS files, *.js, *.cjs only. Mostly it's deploying scripts and configs
27
+ nodeCommonJs,
28
+
29
+ // Recommended prettier rules
30
+ prettier,
31
+
32
+ // React + React Hooks rules
33
+ react,
34
+
35
+ // Strict rules for React
36
+ reactStrict,
37
+
38
+ // A bit more strict and contains less autofixes than the base config
39
+ strict,
40
+
41
+ // Rules from typescript-eslint
42
+ ts,
43
+
44
+ // Rules from typescript-eslint
45
+ tsStrict,
46
+
47
+ // https://github.com/sindresorhus/eslint-plugin-unicorn
48
+ unicorn,
49
+ };
50
+
51
+ export default { configs };
@@ -0,0 +1,19 @@
1
+ export default function flatArrayConfig(arrayConfig) {
2
+ if (Array.isArray(arrayConfig)) {
3
+ const mergedConfig = { languageOptions: {}, plugins: {}, rules: {} };
4
+
5
+ for (const config of arrayConfig) {
6
+ Object.assign(mergedConfig.languageOptions, config.languageOptions);
7
+ Object.assign(mergedConfig.plugins, config.plugins);
8
+ Object.assign(mergedConfig.rules, config.rules);
9
+ }
10
+
11
+ return mergedConfig;
12
+ }
13
+
14
+ if (typeof arrayConfig === 'object' && arrayConfig !== null) {
15
+ return arrayConfig;
16
+ }
17
+
18
+ throw new Error('Invalid array config');
19
+ }
@@ -0,0 +1,8 @@
1
+ import { configs, defineConfig } from './eslint/index.js';
2
+
3
+ export default defineConfig(
4
+ configs.base,
5
+ configs.strict,
6
+ configs.prettier,
7
+ configs.esm,
8
+ );
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@todesktop/dev-config",
3
+ "version": "1.0.0",
4
+ "description": "Shared dev configs for ESLint, Prettier, TypeScript, etc",
5
+ "author": "ToDesktop <hello@todesktop.com>",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "scripts": {
9
+ "format": "prettier . --write && eslint --fix",
10
+ "lint": "prettier . --check && eslint"
11
+ },
12
+ "exports": {
13
+ "./*": "./*",
14
+ "./eslint": "./eslint/index.js",
15
+ "./prettier": "./prettier/index.js"
16
+ },
17
+ "dependencies": {
18
+ "@eslint/js": "^9.37.0",
19
+ "eslint-config-airbnb-extended": "^2.3.2",
20
+ "eslint-config-prettier": "^10.1.8",
21
+ "eslint-import-resolver-typescript": "^4.4.4",
22
+ "eslint-plugin-import-x": "^4.16.1",
23
+ "eslint-plugin-n": "^17.23.1",
24
+ "eslint-plugin-perfectionist": "^4.15.1",
25
+ "eslint-plugin-prettier": "^5.5.4",
26
+ "eslint-plugin-react": "^7.37.5",
27
+ "eslint-plugin-react-hooks": "^7.0.0",
28
+ "eslint-plugin-unicorn": "^61.0.2",
29
+ "globals": "^15.15.0",
30
+ "typescript-eslint": "^8.46.1"
31
+ },
32
+ "devDependencies": {
33
+ "eslint": "^9.37.0",
34
+ "prettier": "^3.6.2"
35
+ }
36
+ }
@@ -0,0 +1,13 @@
1
+ export default {
2
+ overrides: [
3
+ {
4
+ files: ['*.yml'],
5
+ options: {
6
+ singleQuote: false,
7
+ },
8
+ },
9
+ ],
10
+ proseWrap: 'always',
11
+ quoteProps: 'consistent',
12
+ singleQuote: true,
13
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "esModuleInterop": true,
5
+ "module": "node20",
6
+ "moduleResolution": "Node16",
7
+ "noEmit": true,
8
+ "skipLibCheck": true,
9
+ "strict": true,
10
+ "target": "es2022"
11
+ }
12
+ }