Rules

Below is an unordered list of rules used by publint for linting.

IMPLICIT_INDEX_JS_INVALID_FORMAT

If there are no entrypoints specified, e.g. via the main, module, and exports fields, it's assumed that the root index.js is the default entrypoint (if it exists). If the file has an invalid format, the error is reported.

An invalid format is defined as whether it has correct ESM or CJS usage. If a code is written in ESM or CJS, it doesn't mean that it would be interpreted as ESM or CJS respectively. In brief, it's dictated by:

publint will check these two behaviour if the file will be intepreted correctly.

FILE_INVALID_FORMAT

If the file has an invalid format through explicit entrypoints, e.g. the main, module, and exports fields, the error is reported.

Invalid format checks are the same as above.

FILE_INVALID_EXPLICIT_FORMAT

If the file has an invalid format through explicit entrypoints, e.g. the main, module, and exports fields, and the file has an explicit extension, e.g. .mjs and .cjs, the error is reported.

Invalid format checks are the same as above, except scoped down for explicit extensions for better error messages.

FILE_DOES_NOT_EXIST

The specified file does not exist.

FILE_NOT_PUBLISHED

The specified file exists locally but isn't published to npm. This error only appears when running publint locally.

MODULE_SHOULD_BE_ESM

The module field should be ESM only as per convention.

HAS_MODULE_BUT_NO_EXPORTS

If the package has a module field, but has no exports field, suggest to use exports instead. This is because Node.js doesn't recognize the module field, so instead using exports would increase compatibility with it.

If the package isn't meant for Node.js usage, it is safe to ignore this suggestion, but it is still recommended to use exports whenever possible.

HAS_ESM_MAIN_BUT_NO_EXPORTS

If the main field is in ESM, but there's no exports field, it's recommended to use the exports field instead as it's initially introduced for better ESM compatibility.

If you're not supporting Node.js 12.6 and below, you can also remove the main field as all tooling would read from exports only and skip main.

EXPORTS_GLOB_NO_MATCHED_FILES

If the exports field contains glob paths, but it doesn't match any files, report this issue.

EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING

The exports field should not have globs defined with trailing slashes. It is deprecated and should use subpath patterns, e.g. a trailing /* instead.

EXPORTS_TYPES_SHOULD_BE_FIRST

Ensure types condition to be the first. The TypeScript docs recommends so, but it's also because the exports field is order-based.

For example, a scenario where both the types and import condition could be active, types should be first so that it matches and returns a .d.ts file, rather than a .js file from the import condition.

EXPORTS_DEFAULT_SHOULD_BE_LAST

Ensure default condition to be the last according to the Node.js docs, but it's also because the exports field is order-based.

The example above also applies here as to why it should be last.

EXPORTS_MODULE_SHOULD_BE_ESM

The module condition should be ESM only.

EXPORTS_VALUE_INVALID

The exports field value should always start with a ./. It does not support omitted relative paths like "subpath/index.js".

USE_EXPORTS_BROWSER

The browser field and exports browser condition works similarly to define the browser counterpart of a package. With the overlap, it's usually better to use the exports field instead as it's widely supported, and keeps one true way of defining your package entrypoints.

It's important to note that the browser field can be used for many more cases, like:

So switching to the exports field may not be a one-to-one migration, and that's fine! Once you're ready to restructure your code, you can make these changes going forward.

publint logo