#!/usr/bin/env node // the .mjs extension is important // run this inside the directory containing the `elm.json` file // (if it's not executable, run `chmod +x elm-build-cache.mjs`) // with VERBOSE=1 env var it will show you results of the exec commands import fs from 'fs/promises'; import {exec} from 'child_process'; const tempDir = 'elm-stuff/elm-build-cache'; const shouldLog = process.env.VERBOSE === '1'; // false; // true; const ourExec = async (cmd) => new Promise((resolve, reject) => { exec(cmd, (error,stdout,stderr) => { if (error) reject(error); if (shouldLog) console.log({cmd,stdout,stderr}); resolve([stdout,stderr]); }); }); const downloadDependency = async ([pkg,version]) => { const pkgWithDash = pkg.replace('/','-'); const zipballUrl = `https://github.com/${pkg}/zipball/${version}/`; const zipballPath = `${tempDir}/${pkgWithDash}-${version}.zip`; // based on info in https://package.elm-lang.org/packages/elm/project-metadata-utils/latest/ const elmHome = process.env.ELM_HOME ?? process.platform === 'win32' ? `${process.env.APPDATA}/elm` : `~/.elm`; const packagePath = `${elmHome}/0.19.1/packages/${pkg}/${version}`; await ourExec(`mkdir -p ${tempDir}`); await ourExec(`rm -rf ${packagePath}`); await ourExec(`mkdir -p ${packagePath}`); await ourExec(`curl -L ${zipballUrl} -o ${zipballPath}`); await ourExec(`unzip ${zipballPath} -d ${tempDir}`); await ourExec(`mv ${tempDir}/${pkgWithDash}-*/* ${packagePath}`); await ourExec(`rm -rf '${zipballPath}'`); } const pickLowerBound = version => version.slice(0,version.indexOf(' ')); const getPackageDeps = elmJson => Object.fromEntries( [ ...Object.entries(elmJson.dependencies), ...Object.entries(elmJson['test-dependencies']), ].map(([k,v]) => [k,pickLowerBound(v)]) ); const getAppDeps = elmJson => ({ ...elmJson.dependencies.direct, ...elmJson.dependencies.indirect, ...elmJson['test-dependencies'].direct, ...elmJson['test-dependencies'].indirect, }); const getElmJsonDeps = elmJson => elmJson.type === 'application' ? getAppDeps(elmJson) : getPackageDeps(elmJson); const main = async () => { const elmJson = JSON.parse(await fs.readFile('./elm.json','utf-8')); const deps = getElmJsonDeps(elmJson); console.log({deps}); await Promise.all(Object.entries(deps).map(downloadDependency)); } await ourExec(`rm -rf '${tempDir}'`); await main(); await ourExec(`rm -rf '${tempDir}'`);