build.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /** Run the complete repository build and bind its client artifacts to their public environment. */
  2. import { spawnSync } from 'node:child_process'
  3. import { rmSync } from 'node:fs'
  4. import { resolve } from 'node:path'
  5. import { parseArgs } from 'node:util'
  6. import {
  7. CLIENT_BUILD_RECORD_PATH,
  8. clientBuildProcessEnvironment,
  9. repositoryCommitHash,
  10. resolveClientBuildEnvironment,
  11. writeClientBuildRecord,
  12. } from './client-build-environment.ts'
  13. /** Run one package script through the package manager that invoked this build. */
  14. function runScript(script: string, environment: NodeJS.ProcessEnv): void {
  15. const packageManager = process.env.npm_execpath
  16. if (packageManager === undefined || packageManager === '') {
  17. throw new Error('build: npm_execpath is unavailable; invoke the build through a package script')
  18. }
  19. const result = spawnSync(process.execPath, [packageManager, 'run', script], {
  20. cwd: resolve(import.meta.dirname, '..'),
  21. env: environment,
  22. stdio: 'inherit',
  23. })
  24. if (result.error !== undefined) throw result.error
  25. if (result.status !== 0) {
  26. throw new Error(`build: ${script} exited with ${String(result.status ?? result.signal)}`)
  27. }
  28. }
  29. /** Run the full build selected by `--profile` or `DSH_BUILD_CLIENT_PROFILE`. */
  30. function main(): void {
  31. const { values } = parseArgs({
  32. options: { profile: { type: 'string' } },
  33. allowPositionals: false,
  34. })
  35. const root = resolve(import.meta.dirname, '..')
  36. const parentEnvironment = {
  37. ...process.env,
  38. DSH_CLIENT_COMMIT_HASH: repositoryCommitHash(root, process.env),
  39. }
  40. const clientEnvironment = resolveClientBuildEnvironment(parentEnvironment, values.profile)
  41. const buildEnvironment = clientBuildProcessEnvironment(parentEnvironment, clientEnvironment)
  42. rmSync(resolve(root, CLIENT_BUILD_RECORD_PATH), { force: true })
  43. runScript('build:lib', buildEnvironment)
  44. runScript('build:web', buildEnvironment)
  45. const record = writeClientBuildRecord(root, clientEnvironment)
  46. console.log(
  47. `build: recorded ${String(record.artifacts.fileCount)} client artifact(s) with ${String(Object.keys(record.environment).length)} public value(s)`,
  48. )
  49. }
  50. if (import.meta.main) main()