Skip to content

adonisjs/eslint-plugin-adonisjs

@adonisjs/eslint-plugin

Compatible with ESLint>=9.0 and TypeScript >=5.4



ESLint plugin for AdonisJS applications

The plugin forces your application to use lazy imports for controllers and event listeners. Lazy imports are a must when you are using HMR mode in AdonisJS.


gh-workflow-image typescript-image npm-image license-image

Installation

The package comes pre-configured with the @adonisjs/eslint-config preset and hence manual installation is not required.

However, you can install and configure it as follows.

npm i -D @adonisjs/eslint-plugin@beta

# Install peer dependencies
npm i -D eslint@9 typescript typescript-eslint

Usage

After installation, you can register the following as follows. Make sure to also setup the typescript-eslint parser in order for the rules to work.

// eslint.config.js
import adonisJSPlugin from '@adonisjs/eslint-plugin'

export default [
  {
    plugins: {
      '@adonisjs': adonisJSPlugin,
    },
    rules: {
      '@adonisjs/prefer-lazy-controller-import': 'error',
      '@adonisjs/prefer-lazy-listener-import': 'error',
    },
  },
]

prefer-lazy-controller-import

Important

The HMR mode of AdonisJS only works with Lazy loaded controllers

The @adonisjs/prefer-lazy-controller-import rule complains when you import a controller using the import expression and assign it to a route. For example:

import router from '@adonisjs/core/services/router'
// ❌ Error: Replace standard import with lazy controller import
import UsersController from '#controllers/user_controller'

router.get('users', [UsersController, 'index'])

The rule is auto fixable, therefore you can apply the fix depending upon the shortcuts provided by your code editor.

import router from '@adonisjs/core/services/router'
// ✅ Fixed
const UsersController = () => import('#controllers/user_controller')

router.get('users', [UsersController, 'index'])

prefer-lazy-listener-import

Important

The HMR mode of AdonisJS only works with Lazy loaded event listeners

The @adonisjs/prefer-lazy-listener-import rule complains when you import an event listener using the import expression and assign it to an event. For example:

import emitter from '@adonisjs/core/services/emitter'
// ❌ Error: Replace standard import with lazy controller import
import SendVerificationEmail from '#listeners/send_verification_email'

emitter.on('user:created', [SendVerificationEmail, 'handle'])

The rule is auto fixable, therefore you can apply the fix depending upon the shortcuts provided by your code editor.

import emitter from '@adonisjs/core/services/emitter'
// ✅ Fixed
const SendVerificationEmail = () => import('#listeners/send_verification_email')

emitter.on('user:created', [SendVerificationEmail, 'handle'])

prefer-adonisjs-inertia-link

Note

This rule is for AdonisJS 7+ projects using @adonisjs/inertia v4+.

The @adonisjs/prefer-adonisjs-inertia-link rule warns when you import the Link component from @inertiajs/react or @inertiajs/vue3 instead of using the typesafe version from @adonisjs/inertia.

// ❌ Warning: Prefer importing Link from @adonisjs/inertia/react for typesafe routing
import { Link } from '@inertiajs/react'
// ✅ Correct
import { Link } from '@adonisjs/inertia/react'

prefer-adonisjs-inertia-form

Note

This rule is for AdonisJS 7+ projects using @adonisjs/inertia v4+. You must enable it manually.

The @adonisjs/prefer-adonisjs-inertia-form rule warns when you import the Form component from @inertiajs/react or @inertiajs/vue3 instead of using the typesafe version from @adonisjs/inertia.

// ❌ Warning: Prefer importing Form from @adonisjs/inertia/react for typesafe routing
import { Form } from '@inertiajs/react'
// ✅ Correct
import { Form } from '@adonisjs/inertia/react'

no-backend-import-in-frontend

The @adonisjs/no-backend-import-in-frontend rule prevents importing backend code in your frontend files located in the inertia/ directory.

The rule detects both:

  • Subpath imports (#models/user) - automatically reads your package.json imports field
  • Relative imports (../../app/models/user) - checks if the resolved path is outside inertia/
// inertia/pages/users.tsx

// ❌ Error: Importing backend code in frontend files is not allowed
import User from '#models/user'
import { UserService } from '../../app/services/user_service'
// inertia/pages/users.tsx

// ✅ Correct - type-only imports are allowed
import type { User } from '#models/user'
import type { UserService } from '../../app/services/user_service'

// ✅ Correct - imports pointing to inertia/ are allowed
import { Button } from '#components/button' // if #components/* -> ./inertia/components/*
import { utils } from '../utils'

Sharing code between frontend and backend

If you have shared code (e.g., enums, constants, utility types) in your backend that you want to import in your frontend, you can use the allowed option to whitelist specific paths:

// eslint.config.js
export default [
  {
    rules: {
      '@adonisjs/no-backend-import-in-frontend': [
        'error',
        {
          allowed: [
            '#shared/*', // allows #shared/enums, #shared/constants, etc.
            '#shared/**', // allows #shared/utils/helpers (deep nested)
            '#enums', // exact match
          ],
        },
      ],
    },
  },
]

The allowed option uses micromatch for glob pattern matching.

// inertia/pages/users.tsx

// ✅ Correct - #shared/* is in the allowed list
import { UserStatus } from '#shared/enums'
Built with ❤︎ by Julien Ripouteau and Harminder Virk

About

ESLint plugin for AdonisJS to enforce framework specific rules

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 2

  •  
  •