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:
| Setting | Value |
|---|---|
| Apps directory | apps/ |
| Libs directory | libs/ |
| Default base branch | main |
| 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:
| Export | Purpose |
|---|---|
stateService | Session, device, place, access mode (GUEST / LOGIN) |
viewService | Current view (LOGIN, USER, PLACE, GUEST), edit mode, panels |
eventbusService | Global pub/sub event bus |
httpService | HTTP client with online/offline detection |
adhocService | Typed API requests to the backend |
clockService | Periodic tick for deferred UI refresh |
storeService | Ionic Storage wrapper (local persistence) |
languageService | i18n module loader and translation |
platformService | Device type, theme, kiosk mode detection |
socketService | WebSocket abstraction |
uploadService | File upload handling |
alertService | Modal alerts and input dialogs |
toastService | Toast notifications |
preloadService | Asset 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:
| Export | Purpose |
|---|---|
DataObject subclasses | Domain objects: Product, Ticket, Place, User, Category, etc. |
ViewObject subclasses | View wrappers with computed properties and reactive refresh |
dataService | Central data store, object factory, commit pipeline |
syncService | Server connection, long-poll sync, change queue |
cacheService | IndexedDB-backed local cache for session/place data |
loginService | Authentication 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:
| Export | Purpose |
|---|---|
upp-application | Root application shell |
upp-panel, upp-header | Layout components |
upp-grid, upp-scrollable | Data display |
upp-input, upp-textarea, upp-select | Form controls |
upp-dropdown, upp-tabbar | Navigation |
upp-image, upp-thumb, upp-crop | Image handling |
upp-search, upp-form, upp-address | Composite form components |
uppDataId, uppTouch, uppVisible | Directives |
uppRenderer | Rendering service |
Layer 5 — Feature Libraries
Domain-specific features under libs/feature/. Each feature encapsulates one functional area:
| Feature | Purpose |
|---|---|
feature/login | Login/registration UI |
feature/topbar | Application top bar |
feature/user | User management screens |
feature/place | Place selection and management |
feature/ticket | Ticket (sale) creation and editing |
feature/product | Product catalog management |
feature/category | Category management |
feature/offer | Offers and promotions |
feature/extra | Extras configuration |
feature/employee | Employee management |
feature/qrcode | QR code / table management |
feature/shortcut | Quick-access shortcuts |
feature/period | Period (scheduling) management |
feature/assets | Shared 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.