Skip to content

Commit b5d25cd

Browse files
committed
Migrate from Hono to SvelteKit
- Convert all API routes to SvelteKit file-based routing - Move services, types, and utils under src/lib/ - Add SvelteKit hooks for auth and validation - Add standalone Bun server (server.ts) and Dockerfile - Replace Hono middleware with SvelteKit hooks.server.ts - Add GitHub OAuth ON CONFLICT upsert for existing users - Disable CSRF origin check for cross-origin API usage
1 parent 37744e4 commit b5d25cd

149 files changed

Lines changed: 3537 additions & 3222 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ node_modules
44
# output
55
out
66
dist
7+
build
78
*.tgz
89

10+
# SvelteKit
11+
.svelte-kit
12+
913
# code coverage
1014
coverage
1115
*.lcov

DEPLOY.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Deploy
2+
3+
## Infrastructure setup (from scratch)
4+
5+
All infrastructure operations use the CLI with a **DB alias** (direct PostgreSQL access).
6+
7+
### 1. Configure CLI alias
8+
9+
```bash
10+
ow alias set infra --db postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost/$POSTGRES_DB
11+
```
12+
13+
### 2. Run migrations
14+
15+
```bash
16+
ow infra migrate status
17+
ow infra migrate run
18+
```
19+
20+
### 3. Claim the system user
21+
22+
The system user (`00000000-...`) owns shared resources (the API database config, etc.). Claim it with your username:
23+
24+
```bash
25+
ow infra users create your-username --system
26+
ow alias set infra --db postgres://... --user your-username --force
27+
```
28+
29+
### 4. Configure platform storage
30+
31+
Required for worker uploads (assets are stored in S3/R2):
32+
33+
```bash
34+
ow infra setup-storage \
35+
--endpoint https://xxx.r2.cloudflarestorage.com \
36+
--bucket my-bucket \
37+
--access-key-id AKIA... \
38+
--secret-access-key ...
39+
```
40+
41+
### 5. Deploy the API
42+
43+
```bash
44+
# Create environment, worker, and link them
45+
ow infra env create openworkers-api-env
46+
ow infra worker create openworkers-api
47+
ow infra worker link openworkers-api openworkers-api-env
48+
49+
# Bind the database (migration 15 creates 'openworkers-api' database config)
50+
ow infra env bind openworkers-api-env DATABASE openworkers-api --type database
51+
52+
# Bind assets storage (for SvelteKit client files)
53+
ow infra storage create openworkers-api-storage
54+
ow infra env bind openworkers-api-env ASSETS openworkers-api-storage --type assets
55+
56+
# Set variables and secrets
57+
ow infra env set openworkers-api-env APP_URL https://dash.example.com
58+
ow infra env set openworkers-api-env JWT_ACCESS_SECRET --secret
59+
ow infra env set openworkers-api-env JWT_REFRESH_SECRET --secret
60+
# ... (see environment variables table below)
61+
62+
# Build and upload
63+
cd openworkers-api
64+
bun install && bun run build
65+
ow infra worker upload openworkers-api ./build
66+
```
67+
68+
### 6. Deploy the dashboard
69+
70+
```bash
71+
cd openworkers-dash
72+
bun install && bun run deploy:prepare
73+
74+
ow infra worker create openworkers-dash
75+
ow infra storage create openworkers-dash-storage
76+
ow infra env create openworkers-dash-env
77+
ow infra env bind openworkers-dash-env ASSETS openworkers-dash-storage --type assets
78+
ow infra worker link openworkers-dash openworkers-dash-env
79+
ow infra worker upload openworkers-dash ./dist/openworkers
80+
```
81+
82+
## Worker mode (subsequent deploys)
83+
84+
Build then upload as a worker:
85+
86+
```bash
87+
bun run build
88+
ow <space> worker upload openworkers-api ./build
89+
```
90+
91+
Where `<space>` is the target namespace (`dev`, `infra`, `main`, `ps`, ...).
92+
93+
Create the environment **before** the first upload so the project inherits it automatically. If the worker was already uploaded without an environment, `worker link` will cascade it to the project and all function workers.
94+
95+
### Environment variables
96+
97+
Secrets are prompted interactively (masked input) when value is omitted:
98+
99+
```bash
100+
# Variables (plain text)
101+
ow <space> env set openworkers-api-env APP_URL https://dash.example.com
102+
103+
# Secrets (prompted interactively, not stored in shell history)
104+
ow <space> env set openworkers-api-env JWT_ACCESS_SECRET --secret
105+
```
106+
107+
| Variable | Type | Required | Description |
108+
| ---------------------------------- | ------- | -------- | -------------------------------------- |
109+
| `DATABASE` | binding | yes | Database binding (type: database) |
110+
| `APP_URL` | var | yes | Dashboard URL (for OAuth redirects) |
111+
| `JWT_ACCESS_SECRET` | secret | yes | JWT signing secret (>= 32 chars) |
112+
| `JWT_REFRESH_SECRET` | secret | yes | JWT refresh token secret (>= 32 chars) |
113+
| `GITHUB_CLIENT_ID` | secret | no | GitHub OAuth app client ID |
114+
| `GITHUB_CLIENT_SECRET` | secret | no | GitHub OAuth app client secret |
115+
| `MISTRAL_API_KEY` | secret | no | Mistral AI API key |
116+
| `ANTHROPIC_API_KEY` | secret | no | Anthropic API key |
117+
| `SHARED_STORAGE_BUCKET` | secret | no | S3 bucket name |
118+
| `SHARED_STORAGE_ENDPOINT` | secret | no | S3 endpoint URL |
119+
| `SHARED_STORAGE_ACCESS_KEY_ID` | secret | no | S3 access key |
120+
| `SHARED_STORAGE_SECRET_ACCESS_KEY` | secret | no | S3 secret key |
121+
| `SHARED_STORAGE_PUBLIC_URL` | var | no | S3 public URL |
122+
| `EMAIL_PROVIDER` | var | no | Email provider (e.g. `scaleway`) |
123+
| `EMAIL_FROM` | var | no | Sender email address |
124+
| `SCW_SECRET_KEY` | secret | no | Scaleway secret key |
125+
| `SCW_PROJECT_ID` | secret | no | Scaleway project ID |
126+
| `SCW_REGION` | var | no | Scaleway region |
127+
128+
Note: `POSTGATE_URL` and `POSTGATE_TOKEN` are only needed when running outside OpenWorkers (Docker mode). In worker mode, the `DATABASE` binding provides direct database access.
129+
130+
## Docker mode
131+
132+
```bash
133+
docker build -t openworkers-api .
134+
docker run -p 7000:7000 --env-file .env openworkers-api
135+
```
136+
137+
Or without Docker:
138+
139+
```bash
140+
bun run build
141+
bun start
142+
```
143+
144+
The server listens on `PORT` (default `7000`).
145+
146+
In Docker mode, set `POSTGATE_URL` and `POSTGATE_TOKEN` in `.env` instead of the `DB` binding.
147+
148+
## Managing projects
149+
150+
Workers that are uploaded with multiple routes/functions are automatically promoted to **projects**. Projects group related workers.
151+
152+
```bash
153+
ow <space> projects list # List all projects
154+
ow <space> projects delete my-app # Delete project and all its workers
155+
```
156+
157+
To delete a worker that belongs to a project, delete the project instead:
158+
159+
```bash
160+
# This fails:
161+
ow <space> worker delete my-app
162+
# → "Cannot delete main worker - delete the project instead"
163+
164+
# Do this instead:
165+
ow <space> projects delete my-app
166+
```

