Service Architecture

WorkSpaceMan is a monorepo using Lerna + Yarn Workspaces, with five main runtime services:

[Nginx Reverse Proxy] | +-- my.wsm.nl --> OpenMembers (Port 4000) -- Member-facing portal +-- api.wsm.nl --> API Server (Port 4001) -- REST API + MongoDB +-- crm.wsm.nl --> CRM (Port 4002) -- Sales pipeline [Background Services] +-- Jobs Worker -- Consumes Google Pub/Sub messages +-- Cron -- Scheduled tasks (Xero refresh, quotas, health checks) [Data Stores] +-- MongoDB -- Primary database (all business data) +-- Redis -- Sessions + cache +-- Elasticsearch -- Full-text search

Services Detail

ServicePortEntry PointPurpose
API 4001 packages/api/bin/server.js Core REST API, data models, business logic via JXP framework
OpenMembers 4000 packages/openmembers/bin/www Member-facing web portal (Express + Handlebars)
CRM 4002 packages/crm/bin/www Sales pipeline, lead management, opportunities
Jobs N/A packages/jobs/worker.js Async job processor — emails, invoices, payments, user ops
Cron N/A packages/cron/cron.js Scheduled tasks from database schedule records

Message Queue Flow

Asynchronous processing uses Google Cloud Pub/Sub:

API / OpenMembers | | messagequeue.action(type, op, user, item) v [Google Cloud Pub/Sub Topic] | | Attributes: { type, op, _id } | Payload: { user, item } v Jobs Worker (subscriber) | +-- Email notifications +-- Invoice creation / Xero sync +-- Payment processing +-- User setup (Papercut, WiFi, PIN) +-- Organization management

Deployment

Docker

DockerfileBase ImageNotes
Dockerfile-api node:16 API service — Node 16 is EOL (Sept 2023)
packages/openmembers/Dockerfile node:carbon OpenMembers — Node 8 "carbon" is EOL (Dec 2019)

Systemd Services (Production)

ServiceDepends On
wsm-api.service
wsm-my.servicewsm-api
wsm-jobs.servicewsm-api
wsm-cron.servicewsm-api
wsm-crm.servicewsm-api

Nginx Reverse Proxy

Data Persistence

StoreUsageConfiguration
MongoDB All business data, models Pool size 10, auth source: admin, retryWrites
Redis Express sessions, caching connect-redis + ioredis
Elasticsearch Full-text search: users, orgs, rooms, invoices, guests, logs Index name: "myopen"
Google BigQuery Analytics and logging Via packages/api/bin/bqlogger.js

Monorepo Structure

workspaceman/ +-- config/ # Configuration files (per-environment) +-- models/ # Mongoose data models (shared) +-- packages/ | +-- api/ # Core REST API | +-- openmembers/ # Member portal + all integrations | +-- crm/ # CRM service | +-- jobs/ # Pub/Sub job worker | +-- cron/ # Scheduled task runner | +-- accounting/ # Accounting module (TypeScript/Handlebars) | +-- xero/ # Xero integration (Svelte + TypeScript) | +-- pos/ # Point of sale (Vue 2) | +-- doors/ # Access control (Svelte) | +-- reports/ # Reporting tools | +-- shared/ # Shared libraries (apihelper, booking logic) | +-- components/ # Shared frontend components | +-- config/ # Config utilities | +-- mailchimp/ # Email marketing | +-- matrix/ # Matrix chat integration | +-- scaffold/ # Project scaffolding | +-- simulate_payment/ # Payment testing tools | +-- vue/ # Vue frontend components | +-- fnb/ # FNB banking integration | +-- mips/ # MIPS payment integration | +-- mockery/ # Test mocks | +-- icalimporter/ # iCal import tool | +-- public/ # Public assets +-- setup/ | +-- systemd/system/ # Service definitions | +-- nginx/ # Nginx configurations +-- deploy/ # Deployment scripts +-- wsm_tests/ # Test suites +-- docker-compose.yml +-- Dockerfile-api +-- lerna.json +-- package.json

Build Pipeline

CommandWhat It Does
yarn dev:apiAPI with nodemon (hot reload)
yarn dev:openmembersFrontend with hot reload
yarn dev:crmCRM service
yarn dev:jobsJob worker
yarn dev:cronScheduler
yarn build:vueProduction Vue build
yarn build:openmembersWebpack build (needs --openssl-legacy-provider)
yarn build:posPOS Rollup build
yarn testFull Jest test suite