Skip to content

About

Localization and translation management for SELISE Blocks: languages, translation keys and resource delivery.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

46 stars

Watchers

0 watching

Forks

Repository files navigation

Blocks Localization (blocks-localization)

Product name: Blocks Localization. The legacy name EuroLM survives only in internal plumbing (namespaces such as Eurolm.DomainService, eurolm_* message queues) and is being retired incrementally.

ASP.NET Core (net10.0) + React (Vite, TypeScript) Blocks Identity / cloud admin surfaces with Blocks Localization domain extensions (Eurolm.DomainService, legacy EuroLM naming). The web host (Genesis/Blocks configuration, FluentValidation, health checks) serves the SPA from server/Api/wwwroot; GlobalApiRoutePrefixConvention prefixes attribute routes with api. A separate Worker (blocks-eurolm-worker) runs message consumers. Node/npm are for the client toolchain (npm install, npm run dev, npm run build).

Project structure

blocks-localization/
β”œβ”€β”€ client/                                   # React + Vite + TypeScript (package name: blocks-localization-client)
β”‚   β”œβ”€β”€ app/                                  # Source (iam, cross-modules, routes, components, lib, …)
β”‚   β”‚   β”œβ”€β”€ iam/                              # Auth, IAM, captcha, API settings, …
β”‚   β”‚   β”œβ”€β”€ cross-modules/                     # Shared areas (ai, communication, identifier, lmt, …)
β”‚   β”‚   β”œβ”€β”€ routes/, pages/, layouts/, hooks/
β”‚   β”‚   └── lib/                              # e.g. get-api-path.ts, runtime-env.ts, http-client.ts
β”‚   β”œβ”€β”€ index.html                            # Inline __BLOCKS_* placeholders for prod substitution
β”‚   β”œβ”€β”€ vite.config.ts                        # build.outDir β†’ ../server/Api/wwwroot; dev port 4000; BLOCKS_ env
β”‚   β”œβ”€β”€ package.json
β”‚   └── .env.example                           # Template for local BLOCKS_* (copy to .env)
β”œβ”€β”€ server/
β”‚   β”œβ”€β”€ Api/                                  # Kestrel host (static SPA + JSON API)
β”‚   β”‚   β”œβ”€β”€ Controllers/                      # See β€œAPI / routing” below (~23 controllers)
β”‚   β”‚   β”œβ”€β”€ wwwroot/                          # Vite output (generated; do not edit)
β”‚   β”‚   β”œβ”€β”€ Program.cs                        # Middleware, SPA fallback, optional token replacement into built assets
β”‚   β”‚   β”œβ”€β”€ Api.csproj
β”‚   β”‚   └── Properties/launchSettings.json    # Example: http://localhost:5000
β”‚   β”œβ”€β”€ Worker/                               # Background consumers (hosted service name in code)
β”‚   β”œβ”€β”€ Eurolm.DomainService/                  # EuroLM-specific services and data
β”‚   β”œβ”€β”€ DomainService/                        # Standalone *.csproj on disk; not in Blocks.slnx; most `DomainService.*` namespaces live under other *Domain* projects
β”‚   β”œβ”€β”€ Authentication.DomainService/
β”‚   β”œβ”€β”€ Captcha.DomainService/
β”‚   β”œβ”€β”€ Cloud.DomainService/
β”‚   β”œβ”€β”€ Cloud.LmtService/
β”‚   β”œβ”€β”€ CloudConfiguration.DomainService/
β”‚   β”œβ”€β”€ Iam.DomainService/
β”‚   β”œβ”€β”€ Identifier.DomainService/
β”‚   β”œβ”€β”€ Mfa.DomainService/
β”‚   β”œβ”€β”€ *_Driver/                             # Captcha.Driver, Iam.Driver, Mfa.Driver (outside solution)
β”‚   β”œβ”€β”€ XUnitTest/
β”‚   β”œβ”€β”€ Directory.Build.props                   # TargetFramework net10.0
β”‚   └── Blocks.slnx                            # Api, domain projects, Worker, XUnitTest
β”œβ”€β”€ run.sh                                    # Build client β†’ run API from server/Api
β”œβ”€β”€ run-app-combined.sh                       # Optional npm i, build, Worker + API on :5000; optional distβ†’wwwroot rsync*
β”œβ”€β”€ run-api-only.sh                           # Free :5000, dotnet run Api
β”œβ”€β”€ run-fe-only.sh                            # Prompt for Vite `--host`; map /etc/hosts; npm run dev
β”œβ”€β”€ run-worker-only.sh                         # dotnet run Worker
β”œβ”€β”€ e2e/                                      # Playwright end-to-end tests (see e2e/README.md)
β”œβ”€β”€ scripts/                                  # scan.sh and deploy.sh entry points
β”œβ”€β”€ Dockerfile, Dockerfile.worker              # CI/production images (multi-stage API + Worker)
β”œβ”€β”€ LICENSE
β”œβ”€β”€ README.md
└── …

