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
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
6.1 KiB
6.1 KiB
Building Enterprise Edition
This project uses a monorepo structure to integrate the enterprise edition (EE) code with the community edition (CE) code while maintaining them as a single unit.
Project Structure
/
├── package.json # Root package.json with all dependencies
├── docker-compose.yaml # Base docker-compose configuration
├── server/ # Community Edition
│ ├── package.json # CE package.json (minimal, uses workspace)
│ ├── tsconfig.json # Base TypeScript config
│ └── src/
│ ├── components/
│ ├── lib/
│ └── services/
└── ee/
└── server/ # Enterprise Edition
├── package.json # EE package.json (minimal, uses workspace)
├── tsconfig.json# EE TypeScript config (extends base)
└── src/
├── components/
├── lib/
└── services/
Docker Compose Configuration
The project uses a layered docker-compose configuration to support both CE and EE deployments:
-
Base Configuration (
docker-compose.yaml):- Contains common service definitions
- Defines shared environment variables including EDITION
- Sets up base networking
-
EE Configuration (
ee/setup/docker-compose.yaml):- Extends services from base configuration
- Sets EDITION=enterprise
- Uses EE-specific Dockerfile and configurations
Running CE Version
# From project root
EDITION=community docker compose -f docker-compose.yaml up
Running EE Version
# From project root
EDITION=enterprise docker compose -f docker-compose.yaml -f ee/setup/docker-compose.yaml up
Workspace Setup
- Root
package.jsondefines workspaces and contains all dependencies:
{
"workspaces": [
"server",
"ee/server"
],
"dependencies": {
// All project dependencies are defined here
}
}
- CE and EE
package.jsonfiles are minimal:
{
"name": "sebastian-ee",
"version": "0.1.0",
"private": true,
"workspaces": {
"nohoist": ["*"]
}
}
TypeScript Configuration
- Base TypeScript config in
server/tsconfig.json:
{
"compilerOptions": {
}
}
- EE TypeScript config in
ee/server/tsconfig.jsonextends the base:
{
"extends": "../../server/tsconfig.json",
"compilerOptions": {
"paths": {
"@/*": ["../../server/src/*"],
"@ee/*": ["./src/*"]
},
"baseUrl": "."
}
}
Path Aliases
Use path aliases instead of relative paths:
@/*for CE imports@ee/*for EE imports
Example:
// Instead of relative paths like:
import { Something } from "../../../../../server/src/components/Something";
// Use path aliases:
import { Something } from "server/src/components/Something";
import { EEFeature } from "ee/components/EEFeature";
Feature Flags
Use feature flags to conditionally include EE features:
// server/src/lib/features.ts
export const isEnterprise = process.env.EDITION === 'enterprise';
export function getFeatureImplementation<T>(ceModule: T, eeModule?: T): T {
if (isEnterprise && eeModule) {
return eeModule;
}
return ceModule;
}
Usage:
import { CEFeature } from "features/CEFeature";
import { EEFeature } from "ee/features/EEFeature";
import { getFeatureImplementation } from "server/src/lib/features";
const FeatureComponent = getFeatureImplementation(CEFeature, EEFeature);
Conditional Dependencies
Some packages may only be needed when running in enterprise mode. To handle these cases:
- Install the package conditionally in your code:
let anthropicClient;
if (process.env.EDITION === 'enterprise') {
// Dynamic import ensures the package is only loaded if EE is active
const { default: Anthropic } = await import('anthropic-sdk');
anthropicClient = new Anthropic();
}
- Add the package to your dependencies in root package.json:
{
"dependencies": {
"anthropic-sdk": "^0.1.0" // Will only be used when EE is active
}
}
This approach ensures that:
- The package is available when needed in EE mode
- The package is not loaded or used in CE mode
- TypeScript still has access to types for development
Type Declarations
For TypeScript support of EE imports:
// server/src/types/ee.d.ts
declare module '@ee/*' {
const content: unknown;
export default content;
}
Build Scripts
The build scripts are defined in the root package.json:
{
"scripts": {
"dev": "cd server && EDITION=enterprise next dev",
"build": "cd server && next build",
"build:ee": "cd server && EDITION=enterprise next build"
}
}
Best Practices
-
Dependencies:
- Keep all dependencies in the root
package.json - Use workspace references in CE and EE packages
- Use dynamic imports for EE-only packages
- Keep all dependencies in the root
-
Code Organization:
- Keep shared code in the CE codebase
- Use path aliases consistently
- Mirror CE directory structure in EE when extending features
-
Types:
- Define shared interfaces in CE
- Extend CE types in EE when needed
- Use TypeScript path aliases for clean imports
-
Feature Flags:
- Use the feature flag system for EE features
- Document feature flag usage
- Test both CE and EE configurations
-
Testing:
- Test both editions during development
- Use environment variables to control edition in tests
- Ensure CE works independently of EE
Development Workflow
- Run the development server:
npm run dev # Runs with EE features enabled
- Build the project:
npm run build # CE build
npm run build:ee # EE build
- Run with Docker Compose:
# Community Edition
EDITION=community docker compose -f docker-compose.yaml up
# Enterprise Edition
EDITION=enterprise docker compose -f docker-compose.yaml -f ee/setup/docker-compose.yaml up
Remember to:
- Document new EE features
- Test both CE and EE builds
- Keep the dependency tree unified
- Use TypeScript path aliases consistently
- Follow the established directory structure