import { readPackageJSON, writePackageJSON } from 'pkg-types'; import { readdirSync } from 'node:fs'; import { spawnSync } from 'node:child_process'; import { replaceInFile, npmRun } from './lib'; /* Constants */ const FLAKE = process.env.FLAKE as string; const updatePackageJson = async(workspaceDir: string, updates: object) => { const currentPackageJson = await readPackageJSON(`${workspaceDir}/package.json`); const outdated = JSON.parse(npmRun(['outdated', '--json'], workspaceDir)); const updateDeps = (deps: string) => { Object.keys(currentPackageJson[deps]).forEach((dep) => { const versions = outdated[dep]; const current = versions?.wanted || versions?.current; if (!current) { return; } if (current !== versions.latest) { updates[dep] = `${current} -> ${versions.latest}`; } currentPackageJson[deps][dep] = versions.latest; }); }; if (currentPackageJson.dependencies) { updateDeps('dependencies'); } if (currentPackageJson.devDependencies) { updateDeps('devDependencies'); } await writePackageJSON(`${workspaceDir}/package.json`, currentPackageJson); }; const prefetchNpmDeps = (workspaceDir: string): string => { npmRun(['install', '--package-lock-only'], workspaceDir); return spawnSync( 'prefetch-npm-deps', [`${workspaceDir}/package-lock.json`], ).stdout.toString().replace('\n', ''); }; export default async() => { const updates = {}; const packages = readdirSync(FLAKE, { withFileTypes: true, recursive: true }); for (const path of packages) { if ( path.name === 'package.json' && !path.parentPath.includes('node_modules') && !path.parentPath.includes('apps/config') ) { await updatePackageJson(path.parentPath, updates); const hash = prefetchNpmDeps(path.parentPath); replaceInFile( /npmDepsHash = ".*";/, `npmDepsHash = "${hash}";`, `${path.parentPath}/default.nix`, ); } } return Object.entries(updates) .map(([key, dep]) => `${key}: ${dep}`) .join('\n'); };