@xbg.solutions/create-backend 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/init.js +55 -12
- package/lib/commands/init.js.map +1 -1
- package/package.json +1 -1
- package/src/project-template/.claude/settings.local.json +57 -0
- package/src/project-template/.claude/skills/bpbe/api/skill.md +403 -0
- package/src/project-template/.claude/skills/bpbe/data/skill.md +442 -0
- package/src/project-template/.claude/skills/bpbe/services/skill.md +497 -0
- package/src/project-template/.claude/skills/bpbe/setup/skill.md +301 -0
- package/src/project-template/.claude/skills/bpbe/skill.md +153 -0
- package/src/project-template/.claude/skills/bpbe/utils/skill.md +527 -0
- package/src/project-template/.claude/skills/skill.md +30 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Setup, configuration, and development workflow for the XBG boilerplate backend: creating projects with the CLI, .env variables, npm scripts, Firebase config, validation, and local dev server."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# XBG Boilerplate Backend — Setup & Configuration
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Quick Start — New Project
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Scaffold a new project with the CLI
|
|
13
|
+
npx @xbg.solutions/create-backend init
|
|
14
|
+
|
|
15
|
+
# The CLI will:
|
|
16
|
+
# - Ask about your project (name, Firebase project, features)
|
|
17
|
+
# - Let you select which utilities to include
|
|
18
|
+
# - Generate project structure with selected @xbg.solutions/* packages
|
|
19
|
+
# - Install dependencies
|
|
20
|
+
|
|
21
|
+
# Once scaffolded:
|
|
22
|
+
cd my-project/functions
|
|
23
|
+
|
|
24
|
+
# Interactive setup wizard (generates .env, configures Firebase)
|
|
25
|
+
npm run setup
|
|
26
|
+
|
|
27
|
+
# Validate configuration + run tests
|
|
28
|
+
npm run validate
|
|
29
|
+
|
|
30
|
+
# Start local dev server
|
|
31
|
+
npm start
|
|
32
|
+
# Visit: http://localhost:5001/health
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### What a Generated Project Looks Like
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
my-project/
|
|
39
|
+
├── functions/
|
|
40
|
+
│ ├── src/
|
|
41
|
+
│ │ ├── index.ts # Firebase Functions entry point
|
|
42
|
+
│ │ └── generated/ # Code generator output
|
|
43
|
+
│ ├── package.json # Depends on @xbg.solutions/* packages
|
|
44
|
+
│ ├── tsconfig.json
|
|
45
|
+
│ └── .env
|
|
46
|
+
├── __scripts__/ # Setup, generate, deploy, validate
|
|
47
|
+
├── __examples__/ # Example data models
|
|
48
|
+
├── firebase.json
|
|
49
|
+
└── .firebaserc
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Updating an Existing Project
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Check for and apply boilerplate updates
|
|
56
|
+
npx @xbg.solutions/create-backend sync
|
|
57
|
+
|
|
58
|
+
# Update packages to latest versions
|
|
59
|
+
cd functions && npm update
|
|
60
|
+
|
|
61
|
+
# Add a new utility
|
|
62
|
+
npx @xbg.solutions/create-backend add-util
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Environment Variables
|
|
68
|
+
|
|
69
|
+
Copy `.env.example` to `.env` in the `functions/` directory. All config is env-driven — never hardcode values.
|
|
70
|
+
|
|
71
|
+
### Core Variables
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Application
|
|
75
|
+
APP_NAME=my-backend-api
|
|
76
|
+
APP_VERSION=1.0.0
|
|
77
|
+
NODE_ENV=development # development | staging | production
|
|
78
|
+
PORT=5001
|
|
79
|
+
|
|
80
|
+
# Firebase
|
|
81
|
+
FIREBASE_PROJECT_ID=your-project-id
|
|
82
|
+
|
|
83
|
+
# API
|
|
84
|
+
API_BASE_PATH=/api/v1
|
|
85
|
+
CORS_ORIGINS=http://localhost:3000,http://localhost:5173
|
|
86
|
+
REQUEST_SIZE_LIMIT=10mb
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Feature Flags
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
FEATURE_AUTHENTICATION=true # JWT auth middleware
|
|
93
|
+
FEATURE_MULTI_TENANT=false # Multi-tenant mode
|
|
94
|
+
FEATURE_FILE_UPLOADS=true
|
|
95
|
+
FEATURE_NOTIFICATIONS=true
|
|
96
|
+
FEATURE_ANALYTICS=false
|
|
97
|
+
FEATURE_REALTIME=true
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Feature flags gate entire subsystems. Check them in code:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { isFeatureEnabled } from '@xbg.solutions/backend-core';
|
|
104
|
+
|
|
105
|
+
if (isFeatureEnabled('notifications')) {
|
|
106
|
+
await pushNotificationsConnector.send({ ... });
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Auth / Token Variables
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
JWT_ISSUER=my-backend-api
|
|
114
|
+
JWT_AUDIENCE=my-backend-api
|
|
115
|
+
JWT_EXPIRES_IN=1h
|
|
116
|
+
JWT_REFRESH_EXPIRES_IN=7d
|
|
117
|
+
TOKEN_BLACKLIST_ENABLED=true
|
|
118
|
+
TOKEN_BLACKLIST_CLEANUP_INTERVAL=3600000
|
|
119
|
+
TOKEN_BLACKLIST_RETENTION_DAYS=30
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Database
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
MAIN_DATABASE_ID=(default) # Primary Firestore database ID
|
|
126
|
+
ANALYTICS_DATABASE_ID=analytics # Secondary database (optional)
|
|
127
|
+
DB_RETRY_ATTEMPTS=3
|
|
128
|
+
DB_RETRY_DELAY=1000
|
|
129
|
+
DB_TIMEOUT=10000
|
|
130
|
+
DB_ENABLE_CACHE=true
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### PII Encryption
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Generate: openssl rand -hex 32
|
|
137
|
+
PII_ENCRYPTION_KEY=your-64-hex-char-key
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Required for the hashing utility (`@xbg.solutions/utils-hashing`). Without it, `hashValue()` will throw at runtime.
|
|
141
|
+
|
|
142
|
+
### Caching
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
CACHE_ENABLED=false # Global cache switch
|
|
146
|
+
CACHE_DEFAULT_PROVIDER=memory # memory | firestore | redis
|
|
147
|
+
CACHE_DEFAULT_TTL=300 # seconds
|
|
148
|
+
CACHE_NAMESPACE=myapp
|
|
149
|
+
# Redis (optional):
|
|
150
|
+
CACHE_REDIS_HOST=localhost
|
|
151
|
+
CACHE_REDIS_PORT=6379
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Rate Limiting
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
RATE_LIMIT_ENABLED=true
|
|
158
|
+
RATE_LIMIT_WINDOW_MS=900000 # 15 minutes
|
|
159
|
+
RATE_LIMIT_MAX=100 # requests per window
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Configuration in Code
|
|
165
|
+
|
|
166
|
+
All config is centralized via `@xbg.solutions/backend-core`. In a generated project, configuration is driven entirely by environment variables.
|
|
167
|
+
|
|
168
|
+
Reading config in your code:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// ✅ Correct — import from @xbg.solutions/backend-core
|
|
172
|
+
import { APP_CONFIG, isFeatureEnabled } from '@xbg.solutions/backend-core';
|
|
173
|
+
const basePath = APP_CONFIG.api.basePath;
|
|
174
|
+
const env = APP_CONFIG.app.environment;
|
|
175
|
+
|
|
176
|
+
// ❌ Wrong — don't access process.env scattered through your code
|
|
177
|
+
const basePath = process.env.API_BASE_PATH; // don't do this
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## npm Scripts
|
|
183
|
+
|
|
184
|
+
Run from `functions/` in a generated project:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Development
|
|
188
|
+
npm start # Local server (http://localhost:5001)
|
|
189
|
+
npm run serve # Firebase emulators
|
|
190
|
+
npm run build # TypeScript compile
|
|
191
|
+
npm run build:watch # Watch mode
|
|
192
|
+
|
|
193
|
+
# Testing
|
|
194
|
+
npm test # All tests
|
|
195
|
+
npm run test:coverage # Coverage report
|
|
196
|
+
npm run test:watch # Watch mode
|
|
197
|
+
|
|
198
|
+
# Code Quality
|
|
199
|
+
npm run lint # ESLint
|
|
200
|
+
npm run lint:fix # Auto-fix lint issues
|
|
201
|
+
|
|
202
|
+
# Setup & Validation
|
|
203
|
+
npm run setup # Interactive setup wizard
|
|
204
|
+
npm run validate # Full: build + lint + tests
|
|
205
|
+
npm run validate:quick # Quick: build + lint only
|
|
206
|
+
|
|
207
|
+
# Code Generation
|
|
208
|
+
npm run generate <model-file> # Generate from DataModelSpecification
|
|
209
|
+
# Example:
|
|
210
|
+
npm run generate ../__examples__/blog-platform.model.ts
|
|
211
|
+
|
|
212
|
+
# Deployment
|
|
213
|
+
npm run deploy # Deploy to Firebase
|
|
214
|
+
npm run logs # View Firebase logs
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Firebase Configuration
|
|
220
|
+
|
|
221
|
+
### `firebase.json` (project root)
|
|
222
|
+
|
|
223
|
+
Defines functions source directory and references `firestore.rules`. Generally don't modify this.
|
|
224
|
+
|
|
225
|
+
### `firestore.rules` (project root)
|
|
226
|
+
|
|
227
|
+
Deny-all rules for client SDK access. This backend uses the Admin SDK (which bypasses rules). These rules act as defense-in-depth against accidental client-side database exposure.
|
|
228
|
+
|
|
229
|
+
### `.firebaserc` (project root)
|
|
230
|
+
|
|
231
|
+
Maps aliases to Firebase project IDs:
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"projects": {
|
|
236
|
+
"default": "your-firebase-project-id",
|
|
237
|
+
"staging": "your-staging-project-id",
|
|
238
|
+
"production": "your-production-project-id"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Switch projects: `firebase use staging`
|
|
244
|
+
|
|
245
|
+
### Local Development with Emulators
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Start Firestore emulator
|
|
249
|
+
firebase emulators:start --only firestore
|
|
250
|
+
|
|
251
|
+
# In .env, add:
|
|
252
|
+
FIRESTORE_EMULATOR_HOST=localhost:8080
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Validation
|
|
258
|
+
|
|
259
|
+
Run `npm run validate` before deploying. It checks:
|
|
260
|
+
|
|
261
|
+
- Node.js version (22+)
|
|
262
|
+
- Firebase CLI installed
|
|
263
|
+
- TypeScript compiles cleanly
|
|
264
|
+
- All tests pass
|
|
265
|
+
- `.env` has required variables
|
|
266
|
+
- No placeholder values left in config
|
|
267
|
+
|
|
268
|
+
Common validation failures and fixes:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# "TypeScript compilation failed"
|
|
272
|
+
npm run build # See full TS errors
|
|
273
|
+
|
|
274
|
+
# "Tests failing"
|
|
275
|
+
npm test # See which tests
|
|
276
|
+
|
|
277
|
+
# "PII_ENCRYPTION_KEY not set"
|
|
278
|
+
openssl rand -hex 32 # Generate a key, add to .env
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Anti-Examples
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
// ❌ Don't hardcode env values
|
|
287
|
+
export const config = {
|
|
288
|
+
apiKey: 'abc123' // Never do this
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// ❌ Don't scatter process.env calls
|
|
292
|
+
const limit = parseInt(process.env.RATE_LIMIT_MAX); // Use APP_CONFIG
|
|
293
|
+
|
|
294
|
+
// ❌ Don't ignore feature flags
|
|
295
|
+
await emailConnector.send({ ... }); // Check isFeatureEnabled('notifications') first
|
|
296
|
+
|
|
297
|
+
// ✅ Correct pattern
|
|
298
|
+
if (isFeatureEnabled('notifications')) {
|
|
299
|
+
await emailConnector.send({ ... });
|
|
300
|
+
}
|
|
301
|
+
```
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Overview of the XBG boilerplate backend: architecture, philosophy, layered structure, and navigation guide to sub-skills for setup, data, services, utilities, and API."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# XBG Boilerplate Backend — Overview
|
|
6
|
+
|
|
7
|
+
A production-ready Node.js/TypeScript backend distributed as **npm packages** (`@xbg.solutions/*`) and optimized for AI-assisted development. Built on Firebase Functions + Firestore + Express.js, designed so that AI can reliably generate, extend, and debug application code.
|
|
8
|
+
|
|
9
|
+
**Repository:** `boilerplate_backend` (sister: `boilerplate_frontend` — SvelteKit 5)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Core Philosophy
|
|
14
|
+
|
|
15
|
+
This boilerplate provides **infrastructure**; you (or AI) provide **business logic**. The pattern is:
|
|
16
|
+
|
|
17
|
+
1. Scaffold a new project with `npx @xbg.solutions/create-backend init`
|
|
18
|
+
2. Define a declarative data model (`DataModelSpecification`)
|
|
19
|
+
3. Run the generator to scaffold Controller/Service/Repository/Entity
|
|
20
|
+
4. Register the controller in `functions/src/index.ts`
|
|
21
|
+
5. Add business logic in the service layer
|
|
22
|
+
|
|
23
|
+
The boilerplate never ships pre-built domain models (no User, Product, Order). That's intentional — AI generates those from your model spec.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Architecture: Distributable npm Packages
|
|
28
|
+
|
|
29
|
+
This boilerplate is structured as a **monorepo of publishable npm packages**, enabling update propagation to projects built on it.
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
boilerplate_backend/
|
|
33
|
+
├── packages/
|
|
34
|
+
│ ├── core/ → @xbg.solutions/backend-core
|
|
35
|
+
│ │ ├── src/
|
|
36
|
+
│ │ │ ├── base/ # BaseEntity, BaseRepository, BaseService, BaseController
|
|
37
|
+
│ │ │ ├── middleware/ # Auth, CORS, rate limiting, error handling, logging
|
|
38
|
+
│ │ │ ├── config/ # App, database, auth, cache, middleware config
|
|
39
|
+
│ │ │ ├── types/ # Custom error classes
|
|
40
|
+
│ │ │ ├── generator/ # Code generator engine
|
|
41
|
+
│ │ │ ├── templates/ # Handlebars templates for code generation
|
|
42
|
+
│ │ │ └── app.ts # Express app factory
|
|
43
|
+
│ │ └── package.json
|
|
44
|
+
│ │
|
|
45
|
+
│ ├── utils-logger/ → @xbg.solutions/utils-logger
|
|
46
|
+
│ ├── utils-events/ → @xbg.solutions/utils-events
|
|
47
|
+
│ ├── utils-errors/ → @xbg.solutions/utils-errors
|
|
48
|
+
│ ├── utils-cache-connector/ → @xbg.solutions/utils-cache-connector
|
|
49
|
+
│ ├── utils-firestore-connector/ → @xbg.solutions/utils-firestore-connector
|
|
50
|
+
│ ├── utils-hashing/ → @xbg.solutions/utils-hashing
|
|
51
|
+
│ ├── utils-token-handler/ → @xbg.solutions/utils-token-handler
|
|
52
|
+
│ ├── utils-email-connector/ → @xbg.solutions/utils-email-connector
|
|
53
|
+
│ ├── utils-sms-connector/ → @xbg.solutions/utils-sms-connector
|
|
54
|
+
│ ├── ... (20+ utility packages)
|
|
55
|
+
│ │
|
|
56
|
+
│ └── create-backend/ → @xbg.solutions/create-backend (CLI scaffolding tool)
|
|
57
|
+
│
|
|
58
|
+
├── functions/ ← Local development/testing workspace (not published)
|
|
59
|
+
│ ├── src/ # Mirrors packages structure for local dev
|
|
60
|
+
│ └── __tests__/ # Test suite
|
|
61
|
+
├── __examples__/ ← Sample DataModelSpecification files
|
|
62
|
+
├── __scripts__/ ← Project-level scripts (setup, generate, deploy, validate)
|
|
63
|
+
└── package.json ← Monorepo root (npm workspaces)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Two-Part Distribution Model
|
|
67
|
+
|
|
68
|
+
1. **npm packages** (runtime dependencies) — Base classes, middleware, config, and utilities live in `node_modules/`. Updates propagate via `npm update`. Semver protects against breaking changes.
|
|
69
|
+
|
|
70
|
+
2. **CLI scaffolding tool** (`@xbg.solutions/create-backend`) — Handles project structure, config files, scripts, and templates. Operates in init mode (new project) and sync mode (update existing).
|
|
71
|
+
|
|
72
|
+
This is the same pattern as `firebase-tools` + `firebase init`.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Architecture: Strict 3-Layer Stack
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
HTTP Request
|
|
80
|
+
↓
|
|
81
|
+
BaseController ← Route handling, request/response shaping
|
|
82
|
+
↓
|
|
83
|
+
BaseService ← Business logic, auth checks, event publishing
|
|
84
|
+
↓
|
|
85
|
+
BaseRepository ← Firestore CRUD, soft-delete, caching
|
|
86
|
+
↓
|
|
87
|
+
Firestore
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
All generated code follows this exact pattern. Never put business logic in controllers, never put Firestore calls in services.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Sub-Skills — When to Use Each
|
|
95
|
+
|
|
96
|
+
| Skill | Use when you need to... |
|
|
97
|
+
|---|---|
|
|
98
|
+
| `bpbe/setup/skill.md` | Create a new project, configure .env, understand npm scripts, validate config |
|
|
99
|
+
| `bpbe/data/skill.md` | Define entities, understand BaseEntity, use the generator, work with Firestore schemas |
|
|
100
|
+
| `bpbe/services/skill.md` | Write service methods, handle events, implement auth/access control, lifecycle hooks |
|
|
101
|
+
| `bpbe/utils/skill.md` | Use logger, PII hashing, cache, token handler, or any communication connector |
|
|
102
|
+
| `bpbe/api/skill.md` | Add routes, register controllers, use middleware, understand API response shapes |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Key Import Paths
|
|
107
|
+
|
|
108
|
+
All imports come from npm packages — no relative paths to boilerplate internals.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// Base classes (from @xbg.solutions/backend-core)
|
|
112
|
+
import { BaseEntity, ValidationHelper, ValidationResult } from '@xbg.solutions/backend-core';
|
|
113
|
+
import { BaseRepository, QueryOptions } from '@xbg.solutions/backend-core';
|
|
114
|
+
import { BaseService, RequestContext, ServiceResult } from '@xbg.solutions/backend-core';
|
|
115
|
+
import { BaseController, ApiResponse } from '@xbg.solutions/backend-core';
|
|
116
|
+
|
|
117
|
+
// App factory and config
|
|
118
|
+
import { createApp, APP_CONFIG, isFeatureEnabled } from '@xbg.solutions/backend-core';
|
|
119
|
+
|
|
120
|
+
// Middleware
|
|
121
|
+
import { createAuthMiddleware, requireRoles, requireAdmin } from '@xbg.solutions/backend-core';
|
|
122
|
+
|
|
123
|
+
// Utilities (each is a separate package)
|
|
124
|
+
import { logger } from '@xbg.solutions/utils-logger';
|
|
125
|
+
import { eventBus, EventType } from '@xbg.solutions/utils-events';
|
|
126
|
+
import { hashValue, hashFields, unhashValue } from '@xbg.solutions/utils-hashing';
|
|
127
|
+
import { getCacheConnector } from '@xbg.solutions/utils-cache-connector';
|
|
128
|
+
import { tokenHandler } from '@xbg.solutions/utils-token-handler';
|
|
129
|
+
import { emailConnector } from '@xbg.solutions/utils-email-connector';
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Tech Stack
|
|
135
|
+
|
|
136
|
+
- **Runtime:** Node.js 22+, TypeScript (strict mode)
|
|
137
|
+
- **Framework:** Express.js
|
|
138
|
+
- **Deployment:** Firebase Functions (also runs on Cloud Run, AWS Lambda, Docker)
|
|
139
|
+
- **Database:** Firestore (multi-database support)
|
|
140
|
+
- **Auth:** Firebase Auth + custom JWT token handler with blacklisting
|
|
141
|
+
- **Testing:** Jest, 796 passing tests
|
|
142
|
+
- **Caching:** Memory / Firestore / Redis (progressive, per-repository opt-in)
|
|
143
|
+
- **Events:** Internal EventEmitter-based event bus (not Pub/Sub)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Non-Obvious Decisions
|
|
148
|
+
|
|
149
|
+
- **Soft delete by default.** `BaseRepository.delete()` sets `deletedAt`; pass `hardDelete=true` for permanent. `findAll()` automatically excludes soft-deleted records.
|
|
150
|
+
- **`deletedAt === null` in Firestore queries.** The repository filters by `where('deletedAt', '==', null)` — this requires a composite index if combined with other where clauses.
|
|
151
|
+
- **Events are synchronous.** The event bus uses Node.js `EventEmitter`. It's fire-and-forget within the request lifecycle, not durable. For durable async, use Firebase Pub/Sub or queue systems.
|
|
152
|
+
- **Generated code goes in `src/generated/`.** This directory is gitignored in production projects. Treat generated files as a starting point — copy and modify in your own directories.
|
|
153
|
+
- **Config is all env-driven.** Never hardcode values in config. Feature flags via `FEATURE_*` env vars.
|