Skip to content

Instantly share code, notes, and snippets.

@jzaefferer
Created February 18, 2021 15:20
Show Gist options
  • Save jzaefferer/39bd074b5a448cace1e3fe9f7c57e2b4 to your computer and use it in GitHub Desktop.
Save jzaefferer/39bd074b5a448cace1e3fe9f7c57e2b4 to your computer and use it in GitHub Desktop.
Automatically check if installed packages are up-to-date, before start and lint scripts, and on `git pull`; MIT License, Copyright Jörn Zaefferer
#!/usr/bin/env node
//@ts-check
const { execSync } = require('child_process')
const mainPackage = require('../package.json')
const packageLock = require('../package-lock.json')
const outdated = []
Object.keys(mainPackage.dependencies)
.concat(Object.keys(mainPackage.devDependencies))
.forEach(packageName => {
try {
const installedPackage = require(`${packageName}/package.json`)
const installedVersion = installedPackage.version
const desiredVersion = packageLock.dependencies[packageName].version
if (installedVersion !== desiredVersion) {
outdated.push(
`${packageName}:, installed ${installedVersion}, desired ${desiredVersion}`
)
}
} catch (error) {
if (error.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED') {
console.error(error)
process.exit(1)
}
}
})
if (outdated.length > 0) {
console.log(`some package(s) are outdated, updating`)
console.log(outdated.join('\n'))
execSync(`npm i --registry=https://registry.npmjs.org/`)
}
{
"other": "stuff,
"scripts": {
"prelint": "node scripts/check-packages.js",
"prestart": "node scripts/check-packages.js"
},
"husky": {
"hooks": {
"post-merge": "node scripts/check-packages.js"
}
},
}
@manuschillerdev
Copy link

manuschillerdev commented Feb 20, 2021

ah, I see - thanks! I misunderstood the use case.
so basically for yarn it's the same as you and your team did:

const { parse } = require("@yarnpkg/lockfile");
const { readFileSync } = require("fs");
const { execSync } = require("child_process");

const yarnLock = readFileSync("./yarn.lock", "utf8");
const { object: lockedDependencies } = parse(yarnLock);

const pkg = require("./package.json");
const dependencies = {
  ...(pkg.dependencies || {}),
  ...(pkg.devDependencies || {}),
};

const install = () => execSync("yarn");

for (const [name, version] of Object.entries(dependencies)) {
  try {
    const installed = require(`${name}/package.json`);
    const locked = lockedDependencies[`${name}@${version}`];
    if (!locked || installed.version !== locked.version) {
      install();
      break;
    }
  } catch (e) {
    if (e.code === "MODULE_NOT_FOUND") install();
    else throw e;
  }
}

Would be cool if we turned this into a module that supports npm, yarn and pnpm probably!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment