PSA/docs/architecture/package-build-system.md
Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

4.3 KiB

Package Build System

The monorepo uses a hybrid build strategy for @alga-psa/* packages under packages/.

Two resolution modes

Mode Resolved from When Used by
Pre-built packages/<pkg>/dist/ Webpack aliases point to dist/ Next.js production build, dev server
Source-transpiled packages/<pkg>/src/ Listed in transpilePackages with aliases to src/ Next.js (for packages not yet flipped)

TypeScript type checking (tsc --noEmit) always resolves from src/ via tsconfig paths, regardless of which mode a package is in.

Pre-built packages

These packages are compiled by tsup before next build runs. Webpack resolves their imports from dist/ instead of compiling from source.

Currently flipped (8 packages):

  • clients, sla, assets, tags (domain packages, CSS-free)
  • types, core, validation, event-schemas (leaf/horizontal packages)

Still source-transpiled: formatting (deep subpath imports across many packages), ui, billing, scheduling, tickets, projects, documents (have CSS imports), auth, integrations, notifications, users (CE/EE complexity), and composition layers.

Shared tsup preset

All pre-built packages use a shared config at packages/build-tools/tsup-preset.ts:

import { defineConfig } from 'tsup';
import { makeConfig } from '../build-tools/tsup-preset';

export default defineConfig(makeConfig({
  jsxEnabled: true,      // for packages with .tsx files
  external: ['react'],   // extra externals beyond @alga-psa/*
  addJsExtensions: true, // for packages imported by Node.js directly
}));

Options

  • jsxEnabled — enables automatic JSX transform. Required for packages containing .tsx files (React components).
  • external — additional externals. @alga-psa/* and @shared/* are always external. With bundle: false this is mostly for documentation; imports are preserved as-is.
  • addJsExtensions — post-build rewrite adding .js extensions to relative imports. Required for packages imported directly by Node.js ESM (not via webpack). Currently only event-schemas (used by Temporal worker).

How packages get built

Local development

npm run dev automatically runs npx nx build-deps server before starting the Next.js dev server. This builds all pre-built packages so their dist/ directories are fresh. No manual setup needed after pulling.

During a running dev session, if you edit source in a pre-built package, rebuild it manually:

cd packages/<pkg> && npx tsup

Source-transpiled packages get hot-reloaded by Next.js automatically.

CI / Docker builds

All Dockerfiles and CI workflows use Nx to build packages before next build:

npx nx build-deps server   # builds all server dependencies (Dockerfiles)
npx nx build server         # builds deps + runs next build (CI)

The build-deps target is auto-generated by @nx/next. It runs dependsOn: ["^build"] for all server upstream packages, then exits (noop executor). This means:

  • Dependency ordering is handled automatically by Nx
  • No manual package list to maintain
  • New flipped packages are picked up automatically

Argo production builds

The Argo workflow uses npx nx next:build server in the build-app-ee step, which triggers ^build for all dependencies. The ee/server/Dockerfile (pre-built artifacts) copies ./packages/ including dist/ directories.

How to flip a new package

  1. Create packages/<pkg>/tsup.config.ts using the shared preset
  2. Build: cd packages/<pkg> && npx tsup
  3. Update server/next.config.mjs:
    • Change webpack alias from packages/<pkg>/src to packages/<pkg>/dist
    • Same for trailing-slash alias
    • Remove from transpilePackages array
    • Update Turbopack aliases if present
  4. Update packages/<pkg>/package.json: change "build" script to "tsup"
  5. Verify: tsc --noEmit passes (types still from src), npm run build succeeds (runtime from dist)

Do NOT change tsconfig paths — types always resolve from src/.

Packages that should stay source-transpiled

Package Reason
ui Heavy CSS integration (7 CSS imports), changes frequently
msp-composition Composition layer, imports from all verticals
client-portal-composition Same
ee-stubs Build-time CE/EE switching