Skip to main content

Monorepo Architecture

The unpispas.nx workspace is an Nx-managed monorepo that combines an Angular/Ionic front-end, a PHP REST API backend, and a Docker-based deployment stack. This page explains how the pieces fit together.

Nx Build System

The workspace uses Nx to orchestrate builds, tests, and linting across all projects. The root nx.json defines shared defaults:

SettingValue
Apps directoryapps/
Libs directorylibs/
Default base branchmain
Angular build executor@angular-devkit/build-angular:browser-esbuild
Test runner@nx/jest:jest
Linter@nx/eslint:lint

Every build target declares dependsOn: ["^build"], which means Nx automatically builds library dependencies before building the consuming project. Caching is enabled for builds, tests, and lints, so unchanged projects are not rebuilt.

High-Level Overview

graph TB
subgraph Apps
POS["unpispas-pos<br/>(main POS app)"]
TEST["upp-test<br/>(demos & examples)"]
GUIDE["upp-guide<br/>(documentation)"]
end

subgraph General Libraries
DEFS["upp-defs<br/>(constants & utils)"]
BASE["upp-base<br/>(services & platform)"]
DATA["upp-data<br/>(data model & sync)"]
WDGT["upp-wdgt<br/>(UI widgets)"]
end

subgraph Feature Libraries
FL["feature/login"]
FT["feature/topbar"]
FU["feature/user"]
FP["feature/place"]
FK["feature/ticket"]
FO["...other features"]
end

subgraph Backend
PHP["server/<br/>(PHP REST API)"]
end

POS --> WDGT
POS --> FL & FT & FU & FP
WDGT --> BASE
DATA --> BASE
BASE --> DEFS
FL & FT & FU & FP --> DATA
FL & FT & FU & FP --> WDGT
POS -.HTTP.-> PHP

Library Dependency Graph

Libraries form a strict layered dependency chain. Each layer can only depend on layers below it.

Layer 1 — upp-defs (Definitions)

The foundation layer. Contains application-wide constants (AppConstants) and pure utility functions (GenericUtils). Has no Angular dependencies beyond the component scaffold.

Exports: AppConstants, GenericUtils, UppDefsComponent

Layer 2 — upp-base (Base Services)

Platform and infrastructure services. Depends only on upp-defs. Provides:

ExportPurpose
stateServiceSession, device, place, access mode (GUEST / LOGIN)
viewServiceCurrent view (LOGIN, USER, PLACE, GUEST), edit mode, panels
eventbusServiceGlobal pub/sub event bus
httpServiceHTTP client with online/offline detection
adhocServiceTyped API requests to the backend
clockServicePeriodic tick for deferred UI refresh
storeServiceIonic Storage wrapper (local persistence)
languageServicei18n module loader and translation
platformServiceDevice type, theme, kiosk mode detection
socketServiceWebSocket abstraction
uploadServiceFile upload handling
alertServiceModal alerts and input dialogs
toastServiceToast notifications
preloadServiceAsset preloading

The UppBaseModule configures Ionic, Ionic Storage, HTTP client, and Cordova plugins.

Layer 3 — upp-data (Data Model & Sync)

The data layer. Depends on upp-base and upp-defs. Contains the full object model and synchronization engine:

ExportPurpose
DataObject subclassesDomain objects: Product, Ticket, Place, User, Category, etc.
ViewObject subclassesView wrappers with computed properties and reactive refresh
dataServiceCentral data store, object factory, commit pipeline
syncServiceServer connection, long-poll sync, change queue
cacheServiceIndexedDB-backed local cache for session/place data
loginServiceAuthentication flow

The UppDataModule is intentionally lightweight (just CommonModule); all services use providedIn: 'root'.

Layer 4 — upp-wdgt (Widgets)

Reusable UI components. Depends on upp-base:

ExportPurpose
upp-applicationRoot application shell
upp-panel, upp-headerLayout components
upp-grid, upp-scrollableData display
upp-input, upp-textarea, upp-selectForm controls
upp-dropdown, upp-tabbarNavigation
upp-image, upp-thumb, upp-cropImage handling
upp-search, upp-form, upp-addressComposite form components
uppDataId, uppTouch, uppVisibleDirectives
uppRendererRendering service

Layer 5 — Feature Libraries

Domain-specific features under libs/feature/. Each feature encapsulates one functional area:

FeaturePurpose
feature/loginLogin/registration UI
feature/topbarApplication top bar
feature/userUser management screens
feature/placePlace selection and management
feature/ticketTicket (sale) creation and editing
feature/productProduct catalog management
feature/categoryCategory management
feature/offerOffers and promotions
feature/extraExtras configuration
feature/employeeEmployee management
feature/qrcodeQR code / table management
feature/shortcutQuick-access shortcuts
feature/periodPeriod (scheduling) management
feature/assetsShared static assets

Feature libraries depend on upp-data and upp-wdgt, and are consumed directly by the applications.

How Apps Consume Libraries

The main application (unpispas-pos) imports libraries through Angular modules:

@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(appRoutes),
FormsModule,
ReactiveFormsModule,
UppBaseModule, // Layer 2
UppWdgtModule, // Layer 4
FeatureLoginModule, // Layer 5
FeatureTopbarModule,
FeatureUserModule,
FeaturePlaceModule,
IonicModule.forRoot(),
NgcCookieConsentModule.forRoot({ ... })
],
providers: [
{ provide: APP_BASE_HREF, useFactory: ... },
{ provide: langsPath, useFactory: ... }
],
bootstrap: [AppComponent],
})
export class AppModule {}

Services from upp-base and upp-data are available application-wide through providedIn: 'root' — they do not need explicit module imports. Only modules that declare Angular components/directives (UppBaseModule, UppWdgtModule, feature modules) need to appear in the imports array.

Build Dependencies

The project.json for unpispas-pos explicitly declares build-time dependencies:

"dependsOn": [
{
"target": "build",
"projects": [
"upp-data",
"upp-wdgt",
"feature-login",
"feature-topbar",
"feature-user",
"feauture-place"
]
}
]

This ensures that when you run npx nx build unpispas-pos, all dependent libraries are built first in the correct order.

Build Output

All build artifacts go to dist/apps/<app-name>/. The production Docker stack serves these via Nginx from the frontend container.