*With the current client/vite.config.ts, vite build writes directly to server/Api/wwwroot. If client/dist does not exist, the rsync branch in run-app-combined.sh is skipped; the SPA is already in wwwroot from the build step.

Prerequisites

Local infrastructure

This app expects Genesis/Blocks configuration and backing services appropriate to your environment. For local stacks (databases, messaging, related services), use blocks-infra Docker Compose as documented in that repository (docker compose up, etc.); bring Compose up before or alongside the API/Worker here so connectivity and vault/secrets behave as intended.

Docker alone is optional for raw dotnet/npm runs unless you explicitly depend on that Compose stack.

How to run

Ports

Process Typical port
API (Kestrel) 5000 (server/Api/Properties/launchSettings.json)
Vite (npm run dev) 4000 (client/vite.config.ts and client/package.json script)

launchSettings.json governs dotnet run from the IDE; shell scripts enforce 5000 their own way (see below).


run.sh (simple integration)

Runs from repo root:

  1. npm run build in client/ (fills server/Api/wwwroot per Vite)
  2. dotnet run in server/Api/

No flags. Example:

chmod +x run.sh   # once
./run.sh

run-app-combined.sh

  • Installs client/node_modules with npm i only if missing
  • Builds the client (npm run build)
  • If client/dist/ exists, rsync-syncs client/dist/ β†’ server/Api/wwwroot/ (rsync -a --delete); redundant when Vite output already targets wwwroot (current config)
  • Frees listeners on 5000 via lsof + kill
  • Starts Worker as a background job, then runs Api (foreground); Ctrl+C / cleanup stops the Worker

Example:

chmod +x run-app-combined.sh
./run-app-combined.sh

run-api-only.sh

Frees 5000, then dotnet run on server/Api/Api.csproj from repo root.

./run-api-only.sh

run-worker-only.sh

dotnet run on server/Worker/Worker.csproj (no API port logic).

./run-worker-only.sh

run-fe-only.sh

  • Parses block dev host from package.json scripts.dev (--host …)
  • Prompts for a domain (defaults to detected host); may append 127.0.0.1 <domain> to /etc/hosts (sudo)
  • Clears 4000 the same pattern as combined script does for 5000
  • Writes the chosen --host back into package.json
  • Runs npm run dev in client/

Use this when you want Vite hot reload behind a hostname you map locally.


Windows

There is no run.ps1 in this repository. Use WSL or Git Bash for the .sh scripts, or invoke dotnet/ npm manually (below).


Without the scripts

Ensure wwwroot is populated (either run npm run build in client/ first, or your publish pipeline copied assets):

dotnet run --project server/Api/Api.csproj

Worker separately:

dotnet run --project server/Worker/Worker.csproj

Frontend dev server (see vite.config.ts: BLOCKS_API_BASE_URL enables dev proxy prefixes such as /api, /iam, /communication, etc.):

cd client && npm install && npm run dev

Client environment (BLOCKS_*)

Vite envPrefix is BLOCKS_ (client/vite.config.ts). For production bundles, placeholders in client/index.html can be rewritten at startup by server/Api/Program.cs using process environment (DotNetEnv) for:

  • BLOCKS_API_BASE_URL
  • BLOCKS_X_BLOCKS_KEY
  • BLOCKS_GOOGLE_SITE_KEY
  • BLOCKS_CONSTRUCT_URL

Copy client/.env.example β†’ client/.env for values consumed at npm run / vite build time.

Variable Role
BLOCKS_API_BASE_URL API base URL; import.meta.env and runtime replacement; triggers Vite proxy when non-empty (client/vite.config.ts)
BLOCKS_X_BLOCKS_KEY X-Blocks-Key and project-style usage (client/app/lib/http-client.ts, auth/IAM flows)
BLOCKS_GOOGLE_SITE_KEY hCaptcha/Google flows in auth forms
BLOCKS_CONSTRUCT_URL Construct service links (client/app/lib/runtime-env.ts, OIDC/UI)
BLOCKS_APP_URL Build-time branching in PAT/SSO UI (import.meta.env)
BLOCKS_BASE_DOMAIN Project/help domain fallback (client/app/hooks/use-project.ts)
BLOCKS_BLOCKED_MENU JSON string for menu filtering (client/app/hooks/use-filtered-menus.ts)
BLOCKS_GITHUB_CLIENT_ID DevOps/GitHub OAuth client id (client/app/cross-modules/devops/services/providers.service.ts)

