Skip to content

Custom rules

You can define custom rules that can be enforced via the createRule function.

monoswan.config.ts
import { writeFile } from "node:fs/promises";
import { createRule, defineConfig } from "monoswan";
const requireDescription = createRule(() => ({
name: "require-description",
check: (context) =>
context.packageJson.description == null
? [
{
message: "Expected a description",
packageContext: context,
filePath: `${context.packagePath}/package.json`,
locator: { type: "json", locator: ["description"] },
autofix: async ({ packageJson, packagePath }) => {
const updated = { ...packageJson, description: "TODO" };
await writeFile(
`${packagePath}/package.json`,
`${JSON.stringify(updated, null, "\t")}\n`,
);
},
},
]
: [],
}));
export default defineConfig({
rules: [requireDescription()],
});

A rule receives packageName, packagePath, packageJson, and the resolved variant. Any other files may be loaded directly via node:fs APIs. Run monoswan lint --fix to apply returned autofixes.

You can define custom options for consumers as part of the rule definition.

monoswan.config.ts
import { createRule, defineConfig } from "monoswan";
interface RequireFieldOptions {
field: "description" | "license";
}
const requireField = createRule<RequireFieldOptions>(({ field }) => ({
name: `require-${field}`,
check: (context) =>
context.packageJson[field] == null
? [
{
message: `Expected ${field}`,
packageContext: context,
filePath: `${context.packagePath}/package.json`,
locator: { type: "json", locator: [field] },
},
]
: [],
}));
export default defineConfig({
rules: [requireField({ field: "license" }, { ignore: { paths: ["examples/**"] } })],
});