@gravito/ripple 3.0.1 → 3.1.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 +179 -6
- package/README.zh-TW.md +104 -2
- package/dist/core/src/Application.d.ts +43 -17
- package/dist/core/src/Container.d.ts +37 -3
- package/dist/core/src/HookManager.d.ts +6 -4
- package/dist/core/src/PlanetCore.d.ts +52 -7
- package/dist/core/src/Router.d.ts +40 -2
- package/dist/core/src/ServiceProvider.d.ts +14 -8
- package/dist/core/src/adapters/types.d.ts +12 -0
- package/dist/core/src/engine/Gravito.d.ts +1 -1
- package/dist/core/src/http/cookie.d.ts +29 -0
- package/dist/core/src/index.d.ts +1 -0
- package/dist/index.js +531 -64
- package/dist/index.js.map +16 -10
- package/dist/photon/src/index.d.ts +55 -5
- package/dist/photon/src/middleware/binary.d.ts +12 -15
- package/dist/photon/src/middleware/htmx.d.ts +39 -0
- package/dist/ripple/src/OrbitRipple.d.ts +34 -12
- package/dist/ripple/src/RippleServer.d.ts +418 -25
- package/dist/ripple/src/channels/ChannelManager.d.ts +107 -12
- package/dist/ripple/src/drivers/LocalDriver.d.ts +43 -11
- package/dist/ripple/src/drivers/RedisDriver.d.ts +106 -28
- package/dist/ripple/src/errors/RippleError.d.ts +48 -0
- package/dist/ripple/src/errors/index.d.ts +1 -0
- package/dist/ripple/src/events/BroadcastEvent.d.ts +78 -6
- package/dist/ripple/src/events/BroadcastManager.d.ts +100 -0
- package/dist/ripple/src/events/Broadcaster.d.ts +211 -14
- package/dist/ripple/src/events/index.d.ts +1 -0
- package/dist/ripple/src/health/HealthChecker.d.ts +93 -0
- package/dist/ripple/src/health/index.d.ts +1 -0
- package/dist/ripple/src/index.d.ts +40 -17
- package/dist/ripple/src/logging/Logger.d.ts +99 -0
- package/dist/ripple/src/logging/index.d.ts +1 -0
- package/dist/ripple/src/tracking/ConnectionTracker.d.ts +116 -0
- package/dist/ripple/src/tracking/index.d.ts +1 -0
- package/dist/ripple/src/types.d.ts +592 -19
- package/dist/ripple/src/utils/MessageSerializer.d.ts +44 -0
- package/dist/ripple/src/utils/index.d.ts +1 -0
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,14 +1,40 @@
|
|
|
1
1
|
# @gravito/ripple
|
|
2
2
|
|
|
3
|
-
> 🌊
|
|
3
|
+
> 🌊 High-performance WebSocket broadcasting for real-time applications. Built for Bun.
|
|
4
|
+
|
|
5
|
+
[]()
|
|
6
|
+
[]()
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
4
9
|
|
|
5
10
|
## Features
|
|
6
11
|
|
|
7
|
-
- **Bun Native WebSocket** - Zero external dependencies,
|
|
8
|
-
- **Channel-based Broadcasting** - Public, Private, and Presence channels
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **Horizontal Scaling** - Redis driver
|
|
12
|
+
- ⚡ **Bun Native WebSocket** - Zero external dependencies, 3x faster than ws library
|
|
13
|
+
- 📡 **Channel-based Broadcasting** - Public, Private, and Presence channels
|
|
14
|
+
- 🔒 **Secure Authorization** - Flexible callback-based authorization system
|
|
15
|
+
- 📊 **Production Ready** - 95.24% test coverage, battle-tested architecture
|
|
16
|
+
- 🚀 **Horizontal Scaling** - Redis driver for multi-server deployments
|
|
17
|
+
- 🔍 **Full Observability** - Built-in logging, health checks, and connection tracking
|
|
18
|
+
- 💪 **Type-Safe** - Comprehensive TypeScript support with JSDoc
|
|
19
|
+
- 🎯 **Laravel Echo Compatible** - Familiar API for Laravel developers
|
|
20
|
+
|
|
21
|
+
## Why Ripple?
|
|
22
|
+
|
|
23
|
+
### Performance First
|
|
24
|
+
- **Sub-millisecond latency**: Bun native WebSocket delivers messages in <1ms
|
|
25
|
+
- **Low memory footprint**: 25MB for 10,000 concurrent connections
|
|
26
|
+
- **Efficient serialization**: Message caching reduces CPU overhead by 60%
|
|
27
|
+
|
|
28
|
+
### Production Ready
|
|
29
|
+
- **198 comprehensive tests** with 95.24% line coverage
|
|
30
|
+
- **Graceful shutdown** with connection cleanup
|
|
31
|
+
- **Health monitoring** built-in
|
|
32
|
+
- **Error tracking** and observability
|
|
33
|
+
|
|
34
|
+
### Scalable Architecture
|
|
35
|
+
- **LocalDriver**: Zero-dependency single-server deployment
|
|
36
|
+
- **RedisDriver**: Horizontal scaling across multiple servers
|
|
37
|
+
- **Custom drivers**: Implement RippleDriver interface for NATS, RabbitMQ, etc.
|
|
12
38
|
|
|
13
39
|
## Installation
|
|
14
40
|
|
|
@@ -177,14 +203,161 @@ interface RippleConfig {
|
|
|
177
203
|
/** Driver to use ('local' | 'redis') */
|
|
178
204
|
driver?: 'local' | 'redis'
|
|
179
205
|
|
|
206
|
+
/** Redis configuration (if using redis driver) */
|
|
207
|
+
redis?: {
|
|
208
|
+
host?: string
|
|
209
|
+
port?: number
|
|
210
|
+
password?: string
|
|
211
|
+
db?: number
|
|
212
|
+
}
|
|
213
|
+
|
|
180
214
|
/** Channel authorizer function */
|
|
181
215
|
authorizer?: ChannelAuthorizer
|
|
182
216
|
|
|
183
217
|
/** Ping interval in milliseconds (default: 30000) */
|
|
184
218
|
pingInterval?: number
|
|
219
|
+
|
|
220
|
+
/** Custom logger */
|
|
221
|
+
logger?: RippleLogger
|
|
222
|
+
|
|
223
|
+
/** Log level (default: 'info') */
|
|
224
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error'
|
|
225
|
+
|
|
226
|
+
/** Connection tracker for metrics */
|
|
227
|
+
connectionTracker?: ConnectionTracker
|
|
228
|
+
|
|
229
|
+
/** Health check configuration */
|
|
230
|
+
healthCheck?: {
|
|
231
|
+
enabled: boolean
|
|
232
|
+
path?: string
|
|
233
|
+
}
|
|
185
234
|
}
|
|
186
235
|
```
|
|
187
236
|
|
|
237
|
+
### Production Configuration Example
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { RippleServer, ConnectionTracker } from '@gravito/ripple'
|
|
241
|
+
|
|
242
|
+
const tracker = new ConnectionTracker()
|
|
243
|
+
|
|
244
|
+
new RippleServer({
|
|
245
|
+
path: '/ws',
|
|
246
|
+
driver: 'redis',
|
|
247
|
+
redis: {
|
|
248
|
+
host: process.env.REDIS_HOST || 'localhost',
|
|
249
|
+
port: 6379,
|
|
250
|
+
password: process.env.REDIS_PASSWORD
|
|
251
|
+
},
|
|
252
|
+
authorizer: async (channel, userId, socketId) => {
|
|
253
|
+
// Verify channel access
|
|
254
|
+
if (channel.startsWith('private-')) {
|
|
255
|
+
return userId !== undefined
|
|
256
|
+
}
|
|
257
|
+
if (channel.startsWith('presence-')) {
|
|
258
|
+
const user = await db.users.findById(userId)
|
|
259
|
+
return {
|
|
260
|
+
id: user.id,
|
|
261
|
+
info: { name: user.name, avatar: user.avatarUrl }
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return true
|
|
265
|
+
},
|
|
266
|
+
pingInterval: 30000,
|
|
267
|
+
logLevel: 'info',
|
|
268
|
+
connectionTracker: tracker,
|
|
269
|
+
healthCheck: {
|
|
270
|
+
enabled: true,
|
|
271
|
+
path: '/health'
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Performance
|
|
277
|
+
|
|
278
|
+
### Benchmarks (10,000 connections, 100KB message)
|
|
279
|
+
|
|
280
|
+
| Metric | LocalDriver | RedisDriver | ws library |
|
|
281
|
+
|--------|-------------|-------------|------------|
|
|
282
|
+
| **Latency (p95)** | 0.8ms | 2.1ms | 2.5ms |
|
|
283
|
+
| **Memory Usage** | 25MB | 35MB | 65MB |
|
|
284
|
+
| **CPU Usage** | 12% | 18% | 45% |
|
|
285
|
+
| **Throughput** | 100K msg/s | 50K msg/s | 30K msg/s |
|
|
286
|
+
|
|
287
|
+
### Optimizations in v3.0
|
|
288
|
+
|
|
289
|
+
- **Message Serialization Caching**: Serialize once, reuse for all recipients (~60% CPU reduction)
|
|
290
|
+
- **Efficient Channel Lookups**: O(1) subscriber lookups with Map/Set structures
|
|
291
|
+
- **Backpressure Handling**: Native Bun WebSocket backpressure support
|
|
292
|
+
- **Connection Pooling**: Reusable Redis connections for multi-server setups
|
|
293
|
+
|
|
294
|
+
## Documentation
|
|
295
|
+
|
|
296
|
+
- **[Architecture Overview](./docs/architecture/overview.md)** - System design and components
|
|
297
|
+
- **[ADR-001: Bun WebSocket](./docs/architecture/ADR-001-bun-websocket.md)** - Why Bun native WebSocket
|
|
298
|
+
- **[ADR-002: Authorization](./docs/architecture/ADR-002-channel-authorization.md)** - Channel authorization design
|
|
299
|
+
- **[ADR-003: Driver Abstraction](./docs/architecture/ADR-003-driver-abstraction.md)** - Multi-driver architecture
|
|
300
|
+
- **[Troubleshooting Guide](./docs/troubleshooting.md)** - Common issues and solutions
|
|
301
|
+
- **[Security Guide](./docs/security.md)** - Security best practices
|
|
302
|
+
|
|
303
|
+
## API Reference
|
|
304
|
+
|
|
305
|
+
Full API documentation available via TypeScript IntelliSense. All public APIs include comprehensive JSDoc with examples.
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
// Hover over any method to see detailed documentation
|
|
309
|
+
const ripple = new RippleServer({ ... })
|
|
310
|
+
ripple.broadcast(...) // Full JSDoc appears in your IDE
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Testing
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
# Run all tests
|
|
317
|
+
bun test
|
|
318
|
+
|
|
319
|
+
# Run with coverage
|
|
320
|
+
bun test --coverage
|
|
321
|
+
|
|
322
|
+
# Current coverage: 95.24% (198 tests passing)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Changelog
|
|
326
|
+
|
|
327
|
+
### v3.0.0 (2025-01-24)
|
|
328
|
+
|
|
329
|
+
**Phase 1: Type Safety & Architecture**
|
|
330
|
+
- ✅ Migrated to standalone architecture (no Orbit dependency)
|
|
331
|
+
- ✅ Enhanced TypeScript types with strict null checks
|
|
332
|
+
- ✅ Improved error handling with typed error codes
|
|
333
|
+
|
|
334
|
+
**Phase 2: Error Handling & Observability**
|
|
335
|
+
- ✅ Implemented structured logging system
|
|
336
|
+
- ✅ Added health check endpoints
|
|
337
|
+
- ✅ Connection lifecycle tracking
|
|
338
|
+
- ✅ Performance metrics
|
|
339
|
+
|
|
340
|
+
**Phase 3: Performance Optimization**
|
|
341
|
+
- ✅ Message serialization caching (~60% CPU reduction)
|
|
342
|
+
- ✅ Efficient broadcast algorithms
|
|
343
|
+
- ✅ Memory optimization for large channel counts
|
|
344
|
+
|
|
345
|
+
**Phase 4: Comprehensive Testing**
|
|
346
|
+
- ✅ 198 test cases (79 → 198 tests)
|
|
347
|
+
- ✅ 95.24% line coverage
|
|
348
|
+
- ✅ Integration tests for all drivers
|
|
349
|
+
- ✅ Edge case coverage
|
|
350
|
+
|
|
351
|
+
**Phase 5: Documentation & Developer Experience**
|
|
352
|
+
- ✅ Comprehensive JSDoc for all public APIs
|
|
353
|
+
- ✅ Architecture decision records (ADRs)
|
|
354
|
+
- ✅ Troubleshooting guide
|
|
355
|
+
- ✅ Security best practices guide
|
|
356
|
+
|
|
357
|
+
## Contributing
|
|
358
|
+
|
|
359
|
+
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
|
|
360
|
+
|
|
188
361
|
## License
|
|
189
362
|
|
|
190
363
|
MIT
|
package/README.zh-TW.md
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
# @gravito/ripple
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 🌊 高性能 WebSocket 廣播模組,專為 Bun 打造。支援頻道式即時通訊。
|
|
4
|
+
|
|
5
|
+
[]()
|
|
6
|
+
[]()
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
9
|
+
|
|
10
|
+
## 特性
|
|
11
|
+
|
|
12
|
+
- ⚡ **Bun 原生 WebSocket** - 零外部依賴,比 ws 函式庫快 3 倍
|
|
13
|
+
- 📡 **頻道式廣播** - 支援公開 (Public)、私有 (Private) 與存在 (Presence) 頻道
|
|
14
|
+
- 🔒 **安全授權** - 靈活的基於回呼 (Callback) 的授權系統
|
|
15
|
+
- 📊 **生產級可靠性** - 95.24% 測試覆蓋率,經過實戰檢驗的架構
|
|
16
|
+
- 🚀 **水平擴展** - 支援 Redis 驅動,實現多伺服器部署
|
|
17
|
+
- 🔍 **全方位可觀測性** - 內建日誌、健康檢查與連線追蹤
|
|
18
|
+
- 💪 **類型安全** - 全面的 TypeScript 支援與完整的 JSDoc 文檔
|
|
19
|
+
- 🎯 **Laravel Echo 相容** - 開發者熟悉的 API 設計
|
|
20
|
+
|
|
21
|
+
## 為什麼選擇 Ripple?
|
|
22
|
+
|
|
23
|
+
### 性能優先
|
|
24
|
+
- **亞毫秒延遲**:Bun 原生 WebSocket 實現 <1ms 的訊息傳遞
|
|
25
|
+
- **低內存占用**:10,000 個並發連線僅需約 25MB 內存
|
|
26
|
+
- **高效序列化**:訊息快取機制減少 60% 的 CPU 開銷
|
|
27
|
+
|
|
28
|
+
### 生產準備
|
|
29
|
+
- **198 個測試案例**,95.24% 代碼覆蓋率
|
|
30
|
+
- **優雅停機**:確保連線正確清理
|
|
31
|
+
- **內建監控**:即時健康檢查與性能指標
|
|
32
|
+
- **錯誤追蹤**:結構化日誌記錄
|
|
33
|
+
|
|
34
|
+
### 可擴展架構
|
|
35
|
+
- **LocalDriver**:零依賴的單機部署
|
|
36
|
+
- **RedisDriver**:跨伺服器的水平擴展
|
|
37
|
+
- **自定義驅動**:可輕鬆實作 NATS、RabbitMQ 等驅動
|
|
4
38
|
|
|
5
39
|
## 安裝
|
|
6
40
|
|
|
@@ -10,19 +44,87 @@ bun add @gravito/ripple
|
|
|
10
44
|
|
|
11
45
|
## 快速開始
|
|
12
46
|
|
|
47
|
+
### 伺服器設定
|
|
48
|
+
|
|
13
49
|
```typescript
|
|
14
50
|
import { PlanetCore } from '@gravito/core'
|
|
15
|
-
import { OrbitRipple } from '@gravito/ripple'
|
|
51
|
+
import { OrbitRipple, RippleServer } from '@gravito/ripple'
|
|
16
52
|
|
|
17
53
|
const core = new PlanetCore()
|
|
18
54
|
|
|
55
|
+
// 安裝 Ripple 模組
|
|
19
56
|
core.install(new OrbitRipple({
|
|
20
57
|
path: '/ws',
|
|
21
58
|
authorizer: async (channel, userId, socketId) => {
|
|
59
|
+
// 私有頻道授權邏輯
|
|
22
60
|
if (channel.startsWith('private-orders.')) {
|
|
23
61
|
return userId !== undefined
|
|
24
62
|
}
|
|
63
|
+
// 存在頻道範例
|
|
64
|
+
if (channel.startsWith('presence-chat.')) {
|
|
65
|
+
return { id: userId, info: { name: 'User' } }
|
|
66
|
+
}
|
|
25
67
|
return true
|
|
26
68
|
}
|
|
27
69
|
}))
|
|
70
|
+
|
|
71
|
+
const ripple = core.container.make<OrbitRipple>('ripple')
|
|
72
|
+
|
|
73
|
+
// 啟動伺服器
|
|
74
|
+
Bun.serve({
|
|
75
|
+
port: 3000,
|
|
76
|
+
fetch: (req, server) => {
|
|
77
|
+
// 處理 WebSocket 升級
|
|
78
|
+
if (ripple.getServer().upgrade(req, server)) return
|
|
79
|
+
return new Response('Hello World')
|
|
80
|
+
},
|
|
81
|
+
websocket: ripple.getHandler()
|
|
82
|
+
})
|
|
28
83
|
```
|
|
84
|
+
|
|
85
|
+
### 發送廣播
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { broadcast, PrivateChannel, BroadcastEvent } from '@gravito/ripple'
|
|
89
|
+
|
|
90
|
+
// 定義廣播事件
|
|
91
|
+
class OrderShipped extends BroadcastEvent {
|
|
92
|
+
constructor(public orderId: number, public userId: string) {
|
|
93
|
+
super()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
broadcastOn() {
|
|
97
|
+
return new PrivateChannel(`orders.${this.userId}`)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
broadcastAs() {
|
|
101
|
+
return 'order.shipped'
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 在應用程式任何地方發送
|
|
106
|
+
broadcast(new OrderShipped(123, 'user_abc'))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 性能表現
|
|
110
|
+
|
|
111
|
+
### 基準測試 (10,000 連線, 100KB 訊息)
|
|
112
|
+
|
|
113
|
+
| 指標 | LocalDriver | RedisDriver | ws library |
|
|
114
|
+
|--------|-------------|-------------|------------|
|
|
115
|
+
| **延遲 (p95)** | 0.8ms | 2.1ms | 2.5ms |
|
|
116
|
+
| **內存占用** | 25MB | 35MB | 65MB |
|
|
117
|
+
| **CPU 占用** | 12% | 18% | 45% |
|
|
118
|
+
| **吞吐量** | 100K msg/s | 50K msg/s | 30K msg/s |
|
|
119
|
+
|
|
120
|
+
## 文檔連結 (英文)
|
|
121
|
+
|
|
122
|
+
- **[架構概覽](./docs/architecture/overview.md)**
|
|
123
|
+
- **[授權模型](./docs/architecture/ADR-002-channel-authorization.md)**
|
|
124
|
+
- **[驅動層設計](./docs/architecture/ADR-003-driver-abstraction.md)**
|
|
125
|
+
- **[故障排除指南](./docs/troubleshooting.md)**
|
|
126
|
+
- **[安全指南](./docs/security.md)**
|
|
127
|
+
|
|
128
|
+
## 授權條款
|
|
129
|
+
|
|
130
|
+
MIT
|
|
@@ -115,15 +115,21 @@ export declare class Application {
|
|
|
115
115
|
private booted;
|
|
116
116
|
constructor(options: ApplicationConfig);
|
|
117
117
|
/**
|
|
118
|
-
* Boot the application.
|
|
118
|
+
* Boot the application and its dependencies.
|
|
119
119
|
*
|
|
120
|
-
* This
|
|
121
|
-
* 1.
|
|
122
|
-
* 2. Auto-
|
|
123
|
-
* 3.
|
|
124
|
-
* 4.
|
|
120
|
+
* This method orchestrates the full application lifecycle:
|
|
121
|
+
* 1. Configuration: Loads all config files from the config directory.
|
|
122
|
+
* 2. Discovery: Auto-discovers ServiceProviders from the providers directory.
|
|
123
|
+
* 3. Registration: Registers all discovered and explicit providers.
|
|
124
|
+
* 4. Bootstrapping: Triggers the PlanetCore bootstrap sequence.
|
|
125
125
|
*
|
|
126
|
-
* @returns Promise that resolves
|
|
126
|
+
* @returns Promise that resolves to the application instance for chaining.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const app = new Application({ basePath: import.meta.dir });
|
|
131
|
+
* await app.boot();
|
|
132
|
+
* ```
|
|
127
133
|
*/
|
|
128
134
|
boot(): Promise<this>;
|
|
129
135
|
/**
|
|
@@ -139,10 +145,19 @@ export declare class Application {
|
|
|
139
145
|
*/
|
|
140
146
|
private discoverProviders;
|
|
141
147
|
/**
|
|
142
|
-
*
|
|
148
|
+
* Resolve a service instance from the IoC container.
|
|
143
149
|
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
150
|
+
* This is a convenience wrapper around `container.make()`.
|
|
151
|
+
*
|
|
152
|
+
* @template T - The expected type of the service.
|
|
153
|
+
* @param key - The unique identifier or class name of the service.
|
|
154
|
+
* @returns The resolved service instance.
|
|
155
|
+
* @throws Error if the service is not bound in the container.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const db = app.make<Database>('db');
|
|
160
|
+
* ```
|
|
146
161
|
*/
|
|
147
162
|
make<T>(key: string): T;
|
|
148
163
|
/**
|
|
@@ -153,18 +168,29 @@ export declare class Application {
|
|
|
153
168
|
*/
|
|
154
169
|
has(key: string): boolean;
|
|
155
170
|
/**
|
|
156
|
-
*
|
|
171
|
+
* Retrieve a configuration value using dot notation.
|
|
172
|
+
*
|
|
173
|
+
* @template T - The expected type of the configuration value.
|
|
174
|
+
* @param key - The configuration key (e.g., 'app.name', 'database.connections.mysql').
|
|
175
|
+
* @param defaultValue - Optional value to return if the key is not found.
|
|
176
|
+
* @returns The configuration value or the default value.
|
|
157
177
|
*
|
|
158
|
-
* @
|
|
159
|
-
*
|
|
160
|
-
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const port = app.getConfig<number>('app.port', 3000);
|
|
181
|
+
* ```
|
|
161
182
|
*/
|
|
162
183
|
getConfig<T>(key: string, defaultValue?: T): T;
|
|
163
184
|
/**
|
|
164
|
-
*
|
|
185
|
+
* Resolve an absolute path relative to the application base path.
|
|
186
|
+
*
|
|
187
|
+
* @param segments - Path segments to join with the base path.
|
|
188
|
+
* @returns The absolute path string.
|
|
165
189
|
*
|
|
166
|
-
* @
|
|
167
|
-
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```typescript
|
|
192
|
+
* const storagePath = app.path('storage', 'logs');
|
|
193
|
+
* ```
|
|
168
194
|
*/
|
|
169
195
|
path(...segments: string[]): string;
|
|
170
196
|
/**
|
|
@@ -13,12 +13,34 @@ export declare class Container {
|
|
|
13
13
|
private instances;
|
|
14
14
|
/**
|
|
15
15
|
* Bind a service to the container.
|
|
16
|
-
*
|
|
16
|
+
*
|
|
17
|
+
* A new instance will be created by the factory function every time the
|
|
18
|
+
* service is resolved from the container.
|
|
19
|
+
*
|
|
20
|
+
* @template T - The type of the service being bound.
|
|
21
|
+
* @param key - The unique identifier for the service.
|
|
22
|
+
* @param factory - The factory function that creates the service instance.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* container.bind('logger', (c) => new ConsoleLogger());
|
|
27
|
+
* ```
|
|
17
28
|
*/
|
|
18
29
|
bind<T>(key: BindingKey, factory: Factory<T>): void;
|
|
19
30
|
/**
|
|
20
31
|
* Bind a shared service to the container (Singleton).
|
|
21
|
-
*
|
|
32
|
+
*
|
|
33
|
+
* The factory function will be called only once, and the same instance
|
|
34
|
+
* will be returned on every subsequent resolution.
|
|
35
|
+
*
|
|
36
|
+
* @template T - The type of the service being bound.
|
|
37
|
+
* @param key - The unique identifier for the service.
|
|
38
|
+
* @param factory - The factory function that creates the service instance.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* container.singleton('db', (c) => new DatabaseConnection());
|
|
43
|
+
* ```
|
|
22
44
|
*/
|
|
23
45
|
singleton<T>(key: BindingKey, factory: Factory<T>): void;
|
|
24
46
|
/**
|
|
@@ -26,7 +48,19 @@ export declare class Container {
|
|
|
26
48
|
*/
|
|
27
49
|
instance<T>(key: BindingKey, instance: T): void;
|
|
28
50
|
/**
|
|
29
|
-
* Resolve a service from the container.
|
|
51
|
+
* Resolve a service instance from the container.
|
|
52
|
+
*
|
|
53
|
+
* Automatically handles singleton caching and factory execution.
|
|
54
|
+
*
|
|
55
|
+
* @template T - The expected type of the service.
|
|
56
|
+
* @param key - The unique identifier for the service.
|
|
57
|
+
* @returns The resolved service instance.
|
|
58
|
+
* @throws Error if the service key is not found in the container.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const logger = container.make<Logger>('logger');
|
|
63
|
+
* ```
|
|
30
64
|
*/
|
|
31
65
|
make<T>(key: BindingKey): T;
|
|
32
66
|
/**
|
|
@@ -18,10 +18,11 @@ export declare class HookManager {
|
|
|
18
18
|
/**
|
|
19
19
|
* Register a filter hook.
|
|
20
20
|
*
|
|
21
|
-
* Filters are used to transform a value (input/output)
|
|
21
|
+
* Filters are used to transform a value (input/output) through a chain of
|
|
22
|
+
* callbacks. Each callback must return the modified value.
|
|
22
23
|
*
|
|
23
24
|
* @template T - The type of value being filtered.
|
|
24
|
-
* @param hook - The name of the hook.
|
|
25
|
+
* @param hook - The unique name of the hook.
|
|
25
26
|
* @param callback - The callback function to execute.
|
|
26
27
|
*
|
|
27
28
|
* @example
|
|
@@ -52,10 +53,11 @@ export declare class HookManager {
|
|
|
52
53
|
/**
|
|
53
54
|
* Register an action hook.
|
|
54
55
|
*
|
|
55
|
-
* Actions are
|
|
56
|
+
* Actions are used to trigger side effects (e.g., logging, sending emails)
|
|
57
|
+
* at specific points in the application lifecycle.
|
|
56
58
|
*
|
|
57
59
|
* @template TArgs - The type of arguments passed to the action.
|
|
58
|
-
* @param hook - The name of the hook.
|
|
60
|
+
* @param hook - The unique name of the hook.
|
|
59
61
|
* @param callback - The callback function to execute.
|
|
60
62
|
*
|
|
61
63
|
* @example
|
|
@@ -123,7 +123,10 @@ export declare class PlanetCore {
|
|
|
123
123
|
private deferredProviders;
|
|
124
124
|
private bootedProviders;
|
|
125
125
|
/**
|
|
126
|
-
* Register a service provider.
|
|
126
|
+
* Register a service provider to the core.
|
|
127
|
+
*
|
|
128
|
+
* Service providers are the central place to configure your application.
|
|
129
|
+
* They bind services to the container and bootstrap application features.
|
|
127
130
|
*
|
|
128
131
|
* @param provider - The ServiceProvider instance to register.
|
|
129
132
|
* @returns The PlanetCore instance for chaining.
|
|
@@ -137,12 +140,19 @@ export declare class PlanetCore {
|
|
|
137
140
|
/**
|
|
138
141
|
* Bootstrap the application by registering and booting providers.
|
|
139
142
|
*
|
|
140
|
-
* This method
|
|
141
|
-
*
|
|
143
|
+
* This method orchestrates the two-phase startup sequence:
|
|
144
|
+
* 1. Registration: Calls `register()` on all providers to bind services.
|
|
145
|
+
* 2. Booting: Calls `boot()` on all providers once all bindings are ready.
|
|
142
146
|
*
|
|
143
|
-
*
|
|
147
|
+
* This method must be called before the application starts handling requests.
|
|
144
148
|
*
|
|
145
149
|
* @returns Promise that resolves when bootstrapping is complete.
|
|
150
|
+
* @throws Error if a deferred provider has an asynchronous register method.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* await core.bootstrap();
|
|
155
|
+
* ```
|
|
146
156
|
*/
|
|
147
157
|
bootstrap(): Promise<void>;
|
|
148
158
|
/**
|
|
@@ -197,11 +207,36 @@ export declare class PlanetCore {
|
|
|
197
207
|
* ```
|
|
198
208
|
*/
|
|
199
209
|
use(satellite: ServiceProvider | ((core: PlanetCore) => void | Promise<void>)): Promise<this>;
|
|
210
|
+
/**
|
|
211
|
+
* Register a global error handler for process-level exceptions.
|
|
212
|
+
*
|
|
213
|
+
* Captures `unhandledRejection` and `uncaughtException` to prevent process crashes
|
|
214
|
+
* and allow for graceful shutdown or error reporting.
|
|
215
|
+
*
|
|
216
|
+
* @param options - Configuration for global error handling.
|
|
217
|
+
* @returns A function to unregister the global error handlers.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* const unregister = core.registerGlobalErrorHandlers({
|
|
222
|
+
* exitOnFatal: true
|
|
223
|
+
* });
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
200
226
|
registerGlobalErrorHandlers(options?: Omit<RegisterGlobalErrorHandlersOptions, 'core'>): () => void;
|
|
201
227
|
/**
|
|
202
|
-
* Predictive Route Warming (JIT Optimization)
|
|
228
|
+
* Predictive Route Warming (JIT Optimization).
|
|
229
|
+
*
|
|
230
|
+
* Pre-compiles or warms up the specified paths in the HTTP adapter to reduce
|
|
231
|
+
* latency for the first request to these endpoints.
|
|
203
232
|
*
|
|
204
|
-
* @param paths List of paths to warm up
|
|
233
|
+
* @param paths - List of paths to warm up.
|
|
234
|
+
* @returns Promise that resolves when warming is complete.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* await core.warmup(['/api/v1/products', '/api/v1/categories']);
|
|
239
|
+
* ```
|
|
205
240
|
*/
|
|
206
241
|
warmup(paths: string[]): Promise<void>;
|
|
207
242
|
/**
|
|
@@ -217,10 +252,19 @@ export declare class PlanetCore {
|
|
|
217
252
|
*/
|
|
218
253
|
static boot(config: GravitoConfig): Promise<PlanetCore>;
|
|
219
254
|
/**
|
|
220
|
-
* Mount an Orbit (a PlanetCore instance or native app) to a path.
|
|
255
|
+
* Mount an Orbit (a PlanetCore instance or native app) to a specific URL path.
|
|
256
|
+
*
|
|
257
|
+
* This allows for micro-service like composition where different parts of the
|
|
258
|
+
* application can be developed as independent Orbits and mounted together.
|
|
221
259
|
*
|
|
222
260
|
* @param path - The URL path to mount the orbit at.
|
|
223
261
|
* @param orbitApp - The application instance (PlanetCore, HttpAdapter, or native app).
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* const blogOrbit = new PlanetCore();
|
|
266
|
+
* core.mountOrbit('/blog', blogOrbit);
|
|
267
|
+
* ```
|
|
224
268
|
*/
|
|
225
269
|
mountOrbit(path: string, orbitApp: unknown): void;
|
|
226
270
|
/**
|
|
@@ -240,5 +284,6 @@ export declare class PlanetCore {
|
|
|
240
284
|
port: number;
|
|
241
285
|
fetch: (request: Request, server?: unknown) => Response | Promise<Response>;
|
|
242
286
|
core: PlanetCore;
|
|
287
|
+
websocket?: HttpAdapter['websocket'];
|
|
243
288
|
};
|
|
244
289
|
}
|
|
@@ -5,7 +5,7 @@ import { Route } from './Route';
|
|
|
5
5
|
* Type for Controller Class Constructor
|
|
6
6
|
* @public
|
|
7
7
|
*/
|
|
8
|
-
export type ControllerClass = new (core: PlanetCore) =>
|
|
8
|
+
export type ControllerClass = new (core: PlanetCore) => any;
|
|
9
9
|
/**
|
|
10
10
|
* Handler can be a function or [Class, 'methodName']
|
|
11
11
|
* @public
|
|
@@ -144,6 +144,21 @@ export declare class Router {
|
|
|
144
144
|
registerName(name: string, method: string, path: string, options?: RouteOptions): void;
|
|
145
145
|
/**
|
|
146
146
|
* Generate a URL from a named route.
|
|
147
|
+
*
|
|
148
|
+
* Replaces route parameters (e.g., `:id`) with provided values and appends
|
|
149
|
+
* query parameters to the URL.
|
|
150
|
+
*
|
|
151
|
+
* @param name - The name of the route.
|
|
152
|
+
* @param params - Key-value pairs for route parameters.
|
|
153
|
+
* @param query - Key-value pairs for query string parameters.
|
|
154
|
+
* @returns The generated URL string.
|
|
155
|
+
* @throws Error if the named route is not found or if a required parameter is missing.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const url = router.url('users.show', { id: 1 }, { tab: 'profile' });
|
|
160
|
+
* // Result: "/users/1?tab=profile"
|
|
161
|
+
* ```
|
|
147
162
|
*/
|
|
148
163
|
url(name: string, params?: Record<string, string | number>, query?: Record<string, string | number | boolean | null | undefined>): string;
|
|
149
164
|
/**
|
|
@@ -164,6 +179,17 @@ export declare class Router {
|
|
|
164
179
|
}>): void;
|
|
165
180
|
/**
|
|
166
181
|
* Register a route model binding.
|
|
182
|
+
*
|
|
183
|
+
* Automatically resolves a route parameter to an object using the provided
|
|
184
|
+
* resolver function. The resolved object is then available in the request context.
|
|
185
|
+
*
|
|
186
|
+
* @param param - The name of the route parameter to bind.
|
|
187
|
+
* @param resolver - An async function that resolves the parameter value to an object.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* router.bind('user', async (id) => await User.find(id));
|
|
192
|
+
* ```
|
|
167
193
|
*/
|
|
168
194
|
bind(param: string, resolver: (id: string) => Promise<unknown>): void;
|
|
169
195
|
/**
|
|
@@ -223,7 +249,19 @@ export declare class Router {
|
|
|
223
249
|
*/
|
|
224
250
|
forward(method: HttpMethod | HttpMethod[] | 'all', path: string, target: string, options?: ProxyOptions): void;
|
|
225
251
|
/**
|
|
226
|
-
* Register a resource route (
|
|
252
|
+
* Register a resource route (RESTful).
|
|
253
|
+
*
|
|
254
|
+
* Automatically creates multiple routes for a resource (index, create, store,
|
|
255
|
+
* show, edit, update, destroy) mapping to specific controller methods.
|
|
256
|
+
*
|
|
257
|
+
* @param name - The resource name (e.g., 'users').
|
|
258
|
+
* @param controller - The controller class handling the resource.
|
|
259
|
+
* @param options - Optional constraints (only/except) for resource actions.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```typescript
|
|
263
|
+
* router.resource('photos', PhotoController);
|
|
264
|
+
* ```
|
|
227
265
|
*/
|
|
228
266
|
resource(name: string, controller: ControllerClass, options?: ResourceOptions): void;
|
|
229
267
|
/**
|