Angular UI
Standalone, strict, zoneless Angular application with customer intake, staff production workspace, responsive layout, and printable job sheets.
src/
Current architecture · August 23, 2026
The real implementation foundation: an Angular customer and staff interface backed by a modular Hono Worker, locally simulated Cloudflare D1, and locally simulated R2.
01 · At a glance
The active application keeps the user interface, API, structured records, and uploaded file bytes in clearly separated layers.
Standalone, strict, zoneless Angular application with customer intake, staff production workspace, responsive layout, and printable job sheets.
src/
Cloudflare Worker-compatible API split into focused routes, identity middleware, validation, and order query/command modules.
worker/
Departments, workstation identities, orders, file metadata, activity events, and daily counters live behind the D1 binding.
env.DB
Uploaded bytes use private generated object keys in the R2 binding. Searchable metadata and original filenames remain in D1.
env.FILES
02 · Runtime shape
During normal development, Angular serves the UI on port 4200 and proxies /api to Wrangler on port 8787. Wrangler runs the Worker and simulates both Cloudflare storage bindings through Miniflare.
Customer intake at / or staff workspace at /staff.
Renders UI and sends typed requests from OrderApiService.
Validates requests, applies identity context, and coordinates persistence.
D1 stores relational state; R2 stores uploaded file bodies.
npm run preview builds Angular and lets the Worker serve the compiled single-page application and API together from port 8787. Wrangler is configured to run the Worker first for /api/* and fall back to the SPA for browser routes.
03 · Worker organization
worker/app.ts is intentionally an 18-line composition root. It creates Hono, installs shared error behavior, registers route groups, and returns the app. Business rules and SQL are kept out of that file.
Health, departments, local identities, local session creation, session lookup, and sign-out.
Public initiation, Worker-mediated R2 upload, stored-size verification, and order completion.
Staff listing/detail, filters, status transitions, cancellation, downloads, audit events, and reset.
D1 reads, list filtering, joined order summaries, files, events, departments, and submitted-order lookup.
Atomic public IDs, idempotent initiation, writes, status/cancel events, and download attribution.
Internal D1 row shapes and reusable select projections, separate from public API contracts.
Development-only environment guard, principal lookup, and staff middleware.
Required fields, due date/time, delivery, extension, count, and byte-limit rules.
Consistent JSON errors, safe JSON parsing, and content-disposition handling.
Deletes local R2 objects, clears D1 test data in dependency order, and reapplies the seed.
Binding types, request principal type, and small typed D1 result helpers.
Creates the composed application once and exports it as the Worker entry point.
04 · Data layer
The Drizzle schema is the readable source of truth; generated SQL migrations are applied by Wrangler. Prepared D1 statements and batches are used at runtime. File bodies never go into D1.
CS-YYMMDD-NNNNavailable. A successful upload can be safely retried.05 · HTTP interface
Customer intake and department lookup are public. Local identity helpers exist only in local and test. Staff routes require the selected local principal on the server.
| Method | Route | Scope | Purpose |
|---|---|---|---|
| GET | /api/health | Public | Runtime health and environment. |
| GET | /api/departments | Public | Active D1-backed department choices. |
| POST | /api/orders/initiate | Public | Validate and create a pending, idempotent order. |
| PUT | /api/uploads/:token | Public token | Stream one validated file to local R2. |
| POST | /api/orders/:id/complete | Public | Require available files and submit the order. |
| GET | /api/local-identities | Local/test | List seeded workstation identities. |
| POST | /api/local-session | Local/test | Select identity and set an HttpOnly cookie. |
| GET · DELETE | /api/session | Local/test | Read or clear the current development session. |
| GET | /api/staff/orders | Staff | List and filter submitted orders. |
| GET | /api/staff/orders/:id | Staff | Order detail, files, and activity. |
| PATCH | /api/staff/orders/:id/status | Staff | Enforce forward-only workflow transitions and record actor. |
| POST | /api/staff/orders/:id/cancel | Staff | Cancel without rewriting production status; record actor. |
| GET | /api/staff/orders/:id/files/:fileId | Staff | Stream an individual R2 object and audit the download. |
| POST | /api/dev/reset | Local staff | Clear test records and R2 objects, then reseed. |
Intentionally absent: there is no bulk ZIP endpoint. Individual file downloads are the supported interface.
06 · Development identity
A “user” is currently modeled as an email identity for a department workstation. The schema permits multiple active emails per department even though the local seed starts with one fake .local identity for each of the five departments.
copies@thecopyshop.localuser-copiesdept-copies07 · Local development
npm run dev applies pending D1 migrations, runs the idempotent local seed, then starts Wrangler and Angular together. Persistent local D1 and R2 emulator state lives under the ignored .wrangler/state/ directory.
npm install
npm run dev
# UI
http://127.0.0.1:4200
# Worker health
http://127.0.0.1:8787/api/healthnpm run db:migrate:local
npm run db:seed:local
npm run db:setup
npm run db:generatenpm run preview
# Compiled SPA + Worker API
http://127.0.0.1:8787npm run lint
npm test
npm run build
npm run test:e2e
# Everything above
npm run checkAngular commands run through scripts/angular.mjs. It clears only generated Angular cache data and forces the SQLite cache backend, avoiding the local LMDB crash and Angular 22’s stale compiled-byte serialization problem.
seed/local.sql contains five departments, five fake workstation identities, current sample orders, metadata-only sample attachments, events, and counters. The staff reset control removes new R2 objects and restores these records.
08 · Verification
The complete acceptance command currently passes lint, Angular tests, isolated Worker tests, a production Angular build plus Worker dry run, and Playwright workflows.
Formatting, API request contracts, and customer component behavior.
Fresh D1/R2 bindings per test, identity, uploads, idempotency, filters, workflow, audit, and reset.
End-to-end submission, download, statuses, cancellation, identity switching, filters, responsive/print behavior, and overflow regression.
09 · Production roadmap
This branch deliberately stops at a strong local core. It creates no Cloudflare account resources, DNS records, production credentials, or real authentication.
Verified-email authentication, Cloudflare Access or an approved provider, explicit allowlists, and D1 user-to-department authorization.
Separate preview/production D1 databases and R2 buckets, reviewed remote migrations, private objects, lifecycle policies, and backups.
Short-lived direct R2 URLs or multipart uploads, checksums, narrow CORS, orphan cleanup, and approved malware controls.
Turnstile, rate limiting, quotas, file-signature checks, abuse monitoring, and safe retention.
Notifications, observability, incident ownership, restore testing, rollback, and a limited parallel-operation period.
Configure orders.thecopyshoponline.com as a future Worker Custom Domain only after resource and DNS review.
The complete checklist lives in docs/production-deployment.md.