Skip to content

Commit c6565c9

Browse files
committed
add development doc
1 parent 4c17255 commit c6565c9

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

DEVELOPMENT.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# Development Guide
2+
3+
Local development setup for running functions against real infrastructure (Postgres, GraphQL, Mailpit).
4+
5+
## Prerequisites
6+
7+
- Node.js >= 18.17.0
8+
- pnpm >= 10
9+
- Docker Desktop
10+
11+
## Quick Start
12+
13+
```bash
14+
# 1. Generate workspace packages from function templates
15+
pnpm generate
16+
17+
# 2. Install dependencies
18+
pnpm install
19+
20+
# 3. Build everything (packages, job service, generated functions)
21+
pnpm build
22+
23+
# 4. Start infrastructure (Postgres, DB migrations, GraphQL server, Mailpit)
24+
make dev
25+
26+
# 5. Wait for db-setup to finish (watch logs)
27+
make dev-logs
28+
29+
# 6. Start functions as local Node processes
30+
make dev-fn
31+
```
32+
33+
## Step-by-Step
34+
35+
### 1. Generate + Build
36+
37+
The generate step reads `functions/*/handler.json` manifests, resolves templates from `templates/node-graphql/`, and produces full workspace packages in `generated/`.
38+
39+
```bash
40+
pnpm generate # Generate all functions
41+
pnpm install # Install dependencies (including generated packages)
42+
pnpm build # Build all workspace packages
43+
```
44+
45+
After this you should have built artifacts in:
46+
47+
| Package | Output |
48+
|---------|--------|
49+
| `generated/send-email-link/dist/` | Send-email-link function server |
50+
| `generated/simple-email/dist/` | Simple-email function server |
51+
| `generated/example/dist/` | Example function server |
52+
| `job/service/dist/` | Knative job service (worker + scheduler) |
53+
| `packages/fn-runtime/dist/` | Function runtime library |
54+
| `packages/fn-app/dist/` | Function app framework |
55+
56+
### 2. Start Infrastructure
57+
58+
```bash
59+
make dev
60+
```
61+
62+
This runs `docker compose up -d` which starts:
63+
64+
| Service | Description | Port |
65+
|---------|-------------|------|
66+
| **postgres** | PostgreSQL 16 with pgvector + PostGIS | 5432 |
67+
| **db-setup** | One-shot: creates DB, bootstraps roles, deploys pgpm packages | (exits on completion) |
68+
| **graphql-server** | Constructive admin GraphQL API (header-based routing) | 3002 |
69+
| **mailpit** | SMTP capture server with web UI | 1025 (SMTP), 8025 (UI) |
70+
71+
The `db-setup` container must finish before `graphql-server` starts (enforced by `service_completed_successfully`). Watch progress:
72+
73+
```bash
74+
make dev-logs
75+
# or
76+
docker compose logs -f db-setup
77+
```
78+
79+
Verify everything is running:
80+
81+
```bash
82+
docker compose ps
83+
```
84+
85+
You should see:
86+
- `postgres` — running (healthy)
87+
- `db-setup` — exited (0)
88+
- `graphql-server` — running
89+
- `mailpit` — running
90+
91+
### 3. Start Functions Locally
92+
93+
```bash
94+
make dev-fn
95+
```
96+
97+
This runs `scripts/dev.ts` which spawns local Node processes with env vars pointing to Docker services:
98+
99+
| Process | Port | Script |
100+
|---------|------|--------|
101+
| **job-service** | 8080 | `job/service/dist/run.js` |
102+
| **simple-email** | 8081 | `generated/simple-email/dist/index.js` |
103+
| **send-email-link** | 8082 | `generated/send-email-link/dist/index.js` |
104+
105+
To start a single function:
106+
107+
```bash
108+
pnpm dev:fn -- --only=send-email-link
109+
```
110+
111+
### 4. Test a Function
112+
113+
Send a request to `send-email-link`:
114+
115+
```bash
116+
curl -X POST http://localhost:8082 \
117+
-H 'Content-Type: application/json' \
118+
-H 'X-Database-Id: constructive' \
119+
-d '{"email_type":"invite_email","email":"test@example.com"}'
120+
```
121+
122+
Check captured emails at http://localhost:8025 (Mailpit UI).
123+
124+
Query the GraphQL API directly:
125+
126+
```bash
127+
curl http://localhost:3002/graphql \
128+
-H 'Content-Type: application/json' \
129+
-H 'X-Database-Id: constructive' \
130+
-d '{"query":"{ __typename }"}'
131+
```
132+
133+
### 5. Shut Down
134+
135+
```bash
136+
make dev-down # Stop Docker infrastructure
137+
```
138+
139+
`Ctrl+C` in the `make dev-fn` terminal stops the local function processes.
140+
141+
## Commands Reference
142+
143+
| Command | Description |
144+
|---------|-------------|
145+
| `pnpm generate` | Generate workspace packages from function templates |
146+
| `pnpm build` | Build all workspace packages |
147+
| `make dev` | Start Docker infrastructure |
148+
| `make dev-fn` | Start functions as local Node processes |
149+
| `make dev-down` | Stop Docker infrastructure |
150+
| `make dev-logs` | Follow Docker service logs |
151+
| `pnpm test` | Run all tests |
152+
| `pnpm test:unit` | Run unit tests only (`functions/*/__tests__/`) |
153+
| `pnpm test:integration` | Run integration tests only (`tests/integration/`) |
154+
155+
## Port Map
156+
157+
| Service | Port |
158+
|---------|------|
159+
| PostgreSQL | 5432 |
160+
| GraphQL API | 3002 |
161+
| Mailpit SMTP | 1025 |
162+
| Mailpit UI | 8025 |
163+
| Job Service | 8080 |
164+
| simple-email | 8081 |
165+
| send-email-link | 8082 |
166+
167+
## Architecture
168+
169+
```
170+
Docker Compose (infrastructure):
171+
postgres -> db-setup (migrations) -> graphql-server
172+
mailpit
173+
174+
Local Node processes (functions):
175+
job/service/dist/run.js (port 8080)
176+
generated/simple-email/dist/index.js (port 8081)
177+
generated/send-email-link/dist/index.js (port 8082)
178+
```
179+
180+
Infrastructure runs in Docker. Functions run as local Node processes from `generated/` — no Docker rebuild needed when function code changes. Edit `functions/*/handler.ts`, rebuild (`pnpm build`), restart `make dev-fn`.
181+
182+
## Troubleshooting
183+
184+
**db-setup fails or graphql-server won't start**
185+
186+
Check if the GHCR image is accessible:
187+
188+
```bash
189+
docker pull ghcr.io/constructive-io/constructive:latest
190+
```
191+
192+
If authentication is required, log in first:
193+
194+
```bash
195+
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
196+
```
197+
198+
**Port already in use**
199+
200+
Stop any existing services using the ports:
201+
202+
```bash
203+
make dev-down
204+
lsof -ti:5432,3002,1025,8025,8080,8081,8082 | xargs kill -9
205+
```
206+
207+
**Functions can't connect to GraphQL**
208+
209+
Ensure infrastructure is fully up before starting functions:
210+
211+
```bash
212+
docker compose ps # db-setup should show "Exited (0)", graphql-server should be "running"
213+
curl http://localhost:3002/graphql -H 'Content-Type: application/json' -d '{"query":"{ __typename }"}'
214+
```
215+
216+
**Stale build artifacts**
217+
218+
Clean and rebuild from scratch:
219+
220+
```bash
221+
pnpm clean
222+
pnpm generate
223+
pnpm install
224+
pnpm build
225+
```

0 commit comments

Comments
 (0)