Skip to content

Commit

Permalink
Move install commands to postinstall script
Browse files Browse the repository at this point in the history
Closes #117
Closes #163
Closes #161
  • Loading branch information
karlhorky committed Oct 18, 2022
1 parent 79b009c commit df6666e
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 79 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"author": "Karl Horky <karl.horky@gmail.com>",
"license": "MIT",
"scripts": {
"postinstall": "scripts/postinstall.js",
"postpublish": "cd __tests__ && yarn update-config-version"
},
"devDependencies": {
Expand Down
12 changes: 1 addition & 11 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,7 @@ UpLeveled ESLint defaults for programming in JavaScript, TypeScript, React and N
To add ESLint configuration to a project, install the dependencies and add the config files:

```sh
CI=true npx install-peerdeps@latest --yarn --dev @upleveled/eslint-config-upleveled
cp node_modules/@upleveled/eslint-config-upleveled/templates/{*,.eslint*} .
grep -Fxq ".eslintcache" .gitignore || printf "\n.eslintcache" >> .gitignore
grep -Fxq ".tsbuildinfo" .gitignore || printf "\n*.tsbuildinfo" >> .gitignore
node node_modules/@upleveled/eslint-config-upleveled/scripts/install.js
```

If you have a monorepo using Yarn Workspaces and would like to install the config in the workspace root, change the first line to this:

```sh
CI=true npx install-peerdeps@latest --yarn --dev @upleveled/eslint-config-upleveled --extra-args "-W"
yarn add --dev @upleveled/eslint-config-upleveled
```

<!--
Expand Down
68 changes: 0 additions & 68 deletions scripts/install.js

This file was deleted.

155 changes: 155 additions & 0 deletions scripts/postinstall.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env node

import { execSync } from 'node:child_process';
import {
existsSync,
readdirSync,
readFileSync,
rmSync,
writeFileSync,
} from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const { peerDependencies } = JSON.parse(
readFileSync(
resolve(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'),
'utf-8',
),
);

// Remove SafeQL dependencies for now on Windows
// https://github.com/ts-safeql/safeql/issues/80
if (process.platform === 'win32') {
delete peerDependencies['@ts-safeql/eslint-plugin'];
delete peerDependencies['libpg-query'];
}

const packageJsonPath = join(process.cwd(), 'package.json');
const packageJsonObj = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));

// Add all config peerDependencies to devDependencies of
// project, upgrading existing package versions and
// sorting alphabetically
packageJsonObj.devDependencies = Object.fromEntries(
Object.entries({
...packageJsonObj.devDependencies,
...peerDependencies,
}).sort(),
);

packageJsonObj.resolutions = {
...packageJsonObj.resolutions,
// Force installation of the "dependencies" version of these
// ESLint dependencies to avoid conflicting version numbers
// between `eslint-config-react-app` and
// `@upleveled/eslint-config-upleveled` (they use the same
// ESLint dependencies, but may have slightly different
// versions).
//
// These conflicts can result in ESLint errors like:
//
// ESLint couldn't determine the plugin "import" uniquely.
//
// - /home/runner/work/preflight/preflight/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.cjs » @upleveled/eslint-config-upleveled")
// - /home/runner/work/preflight/preflight/node_modules/eslint-config-react-app/node_modules/eslint-plugin-import/lib/index.js (loaded in ".eslintrc.cjs » @upleveled/eslint-config-upleveled » eslint-config-react-app")
...[
'@typescript-eslint/eslint-plugin',
'@typescript-eslint/parser',
'eslint-plugin-import',
'eslint-plugin-jest',
'eslint-plugin-jsx-a11y',
'eslint-plugin-react',
'eslint-plugin-react-hooks',
].reduce(
(resolutions, packageName) => ({
...resolutions,
[packageName]: packageJsonObj.devDependencies[packageName],
}),
{},
),
'@typescript-eslint/utils':
packageJsonObj.devDependencies['@typescript-eslint/parser'],
};

writeFileSync(packageJsonPath, JSON.stringify(packageJsonObj, null, 2) + '\n');

console.log('Installing ESLint config dependencies...');

execSync('yarn install', { stdio: 'inherit' });

console.log('✅ Done installing dependencies');

console.log('Writing config files...');

const templatePath = resolve(
dirname(fileURLToPath(import.meta.url)),
'..',
'templates',
);

const templateFileNamesAndPaths = /** @type {[string, string][]} */ (
readdirSync(templatePath).map((name) => [name, join(templatePath, name)])
);

for (const [templateFileName, templateFilePath] of templateFileNamesAndPaths) {
const destinationFilePath = join(process.cwd(), templateFileName);

if (existsSync(destinationFilePath)) {
console.log(`Skipping update to ${templateFileName} (already exists)`);
continue;
}

try {
writeFileSync(destinationFilePath, readFileSync(templateFilePath, 'utf-8'));
console.log(`Wrote ${templateFileName}`);
} catch (err) {
console.error('err', err);
}
}

console.log('✅ Done updating config files');

console.log('Updating .gitignore...');

const gitignorePath = join(process.cwd(), '.gitignore');

/** @type {string[]} */
let gitignoreContentLines = [];

try {
gitignoreContentLines = readFileSync(gitignorePath, 'utf-8').split('\n');
} catch (err) {
// Swallow error in case .gitignore doesn't exist yet
}

for (const ignorePath of ['.eslintcache', '*.tsbuildinfo']) {
if (gitignoreContentLines.includes(ignorePath)) {
continue;
}

gitignoreContentLines.push(ignorePath);
}

writeFileSync(
gitignorePath,
gitignoreContentLines.join('\n') +
// Add trailing newline if last line is not empty
(gitignoreContentLines.at(-1) === '' ? '' : '\n'),
);

console.log('✅ Done updating .gitignore');

try {
if (
readFileSync(join(process.cwd(), '.eslintrc.json'), 'utf-8').trim() ===
`{
"extends": "next/core-web-vitals"
}`
) {
rmSync(join(process.cwd(), '.eslintrc.json'));
console.log('Removed default Next.js ESLint config');
}
} catch (err) {
// Swallow error if .eslintrc.json file does not exist
}

0 comments on commit df6666e

Please sign in to comment.