@evolu/relay 1.1.2-preview.0
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/.dockerignore +16 -0
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +1172 -0
- package/Dockerfile +66 -0
- package/LICENSE +21 -0
- package/README.docker.md +154 -0
- package/README.md +91 -0
- package/data/.gitkeep +2 -0
- package/dist/package.json +41 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +42 -0
- package/dist/src/logger.d.ts +2 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +4 -0
- package/dist/src/nodejs.d.ts +3 -0
- package/dist/src/nodejs.d.ts.map +1 -0
- package/dist/src/nodejs.js +24 -0
- package/dist/src/params.d.ts +7 -0
- package/dist/src/params.d.ts.map +1 -0
- package/dist/src/params.js +6 -0
- package/docker-compose.yml +56 -0
- package/package.json +41 -0
- package/src/cli.ts +59 -0
- package/src/logger.ts +5 -0
- package/src/nodejs.ts +30 -0
- package/src/params.ts +9 -0
- package/tsconfig.json +10 -0
package/Dockerfile
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
FROM node:22-alpine AS base
|
|
2
|
+
ENV PNPM_HOME="/pnpm"
|
|
3
|
+
ENV PATH="$PNPM_HOME:$PATH"
|
|
4
|
+
|
|
5
|
+
FROM base AS builder
|
|
6
|
+
RUN apk update && apk add --no-cache libc6-compat
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
RUN corepack enable pnpm
|
|
9
|
+
RUN pnpm install -g turbo
|
|
10
|
+
COPY . .
|
|
11
|
+
|
|
12
|
+
# Generate a partial monorepo with a pruned lockfile for the relay workspace
|
|
13
|
+
RUN turbo prune @evolu/relay --docker
|
|
14
|
+
|
|
15
|
+
# ------------------------------------------------------------
|
|
16
|
+
# Installer stage - build the pruned workspace
|
|
17
|
+
FROM base AS installer
|
|
18
|
+
RUN apk update && apk add --no-cache libc6-compat
|
|
19
|
+
WORKDIR /app
|
|
20
|
+
|
|
21
|
+
# Install pnpm and turbo
|
|
22
|
+
RUN corepack enable pnpm
|
|
23
|
+
RUN pnpm install -g turbo
|
|
24
|
+
|
|
25
|
+
# Install dependencies from pruned lockfile
|
|
26
|
+
COPY --from=builder /app/out/json/ .
|
|
27
|
+
RUN pnpm install --frozen-lockfile
|
|
28
|
+
|
|
29
|
+
# Copy source and build
|
|
30
|
+
COPY --from=builder /app/out/full/ .
|
|
31
|
+
# Ensure README.md is available at the root for the build process
|
|
32
|
+
COPY --from=builder /app/README.md ./README.md
|
|
33
|
+
RUN turbo run build
|
|
34
|
+
|
|
35
|
+
# ------------------------------------------------------------
|
|
36
|
+
# Runner stage - minimal runtime image
|
|
37
|
+
FROM base AS runner
|
|
38
|
+
WORKDIR /app
|
|
39
|
+
|
|
40
|
+
# Create non-root user
|
|
41
|
+
RUN addgroup --system --gid 1001 nodejs && \
|
|
42
|
+
adduser --system --uid 1001 evolu --ingroup nodejs
|
|
43
|
+
RUN chown evolu:nodejs /app
|
|
44
|
+
USER evolu
|
|
45
|
+
|
|
46
|
+
# Copy built application
|
|
47
|
+
COPY --from=installer --chown=evolu:nodejs /app/apps/relay/dist ./dist
|
|
48
|
+
|
|
49
|
+
# Copy the complete node_modules with all dependencies
|
|
50
|
+
COPY --from=installer --chown=evolu:nodejs /app/node_modules ./node_modules
|
|
51
|
+
|
|
52
|
+
# Copy the built workspace packages that the relay needs at runtime
|
|
53
|
+
COPY --from=installer --chown=evolu:nodejs /app/packages/common/dist ./node_modules/@evolu/common/dist
|
|
54
|
+
COPY --from=installer --chown=evolu:nodejs /app/packages/common/package.json ./node_modules/@evolu/common/package.json
|
|
55
|
+
COPY --from=installer --chown=evolu:nodejs /app/packages/nodejs/dist ./node_modules/@evolu/nodejs/dist
|
|
56
|
+
COPY --from=installer --chown=evolu:nodejs /app/packages/nodejs/package.json ./node_modules/@evolu/nodejs/package.json
|
|
57
|
+
|
|
58
|
+
# Expose port
|
|
59
|
+
EXPOSE 4000
|
|
60
|
+
|
|
61
|
+
# Health check
|
|
62
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
63
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:4000 || exit 1
|
|
64
|
+
|
|
65
|
+
# Start the application
|
|
66
|
+
CMD ["node", "dist/index.js"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Evolu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.docker.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Evolu Relay - Docker Setup
|
|
2
|
+
|
|
3
|
+
Docker configuration for the Evolu Relay.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start for Developers
|
|
6
|
+
|
|
7
|
+
**Just one command to get started:**
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd apps/relay
|
|
11
|
+
pnpm docker:up
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
That's it! This will:
|
|
15
|
+
|
|
16
|
+
- ✅ Automatically build the Docker image
|
|
17
|
+
- ✅ Start the Evolu Relay service
|
|
18
|
+
- ✅ Show real-time logs
|
|
19
|
+
- ✅ Make the service available at `http://localhost:4000`
|
|
20
|
+
|
|
21
|
+
Press `Ctrl+C` to stop the service.
|
|
22
|
+
|
|
23
|
+
### Background Mode (Optional)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
cd apps/relay
|
|
27
|
+
|
|
28
|
+
# Start in background
|
|
29
|
+
pnpm docker:up:detached
|
|
30
|
+
|
|
31
|
+
# View logs when needed
|
|
32
|
+
pnpm docker:logs
|
|
33
|
+
|
|
34
|
+
# Stop when done
|
|
35
|
+
pnpm docker:down
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 🔧 Advanced Usage
|
|
39
|
+
|
|
40
|
+
### All Available Commands
|
|
41
|
+
|
|
42
|
+
| Command | Description | Auto-builds? | Persistence |
|
|
43
|
+
| ------------------------- | ---------------------------------------------- | ------------ | ------------ |
|
|
44
|
+
| `pnpm docker:up` | **Recommended**: Start in foreground with logs | ✅ Yes | Named volume |
|
|
45
|
+
| `pnpm docker:up:detached` | Start in background | ✅ Yes | Named volume |
|
|
46
|
+
| `pnpm docker:down` | Stop services | N/A | N/A |
|
|
47
|
+
| `pnpm docker:restart` | Restart with rebuild | ✅ Yes | Named volume |
|
|
48
|
+
| `pnpm docker:logs` | View logs (live) | N/A | N/A |
|
|
49
|
+
| `pnpm docker:shell` | Access running container shell | N/A | N/A |
|
|
50
|
+
| `pnpm docker:stats` | View container resource usage | N/A | N/A |
|
|
51
|
+
| `pnpm docker:inspect` | View container details | N/A | N/A |
|
|
52
|
+
| `pnpm docker:build` | Build image only | N/A | N/A |
|
|
53
|
+
| `pnpm docker:clean` | Clean up containers and images | N/A | N/A |
|
|
54
|
+
| `pnpm docker:clean:all` | **Full cleanup**: Remove everything | N/A | N/A |
|
|
55
|
+
|
|
56
|
+
### Manual Docker Commands (Alternative)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Build manually
|
|
60
|
+
docker-compose build
|
|
61
|
+
|
|
62
|
+
# Run with Docker Compose
|
|
63
|
+
docker-compose up --build
|
|
64
|
+
|
|
65
|
+
# Run directly with Docker
|
|
66
|
+
docker run -p 4000:4000 evolu/relay:latest
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## ❓ FAQ
|
|
70
|
+
|
|
71
|
+
**Q: Do I need to build the image first?**
|
|
72
|
+
A: No! `pnpm docker:up` automatically builds and starts everything.
|
|
73
|
+
|
|
74
|
+
**Q: How do I update after code changes?**
|
|
75
|
+
A: Just run `pnpm docker:restart` or stop and start again.
|
|
76
|
+
|
|
77
|
+
**Q: How do I know if it's working?**
|
|
78
|
+
A: Check `http://localhost:4000` - you should get a "426 Upgrade Required" response (this is correct for WebSocket servers).
|
|
79
|
+
|
|
80
|
+
**Q: How do I see what's happening?**
|
|
81
|
+
A: Use `pnpm docker:logs` to view live logs.
|
|
82
|
+
|
|
83
|
+
**Q: How do I access the container?**
|
|
84
|
+
A: Use `pnpm docker:shell` to get shell access inside the running container.
|
|
85
|
+
|
|
86
|
+
**Q: How do I clean up everything?**
|
|
87
|
+
A: Run `pnpm docker:clean:all` to remove all containers, images, and networks.
|
|
88
|
+
|
|
89
|
+
## 📁 Docker Files
|
|
90
|
+
|
|
91
|
+
- `Dockerfile` - Multi-stage Docker build configuration
|
|
92
|
+
- `docker-compose.yml` - Docker Compose configuration with health checks
|
|
93
|
+
- `.dockerignore` - Files to exclude from Docker build context
|
|
94
|
+
|
|
95
|
+
## ⚙️ Configuration
|
|
96
|
+
|
|
97
|
+
- **Port**: 4000 (modify in `docker-compose.yml` if needed)
|
|
98
|
+
- **Environment**: `NODE_ENV=production` in Docker
|
|
99
|
+
- **Health Check**: Built-in health monitoring via Docker Compose
|
|
100
|
+
- **Data Persistence**: SQLite database automatically persists via Docker volumes
|
|
101
|
+
|
|
102
|
+
### Container Details
|
|
103
|
+
|
|
104
|
+
| Component | Value | Description |
|
|
105
|
+
| ------------------ | --------------------- | ---------------------------------- |
|
|
106
|
+
| **Container Name** | `evolu-relay-server` | Easy identification |
|
|
107
|
+
| **Image Name** | `evolu/relay:latest` | Tagged for production deployment |
|
|
108
|
+
| **Network** | `evolu-relay-network` | Isolated Docker network |
|
|
109
|
+
| **Volume** | `evolu-relay-data` | Persistent SQLite database storage |
|
|
110
|
+
| **User** | `evolu:nodejs` (1001) | Non-root user for security |
|
|
111
|
+
| **Memory Limit** | 1GB | Resource constraint |
|
|
112
|
+
| **CPU Limit** | 1.0 | CPU resource constraint |
|
|
113
|
+
|
|
114
|
+
## 🚨 Troubleshooting
|
|
115
|
+
|
|
116
|
+
| Issue | Solution |
|
|
117
|
+
| ------------------------ | ---------------------------------------------------------- |
|
|
118
|
+
| Build fails | Run `pnpm docker:clean:all` and try again |
|
|
119
|
+
| Port already in use | Change port in `docker-compose.yml` or stop other services |
|
|
120
|
+
| Container won't start | Check logs with `pnpm docker:logs` |
|
|
121
|
+
| Need container access | Use `pnpm docker:shell` for interactive shell |
|
|
122
|
+
| Performance issues | Check resources with `pnpm docker:stats` |
|
|
123
|
+
| Need to reset everything | Run `pnpm docker:clean:all` |
|
|
124
|
+
|
|
125
|
+
## 🔍 Monitoring & Debugging
|
|
126
|
+
|
|
127
|
+
### Real-time Monitoring
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# View live logs
|
|
131
|
+
pnpm docker:logs
|
|
132
|
+
|
|
133
|
+
# Monitor resource usage
|
|
134
|
+
pnpm docker:stats
|
|
135
|
+
|
|
136
|
+
# Container details
|
|
137
|
+
pnpm docker:inspect
|
|
138
|
+
|
|
139
|
+
# Access container shell
|
|
140
|
+
pnpm docker:shell
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Inside Container Commands
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Access container
|
|
147
|
+
pnpm docker:shell
|
|
148
|
+
|
|
149
|
+
# Then inside container:
|
|
150
|
+
ls -la /app/apps/relay/data/ # View database files
|
|
151
|
+
ps aux # Check running processes
|
|
152
|
+
top # Monitor resource usage
|
|
153
|
+
netstat -tlnp # Check port bindings
|
|
154
|
+
```
|
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Evolu Relay
|
|
2
|
+
|
|
3
|
+
A WebSocket relay server for the Evolu database system that enables real-time synchronization between clients.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start
|
|
6
|
+
|
|
7
|
+
### Docker Development (Recommended)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd apps/relay
|
|
11
|
+
pnpm docker:up
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Production Deployment
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Complete server setup + deployment
|
|
18
|
+
pnpm deploy:full
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The relay will be available at `http://localhost:4000` (Docker) or your server's IP:4000 (production)
|
|
22
|
+
|
|
23
|
+
## 📖 Documentation
|
|
24
|
+
|
|
25
|
+
- **[Docker Setup](./README.docker.md)** - Complete Docker containerization guide
|
|
26
|
+
|
|
27
|
+
## 🔧 Development
|
|
28
|
+
|
|
29
|
+
### Local Development (Node.js)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pnpm dev # Start with file watching
|
|
33
|
+
pnpm build # Build TypeScript
|
|
34
|
+
pnpm start # Start built application
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Docker Development
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm docker:up # Start with logs
|
|
41
|
+
pnpm docker:up:detached # Start in background
|
|
42
|
+
pnpm docker:down # Stop containers
|
|
43
|
+
pnpm docker:logs # View logs
|
|
44
|
+
pnpm docker:shell # Access container shell
|
|
45
|
+
pnpm docker:clean # Clean up everything
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 🛠️ Available Commands
|
|
49
|
+
|
|
50
|
+
### Development
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
| ------------ | ------------------------------------------- |
|
|
54
|
+
| `pnpm dev` | Start development server with file watching |
|
|
55
|
+
| `pnpm build` | Build TypeScript to JavaScript |
|
|
56
|
+
| `pnpm start` | Start the built application |
|
|
57
|
+
| `pnpm clean` | Clean build artifacts |
|
|
58
|
+
|
|
59
|
+
### Docker
|
|
60
|
+
|
|
61
|
+
| Command | Description |
|
|
62
|
+
| ------------------------- | ------------------------------------ |
|
|
63
|
+
| `pnpm docker:up` | Build and start containers with logs |
|
|
64
|
+
| `pnpm docker:up:detached` | Start containers in background |
|
|
65
|
+
| `pnpm docker:down` | Stop all containers |
|
|
66
|
+
| `pnpm docker:restart` | Restart containers with rebuild |
|
|
67
|
+
| `pnpm docker:logs` | View container logs |
|
|
68
|
+
| `pnpm docker:shell` | Access running container shell |
|
|
69
|
+
| `pnpm docker:stats` | View container resource usage |
|
|
70
|
+
| `pnpm docker:clean` | Remove containers and cleanup |
|
|
71
|
+
|
|
72
|
+
## 📋 Requirements
|
|
73
|
+
|
|
74
|
+
- **Node.js** ≥22.0.0
|
|
75
|
+
- **Docker** (for containerized development/deployment)
|
|
76
|
+
- **pnpm** (workspace package manager)
|
|
77
|
+
|
|
78
|
+
## 🔗 Integration
|
|
79
|
+
|
|
80
|
+
After deployment, your Evolu applications can connect to the relay:
|
|
81
|
+
|
|
82
|
+
**Development**: `ws://localhost:4000`
|
|
83
|
+
**Production**: `ws://your-server-ip:4000`
|
|
84
|
+
|
|
85
|
+
The relay handles WebSocket connections and data synchronization across all connected Evolu applications.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
📚 **Quick Links**:
|
|
90
|
+
|
|
91
|
+
- [Docker Setup Guide](./README.docker.md) - Local development and testing
|
package/data/.gitkeep
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@evolu/relay",
|
|
3
|
+
"version": "1.1.2-preview.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"@evolu/relay": "dist/src/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "tsx --watch src/cli.ts -- start",
|
|
10
|
+
"build": "shx rm -rf dist && tsc",
|
|
11
|
+
"start": "node dist/src/cli.js",
|
|
12
|
+
"clean": "shx rm -rf .turbo node_modules dist db.sqlite",
|
|
13
|
+
"docker:build": "docker-compose build --no-cache",
|
|
14
|
+
"docker:up": "docker-compose up --build",
|
|
15
|
+
"docker:up:detached": "docker-compose up -d --build",
|
|
16
|
+
"docker:down": "docker-compose down",
|
|
17
|
+
"docker:restart": "docker-compose down && docker-compose up --build",
|
|
18
|
+
"docker:logs": "docker-compose logs -f evolu-relay",
|
|
19
|
+
"docker:shell": "docker exec -it evolu-relay-server sh",
|
|
20
|
+
"docker:inspect": "docker inspect evolu-relay-server",
|
|
21
|
+
"docker:stats": "docker stats evolu-relay-server",
|
|
22
|
+
"docker:clean": "docker-compose down -v && docker system prune -f",
|
|
23
|
+
"docker:clean:all": "docker-compose down -v && docker system prune -af && docker volume prune -f"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@evolu/common": "workspace:*",
|
|
27
|
+
"@evolu/nodejs": "workspace:*",
|
|
28
|
+
"commander": "^14.0.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@evolu/tsconfig": "workspace:*",
|
|
32
|
+
"@types/node": "^22.17.1",
|
|
33
|
+
"typescript": "^5.9.2"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22.0.0"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/src/cli.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
import { startNodeJsRelay } from "./nodejs.js";
|
|
5
|
+
import { cliParams } from "./params.js";
|
|
6
|
+
function main() {
|
|
7
|
+
const program = new Command()
|
|
8
|
+
.name("@evolu/relay")
|
|
9
|
+
.description("Evolu Relay server")
|
|
10
|
+
.version(packageJson.version || "1.0.0", "-v, --version", "display the version number");
|
|
11
|
+
program
|
|
12
|
+
.command("start")
|
|
13
|
+
.description("start the relay server")
|
|
14
|
+
.addOption(new Option("-n, --name <name>", "database name").default("evolu-relay"))
|
|
15
|
+
.addOption(new Option("-l, --enable-logging", "enable logging").default(false))
|
|
16
|
+
.addOption(new Option("-p, --port <number>", "port to listen on")
|
|
17
|
+
.default(4000)
|
|
18
|
+
.argParser(Number))
|
|
19
|
+
.addOption(new Option("-m, --in-memory", "enable in-memory mode").default(false))
|
|
20
|
+
// .addOption(
|
|
21
|
+
// new Option("--platform <platform>", "platform")
|
|
22
|
+
// .choices(["nodejs", "bun"])
|
|
23
|
+
// .default("nodejs"),
|
|
24
|
+
// )
|
|
25
|
+
.action(async (options) => {
|
|
26
|
+
logger.enabled = true;
|
|
27
|
+
const params = cliParams.fromUnknown(options);
|
|
28
|
+
if (!params.ok) {
|
|
29
|
+
logger.error(params.error.reason);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
await startNodeJsRelay(params.value);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger.error(error);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
program.parse();
|
|
41
|
+
}
|
|
42
|
+
main();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,iCAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodejs.d.ts","sourceRoot":"","sources":["../../src/nodejs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBxE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createNodeJsRelay } from "@evolu/nodejs";
|
|
2
|
+
import { mkdirSync } from "fs";
|
|
3
|
+
import { once } from "node:events";
|
|
4
|
+
import { logger } from "./logger.js";
|
|
5
|
+
export async function startNodeJsRelay(options) {
|
|
6
|
+
// Ensure the database is created in a predictable location for Docker.
|
|
7
|
+
mkdirSync("data", { recursive: true });
|
|
8
|
+
process.chdir("data");
|
|
9
|
+
if (options.enableLogging) {
|
|
10
|
+
logger.enabled = true;
|
|
11
|
+
}
|
|
12
|
+
const relay = await createNodeJsRelay({ console: logger })({
|
|
13
|
+
port: options.port,
|
|
14
|
+
enableLogging: options.enableLogging,
|
|
15
|
+
name: options.name,
|
|
16
|
+
});
|
|
17
|
+
await Promise.race([
|
|
18
|
+
once(process, "SIGINT"), // Ctrl-C
|
|
19
|
+
once(process, "SIGTERM"), // OS/k8s/etc requested termination
|
|
20
|
+
]);
|
|
21
|
+
logger.enabled = true;
|
|
22
|
+
logger.log("Shutting down relay server");
|
|
23
|
+
relay[Symbol.dispose]();
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const cliParams: import("@evolu/common").ObjectType<{
|
|
2
|
+
name: import("@evolu/common").BrandType<import("@evolu/common").Type<"String", string, string, import("@evolu/common").StringError, string, import("@evolu/common").StringError>, "SimpleName", import("@evolu/common").RegexError<"SimpleName">, import("@evolu/common").StringError>;
|
|
3
|
+
enableLogging: import("@evolu/common").Type<"Boolean", boolean, boolean, import("@evolu/common").BooleanError, boolean, import("@evolu/common").BooleanError>;
|
|
4
|
+
port: import("@evolu/common").Type<"Number", number, number, import("@evolu/common").NumberError, number, import("@evolu/common").NumberError>;
|
|
5
|
+
}>;
|
|
6
|
+
export type CliParams = typeof cliParams.Type;
|
|
7
|
+
//# sourceMappingURL=params.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/params.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;;;;EAIpB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
services:
|
|
2
|
+
evolu-relay:
|
|
3
|
+
container_name: evolu-relay-server
|
|
4
|
+
image: evolu/relay:latest
|
|
5
|
+
build:
|
|
6
|
+
context: ../../
|
|
7
|
+
dockerfile: apps/relay/Dockerfile
|
|
8
|
+
tags:
|
|
9
|
+
- evolu/relay:latest
|
|
10
|
+
- evolu/relay:dev
|
|
11
|
+
ports:
|
|
12
|
+
- "4000:4000"
|
|
13
|
+
volumes:
|
|
14
|
+
# Use named volume by default, can be overridden with bind mount if needed
|
|
15
|
+
- evolu-relay-data:/app/apps/relay/data
|
|
16
|
+
environment:
|
|
17
|
+
- NODE_ENV=${NODE_ENV:-production}
|
|
18
|
+
- LOG_LEVEL=${LOG_LEVEL:-info}
|
|
19
|
+
restart: unless-stopped
|
|
20
|
+
deploy:
|
|
21
|
+
resources:
|
|
22
|
+
limits:
|
|
23
|
+
memory: ${MEMORY_LIMIT:-1G}
|
|
24
|
+
cpus: ${CPU_LIMIT:-1.0}
|
|
25
|
+
reservations:
|
|
26
|
+
memory: ${MEMORY_RESERVED:-512M}
|
|
27
|
+
cpus: ${CPU_RESERVED:-0.5}
|
|
28
|
+
healthcheck:
|
|
29
|
+
test:
|
|
30
|
+
[
|
|
31
|
+
"CMD",
|
|
32
|
+
"sh",
|
|
33
|
+
"-c",
|
|
34
|
+
"wget --no-verbose --tries=1 --spider http://localhost:4000 2>&1 | grep -q '426 Upgrade Required' || exit 1",
|
|
35
|
+
]
|
|
36
|
+
interval: 30s
|
|
37
|
+
timeout: 5s
|
|
38
|
+
retries: 3
|
|
39
|
+
start_period: 30s
|
|
40
|
+
logging:
|
|
41
|
+
driver: "json-file"
|
|
42
|
+
options:
|
|
43
|
+
max-size: ${LOG_MAX_SIZE:-50m}
|
|
44
|
+
max-file: ${LOG_MAX_FILES:-5}
|
|
45
|
+
networks:
|
|
46
|
+
- evolu-network
|
|
47
|
+
|
|
48
|
+
volumes:
|
|
49
|
+
evolu-relay-data:
|
|
50
|
+
driver: local
|
|
51
|
+
name: evolu-relay-data
|
|
52
|
+
|
|
53
|
+
networks:
|
|
54
|
+
evolu-network:
|
|
55
|
+
name: evolu-relay-network
|
|
56
|
+
driver: bridge
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@evolu/relay",
|
|
3
|
+
"version": "1.1.2-preview.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"@evolu/relay": "dist/src/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"commander": "^14.0.1",
|
|
10
|
+
"@evolu/common": "6.0.1-preview.19",
|
|
11
|
+
"@evolu/nodejs": "1.0.1-preview.7"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/node": "^22.17.1",
|
|
15
|
+
"typescript": "^5.9.2",
|
|
16
|
+
"@evolu/tsconfig": "0.0.2"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22.0.0"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "tsx --watch src/cli.ts -- start",
|
|
26
|
+
"build": "shx rm -rf dist && tsc",
|
|
27
|
+
"start": "node dist/src/cli.js",
|
|
28
|
+
"clean": "shx rm -rf .turbo node_modules dist db.sqlite",
|
|
29
|
+
"docker:build": "docker-compose build --no-cache",
|
|
30
|
+
"docker:up": "docker-compose up --build",
|
|
31
|
+
"docker:up:detached": "docker-compose up -d --build",
|
|
32
|
+
"docker:down": "docker-compose down",
|
|
33
|
+
"docker:restart": "docker-compose down && docker-compose up --build",
|
|
34
|
+
"docker:logs": "docker-compose logs -f evolu-relay",
|
|
35
|
+
"docker:shell": "docker exec -it evolu-relay-server sh",
|
|
36
|
+
"docker:inspect": "docker inspect evolu-relay-server",
|
|
37
|
+
"docker:stats": "docker stats evolu-relay-server",
|
|
38
|
+
"docker:clean": "docker-compose down -v && docker system prune -f",
|
|
39
|
+
"docker:clean:all": "docker-compose down -v && docker system prune -af && docker volume prune -f"
|
|
40
|
+
}
|
|
41
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
import { startNodeJsRelay } from "./nodejs.js";
|
|
5
|
+
import { cliParams } from "./params.js";
|
|
6
|
+
|
|
7
|
+
function main() {
|
|
8
|
+
const program = new Command()
|
|
9
|
+
.name("@evolu/relay")
|
|
10
|
+
.description("Evolu Relay server")
|
|
11
|
+
.version(
|
|
12
|
+
packageJson.version || "1.0.0",
|
|
13
|
+
"-v, --version",
|
|
14
|
+
"display the version number",
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.command("start")
|
|
19
|
+
.description("start the relay server")
|
|
20
|
+
.addOption(
|
|
21
|
+
new Option("-n, --name <name>", "database name").default("evolu-relay"),
|
|
22
|
+
)
|
|
23
|
+
.addOption(
|
|
24
|
+
new Option("-l, --enable-logging", "enable logging").default(false),
|
|
25
|
+
)
|
|
26
|
+
.addOption(
|
|
27
|
+
new Option("-p, --port <number>", "port to listen on")
|
|
28
|
+
.default(4000)
|
|
29
|
+
.argParser(Number),
|
|
30
|
+
)
|
|
31
|
+
.addOption(
|
|
32
|
+
new Option("-m, --in-memory", "enable in-memory mode").default(false),
|
|
33
|
+
)
|
|
34
|
+
// .addOption(
|
|
35
|
+
// new Option("--platform <platform>", "platform")
|
|
36
|
+
// .choices(["nodejs", "bun"])
|
|
37
|
+
// .default("nodejs"),
|
|
38
|
+
// )
|
|
39
|
+
.action(async (options: unknown) => {
|
|
40
|
+
logger.enabled = true;
|
|
41
|
+
const params = cliParams.fromUnknown(options);
|
|
42
|
+
|
|
43
|
+
if (!params.ok) {
|
|
44
|
+
logger.error(params.error.reason);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await startNodeJsRelay(params.value);
|
|
50
|
+
} catch (error: unknown) {
|
|
51
|
+
logger.error(error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
program.parse();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
main();
|