2022-05-18 07:26:57 +00:00
|
|
|
/* eslint-env node */
|
2023-02-24 14:39:44 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
2022-12-28 19:22:54 +00:00
|
|
|
const guildConfig = require('@theguild/eslint-config/base');
|
2023-02-24 14:39:44 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
2023-02-10 01:15:24 +00:00
|
|
|
const { REACT_RESTRICTED_SYNTAX, RESTRICTED_SYNTAX } = require('@theguild/eslint-config/constants');
|
2024-09-06 16:07:54 +00:00
|
|
|
const path = require('path');
|
2022-12-28 19:22:54 +00:00
|
|
|
|
2023-10-04 14:28:35 +00:00
|
|
|
const SCHEMA_PATH = './packages/services/api/src/modules/*/module.graphql.ts';
|
|
|
|
|
const OPERATIONS_PATHS = [
|
|
|
|
|
'./packages/web/app/**/*.ts',
|
|
|
|
|
'./packages/web/app/**/*.tsx',
|
|
|
|
|
'./packages/web/app/**/*.graphql',
|
|
|
|
|
];
|
|
|
|
|
|
2022-12-28 19:22:54 +00:00
|
|
|
const rulesToExtends = Object.fromEntries(
|
|
|
|
|
Object.entries(guildConfig.rules).filter(([key]) =>
|
|
|
|
|
[
|
|
|
|
|
'import/first',
|
|
|
|
|
'no-restricted-globals',
|
|
|
|
|
'@typescript-eslint/no-unused-vars',
|
2022-12-28 20:38:03 +00:00
|
|
|
'unicorn/no-array-push-push',
|
|
|
|
|
'no-else-return',
|
|
|
|
|
'no-lonely-if',
|
|
|
|
|
'unicorn/prefer-includes',
|
|
|
|
|
'no-extra-boolean-cast',
|
2022-12-28 19:22:54 +00:00
|
|
|
].includes(key),
|
|
|
|
|
),
|
|
|
|
|
);
|
2022-05-18 07:26:57 +00:00
|
|
|
|
2023-02-10 01:15:24 +00:00
|
|
|
const HIVE_RESTRICTED_SYNTAX = [
|
|
|
|
|
{
|
|
|
|
|
// ❌ '0.0.0.0' or `0.0.0.0`
|
|
|
|
|
selector: ':matches(Literal[value="0.0.0.0"], TemplateElement[value.raw="0.0.0.0"])',
|
|
|
|
|
message: 'Use "::" to make it compatible with both IPv4 and IPv6',
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
2024-08-06 13:40:55 +00:00
|
|
|
const tailwindCallees = ['clsx', 'cn', 'cva', 'cx'];
|
|
|
|
|
|
2024-09-06 16:07:54 +00:00
|
|
|
/**
|
|
|
|
|
* @type {import('eslint').Linter.Config}
|
|
|
|
|
*/
|
2022-05-18 07:26:57 +00:00
|
|
|
module.exports = {
|
|
|
|
|
ignorePatterns: [
|
|
|
|
|
'scripts',
|
2022-05-27 12:15:11 +00:00
|
|
|
'rules',
|
2022-05-18 07:26:57 +00:00
|
|
|
'out',
|
2022-12-27 22:36:08 +00:00
|
|
|
'.hive',
|
2026-02-10 01:34:14 +00:00
|
|
|
'packages/web/app/.ladle/**',
|
2022-05-18 07:26:57 +00:00
|
|
|
'public',
|
|
|
|
|
'packages/web/app/src/graphql/index.ts',
|
|
|
|
|
'packages/libraries/cli/src/sdk.ts',
|
2023-07-04 15:19:45 +00:00
|
|
|
'packages/libraries/cli/src/gql/**/*',
|
2022-05-20 11:51:02 +00:00
|
|
|
'packages/services/storage/src/db/types.ts',
|
2023-02-24 14:39:44 +00:00
|
|
|
'packages/web/app/src/gql/**/*',
|
2023-02-26 08:54:32 +00:00
|
|
|
'codegen.cjs',
|
|
|
|
|
'tsup',
|
2026-03-26 09:15:09 +00:00
|
|
|
'packages/libraries/render-laboratory/src/laboratory.ts',
|
|
|
|
|
'packages/web/app/vite.config.ts',
|
2022-05-18 07:26:57 +00:00
|
|
|
],
|
2023-10-04 14:28:35 +00:00
|
|
|
overrides: [
|
|
|
|
|
{
|
|
|
|
|
// Setup GraphQL Parser
|
|
|
|
|
files: '*.{graphql,gql}',
|
|
|
|
|
parser: '@graphql-eslint/eslint-plugin',
|
|
|
|
|
plugins: ['@graphql-eslint'],
|
|
|
|
|
parserOptions: {
|
2026-03-25 08:56:26 +00:00
|
|
|
schema: SCHEMA_PATH,
|
|
|
|
|
operations: OPERATIONS_PATHS,
|
2022-05-18 07:26:57 +00:00
|
|
|
},
|
2026-03-26 09:15:09 +00:00
|
|
|
rules: {
|
|
|
|
|
'@graphql-eslint/no-deprecated': 'error',
|
|
|
|
|
'@graphql-eslint/require-id-when-available': 'error',
|
|
|
|
|
},
|
2023-10-04 14:28:35 +00:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
// Setup processor for operations/fragments definitions on code-files
|
|
|
|
|
files: ['packages/web/app/**/*.tsx', 'packages/web/app/**/*.ts'],
|
|
|
|
|
processor: '@graphql-eslint/graphql',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
files: ['packages/web/app/**/*.graphql'],
|
2024-05-22 07:55:27 +00:00
|
|
|
plugins: ['@graphql-eslint'],
|
2023-10-04 14:28:35 +00:00
|
|
|
rules: {
|
2024-10-17 13:01:48 +00:00
|
|
|
'@graphql-eslint/no-deprecated': 'error',
|
2026-03-26 09:15:09 +00:00
|
|
|
'@graphql-eslint/require-id-when-available': 'error',
|
2022-05-27 12:15:11 +00:00
|
|
|
},
|
2023-10-04 14:28:35 +00:00
|
|
|
},
|
2025-09-18 19:32:49 +00:00
|
|
|
{
|
|
|
|
|
files: ['*.cjs'],
|
|
|
|
|
parserOptions: { ecmaVersion: 2020 },
|
|
|
|
|
},
|
2023-10-04 14:28:35 +00:00
|
|
|
{
|
|
|
|
|
files: ['packages/**/*.ts', 'packages/**/*.tsx', 'cypress/**/*.ts', 'cypress/**/*.tsx'],
|
|
|
|
|
reportUnusedDisableDirectives: true,
|
|
|
|
|
parserOptions: {
|
|
|
|
|
ecmaVersion: 2020,
|
|
|
|
|
sourceType: 'module',
|
2025-11-16 09:38:27 +00:00
|
|
|
project: [path.join(__dirname, './tsconfig.eslint.json')],
|
2023-10-04 14:28:35 +00:00
|
|
|
},
|
|
|
|
|
parser: '@typescript-eslint/parser',
|
|
|
|
|
plugins: [...guildConfig.plugins, 'hive'],
|
|
|
|
|
extends: guildConfig.extends,
|
|
|
|
|
rules: {
|
|
|
|
|
'no-process-env': 'error',
|
|
|
|
|
'no-empty': ['error', { allowEmptyCatch: true }],
|
|
|
|
|
'import/no-absolute-path': 'error',
|
|
|
|
|
'import/no-self-import': 'error',
|
|
|
|
|
'import/no-extraneous-dependencies': [
|
|
|
|
|
'error',
|
|
|
|
|
{
|
|
|
|
|
devDependencies: [
|
|
|
|
|
'packages/services/storage/tools/*.js',
|
|
|
|
|
'packages/services/**',
|
|
|
|
|
'packages/migrations/**',
|
2024-05-17 12:30:10 +00:00
|
|
|
// We bundle it all anyway, so there are no node_modules
|
|
|
|
|
'packages/web/app/**',
|
2026-03-06 21:37:08 +00:00
|
|
|
// We bundle it all anyway, so there are no node_modules
|
|
|
|
|
'packages/libraries/laboratory/**',
|
2024-04-23 15:51:43 +00:00
|
|
|
'**/*.spec.ts',
|
|
|
|
|
'**/*.test.ts',
|
2026-01-25 20:38:44 +00:00
|
|
|
'**/*.e2e.ts',
|
2023-10-04 14:28:35 +00:00
|
|
|
],
|
|
|
|
|
optionalDependencies: false,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
'hive/enforce-deps-in-dev': [
|
|
|
|
|
'error',
|
|
|
|
|
{
|
|
|
|
|
scopes: ['@hive', '@graphql-hive'],
|
|
|
|
|
ignored: ['packages/libraries/**', 'packages/web/**'],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
'@typescript-eslint/no-floating-promises': 'error',
|
2024-10-21 09:57:33 +00:00
|
|
|
'sonarjs/no-unused-collection': 'warn',
|
|
|
|
|
'sonarjs/no-inverted-boolean-check': 'warn',
|
2023-10-04 14:28:35 +00:00
|
|
|
...rulesToExtends,
|
2024-06-14 07:12:07 +00:00
|
|
|
'no-lonely-if': 'off',
|
|
|
|
|
'object-shorthand': 'off',
|
2023-10-04 14:28:35 +00:00
|
|
|
'no-restricted-syntax': ['error', ...HIVE_RESTRICTED_SYNTAX, ...RESTRICTED_SYNTAX],
|
2024-03-26 16:23:10 +00:00
|
|
|
'prefer-destructuring': 'off',
|
2024-05-20 08:22:22 +00:00
|
|
|
'prefer-const': 'off',
|
2024-08-07 08:41:58 +00:00
|
|
|
'no-useless-escape': 'off',
|
2024-08-12 09:23:32 +00:00
|
|
|
'no-inner-declarations': 'off',
|
2024-03-26 16:23:10 +00:00
|
|
|
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
|
2023-10-04 14:28:35 +00:00
|
|
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
|
|
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
|
|
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
|
|
|
'@typescript-eslint/no-namespace': 'off',
|
|
|
|
|
'@typescript-eslint/no-empty-function': 'off',
|
|
|
|
|
'@typescript-eslint/ban-types': 'off',
|
|
|
|
|
'@typescript-eslint/triple-slash-reference': 'off',
|
2026-03-26 09:15:09 +00:00
|
|
|
'@typescript-eslint/no-unused-vars': [
|
|
|
|
|
'error',
|
|
|
|
|
{
|
|
|
|
|
argsIgnorePattern: '^_',
|
|
|
|
|
caughtErrors: 'none',
|
|
|
|
|
caughtErrorsIgnorePattern: '^_',
|
|
|
|
|
destructuredArrayIgnorePattern: '^_',
|
|
|
|
|
varsIgnorePattern: '^_',
|
|
|
|
|
},
|
|
|
|
|
],
|
2023-10-04 14:28:35 +00:00
|
|
|
},
|
|
|
|
|
},
|
2022-05-24 07:41:53 +00:00
|
|
|
{
|
2023-01-09 11:45:20 +00:00
|
|
|
files: ['packages/web/**'],
|
2022-05-24 07:41:53 +00:00
|
|
|
extends: [
|
2023-01-09 11:45:20 +00:00
|
|
|
'@theguild',
|
|
|
|
|
'@theguild/eslint-config/react',
|
2026-01-21 11:11:25 +00:00
|
|
|
'plugin:better-tailwindcss/legacy-recommended',
|
2022-05-24 07:41:53 +00:00
|
|
|
'plugin:@next/next/recommended',
|
|
|
|
|
],
|
|
|
|
|
settings: {
|
2023-02-19 02:50:29 +00:00
|
|
|
'import/resolver': {
|
|
|
|
|
typescript: {
|
|
|
|
|
project: ['packages/web/app/tsconfig.json'],
|
|
|
|
|
},
|
2022-05-24 07:41:53 +00:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
rules: {
|
|
|
|
|
// conflicts with official prettier-plugin-tailwindcss and tailwind v3
|
2026-01-21 11:11:25 +00:00
|
|
|
'better-tailwindcss/enforce-consistent-class-order': 'off',
|
2026-02-03 16:00:15 +00:00
|
|
|
'better-tailwindcss/enforce-canonical-classes': 'off',
|
2026-01-21 11:11:25 +00:00
|
|
|
// keeping classes in one line helps prettier-plugin-tailwindcss
|
|
|
|
|
// enable wrapping in text editors to make classes human readable
|
|
|
|
|
'better-tailwindcss/enforce-consistent-line-wrapping': 'off',
|
|
|
|
|
'better-tailwindcss/enforce-shorthand-classes': 'off',
|
2022-05-24 07:41:53 +00:00
|
|
|
'react/display-name': 'off',
|
|
|
|
|
'react/prop-types': 'off',
|
2022-11-01 00:11:53 +00:00
|
|
|
'react/no-unknown-property': 'off',
|
2022-05-24 13:31:53 +00:00
|
|
|
'jsx-a11y/anchor-is-valid': ['off', { components: ['Link', 'NextLink'] }],
|
|
|
|
|
'jsx-a11y/alt-text': ['warn', { elements: ['img'], img: ['Image', 'NextImage'] }],
|
2023-02-10 01:15:24 +00:00
|
|
|
'no-restricted-syntax': ['error', ...HIVE_RESTRICTED_SYNTAX, ...REACT_RESTRICTED_SYNTAX],
|
2024-03-26 16:23:10 +00:00
|
|
|
'prefer-destructuring': 'off',
|
2023-01-09 11:45:20 +00:00
|
|
|
'no-console': 'off',
|
2024-08-07 08:41:58 +00:00
|
|
|
'no-useless-escape': 'off',
|
2023-01-09 11:45:20 +00:00
|
|
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
|
|
|
'react/jsx-no-useless-fragment': 'off',
|
|
|
|
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
|
|
|
'@typescript-eslint/no-empty-function': 'off',
|
2025-10-08 07:56:32 +00:00
|
|
|
'react-hooks/rules-of-hooks': 'error',
|
2023-01-09 11:45:20 +00:00
|
|
|
'react-hooks/exhaustive-deps': 'off',
|
|
|
|
|
'unicorn/filename-case': 'off',
|
|
|
|
|
'import/no-default-export': 'off',
|
|
|
|
|
'@next/next/no-img-element': 'off',
|
|
|
|
|
'@typescript-eslint/ban-types': 'off',
|
|
|
|
|
'jsx-a11y/label-has-associated-control': 'off',
|
|
|
|
|
'jsx-a11y/click-events-have-key-events': 'off',
|
|
|
|
|
'jsx-a11y/no-static-element-interactions': 'off',
|
|
|
|
|
'@next/next/no-html-link-for-pages': 'off',
|
2024-03-14 10:08:29 +00:00
|
|
|
'unicorn/no-negated-condition': 'off',
|
2024-08-01 15:06:10 +00:00
|
|
|
'no-implicit-coercion': 'off',
|
2025-09-18 19:32:49 +00:00
|
|
|
|
|
|
|
|
'react/jsx-key': 'warn',
|
2023-01-09 11:45:20 +00:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
files: ['packages/web/app/**'],
|
|
|
|
|
settings: {
|
2026-01-21 11:11:25 +00:00
|
|
|
'better-tailwindcss': {
|
|
|
|
|
// tailwindcss 4: the path to the entry file of the css based tailwind config (eg: `src/global.css`)
|
|
|
|
|
entryPoint: 'packages/web/app/src/index.css',
|
2024-08-06 13:40:55 +00:00
|
|
|
callees: tailwindCallees,
|
2023-01-09 11:45:20 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-01-21 11:11:25 +00:00
|
|
|
rules: {
|
|
|
|
|
// better-tailwindcss assumes you're using v4...we're being explicit here due to our dual tailwind setups
|
|
|
|
|
'better-tailwindcss/no-deprecated-classes': 'error',
|
|
|
|
|
// Tailwind v4 uses CSS variables without var() syntax
|
|
|
|
|
'better-tailwindcss/enforce-consistent-variable-syntax': 'off',
|
|
|
|
|
'better-tailwindcss/no-unknown-classes': [
|
|
|
|
|
'error',
|
|
|
|
|
{
|
|
|
|
|
ignore: [
|
|
|
|
|
'drag-none',
|
|
|
|
|
// Animation utilities (from index.css, replaces tailwindcss-animate)
|
|
|
|
|
'animate-in',
|
|
|
|
|
'animate-out',
|
|
|
|
|
'fade-in-.*',
|
|
|
|
|
'fade-out-.*',
|
|
|
|
|
'zoom-in-.*',
|
|
|
|
|
'zoom-out-.*',
|
|
|
|
|
'slide-in-from-.*',
|
|
|
|
|
'slide-out-to-.*',
|
|
|
|
|
// Custom radius from @theme
|
|
|
|
|
'rounded-xs',
|
|
|
|
|
// ring-offset with semantic colors
|
|
|
|
|
'ring-offset-.*',
|
|
|
|
|
// Data attribute variants with custom animations (for Radix UI components)
|
|
|
|
|
'data-\\[side=(top|right|bottom|left)\\]:animate-slide-(up|down|left|right)-fade',
|
|
|
|
|
// GraphiQL classes
|
|
|
|
|
'graphiql-.*',
|
|
|
|
|
// hive classes
|
|
|
|
|
'hive-.*',
|
|
|
|
|
// Schema diff custom classes (defined in index.css)
|
|
|
|
|
'schema-doc-row-.*',
|
|
|
|
|
// No scrollbar utility (defined in index.css)
|
|
|
|
|
'no-scrollbar',
|
|
|
|
|
// Tailwind v4 CSS variable syntax with parentheses
|
|
|
|
|
'.*-\\(--.*\\)',
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
2023-01-09 11:45:20 +00:00
|
|
|
},
|
2025-10-08 07:56:32 +00:00
|
|
|
{
|
|
|
|
|
files: ['packages/web/app/**/*.stories.tsx', 'packages/web/docs/**'],
|
|
|
|
|
rules: {
|
|
|
|
|
'react-hooks/rules-of-hooks': 'off',
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-01-09 11:45:20 +00:00
|
|
|
{
|
|
|
|
|
files: ['packages/web/docs/**'],
|
|
|
|
|
settings: {
|
|
|
|
|
next: {
|
|
|
|
|
rootDir: 'packages/web/docs',
|
|
|
|
|
},
|
2026-01-21 11:11:25 +00:00
|
|
|
'better-tailwindcss': {
|
|
|
|
|
// tailwindcss 3: the path to the tailwind config file (eg: `tailwind.config.js`)
|
|
|
|
|
tailwindConfig: 'packages/web/docs/tailwind.config.ts',
|
2024-08-06 13:40:55 +00:00
|
|
|
callees: tailwindCallees,
|
2023-01-09 11:45:20 +00:00
|
|
|
},
|
|
|
|
|
},
|
2025-01-27 19:44:04 +00:00
|
|
|
rules: {
|
|
|
|
|
'import/extensions': 'off',
|
2026-01-21 11:11:25 +00:00
|
|
|
// better-tailwindcss assumes you're using v4...we're being explicit here due to our dual tailwind setups
|
|
|
|
|
'better-tailwindcss/no-deprecated-classes': 'off',
|
|
|
|
|
'better-tailwindcss/no-unknown-classes': [
|
|
|
|
|
'error',
|
|
|
|
|
{
|
|
|
|
|
ignore: [
|
|
|
|
|
'light',
|
|
|
|
|
'hive-focus',
|
|
|
|
|
'hive-focus-within',
|
|
|
|
|
'nextra-focus',
|
|
|
|
|
'nextra-scrollbar',
|
|
|
|
|
'no-scrollbar', // from Nextra
|
|
|
|
|
'hive-slider',
|
|
|
|
|
'hive-prose',
|
|
|
|
|
'subheader',
|
|
|
|
|
'subheading-anchor',
|
|
|
|
|
'duration-\\[.*\\]', // Allow arbitrary duration values like duration-[.8s]
|
|
|
|
|
'ease-\\[var\\(--.*\\)\\]', // Allow CSS variables in arbitrary ease values
|
|
|
|
|
'x:.*', // Allow Nextra 4 custom variant prefix
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
// Allow CSS variables in arbitrary values for Tailwind v3
|
|
|
|
|
'better-tailwindcss/enforce-consistent-variable-syntax': 'off',
|
2025-01-27 19:44:04 +00:00
|
|
|
},
|
2023-01-09 11:45:20 +00:00
|
|
|
},
|
2022-12-02 10:12:07 +00:00
|
|
|
{
|
|
|
|
|
files: 'cypress/**',
|
|
|
|
|
extends: 'plugin:cypress/recommended',
|
2024-11-21 08:20:29 +00:00
|
|
|
rules: {
|
|
|
|
|
'cypress/no-unnecessary-waiting': 'off',
|
2025-01-09 08:59:17 +00:00
|
|
|
'cypress/unsafe-to-chain-command': 'off',
|
2024-11-21 08:20:29 +00:00
|
|
|
},
|
2022-12-02 10:12:07 +00:00
|
|
|
},
|
2025-01-29 21:15:46 +00:00
|
|
|
{
|
|
|
|
|
files: [
|
|
|
|
|
// environment should be parsed to avoid global dependencies and sacred .env files
|
|
|
|
|
'packages/**/environment.ts',
|
|
|
|
|
// - environment is inlined and must be "registered" in next.config.js
|
|
|
|
|
// - `import.meta.env` is not supported in Next.js yet
|
|
|
|
|
'packages/web/docs/**',
|
|
|
|
|
],
|
|
|
|
|
rules: {
|
|
|
|
|
'no-process-env': 'off',
|
|
|
|
|
},
|
|
|
|
|
},
|
2022-05-24 07:41:53 +00:00
|
|
|
],
|
2022-05-18 07:26:57 +00:00
|
|
|
};
|