From 3a006d3385d94e34c8b064793a5aa759ee1ad2a8 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Fri, 15 Mar 2024 13:28:04 +0100 Subject: [PATCH] update tarsync --- tasks/framework-tools/tarsync.mjs | 214 ++++++++++++++++++------------ 1 file changed, 126 insertions(+), 88 deletions(-) diff --git a/tasks/framework-tools/tarsync.mjs b/tasks/framework-tools/tarsync.mjs index da7751b0f6c5..6eb3c9d49334 100644 --- a/tasks/framework-tools/tarsync.mjs +++ b/tasks/framework-tools/tarsync.mjs @@ -1,5 +1,4 @@ #!/usr/bin/env node -/* eslint-env node */ import { performance } from 'node:perf_hooks' import { fileURLToPath } from 'node:url' @@ -8,12 +7,90 @@ import { parseArgs as nodeUtilParseArgs } from 'node:util' import ora from 'ora' import { cd, chalk, fs, glob, path, within, $ } from 'zx' -const mockSpinner = { - text: '', - succeed: () => {}, -} +const FRAMEWORK_PATH = fileURLToPath(new URL('../../', import.meta.url)) +const TARBALL_DEST_DIRNAME = 'tarballs' async function main() { + const { projectPath, verbose } = await getOptions() + $.verbose = verbose + + cd(FRAMEWORK_PATH) + performance.mark('startFramework') + + const spinner = getFrameworkSpinner({ text: 'building and packing packages' }) + await buildTarballs() + + spinner.text = 'moving tarballs' + await moveTarballs(projectPath) + + spinner.text = 'updating resolutions' + await updateResolutions(projectPath) + + performance.mark('endFramework') + performance.measure('framework', 'startFramework', 'endFramework') + const [entry] = performance.getEntriesByName('framework') + spinner.succeed(`finished in ${(entry.duration / 1000).toFixed(2)} seconds`) + + await yarnInstall(projectPath) + + const entries = performance.getEntriesByType('measure').map((entry) => { + return `• ${entry.name} => ${(entry.duration / 1000).toFixed(2)} seconds` + }) + + for (const entry of entries) { + verbose && console.log(entry) + } +} + +main() + +// Helpers +// ------- + +async function parseArgs() { + const { positionals, values } = nodeUtilParseArgs({ + allowPositionals: true, + + options: { + verbose: { + type: 'boolean', + default: false, + short: 'v', + }, + }, + }) + + const [projectPath] = positionals + + const options = { + verbose: values.verbose, + } + + options.projectPath = projectPath ? projectPath : process.env.RWJS_CWD + + if (!options.projectPath) { + throw new Error( + [ + 'Error: You have to provide the path to a Redwood project as', + '', + ' 1. the first positional argument', + '', + chalk.gray(' yarn project:tarsync /path/to/redwood/project'), + '', + ' 2. the `RWJS_CWD` env var', + '', + chalk.gray(' RWJS_CWD=/path/to/redwood/project yarn project:tarsync'), + ].join('\n') + ) + } + + // This makes `projectPath` an absolute path and throws if it doesn't exist. + options.projectPath = await fs.realpath(options.projectPath) + + return options +} + +async function getOptions() { let options try { @@ -26,33 +103,35 @@ async function main() { const { projectPath, verbose } = options - $.verbose = verbose - - // Closing over `verbose` here. - function getProjectSpinner({ text }) { - return verbose - ? mockSpinner - : ora({ prefixText: `${chalk.green('[ project ]')}`, text }).start() + return { + projectPath, + verbose, } +} - function getFrameworkSpinner({ text }) { - return verbose - ? mockSpinner - : ora({ prefixText: `${chalk.cyan('[framework]')}`, text }).start() - } +const mockSpinner = { + text: '', + succeed: () => { }, +} - const frameworkPath = fileURLToPath(new URL('../../', import.meta.url)) - cd(frameworkPath) - performance.mark('startFramework') +function getProjectSpinner({ text }) { + return $.verbose + ? mockSpinner + : ora({ prefixText: `${chalk.green('[ project ]')}`, text }).start() +} - const spinner = getFrameworkSpinner({ text: 'building and packing packages' }) +function getFrameworkSpinner({ text }) { + return $.verbose + ? mockSpinner + : ora({ prefixText: `${chalk.cyan('[framework]')}`, text }).start() +} +async function buildTarballs() { await $`yarn nx run-many -t build:pack --exclude create-redwood-app` +} - spinner.text = 'moving tarballs' - - const tarballDestDirname = 'tarballs' - const tarballDest = path.join(projectPath, tarballDestDirname) +async function moveTarballs(projectPath) { + const tarballDest = path.join(projectPath, TARBALL_DEST_DIRNAME) await fs.ensureDir(tarballDest) const tarballs = await glob(['./packages/**/*.tgz']) @@ -64,9 +143,25 @@ async function main() { }) ) ) +} - spinner.text = 'updating resolutions' +async function getReactResolutions() { + const packageConfig = await fs.readJson(path.join(FRAMEWORK_PATH, 'packages/web/package.json')) + + const react = packageConfig.peerDependencies.react + const reactDom = packageConfig.peerDependencies['react-dom'] + + if (!react || !reactDom) { + throw new Error("Couldn't find react or react-dom in @redwoodjs/web's peerDependencies") + } + return { + react, + 'react-dom': reactDom, + } +} + +async function updateResolutions(projectPath) { const resolutions = (await $`yarn workspaces list --json`).stdout .trim() .split('\n') @@ -77,9 +172,8 @@ async function main() { return { ...resolutions, // Turn a Redwood package name like `@redwoodjs/project-config` into `redwoodjs-project-config.tgz`. - [name]: `./${tarballDestDirname}/${ - name.replace('@', '').replaceAll('/', '-') + '.tgz' - }`, + [name]: `./${TARBALL_DEST_DIRNAME}/${name.replace('@', '').replaceAll('/', '-') + '.tgz' + }`, } }, {}) @@ -93,20 +187,16 @@ async function main() { resolutions: { ...projectPackageJson.resolutions, ...resolutions, + ...(await getReactResolutions()) }, }, { spaces: 2, } ) +} - performance.mark('endFramework') - performance.measure('framework', 'startFramework', 'endFramework') - - const [entry] = performance.getEntriesByName('framework') - - spinner.succeed(`finished in ${(entry.duration / 1000).toFixed(2)} seconds`) - +async function yarnInstall(projectPath) { await within(async () => { cd(projectPath) performance.mark('startProject') @@ -123,56 +213,4 @@ async function main() { spinner.succeed(`finished in ${(entry.duration / 1000).toFixed(2)} seconds`) }) - const entries = performance.getEntriesByType('measure').map((entry) => { - return `• ${entry.name} => ${(entry.duration / 1000).toFixed(2)} seconds` - }) - - for (const entry of entries) { - verbose && console.log(entry) - } -} - -main() - -async function parseArgs() { - const { positionals, values } = nodeUtilParseArgs({ - allowPositionals: true, - - options: { - verbose: { - type: 'boolean', - default: false, - short: 'v', - }, - }, - }) - - const [projectPath] = positionals - - const options = { - verbose: values.verbose, - } - - options.projectPath = projectPath ? projectPath : process.env.RWJS_CWD - - if (!options.projectPath) { - throw new Error( - [ - 'Error: You have to provide the path to a Redwood project as', - '', - ' 1. the first positional argument', - '', - chalk.gray(' yarn project:tarsync /path/to/redwood/project'), - '', - ' 2. the `RWJS_CWD` env var', - '', - chalk.gray(' RWJS_CWD=/path/to/redwood/project yarn project:tarsync'), - ].join('\n') - ) - } - - // This makes `projectPath` an absolute path and throws if it doesn't exist. - options.projectPath = await fs.realpath(options.projectPath) - - return options }