Mirrored from GitHub
github.com/roostorg/coop
1import fs from 'node:fs';
2import path from 'node:path';
3
4// ESLint is configured per-package (client/.eslintrc, server/.eslintrc) and
5// each package keeps its own plugins in its own node_modules. So we must
6// invoke each package's eslint with paths relative to that package, not from
7// the repo root.
8const eslintInPackage = (pkg) => (files) => {
9 const pkgRoot = path.resolve(pkg);
10 const eslintBin = path.join(pkgRoot, 'node_modules', '.bin', 'eslint');
11 if (!fs.existsSync(eslintBin)) {
12 console.warn(
13 `[lint-staged] skipping eslint in ${pkg}/: run "(cd ${pkg} && npm install)" to enable.`,
14 );
15 return [];
16 }
17 const rels = files
18 .filter((f) => f.startsWith(pkgRoot + path.sep))
19 .map((f) => path.relative(pkgRoot, f));
20 if (rels.length === 0) return [];
21 // Single-quote each path so it survives the outer double-quoted `bash -c`.
22 // The previous JSON.stringify produced double-quoted args, which collapsed
23 // against the outer `"..."` and left eslint with no file args — silently
24 // making it lint the whole package directory instead.
25 const args = rels.map((f) => `'${f.replace(/'/g, `'\\''`)}'`).join(' ');
26 return `bash -c "cd ${pkg} && ./node_modules/.bin/eslint --fix ${args}"`;
27};
28
29export default {
30 '*.{ts,tsx,js,jsx,mjs,cjs,json,md,yaml,yml}': 'prettier --write',
31 'client/**/*.{ts,tsx,js,jsx}': eslintInPackage('client'),
32 'server/**/*.{ts,tsx,js}': eslintInPackage('server'),
33};