@rip-lang/server 0.5.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/README.md ADDED
@@ -0,0 +1,336 @@
1
+ <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.svg" style="width:50px" /> <br>
2
+
3
+ # Rip Server - @rip-lang/server
4
+
5
+ > **Pure Rip application server — multi-worker, hot reload, HTTPS, mDNS**
6
+
7
+ ## Overview
8
+
9
+ `@rip-lang/server` is a production-grade application server written entirely in Rip. It provides multi-worker process management, hot module reloading, automatic HTTPS, and mDNS service discovery — all in a single ~1,100 line file.
10
+
11
+ - **`server.rip`** (~1,082 lines) — Complete server: CLI, workers, load balancing, TLS, mDNS
12
+
13
+ **Core Philosophy**: Application servers should be simple, fast, and reliable. No complex configuration files. No dependency on external process managers. Just run your app.
14
+
15
+ ### Key Features
16
+
17
+ - **Multi-Worker Architecture** — Automatic worker spawning based on CPU cores
18
+ - **Hot Module Reloading** — File-watch based reloading in development
19
+ - **Rolling Restarts** — Zero-downtime deployments
20
+ - **Automatic HTTPS** — TLS with mkcert or self-signed certificates
21
+ - **mDNS Discovery** — `.local` hostname advertisement
22
+ - **Request Queue** — Built-in request buffering and load balancing
23
+ - **CLI Interface** — Simple command-line operation
24
+
25
+ > **See Also**: For the API framework, see [@rip-lang/api](../api/README.md).
26
+
27
+ ## Quick Start
28
+
29
+ ### Installation
30
+
31
+ ```bash
32
+ # Local (per-project)
33
+ bun add @rip-lang/server
34
+
35
+ # Global (use rip-server from anywhere)
36
+ bun add -g rip-lang @rip-lang/server
37
+ ```
38
+
39
+ ### Running Your App
40
+
41
+ ```bash
42
+ # Basic usage (HTTPS on port 443 or fallback)
43
+ rip-server ./app.rip
44
+
45
+ # HTTP only mode
46
+ rip-server http ./app.rip
47
+
48
+ # With mDNS alias
49
+ rip-server ./app.rip@myapp
50
+ ```
51
+
52
+ ### Example App
53
+
54
+ Create `app.rip`:
55
+
56
+ ```coffee
57
+ import { get, post, read, startHandler } from '@rip-lang/api'
58
+
59
+ get '/', ->
60
+ 'Hello from Rip Server!'
61
+
62
+ get '/json', ->
63
+ { message: 'It works!', timestamp: Date.now() }
64
+
65
+ get '/users/:id', ->
66
+ id = read 'id', 'id!'
67
+ { user: { id, name: "User #{id}" } }
68
+
69
+ # Export the handler for rip-server
70
+ export default startHandler()
71
+ ```
72
+
73
+ Run it:
74
+
75
+ ```bash
76
+ rip-server http app.rip
77
+ ```
78
+
79
+ Test it:
80
+
81
+ ```bash
82
+ curl http://localhost/
83
+ # Hello from Rip Server!
84
+
85
+ curl http://localhost/json
86
+ # {"message":"It works!","timestamp":1234567890}
87
+
88
+ curl http://localhost/users/42
89
+ # {"user":{"id":42,"name":"User 42"}}
90
+
91
+ curl http://localhost/status
92
+ # {"status":"healthy","app":"myapp","workers":5,"ports":{"http":80}}
93
+ ```
94
+
95
+ ## CLI Reference
96
+
97
+ ### Basic Syntax
98
+
99
+ ```bash
100
+ rip-server [flags] <app-path>[@alias1,alias2,...]
101
+ ```
102
+
103
+ ### Flags
104
+
105
+ | Flag | Description | Default |
106
+ |------|-------------|---------|
107
+ | `http` | HTTP-only mode (no HTTPS) | HTTPS enabled |
108
+ | `https` | HTTPS mode (explicit) | Auto |
109
+ | `http:<port>` | Set HTTP port | 80 or 5700 |
110
+ | `https:<port>` | Set HTTPS port | 443 or 5700 |
111
+ | `w:<n>` | Worker count (`auto`, `half`, `2x`, `3x`, or number) | `half` of cores |
112
+ | `r:<policy>` | Restart policy (e.g., `1000,3600s,10r`) | `10000,3600s,10r` |
113
+ | `--cert=<path>` | TLS certificate path | Auto-generated |
114
+ | `--key=<path>` | TLS private key path | Auto-generated |
115
+ | `--auto-tls` | Use mkcert for TLS | Fallback to self-signed |
116
+ | `--hsts` | Enable HSTS headers | Disabled |
117
+ | `--no-redirect-http` | Don't redirect HTTP to HTTPS | Redirects enabled |
118
+ | `--reload=<mode>` | Reload mode: `none`, `process`, `module` | `process` |
119
+ | `--json-logging` | Output JSON access logs | Human-readable |
120
+ | `--no-access-log` | Disable access logging | Enabled |
121
+
122
+ ### Subcommands
123
+
124
+ ```bash
125
+ # Stop running server
126
+ rip-server stop
127
+
128
+ # List registered hosts
129
+ rip-server list
130
+ ```
131
+
132
+ ### Examples
133
+
134
+ ```bash
135
+ # Development: HTTP on any available port
136
+ rip-server http app.rip
137
+
138
+ # Development: HTTPS with mkcert
139
+ rip-server --auto-tls app.rip
140
+
141
+ # Production: 8 workers, HTTPS
142
+ rip-server w:8 https app.rip
143
+
144
+ # Custom ports
145
+ rip-server http:3000 app.rip
146
+
147
+ # With mDNS aliases (accessible as myapp.local and api.local)
148
+ rip-server app.rip@myapp,api
149
+
150
+ # Restart after 5000 requests or 1 hour
151
+ rip-server r:5000,3600s app.rip
152
+ ```
153
+
154
+ ## Architecture
155
+
156
+ ### Self-Spawning Design
157
+
158
+ The server uses a single-file, self-spawning architecture:
159
+
160
+ ```
161
+ ┌─────────────────────────────────────────────────────────┐
162
+ │ Main Process │
163
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
164
+ │ │ Server │ │ Manager │ │ Control Socket │ │
165
+ │ │ (HTTP/HTTPS)│ │ (Workers) │ │ (Commands) │ │
166
+ │ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
167
+ └─────────┼────────────────┼──────────────────┼───────────┘
168
+ │ │ │
169
+ ▼ ▼ │
170
+ ┌──────────┐ ┌──────────────┐ │
171
+ │ Requests │ │ Spawn/Monitor│ │
172
+ └────┬─────┘ └──────┬───────┘ │
173
+ │ │ │
174
+ ▼ ▼ │
175
+ ┌─────────────────────────────────────────────│───┐
176
+ │ Worker Processes │ │
177
+ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │
178
+ │ │Worker 0│ │Worker 1│ │Worker N│ ◄────────┘ │
179
+ │ │(Unix) │ │(Unix) │ │(Unix) │ │
180
+ │ └────────┘ └────────┘ └────────┘ │
181
+ └─────────────────────────────────────────────────┘
182
+ ```
183
+
184
+ When `RIP_WORKER_MODE=1` is set, the same `server.rip` file runs as a worker instead of the main server.
185
+
186
+ ### Request Flow
187
+
188
+ 1. **Main Process** receives HTTP/HTTPS request
189
+ 2. **Server** selects available worker from pool
190
+ 3. **Request** forwarded via Unix socket
191
+ 4. **Worker** processes request, returns response
192
+ 5. **Server** forwards response to client
193
+
194
+ ### Hot Reloading
195
+
196
+ Two modes available:
197
+
198
+ - **`process` mode** (default): File changes trigger rolling restart of all workers
199
+ - **`module` mode**: Each worker reloads the app module on file change (faster, but uses more memory)
200
+
201
+ ### Worker Lifecycle
202
+
203
+ Workers are recycled based on configurable limits:
204
+
205
+ - **maxRequests**: Restart after N requests (default: 10,000)
206
+ - **maxSeconds**: Restart after N seconds (default: 3,600)
207
+ - **maxReloads**: Maximum hot reloads before restart (default: 10)
208
+
209
+ ## Built-in Endpoints
210
+
211
+ The server provides these endpoints automatically:
212
+
213
+ | Endpoint | Description |
214
+ |----------|-------------|
215
+ | `/status` | Health check with worker count and uptime |
216
+ | `/server` | Simple "ok" response for load balancer probes |
217
+
218
+ ## TLS Certificates
219
+
220
+ ### Automatic Certificate Generation
221
+
222
+ When HTTPS is enabled without explicit certificates, the server will:
223
+
224
+ 1. Try **mkcert** (if installed and `--auto-tls` flag used)
225
+ 2. Fall back to **self-signed** certificate via OpenSSL
226
+
227
+ Certificates are stored in `~/.rip/certs/`.
228
+
229
+ ### Custom Certificates
230
+
231
+ ```bash
232
+ rip-server --cert=/path/to/cert.pem --key=/path/to/key.pem app.rip
233
+ ```
234
+
235
+ ## mDNS Service Discovery
236
+
237
+ The server automatically advertises itself via mDNS (Bonjour/Zeroconf):
238
+
239
+ ```bash
240
+ # App accessible at myapp.local
241
+ rip-server app.rip@myapp
242
+
243
+ # Multiple aliases
244
+ rip-server app.rip@myapp,api,backend
245
+ ```
246
+
247
+ Requires `dns-sd` (available on macOS by default).
248
+
249
+ ## App Requirements
250
+
251
+ Your app must export a fetch handler. Two patterns are supported:
252
+
253
+ ### Pattern 1: Export `startHandler()` (Recommended)
254
+
255
+ ```coffee
256
+ import { get, startHandler } from '@rip-lang/api'
257
+
258
+ get '/', -> 'Hello!'
259
+
260
+ export default startHandler()
261
+ ```
262
+
263
+ ### Pattern 2: Export fetch function directly
264
+
265
+ ```coffee
266
+ export default (req) ->
267
+ new Response('Hello!')
268
+ ```
269
+
270
+ ### Pattern 3: Export object with fetch method
271
+
272
+ ```coffee
273
+ export default
274
+ fetch: (req) -> new Response('Hello!')
275
+ ```
276
+
277
+ ## Environment Variables
278
+
279
+ | Variable | Description |
280
+ |----------|-------------|
281
+ | `RIP_WORKER_MODE` | Set by server when spawning workers |
282
+ | `RIP_DEBUG` | Enable debug logging |
283
+ | `RIP_MAX_REQUESTS` | Default max requests per worker |
284
+ | `RIP_MAX_SECONDS` | Default max seconds per worker |
285
+ | `RIP_MAX_RELOADS` | Default max reloads per worker |
286
+ | `RIP_MAX_QUEUE` | Maximum request queue size |
287
+ | `RIP_QUEUE_TIMEOUT_MS` | Queue timeout in milliseconds |
288
+ | `RIP_RELOAD` | Reload mode override |
289
+
290
+ ## Dashboard
291
+
292
+ The server includes a built-in dashboard accessible at `http://rip.local/` (when mDNS is active). The dashboard shows server status, worker count, and registered hosts.
293
+
294
+ ## Troubleshooting
295
+
296
+ **Port 80 requires sudo**: Use `http:3000` or another high port, or run with sudo.
297
+
298
+ **mDNS not working**: Ensure `dns-sd` is available (built into macOS). On Linux, install Avahi.
299
+
300
+ **Workers keep restarting**: Check `RIP_DEBUG=1` for import errors in your app.
301
+
302
+ ## Comparison with Other Servers
303
+
304
+ | Feature | rip-server | PM2 | Nginx |
305
+ |---------|------------|-----|-------|
306
+ | Pure Rip | ✅ | ❌ | ❌ |
307
+ | Single File | ✅ (~1,076 lines) | ❌ | ❌ |
308
+ | Hot Reload | ✅ | ✅ | ❌ |
309
+ | Multi-Worker | ✅ | ✅ | ✅ |
310
+ | Auto HTTPS | ✅ | ❌ | ❌ |
311
+ | mDNS | ✅ | ❌ | ❌ |
312
+ | Zero Config | ✅ | ❌ | ❌ |
313
+ | Built-in LB | ✅ | ❌ | ✅ |
314
+
315
+ ## TODO
316
+
317
+ > *Planned improvements for future releases:*
318
+
319
+ - [ ] "Try it Now" section with clone-and-run example
320
+ - [ ] Dashboard screenshots and feature description
321
+ - [ ] Performance benchmarks (req/s, latency)
322
+ - [ ] Scaling guidelines
323
+ - [ ] More troubleshooting scenarios
324
+ - [ ] Static file serving
325
+ - [ ] Rate limiting
326
+ - [ ] Graceful shutdown improvements
327
+
328
+ ## License
329
+
330
+ MIT
331
+
332
+ ## Links
333
+
334
+ - [Rip Language](https://github.com/shreeve/rip-lang)
335
+ - [@rip-lang/api](../api/README.md)
336
+ - [Report Issues](https://github.com/shreeve/rip-lang/issues)
package/bin/rip-server ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync } from 'child_process';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ const serverRip = join(__dirname, '..', 'server.rip');
11
+ const args = process.argv.slice(2).join(' ');
12
+
13
+ try {
14
+ execSync(`rip ${serverRip} ${args}`, { stdio: 'inherit' });
15
+ } catch (error) {
16
+ process.exit(error.status || 1);
17
+ }