Type-only / optional: BLOCKS_CLOUD_DASHBOARD_URL is declared in client/app/vite-env.d.ts: search usages if you rely on it.

Server-side (API startup): BLOCKS_VAULT_TYPE selects Genesis vault parsing when set; otherwise ASPNETCORE_ENVIRONMENT/Development β†’ OnPrem, else Azure (server/Api/Program.cs, server/Worker).

Rebuild the client after changing build-time BLOCKS_*.

Production / publish

Frontend build publishes into server/Api/wwwroot:

(cd client && npm ci && npm run build)
dotnet publish server/Api/Api.csproj -c Release -o ./publish

No Node process is needed on the server at runtime unless you deliberately run tooling there. Prefer the repo Dockerfiles for consistent Node + SDK versions.

Worker image/pattern: Dockerfile.worker.

Tests

Run from the repository root:

# backend unit tests (xUnit)
dotnet test server/XUnitTest/XUnitTest.csproj

# frontend unit tests (Vitest)
npm --prefix client run test

# end-to-end tests (Playwright); needs a reachable app and e2e/.env.e2e,
# see e2e/README.md for setup and target modes
npm --prefix e2e run test

Coverage:

dotnet test server/XUnitTest/XUnitTest.csproj --collect:"XPlat Code Coverage"
npm --prefix client run test -- --coverage

Scanning and deployment

  • scripts/scan.sh is the security scan entry point (SAST, SCA and secret scanning). It is intentionally not tracked in git; internal environments provide it.
  • scripts/deploy.sh is the maintainer deploy script for a systemd host: it checks out the latest inception, builds the client, publishes the Api and Worker projects, and installs and restarts their systemd services.

API / routing

  • Controllers: server/Api/Controllers/ (e.g. Authentication, Iam, Mfa, Captcha, Key, Mail, Storage, Assistant, Module, Project, People, Language, Glossary, Migration, Log, Trace, Notification, Discovery (routes under [Route(".well-known")] prefixed with api), …).
  • Global prefix: api: GlobalApiRoutePrefixConvention in Program.cs prefixes every controller [Route(...)].
  • SPA: UseDefaultFiles, UseStaticFiles, MapFallbackToFile("/index.html") when wwwroot/index.html exists (Program.cs).
  • /api is effectively reserved by the ASP.NET routing convention; Genesis may also expose other path prefixes in middleware; tune CORS/origin when splitting Vite (:4000) from Kestrel (:5000).

Contributing and security

Database placement (Genesis 4.2.2)

API and Worker use the published Genesis 4.2.2 package. Repositories follow persisted tenant connections per operation. No environment-to-connection mapping is added here.

Singleton language, glossary, and key services read the operation's tenant context when creating records; they do not retain the tenant from construction. Module listing with an explicit project key uses that target even when the caller has a different ambient tenant. The generation worker stamps published timeline records with its event's project key. Worker messages still require the expected authenticated tenant context for repository operations that use ambient routing.

Migration source and destination databases remain explicit. Migration trackers belong to the initiating tenant carried by the authenticated message context, which may differ from both environments. Tracker repository writes require that owner; they do not fall back to root when context is missing. The migration worker preserves that context when publishing completion to OS. Shared timeline user enrichment continues using configured RootTenantId on main.

Regression tests cover independent source/target/owner databases, overwrite and retry behavior, concurrent tracker ownership, and completion message context. They use disposable local MongoDB databases through the real Genesis provider:

dotnet test server/XUnitTest/XUnitTest.csproj -c Release

The new routing fixture defaults to localhost:27017. BLOCKS_ROUTING_TEST_MONGO_PORT selects another local test port; remote hosts and deployed credentials are not used. These tests do not establish independent deployed cluster connectivity or an atomic cross-cluster migration.

Deploy API and all translation/import/export/migration workers before enabling OS split placement. Keep the root registry on main. Existing tenant placement/data migration and coordinated cache refresh remain separate work.

License

See LICENSE.

About

Localization and translation management for SELISE Blocks: languages, translation keys and resource delivery.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

46 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages