A complete CRUD API for a users collection, built with
@dharayush7/fireclass-js. It demonstrates the model definition,
typed queries, validation, and the Express error handler.
src/firebase.ts— memoized firebase-admin init (emulator-aware)src/models/user.ts— theUsermodel withclass-validatordecoratorssrc/server.ts— Express routes +fireclassErrorHandler()
# 1. Install
pnpm install
# 2. Start the Firestore emulator (needs the Firebase CLI + Java)
firebase emulators:start --only firestore
# 3. In another terminal, point the app at the emulator and start it
export FIRESTORE_EMULATOR_HOST=localhost:8080
export GCLOUD_PROJECT=fireclass-demo
pnpm dev# Create (validated) — 201
curl -X POST localhost:3000/users -H 'content-type: application/json' \
-d '{"name":"Ada Lovelace","email":"ada@example.com","age":36}'
# Create invalid — 400 with field-level details
curl -X POST localhost:3000/users -H 'content-type: application/json' \
-d '{"name":"A","email":"nope","age":-1}'
# List (optionally filter): GET /users?minAge=18
curl localhost:3000/users
curl 'localhost:3000/users?minAge=30'
# Read / update / delete
curl localhost:3000/users/<id>
curl -X PATCH localhost:3000/users/<id> -H 'content-type: application/json' -d '{"age":37}'
curl -X DELETE localhost:3000/users/<id>Two options, both handled by src/firebase.ts:
-
Drop a key in this folder. Download a service-account key from Firebase Console → Project Settings → Service accounts → Generate new private key and save it here as
serviceAccount.json. It is gitignored (serviceAccount*.json) — never commit it. Then:pnpm start # auto-detects ./serviceAccount.json -
Use ADC. Set
GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json(and optionallyGCLOUD_PROJECT=your-project-id), thenpnpm start.
The database must exist: Firebase Console → Build → Firestore Database → Create database. Otherwise you'll get
PERMISSION_DENIED: Cloud Firestore API has not been used….
GET /users?minAge=30 filters by age and therefore orders by age — because
Firestore requires the field in a range filter (>=, <, …) to be the first
orderBy. Ordering by a different field than the range filter (e.g. filter
age but order by name) needs a composite index, which Firestore will prompt
you to create via a console link in the error. See
src/server.ts for how the example picks the order field.