From 2c94bc98097ab9d3574f7efa948917fd6c684c92 Mon Sep 17 00:00:00 2001 From: matt1432 Date: Sat, 30 Nov 2024 17:59:44 -0500 Subject: [PATCH] feat(update): add auto updates of package.json --- apps/update-sources/default.nix | 2 + apps/update-sources/src/app.ts | 183 +++++++++++++----------- apps/update-sources/src/lib.ts | 13 ++ apps/update-sources/src/node-modules.ts | 89 ++++++++---- nixosModules/ags/config/default.nix | 3 + nixosModules/ags/packages.nix | 2 +- 6 files changed, 183 insertions(+), 109 deletions(-) create mode 100644 nixosModules/ags/config/default.nix diff --git a/apps/update-sources/default.nix b/apps/update-sources/default.nix index 22c2df98..2d66e625 100644 --- a/apps/update-sources/default.nix +++ b/apps/update-sources/default.nix @@ -2,6 +2,7 @@ buildApp, callPackage, nodejs_latest, + prefetch-npm-deps, ... }: buildApp { @@ -10,6 +11,7 @@ buildApp { runtimeInputs = [ nodejs_latest + prefetch-npm-deps (callPackage ../../nixosModules/docker/updateImage.nix {}) ]; } diff --git a/apps/update-sources/src/app.ts b/apps/update-sources/src/app.ts index 41b13cd2..27378377 100644 --- a/apps/update-sources/src/app.ts +++ b/apps/update-sources/src/app.ts @@ -20,88 +20,109 @@ if (!FLAKE) { const args = parseArgs(); -if (args['d'] || args['docker']) { - console.log(updateDocker()); -} - -if (args['i'] || args['inputs']) { - console.log(updateFlakeInputs()); -} - -if (args['f'] || args['firefox']) { - console.log(updateFirefoxAddons()); -} - -if (args['v'] || args['vuetorrent']) { - console.log(updateVuetorrent()); -} - -if (args['c'] || args['custom-sidebar']) { - console.log(updateCustomPackage('scopedPackages.x86_64-linux.lovelace-components.custom-sidebar')); -} - -if (args['s'] || args['some-sass-language-server']) { - console.log(updateCustomPackage('some-sass-language-server')); -} - -if (args['n'] || args['node_modules']) { - updateNodeModules(); -} - -if (args['a'] || args['all']) { - // Update this first because of nix run cmd - const firefoxOutput = updateFirefoxAddons(); - - console.log(firefoxOutput); - - - const flakeOutput = updateFlakeInputs(); - - console.log(flakeOutput); - - - const dockerOutput = updateDocker(); - - console.log(dockerOutput); - - - const vuetorrentOutput = updateVuetorrent(); - - console.log(vuetorrentOutput); - - // This doesn't need to be added to commit msgs - console.log(updateCustomPackage('scopedPackages.x86_64-linux.lovelace-components.custom-sidebar')); - console.log(updateCustomPackage('some-sass-language-server')); - - - spawnSync('nixFastBuild', [], { - shell: true, - stdio: [process.stdin, process.stdout, process.stderr], - }); - - const output = [ - 'chore: update sources\n\n', - ]; - - if (flakeOutput.length > 5) { - output.push(`Flake Inputs:\n${flakeOutput}\n\n`); - } - if (dockerOutput.length > 5) { - output.push(`Docker Images:\n${dockerOutput}\n`); - } - if (firefoxOutput.length > 5) { - output.push(`Firefox Addons:\n${firefoxOutput}\n\n`); - } - if (vuetorrentOutput.length > 5) { - output.push(`Misc Sources:\n${vuetorrentOutput}\n`); +const main = async() => { + if (args['d'] || args['docker']) { + console.log(updateDocker()); } - if (args['f']) { - writeFileSync(args['f'] as string, output.join('')); + if (args['i'] || args['inputs']) { + console.log(updateFlakeInputs()); } - else { - console.log(output.join('')); - } -} -spawnSync('alejandra', ['-q', FLAKE], { shell: true }); + if (args['f'] || args['firefox']) { + console.log(updateFirefoxAddons()); + } + + if (args['v'] || args['vuetorrent']) { + console.log(updateVuetorrent()); + } + + if (args['c'] || args['custom-sidebar']) { + console.log(updateCustomPackage( + 'scopedPackages.x86_64-linux.lovelace-components.custom-sidebar', + )); + } + + if (args['s'] || args['some-sass-language-server']) { + console.log(updateCustomPackage('some-sass-language-server')); + } + + if (args['n'] || args['node_modules']) { + console.log(await updateNodeModules()); + } + + if (args['a'] || args['all']) { + // Update this first because of nix run cmd + const firefoxOutput = updateFirefoxAddons(); + + console.log(firefoxOutput); + + + const flakeOutput = updateFlakeInputs(); + + console.log(flakeOutput); + + + const dockerOutput = updateDocker(); + + console.log(dockerOutput); + + + const nodeModulesOutput = await updateNodeModules(); + + console.log(nodeModulesOutput); + + + const vuetorrentOutput = updateVuetorrent(); + + console.log(vuetorrentOutput); + + + // This doesn't need to be added to commit msgs + console.log(updateCustomPackage( + 'scopedPackages.x86_64-linux.lovelace-components.custom-sidebar', + )); + console.log(updateCustomPackage('some-sass-language-server')); + + + spawnSync('nixFastBuild', [], { + shell: true, + stdio: [process.stdin, process.stdout, process.stderr], + }); + + const indentOutput = (output: string): string => { + return ` ${output.split('\n').join('\n ')}`; + }; + + const output = [ + 'chore: update sources\n\n', + ]; + + if (flakeOutput.length > 5) { + output.push(`Flake Inputs:\n${indentOutput(flakeOutput)}\n\n`); + } + if (dockerOutput.length > 5) { + output.push(`Docker Images:\n${indentOutput(dockerOutput)}\n`); + } + if (firefoxOutput.length > 5) { + output.push(`Firefox Addons:\n${indentOutput(firefoxOutput)}\n\n`); + } + if (nodeModulesOutput.length > 5) { + output.push(`Node modules:\n${indentOutput(nodeModulesOutput)}\n`); + } + if (vuetorrentOutput.length > 5) { + output.push(`Misc Sources:\n${indentOutput(vuetorrentOutput)}\n`); + } + + if (args['f']) { + writeFileSync(args['f'] as string, output.join('')); + } + else { + console.log(output.join('')); + } + } + + spawnSync('alejandra', ['-q', FLAKE], { shell: true }); +}; + +main(); diff --git a/apps/update-sources/src/lib.ts b/apps/update-sources/src/lib.ts index b59d6079..4d29931d 100644 --- a/apps/update-sources/src/lib.ts +++ b/apps/update-sources/src/lib.ts @@ -1,4 +1,5 @@ import { spawnSync } from 'node:child_process'; +import { readFileSync, writeFileSync } from 'node:fs'; export const parseArgs = () => { @@ -28,3 +29,15 @@ export const parseFetchurl = (url: string) => JSON.parse(spawnSync( 'nix', ['store', 'prefetch-file', '--refresh', '--json', '--hash-type', 'sha256', url, '--name', '"escaped"'], { shell: true }, ).stdout.toString()).hash; + +export const replaceInFile = (replace: RegExp, replacement: string, file: string) => { + const fileContents = readFileSync(file); + + const replaced = fileContents.toString().replace(replace, replacement); + + writeFileSync(file, replaced); +}; + +export const npmRun = (args: string[], workspaceDir: string) => spawnSync( + 'npm', args, { cwd: workspaceDir }, +).stdout.toString(); diff --git a/apps/update-sources/src/node-modules.ts b/apps/update-sources/src/node-modules.ts index 07fd3e28..1ba51e6e 100644 --- a/apps/update-sources/src/node-modules.ts +++ b/apps/update-sources/src/node-modules.ts @@ -1,42 +1,77 @@ -import { readPackageJSON } from 'pkg-types'; +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; -export default () => { - readdirSync(FLAKE, { withFileTypes: true, recursive: true }).forEach(async(path) => { - if (path.name === 'package.json' && !path.parentPath.includes('node_modules')) { - const currentWorkspace = path.parentPath; - const currentPackageJson = await readPackageJSON(`${currentWorkspace}/package.json`); - const outdated = JSON.parse(spawnSync( - 'npm', - ['outdated', '--json'], - { cwd: currentWorkspace }, - ).stdout.toString()); +const updatePackageJson = async(workspaceDir: string, updates: object) => { + const currentPackageJson = await readPackageJSON(`${workspaceDir}/package.json`); - Object.keys(currentPackageJson.dependencies ?? {}).forEach((dep) => { - const versions = outdated[dep]; + const outdated = JSON.parse(npmRun(['outdated', '--json'], workspaceDir)); - if (!versions?.current) { - return; - } + const updateDeps = (deps: string) => { + Object.keys(currentPackageJson[deps]).forEach((dep) => { + const versions = outdated[dep]; - console.log(`${dep}: ${versions.current} -> ${versions.latest}`); - }); + if (!versions?.current) { + return; + } - Object.keys(currentPackageJson.devDependencies ?? {}).forEach((dep) => { - const versions = outdated[dep]; + if (!updates[dep]) { + updates[dep] = `${versions.current} -> ${versions.latest}`; + } - if (!versions?.current) { - return; - } + currentPackageJson[deps][dep] = versions.latest; + }); + }; - console.log(`${dep}: ${versions.current} -> ${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')) { + 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'); }; diff --git a/nixosModules/ags/config/default.nix b/nixosModules/ags/config/default.nix new file mode 100644 index 00000000..a7b1a0cd --- /dev/null +++ b/nixosModules/ags/config/default.nix @@ -0,0 +1,3 @@ +{ + npmDepsHash = "sha256-XNvj59XfO6f+04PatCOZ93tkkZ1K7jReZPqLGJL2Ojo="; +} diff --git a/nixosModules/ags/packages.nix b/nixosModules/ags/packages.nix index 4e06bcff..e765117c 100644 --- a/nixosModules/ags/packages.nix +++ b/nixosModules/ags/packages.nix @@ -98,7 +98,7 @@ in { }) // { "${cfg.configDir}/node_modules".source = - buildNodeModules ./config "sha256-XNvj59XfO6f+04PatCOZ93tkkZ1K7jReZPqLGJL2Ojo="; + buildNodeModules ./config (import ./config).npmDepsHash; "${cfg.configDir}/tsconfig.json".source = let inherit (ags.packages.${pkgs.system}) gjs;