Skip to content

Coding Standard

@modularityjs/coding-standard is the shared ESLint flat-config used by every package in this repo, exported in two variants so downstream apps can adopt the same TypeScript baseline without inheriting framework-specific rules they don't need.

Install

bash
pnpm add -D @modularityjs/coding-standard eslint

The package depends on ESLint 10. It bundles typescript-eslint, @eslint/js, eslint-plugin-simple-import-sort, globals, and the in-house framework rules — no extra plugins to install.

The @modularityjs/* scope publishes to a private registry. If pnpm add fails with 404 or 401, see Registry Access for the .npmrc setup.

Pick a variant

FactoryAdds framework rulesinversify blockedUse case
createBaseConfignonoDownstream consumer apps; mixed codebases.
createConfigyesyesThe default. Any package or app that wires up the framework.
createFrameworkConfigyesyesFramework-internal packages. Alias of createConfig — keeps intent explicit at the call site.
createDriverConfigyesnoDI driver packages (di-inversify, di-awilix) that must import the underlying container.

Consumer app (generic)

js
// eslint.config.mjs
import { createBaseConfig } from '@modularityjs/coding-standard';

export default createBaseConfig(import.meta.dirname);

You get: typescript-eslint recommended, simple-import-sort with a slot for @modularityjs/* imports, sane TypeScript defaults (no-floating-promises, no-misused-promises, await-thenable, consistent-type-imports, no-unused-vars with underscore escape), eqeqeq, curly, and strict-boolean-expressions on src/**/*.ts (excluding tests). No framework-specific rules — your code can use forRoot, naming patterns like *Service, etc. without triggering the framework lints.

js
import { createConfig } from '@modularityjs/coding-standard';

export default createConfig(import.meta.dirname);

Adds:

  • driver-service-naming — drivers export {Driver}{Domain}Service, not the inverse.
  • forroot-returns-own-module — a module's forRoot returns its own ModuleDefinition.
  • pool-useclass-contract{ provide, useClass } pairs match contract/driver types.
  • module-name-matches-packageCacheModule lives in @modularityjs/cache.
  • boundary-import — production source only imports from packages declared in the module's imports: [...].
  • plugin-handler-return-type, before-plugin-args-shape, around-plugin-proceed-signature — AOP plugin signatures.
  • hook-name-typo — catches near-misses like onIntit, onReadyonRedy, onShutdownonShutdwn, etc. (canonical names like onReady itself never trip the rule).
  • A no-restricted-imports ban on inversify (use @modularityjs/di).

DI driver

js
import { createDriverConfig } from '@modularityjs/coding-standard';

export default createDriverConfig(import.meta.dirname);

Same as createConfig but lifts the inversify import restriction. Only @modularityjs/di-inversify and @modularityjs/di-awilix need this.

Layering project rules

Each factory returns a plain ESLint flat-config array. Concatenate to add project-specific rules:

js
// eslint.config.mjs
import { createBaseConfig } from '@modularityjs/coding-standard';

export default [
  ...createBaseConfig(import.meta.dirname),
  {
    files: ['src/**/*.ts'],
    rules: {
      // Tighten or override here.
      '@typescript-eslint/explicit-function-return-type': 'error',
    },
  },
];

Companion repo checks

The same package ships three repo-level scripts you can wire into any monorepo using the framework:

ScriptPurpose
node node_modules/@modularityjs/coding-standard/check-boundaries.mjsVerifies every cross-package import corresponds to a @Module({ imports: [...] }) entry. Static enforcement of the abstraction boundary.
node node_modules/@modularityjs/coding-standard/check-dependencies.mjsEnsures dependencies / peerDependencies / devDependencies match what production source and tests actually import.
node node_modules/@modularityjs/coding-standard/check-manifest.mjsVerifies every publishable package declares modularityjs.kind (and modularityjs.extends for drivers and extensions).

The framework monorepo runs these via Turborepo (pnpm check-boundaries, pnpm check-dependencies, pnpm check-manifest). Drop the same turbo task definitions into your repo's turbo.json to gate CI on them.