Dockerfile

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM oven/bun:1.3.3-alpine AS installer
1+
FROM oven/bun:1-alpine AS installer
22

33
RUN mkdir -p /build
44

@@ -16,27 +16,28 @@ FROM installer AS sources
1616

1717
## Copy sources
1818
COPY src /build/src
19+
COPY static /build/static
1920
COPY examples /build/examples
20-
COPY tsconfig.json /build/tsconfig.json
21-
COPY server.ts /build
21+
COPY svelte.config.ts /build/
22+
COPY vite.config.ts /build/
23+
COPY tsconfig.json /build/
24+
COPY server.ts /build/
2225

2326
# Builder Image
2427
FROM sources AS builder
2528

2629
WORKDIR /build
27-
RUN bun compile
30+
RUN bun run build
2831

2932
# Final image
30-
FROM alpine:3.22
31-
32-
# Bun runtime dependencies
33-
RUN apk add --no-cache libstdc++ libgcc
33+
FROM oven/bun:1-alpine
3434

3535
WORKDIR /build
3636

37-
COPY --from=builder /build/dist /build/dist
38-
COPY --from=builder /build/node_modules/@openworkers/croner-wasm/dist/node node_modules/@openworkers/croner-wasm/dist/node
37+
COPY --from=builder /build/.svelte-kit/output/server .svelte-kit/output/server
38+
COPY --from=builder /build/node_modules node_modules
39+
COPY --from=builder /build/server.ts .
3940

