feat: add linting and formatting setup
- Add ESLint configuration with TypeScript support - Add Prettier configuration for code formatting - Add lint and format scripts to package.json - Remove framework-specific configuration - Configure for general JavaScript/TypeScript development
This commit is contained in:
@@ -0,0 +1,353 @@
|
||||
import { fixupPluginRules, includeIgnoreFile } from '@eslint/compat'
|
||||
import checkFilePlugin from 'eslint-plugin-check-file'
|
||||
import importPlugin from 'eslint-plugin-import'
|
||||
import perfectionist from 'eslint-plugin-perfectionist'
|
||||
import globals from 'globals'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import tsEslint, { parser } from 'typescript-eslint'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const gitIgnorePath = path.join(__dirname, '.gitignore')
|
||||
const autofix = process.env.CI ? 'error' : 'warn'
|
||||
|
||||
/** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig.Config[]} */
|
||||
export default [
|
||||
// Global ignore
|
||||
{
|
||||
ignores: ['**/*.json'],
|
||||
name: 'claudesidian/global-ignore',
|
||||
},
|
||||
|
||||
// Git ignore
|
||||
{
|
||||
...includeIgnoreFile(gitIgnorePath),
|
||||
name: 'claudesidian/gitignore',
|
||||
},
|
||||
|
||||
// Default config
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.mjs'],
|
||||
languageOptions: {
|
||||
parser,
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
sourceType: 'module',
|
||||
},
|
||||
linterOptions: {
|
||||
reportUnusedDisableDirectives: 'error',
|
||||
reportUnusedInlineConfigs: 'error',
|
||||
},
|
||||
name: 'claudesidian/default',
|
||||
plugins: {
|
||||
'@typescript-eslint': tsEslint.plugin,
|
||||
'check-file': checkFilePlugin,
|
||||
'import': fixupPluginRules(importPlugin),
|
||||
perfectionist,
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/array-type': [autofix],
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
'error',
|
||||
{ minimumDescriptionLength: 10 },
|
||||
],
|
||||
'@typescript-eslint/ban-tslint-comment': [autofix],
|
||||
'@typescript-eslint/consistent-generic-constructors': [autofix],
|
||||
'@typescript-eslint/consistent-indexed-object-style': [autofix],
|
||||
'@typescript-eslint/consistent-type-assertions': [autofix],
|
||||
'@typescript-eslint/consistent-type-definitions': [autofix],
|
||||
'@typescript-eslint/default-param-last': ['error'],
|
||||
'@typescript-eslint/method-signature-style': [autofix, 'property'],
|
||||
'@typescript-eslint/no-array-constructor': [autofix],
|
||||
'@typescript-eslint/no-empty-function': ['error'],
|
||||
'@typescript-eslint/no-empty-object-type': [
|
||||
'error',
|
||||
{ allowInterfaces: 'with-single-extends' },
|
||||
],
|
||||
'@typescript-eslint/no-explicit-any': ['error'],
|
||||
'@typescript-eslint/no-extra-non-null-assertion': [autofix],
|
||||
'@typescript-eslint/no-import-type-side-effects': [autofix],
|
||||
'@typescript-eslint/no-inferrable-types': [autofix],
|
||||
'@typescript-eslint/no-loop-func': ['error'],
|
||||
'@typescript-eslint/no-misused-new': ['error'],
|
||||
'@typescript-eslint/no-namespace': ['error'],
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': ['error'],
|
||||
'@typescript-eslint/no-require-imports': ['error'],
|
||||
'@typescript-eslint/no-this-alias': ['error'],
|
||||
'@typescript-eslint/no-unnecessary-type-constraint': ['error'],
|
||||
'@typescript-eslint/no-unsafe-declaration-merging': ['error'],
|
||||
'@typescript-eslint/no-unsafe-function-type': ['error'],
|
||||
'@typescript-eslint/no-unused-expressions': ['error'],
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
args: 'all',
|
||||
argsIgnorePattern: '^_',
|
||||
caughtErrors: 'all',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
destructuredArrayIgnorePattern: '^_',
|
||||
ignoreRestSiblings: false,
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-useless-constructor': ['error'],
|
||||
'@typescript-eslint/no-useless-empty-export': [autofix],
|
||||
'@typescript-eslint/no-wrapper-object-types': [autofix],
|
||||
'@typescript-eslint/prefer-as-const': [autofix],
|
||||
'@typescript-eslint/prefer-for-of': ['error'],
|
||||
'@typescript-eslint/prefer-function-type': [autofix],
|
||||
'@typescript-eslint/prefer-literal-enum-member': ['error'],
|
||||
'@typescript-eslint/prefer-namespace-keyword': [autofix],
|
||||
'@typescript-eslint/triple-slash-reference': ['error'],
|
||||
'check-file/filename-naming-convention': [
|
||||
'error',
|
||||
{ '**/*': 'KEBAB_CASE' },
|
||||
{ ignoreMiddleExtensions: true },
|
||||
],
|
||||
'check-file/folder-naming-convention': [
|
||||
'error',
|
||||
{ '**/*': 'NEXT_JS_APP_ROUTER_CASE' },
|
||||
{ ignoreMiddleExtensions: true },
|
||||
],
|
||||
'check-file/no-index': ['error', { ignoreMiddleExtensions: true }],
|
||||
'constructor-super': ['error'],
|
||||
'curly': [autofix, 'multi-line', 'consistent'],
|
||||
'eqeqeq': [autofix, 'always', { null: 'ignore' }],
|
||||
'for-direction': ['error'],
|
||||
'getter-return': ['error'],
|
||||
'import/enforce-node-protocol-usage': [autofix, 'always'],
|
||||
'import/first': [autofix],
|
||||
'import/newline-after-import': [autofix],
|
||||
'import/no-default-export': ['error'],
|
||||
'import/no-duplicates': [autofix],
|
||||
'import/no-mutable-exports': ['error'],
|
||||
'logical-assignment-operators': [autofix],
|
||||
'no-async-promise-executor': ['error'],
|
||||
'no-case-declarations': ['error'],
|
||||
'no-class-assign': ['error'],
|
||||
'no-compare-neg-zero': ['error'],
|
||||
'no-cond-assign': ['error'],
|
||||
'no-const-assign': ['error'],
|
||||
'no-constant-binary-expression': ['error'],
|
||||
'no-constant-condition': ['error'],
|
||||
'no-control-regex': ['error'],
|
||||
'no-debugger': ['error'],
|
||||
'no-delete-var': ['error'],
|
||||
'no-div-regex': [autofix],
|
||||
'no-dupe-args': ['error'],
|
||||
'no-dupe-else-if': ['error'],
|
||||
'no-dupe-keys': ['error'],
|
||||
'no-duplicate-case': ['error'],
|
||||
'no-else-return': [autofix],
|
||||
'no-empty': ['error'],
|
||||
'no-empty-character-class': ['error'],
|
||||
'no-empty-pattern': ['error'],
|
||||
'no-empty-static-block': ['error'],
|
||||
'no-ex-assign': ['error'],
|
||||
'no-extra-bind': [autofix],
|
||||
'no-extra-boolean-cast': [autofix],
|
||||
'no-extra-label': [autofix],
|
||||
'no-fallthrough': ['error', { commentPattern: 'no-fallthrough-ignore' }],
|
||||
'no-func-assign': ['error'],
|
||||
'no-global-assign': ['error'],
|
||||
'no-implicit-coercion': [autofix, { allow: ['!!'] }],
|
||||
'no-import-assign': ['error'],
|
||||
'no-inner-declarations': ['error'],
|
||||
'no-invalid-regexp': ['error'],
|
||||
'no-irregular-whitespace': ['error'],
|
||||
'no-lonely-if': [autofix],
|
||||
'no-misleading-character-class': ['error'],
|
||||
'no-new-native-nonconstructor': ['error'],
|
||||
'no-nonoctal-decimal-escape': ['error'],
|
||||
'no-obj-calls': ['error'],
|
||||
'no-octal': ['error'],
|
||||
'no-prototype-builtins': ['error'],
|
||||
'no-regex-spaces': [autofix],
|
||||
'no-self-assign': ['error'],
|
||||
'no-setter-return': ['error'],
|
||||
'no-shadow-restricted-names': ['error'],
|
||||
'no-sparse-arrays': ['error'],
|
||||
'no-template-curly-in-string': ['error'],
|
||||
'no-this-before-super': ['error'],
|
||||
'no-unassigned-vars': ['error'],
|
||||
'no-undef': ['error'],
|
||||
'no-undef-init': [autofix],
|
||||
'no-unexpected-multiline': ['error'],
|
||||
'no-unneeded-ternary': [autofix],
|
||||
'no-unreachable': ['error'],
|
||||
'no-unsafe-finally': ['error'],
|
||||
'no-unsafe-negation': ['error'],
|
||||
'no-unsafe-optional-chaining': ['error'],
|
||||
'no-unused-labels': [autofix],
|
||||
'no-unused-private-class-members': ['error'],
|
||||
'no-useless-assignment': ['error'],
|
||||
'no-useless-backreference': ['error'],
|
||||
'no-useless-catch': ['error'],
|
||||
'no-useless-computed-key': [autofix],
|
||||
'no-useless-escape': ['error'],
|
||||
'no-useless-rename': [autofix],
|
||||
'no-useless-return': [autofix],
|
||||
'no-var': [autofix],
|
||||
'no-with': ['error'],
|
||||
'object-shorthand': [autofix],
|
||||
'one-var': [autofix, 'never'],
|
||||
'operator-assignment': [autofix],
|
||||
'perfectionist/sort-array-includes': [autofix],
|
||||
'perfectionist/sort-classes': [autofix],
|
||||
'perfectionist/sort-decorators': [autofix],
|
||||
'perfectionist/sort-enums': [autofix],
|
||||
'perfectionist/sort-exports': [autofix],
|
||||
'perfectionist/sort-heritage-clauses': [autofix],
|
||||
'perfectionist/sort-imports': [autofix],
|
||||
'perfectionist/sort-interfaces': [autofix],
|
||||
'perfectionist/sort-intersection-types': [autofix],
|
||||
'perfectionist/sort-jsx-props': [autofix],
|
||||
'perfectionist/sort-maps': [autofix],
|
||||
'perfectionist/sort-modules': [autofix],
|
||||
'perfectionist/sort-named-exports': [autofix],
|
||||
'perfectionist/sort-named-imports': [autofix],
|
||||
'perfectionist/sort-object-types': [autofix],
|
||||
'perfectionist/sort-objects': [autofix],
|
||||
'perfectionist/sort-sets': [autofix],
|
||||
'perfectionist/sort-switch-case': [autofix],
|
||||
'perfectionist/sort-union-types': [autofix],
|
||||
'prefer-const': [autofix],
|
||||
'prefer-exponentiation-operator': [autofix],
|
||||
'prefer-numeric-literals': [autofix],
|
||||
'prefer-object-has-own': [autofix],
|
||||
'prefer-object-spread': [autofix],
|
||||
'prefer-template': [autofix],
|
||||
'radix': ['error'],
|
||||
'require-yield': ['error'],
|
||||
'unicode-bom': [autofix],
|
||||
'use-isnan': ['error'],
|
||||
'valid-typeof': ['error'],
|
||||
'yoda': [autofix],
|
||||
},
|
||||
settings: {
|
||||
perfectionist: {
|
||||
partitionByComment: true,
|
||||
type: 'natural',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Files that require default exports
|
||||
{
|
||||
files: [
|
||||
'**/*config.*',
|
||||
'**/global-error.tsx',
|
||||
'**/error.tsx',
|
||||
'**/layout.tsx',
|
||||
'**/loading.tsx',
|
||||
'**/middleware.ts',
|
||||
'**/page.tsx',
|
||||
'**/not-found.tsx',
|
||||
],
|
||||
name: 'claudesidian/disable-default-export',
|
||||
rules: {
|
||||
'import/no-default-export': 'off',
|
||||
},
|
||||
},
|
||||
|
||||
// Typed rules
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
},
|
||||
name: 'claudesidian/typed',
|
||||
plugins: { tsEslint: tsEslint.plugin },
|
||||
rules: {
|
||||
'@typescript-eslint/await-thenable': ['error'],
|
||||
'@typescript-eslint/consistent-type-exports': [autofix],
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
autofix,
|
||||
{ fixStyle: 'inline-type-imports' },
|
||||
],
|
||||
'@typescript-eslint/dot-notation': [autofix],
|
||||
'@typescript-eslint/explicit-member-accessibility': [
|
||||
autofix,
|
||||
{ overrides: { constructors: 'no-public' } },
|
||||
],
|
||||
'@typescript-eslint/no-array-delete': ['error'],
|
||||
'@typescript-eslint/no-base-to-string': ['error'],
|
||||
'@typescript-eslint/no-confusing-void-expression': [autofix],
|
||||
'@typescript-eslint/no-deprecated': ['error'],
|
||||
'@typescript-eslint/no-duplicate-enum-values': ['error'],
|
||||
'@typescript-eslint/no-duplicate-type-constituents': [autofix],
|
||||
'@typescript-eslint/no-dynamic-delete': [autofix],
|
||||
'@typescript-eslint/no-extraneous-class': ['error'],
|
||||
'@typescript-eslint/no-floating-promises': ['error'],
|
||||
'@typescript-eslint/no-for-in-array': ['error'],
|
||||
'@typescript-eslint/no-implied-eval': ['error'],
|
||||
'@typescript-eslint/no-invalid-void-type': ['error'],
|
||||
'@typescript-eslint/no-meaningless-void-operator': [autofix],
|
||||
'@typescript-eslint/no-misused-promises': [
|
||||
'error',
|
||||
{ checksVoidReturn: false },
|
||||
],
|
||||
'@typescript-eslint/no-misused-spread': ['error'],
|
||||
'@typescript-eslint/no-mixed-enums': ['error'],
|
||||
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': ['error'],
|
||||
'@typescript-eslint/no-non-null-assertion': ['error'],
|
||||
'@typescript-eslint/no-redundant-type-constituents': ['error'],
|
||||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': [autofix],
|
||||
'@typescript-eslint/no-unnecessary-condition': ['error'],
|
||||
'@typescript-eslint/no-unnecessary-qualifier': [autofix],
|
||||
'@typescript-eslint/no-unnecessary-template-expression': [autofix],
|
||||
'@typescript-eslint/no-unnecessary-type-arguments': [autofix],
|
||||
'@typescript-eslint/no-unnecessary-type-assertion': [autofix],
|
||||
'@typescript-eslint/no-unnecessary-type-conversion': ['error'],
|
||||
'@typescript-eslint/no-unnecessary-type-parameters': ['error'],
|
||||
'@typescript-eslint/no-unsafe-argument': ['error'],
|
||||
'@typescript-eslint/no-unsafe-assignment': ['error'],
|
||||
'@typescript-eslint/no-unsafe-call': ['error'],
|
||||
'@typescript-eslint/no-unsafe-enum-comparison': ['error'],
|
||||
'@typescript-eslint/no-unsafe-member-access': ['error'],
|
||||
'@typescript-eslint/no-unsafe-return': ['error'],
|
||||
'@typescript-eslint/no-unsafe-type-assertion': ['error'],
|
||||
'@typescript-eslint/no-unsafe-unary-minus': ['error'],
|
||||
'@typescript-eslint/non-nullable-type-assertion-style': [autofix],
|
||||
'@typescript-eslint/only-throw-error': ['error'],
|
||||
'@typescript-eslint/prefer-destructuring': [autofix, { array: false }],
|
||||
'@typescript-eslint/prefer-find': ['error'],
|
||||
'@typescript-eslint/prefer-includes': [autofix],
|
||||
'@typescript-eslint/prefer-nullish-coalescing': [
|
||||
'error',
|
||||
{ ignorePrimitives: { string: true } },
|
||||
],
|
||||
'@typescript-eslint/prefer-optional-chain': [autofix],
|
||||
'@typescript-eslint/prefer-promise-reject-errors': ['error'],
|
||||
'@typescript-eslint/prefer-readonly': [autofix],
|
||||
'@typescript-eslint/prefer-reduce-type-parameter': [autofix],
|
||||
'@typescript-eslint/prefer-regexp-exec': [autofix],
|
||||
'@typescript-eslint/prefer-return-this-type': [autofix],
|
||||
'@typescript-eslint/prefer-string-starts-ends-with': [autofix],
|
||||
'@typescript-eslint/promise-function-async': [autofix],
|
||||
'@typescript-eslint/related-getter-setter-pairs': ['error'],
|
||||
'@typescript-eslint/require-array-sort-compare': ['error'],
|
||||
'@typescript-eslint/require-await': ['error'],
|
||||
'@typescript-eslint/restrict-plus-operands': ['error'],
|
||||
'@typescript-eslint/restrict-template-expressions': ['error'],
|
||||
'@typescript-eslint/return-await': [autofix],
|
||||
'@typescript-eslint/switch-exhaustiveness-check': ['error'],
|
||||
'@typescript-eslint/unbound-method': ['error'],
|
||||
'@typescript-eslint/unified-signatures': ['error'],
|
||||
'@typescript-eslint/use-unknown-in-catch-callback-variable': ['error'],
|
||||
},
|
||||
},
|
||||
|
||||
// Node environment
|
||||
{
|
||||
files: ['**/*.ts', '**/*.js', '**/*.mjs'],
|
||||
languageOptions: { globals: globals.nodeBuiltin },
|
||||
name: 'claudesidian/node',
|
||||
},
|
||||
|
||||
// App-specific rules
|
||||
]
|
||||
Generated
+5135
File diff suppressed because it is too large
Load Diff
+19
-1
@@ -6,6 +6,10 @@
|
||||
"scripts": {
|
||||
"setup": "pnpm install && echo '✅ Setup complete! Configure GEMINI_API_KEY for vision features'",
|
||||
"test-gemini": "GEMINI_API_KEY=${GEMINI_API_KEY} node .claude/mcp-servers/gemini-vision.mjs",
|
||||
"lint": "eslint . --fix && prettier --write .",
|
||||
"lint:check": "eslint . && prettier --check .",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"attachments:list": "ls -1 '05_Attachments/' | grep -v Organized | head -20",
|
||||
"attachments:count": "ls -1 '05_Attachments/' | grep -v Organized | wc -l",
|
||||
"attachments:organized": "ls -1 '05_Attachments/Organized' 2>/dev/null | wc -l || echo '0'",
|
||||
@@ -32,5 +36,19 @@
|
||||
"dependencies": {
|
||||
"@google/generative-ai": "^0.21.0",
|
||||
"@modelcontextprotocol/sdk": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.35.0",
|
||||
"@typescript-eslint/parser": "^8.35.0",
|
||||
"eslint": "^9.29.0",
|
||||
"eslint-plugin-check-file": "^3.3.0",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-perfectionist": "^4.15.0",
|
||||
"globals": "^16.2.0",
|
||||
"prettier": "^3.6.0",
|
||||
"prettier-plugin-packagejson": "^2.5.15",
|
||||
"prettier-plugin-sort-json": "^4.1.1",
|
||||
"typescript-eslint": "^8.35.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
export default {
|
||||
overrides: [
|
||||
{
|
||||
files: '**/*.tsx',
|
||||
options: {
|
||||
plugins: ['prettier-plugin-tailwindcss'],
|
||||
},
|
||||
},
|
||||
{
|
||||
excludeFiles: '**/package.json',
|
||||
files: '**/*.json',
|
||||
options: {
|
||||
jsonRecursiveSort: true,
|
||||
plugins: ['prettier-plugin-sort-json'],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: '**/package.json',
|
||||
options: {
|
||||
plugins: ['prettier-plugin-packagejson'],
|
||||
trailingComma: 'none',
|
||||
},
|
||||
},
|
||||
],
|
||||
proseWrap: 'always',
|
||||
quoteProps: 'consistent',
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"incremental": true,
|
||||
"isolatedModules": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"noEmit": true,
|
||||
"noImplicitReturns": true, // preferred over https://typescript-eslint.io/rules/consistent-return/
|
||||
"noUnusedLocals": false, // prefer using https://typescript-eslint.io/rules/no-unused-vars/
|
||||
"noUnusedParameters": false, // prefer using https://typescript-eslint.io/rules/no-unused-vars/
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"verbatimModuleSyntax": false // prefer using https://typescript-eslint.io/rules/consistent-type-imports
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user