4041
EXPOSE 7000
4142

42-
CMD [ "./dist/openworkers-api" ]
43+
CMD ["bun", "server.ts"]

README.md

Lines changed: 24 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,44 @@
1-
# OpenWorkers API (Hono + Bun)
1+
# OpenWorkers API
22

3-
Lightweight REST API for OpenWorkers platform using Hono framework and Bun runtime.
3+
REST API for the OpenWorkers platform, built with SvelteKit and deployed as a worker on OpenWorkers itself.
44

55
## Features
66

7-
- **Hono** - Ultra-fast web framework
7+
- **SvelteKit** - File-based routing (`src/routes/api/...`)
88
- **Postgate** - HTTP-based PostgreSQL access via [postgate](https://github.com/openworkers/postgate)
99
- **Zod validation** - Type-safe input/output validation
10-
- **Pure REST** - No GraphQL complexity
11-
- **JWT auth** - Using `hono/jwt`
12-
- **Standalone binary** - Compile to single executable
13-
14-
## Structure
15-
16-
```
17-
src/
18-
├── services/
19-
│ ├── db/
20-
│ │ ├── sql-client.ts - Postgate SQL client (named params support)
21-
│ │ ├── users.ts - User DB queries
22-
│ │ ├── workers.ts - Worker DB queries
23-
│ │ ├── crons.ts - Cron DB queries
24-
│ │ ├── databases.ts - Database DB queries
25-
│ │ ├── environments.ts - Environment DB queries
26-
│ │ └── domains.ts - Domain DB queries
27-
│ ├── postgate.ts - Postgate HTTP client
28-
│ ├── auth.ts - Authentication logic
29-
│ ├── workers.ts - Workers business logic
30-
│ ├── crons.ts - Crons business logic
31-
│ ├── databases.ts - Databases business logic
32-
│ ├── environments.ts - Environments business logic
33-
│ └── domains.ts - Domains business logic
34-
├── routes/
35-
│ ├── auth.ts - Auth endpoints
36-
│ ├── users.ts - User endpoints
37-
│ ├── workers.ts - Workers endpoints
38-
│ ├── crons.ts - Crons endpoints
39-
│ ├── databases.ts - Databases endpoints
40-
│ ├── environments.ts - Environments endpoints
41-
│ └── domains.ts - Domains endpoints
42-
├── middlewares/
43-
│ └── auth.ts - JWT middleware
44-
├── types/
45-
│ ├── schemas/ - Zod validation schemas
46-
│ ├── validators.ts - Schema validators
47-
│ └── index.ts - Type exports
48-
├── utils/
49-
│ └── validate.ts - Response validation helpers
50-
├── config/
51-
│ └── index.ts - Configuration
52-
└── index.ts - Main app
53-
```
10+
- **JWT auth** - Authentication middleware in `hooks.server.ts`
5411

5512
## Quick Start
5613

5714
```bash
58-
# Install dependencies
5915
bun install
60-
61-
# Create .env from example
6216
cp .env.example .env
63-
# Edit .env with your Postgate URL/tokens and JWT secrets
64-
65-
# Run development server (hot reload)
6617
bun run dev
18+
```
6719

68-
# Production (run with Bun)
69-
bun run start
20+
## Build & Deploy
7021

71-
# Compile standalone binary
72-
bun run compile
73-
# → Creates dist/openworkers-api (executable)
22+
```bash
23+
bun run build
7424
```
7525

26+
The build **must** run with `NODE_ENV=production` (already set in the build script).
27+
This is required because SvelteKit and Svelte use `esm-env` to gate Node.js-specific
28+
code behind `if (DEV)` blocks (`node:path`, `node:process` imports for stack trace
29+
formatting). Without production mode, these imports leak into the bundle and cause
30+
`SyntaxError` in the OpenWorkers runtime which supports neither `node:*` builtins
31+
nor dynamic `import()`.
32+
33+
## Docker
34+
35+
```bash
36+
docker build -t openworkers-api .
37+
docker run -p 7000:7000 --env-file .env openworkers-api
38+
```
39+
40+
Or use `bun run build && bun start` to run locally without Docker.
41+
7642
## API Endpoints
7743

7844
### Auth (Public)
@@ -156,4 +122,3 @@ console.log(users[0], users.count);
156122
- SQL validation and injection prevention
157123
- Token-based access control per database
158124
- Same API works from workers (OpenWorkers runtime)
159-

0 commit comments

Comments
 (0)