@gravito/radiance 1.0.3 → 1.0.5

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.
Files changed (149) hide show
  1. package/README.md +30 -7
  2. package/README.zh-TW.md +238 -3
  3. package/dist/core/src/Application.d.ts +256 -0
  4. package/dist/core/src/CommandKernel.d.ts +33 -0
  5. package/dist/core/src/ConfigManager.d.ts +65 -0
  6. package/dist/core/src/Container/RequestScopeManager.d.ts +62 -0
  7. package/dist/core/src/Container/RequestScopeMetrics.d.ts +144 -0
  8. package/dist/core/src/Container.d.ts +153 -0
  9. package/dist/core/src/ErrorHandler.d.ts +66 -0
  10. package/dist/core/src/Event.d.ts +5 -0
  11. package/dist/core/src/EventManager.d.ts +123 -0
  12. package/dist/core/src/GlobalErrorHandlers.d.ts +47 -0
  13. package/dist/core/src/GravitoServer.d.ts +28 -0
  14. package/dist/core/src/HookManager.d.ts +435 -0
  15. package/dist/core/src/Listener.d.ts +4 -0
  16. package/dist/core/src/Logger.d.ts +20 -0
  17. package/dist/core/src/PlanetCore.d.ts +402 -0
  18. package/dist/core/src/RequestContext.d.ts +97 -0
  19. package/dist/core/src/Route.d.ts +36 -0
  20. package/dist/core/src/Router.d.ts +270 -0
  21. package/dist/core/src/ServiceProvider.d.ts +178 -0
  22. package/dist/core/src/adapters/GravitoEngineAdapter.d.ts +27 -0
  23. package/dist/core/src/adapters/bun/BunContext.d.ts +54 -0
  24. package/dist/core/src/adapters/bun/BunNativeAdapter.d.ts +66 -0
  25. package/dist/core/src/adapters/bun/BunRequest.d.ts +31 -0
  26. package/dist/core/src/adapters/bun/BunWebSocketHandler.d.ts +48 -0
  27. package/dist/core/src/adapters/bun/RadixNode.d.ts +19 -0
  28. package/dist/core/src/adapters/bun/RadixRouter.d.ts +32 -0
  29. package/dist/core/src/adapters/bun/index.d.ts +7 -0
  30. package/dist/core/src/adapters/bun/types.d.ts +20 -0
  31. package/dist/core/src/adapters/types.d.ts +235 -0
  32. package/dist/core/src/binary/BinaryUtils.d.ts +105 -0
  33. package/dist/core/src/binary/index.d.ts +5 -0
  34. package/dist/core/src/cli/queue-commands.d.ts +6 -0
  35. package/dist/core/src/compat/async-local-storage.d.ts +7 -0
  36. package/dist/core/src/compat/crypto.d.ts +6 -0
  37. package/dist/core/src/engine/AOTRouter.d.ts +139 -0
  38. package/dist/core/src/engine/FastContext.d.ts +141 -0
  39. package/dist/core/src/engine/Gravito.d.ts +131 -0
  40. package/dist/core/src/engine/MinimalContext.d.ts +102 -0
  41. package/dist/core/src/engine/analyzer.d.ts +113 -0
  42. package/dist/core/src/engine/constants.d.ts +23 -0
  43. package/dist/core/src/engine/index.d.ts +26 -0
  44. package/dist/core/src/engine/path.d.ts +26 -0
  45. package/dist/core/src/engine/pool.d.ts +83 -0
  46. package/dist/core/src/engine/types.d.ts +149 -0
  47. package/dist/core/src/error-handling/RequestScopeErrorContext.d.ts +126 -0
  48. package/dist/core/src/events/BackpressureManager.d.ts +215 -0
  49. package/dist/core/src/events/CircuitBreaker.d.ts +229 -0
  50. package/dist/core/src/events/DeadLetterQueue.d.ts +219 -0
  51. package/dist/core/src/events/EventBackend.d.ts +12 -0
  52. package/dist/core/src/events/EventOptions.d.ts +204 -0
  53. package/dist/core/src/events/EventPriorityQueue.d.ts +63 -0
  54. package/dist/core/src/events/FlowControlStrategy.d.ts +109 -0
  55. package/dist/core/src/events/IdempotencyCache.d.ts +60 -0
  56. package/dist/core/src/events/MessageQueueBridge.d.ts +184 -0
  57. package/dist/core/src/events/PriorityEscalationManager.d.ts +82 -0
  58. package/dist/core/src/events/RetryScheduler.d.ts +104 -0
  59. package/dist/core/src/events/WorkerPool.d.ts +98 -0
  60. package/dist/core/src/events/WorkerPoolConfig.d.ts +153 -0
  61. package/dist/core/src/events/WorkerPoolMetrics.d.ts +65 -0
  62. package/dist/core/src/events/aggregation/AggregationWindow.d.ts +77 -0
  63. package/dist/core/src/events/aggregation/DeduplicationManager.d.ts +135 -0
  64. package/dist/core/src/events/aggregation/EventAggregationManager.d.ts +108 -0
  65. package/dist/core/src/events/aggregation/EventBatcher.d.ts +99 -0
  66. package/dist/core/src/events/aggregation/types.d.ts +117 -0
  67. package/dist/core/src/events/index.d.ts +26 -0
  68. package/dist/core/src/events/observability/EventMetrics.d.ts +132 -0
  69. package/dist/core/src/events/observability/EventTracer.d.ts +68 -0
  70. package/dist/core/src/events/observability/EventTracing.d.ts +161 -0
  71. package/dist/core/src/events/observability/OTelEventMetrics.d.ts +332 -0
  72. package/dist/core/src/events/observability/ObservableHookManager.d.ts +108 -0
  73. package/dist/core/src/events/observability/StreamWorkerMetrics.d.ts +76 -0
  74. package/dist/core/src/events/observability/index.d.ts +24 -0
  75. package/dist/core/src/events/observability/metrics-types.d.ts +16 -0
  76. package/dist/core/src/events/queue-core.d.ts +77 -0
  77. package/dist/core/src/events/task-executor.d.ts +51 -0
  78. package/dist/core/src/events/types.d.ts +134 -0
  79. package/dist/core/src/exceptions/AuthenticationException.d.ts +8 -0
  80. package/dist/core/src/exceptions/AuthorizationException.d.ts +8 -0
  81. package/dist/core/src/exceptions/CircularDependencyException.d.ts +9 -0
  82. package/dist/core/src/exceptions/GravitoException.d.ts +23 -0
  83. package/dist/core/src/exceptions/HttpException.d.ts +9 -0
  84. package/dist/core/src/exceptions/ModelNotFoundException.d.ts +10 -0
  85. package/dist/core/src/exceptions/ValidationException.d.ts +22 -0
  86. package/dist/core/src/exceptions/index.d.ts +7 -0
  87. package/dist/core/src/ffi/NativeAccelerator.d.ts +62 -0
  88. package/dist/core/src/ffi/NativeHasher.d.ts +139 -0
  89. package/dist/core/src/ffi/cbor-fallback.d.ts +96 -0
  90. package/dist/core/src/ffi/hash-fallback.d.ts +33 -0
  91. package/dist/core/src/ffi/index.d.ts +10 -0
  92. package/dist/core/src/ffi/types.d.ts +135 -0
  93. package/dist/core/src/health/HealthProvider.d.ts +67 -0
  94. package/dist/core/src/helpers/Arr.d.ts +19 -0
  95. package/dist/core/src/helpers/Str.d.ts +38 -0
  96. package/dist/core/src/helpers/data.d.ts +25 -0
  97. package/dist/core/src/helpers/errors.d.ts +34 -0
  98. package/dist/core/src/helpers/response.d.ts +41 -0
  99. package/dist/core/src/helpers.d.ts +338 -0
  100. package/dist/core/src/hooks/ActionManager.d.ts +132 -0
  101. package/dist/core/src/hooks/AsyncDetector.d.ts +84 -0
  102. package/dist/core/src/hooks/FilterManager.d.ts +71 -0
  103. package/dist/core/src/hooks/MigrationWarner.d.ts +24 -0
  104. package/dist/core/src/hooks/dlq-operations.d.ts +60 -0
  105. package/dist/core/src/hooks/types.d.ts +107 -0
  106. package/dist/core/src/http/CookieJar.d.ts +51 -0
  107. package/dist/core/src/http/cookie.d.ts +29 -0
  108. package/dist/core/src/http/types.d.ts +395 -0
  109. package/dist/core/src/index.d.ts +565 -0
  110. package/dist/core/src/observability/QueueDashboard.d.ts +136 -0
  111. package/dist/core/src/observability/contracts.d.ts +137 -0
  112. package/dist/core/src/reliability/DeadLetterQueueManager.d.ts +349 -0
  113. package/dist/core/src/reliability/RetryPolicy.d.ts +217 -0
  114. package/dist/core/src/reliability/index.d.ts +6 -0
  115. package/dist/core/src/router/ControllerDispatcher.d.ts +12 -0
  116. package/dist/core/src/router/RequestValidator.d.ts +20 -0
  117. package/dist/core/src/runtime/adapter-bun.d.ts +12 -0
  118. package/dist/core/src/runtime/adapter-deno.d.ts +12 -0
  119. package/dist/core/src/runtime/adapter-node.d.ts +12 -0
  120. package/dist/core/src/runtime/adapter-unknown.d.ts +13 -0
  121. package/dist/core/src/runtime/archive.d.ts +17 -0
  122. package/dist/core/src/runtime/compression.d.ts +21 -0
  123. package/dist/core/src/runtime/deep-equals.d.ts +56 -0
  124. package/dist/core/src/runtime/detection.d.ts +22 -0
  125. package/dist/core/src/runtime/escape.d.ts +34 -0
  126. package/dist/core/src/runtime/index.d.ts +44 -0
  127. package/dist/core/src/runtime/markdown.d.ts +44 -0
  128. package/dist/core/src/runtime/types.d.ts +436 -0
  129. package/dist/core/src/runtime-helpers.d.ts +67 -0
  130. package/dist/core/src/runtime.d.ts +11 -0
  131. package/dist/core/src/security/Encrypter.d.ts +33 -0
  132. package/dist/core/src/security/Hasher.d.ts +29 -0
  133. package/dist/core/src/testing/HttpTester.d.ts +40 -0
  134. package/dist/core/src/testing/TestResponse.d.ts +78 -0
  135. package/dist/core/src/testing/index.d.ts +2 -0
  136. package/dist/core/src/transpiler-utils.d.ts +170 -0
  137. package/dist/core/src/types/events.d.ts +94 -0
  138. package/dist/index.js +1 -274
  139. package/dist/index.js.map +3 -10
  140. package/dist/radiance/src/BroadcastManager.d.ts +124 -0
  141. package/dist/radiance/src/OrbitRadiance.d.ts +98 -0
  142. package/dist/radiance/src/channels/Channel.d.ts +86 -0
  143. package/dist/radiance/src/drivers/AblyDriver.d.ts +73 -0
  144. package/dist/radiance/src/drivers/BroadcastDriver.d.ts +50 -0
  145. package/dist/radiance/src/drivers/PusherDriver.d.ts +95 -0
  146. package/dist/radiance/src/drivers/RedisDriver.d.ts +83 -0
  147. package/dist/radiance/src/drivers/WebSocketDriver.d.ts +89 -0
  148. package/dist/radiance/src/index.d.ts +39 -0
  149. package/package.json +10 -6
@@ -0,0 +1,170 @@
1
+ /**
2
+ * @fileoverview Transpiler 工具庫 - AST 層級代碼分析
3
+ *
4
+ * 使用 Bun.Transpiler API 進行精確的 handler 函式分析,
5
+ * 相比傳統字串匹配,精確度從 ~85% 提升至 ~99%。
6
+ *
7
+ * 核心策略:
8
+ * 1. 使用 transformSync() 標準化代碼格式(統一縮排、引號等)
9
+ * 2. 對轉換後的代碼使用精確的正規表達式匹配 member expression
10
+ * 3. 區分 API 呼叫(.req.header())與變數名稱(const header = ...)
11
+ * 4. 支援解構賦值模式(const { header } = ctx.req)
12
+ * 5. 快取 Transpiler 實例(性能提升 5.9x)+ LRU 快取結果(額外 128x)
13
+ *
14
+ * @module @gravito/core/transpiler-utils
15
+ * @since 3.1.0
16
+ */
17
+ /**
18
+ * TranspilerCache - 管理 Bun.Transpiler 實例與結果快取
19
+ *
20
+ * 避免重複建立 Transpiler(每次建立約需 40µs),
21
+ * 並快取 transformSync 結果(重用快取比每次 transform 快 128x)。
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const cache = TranspilerCache.getInstance()
26
+ * const transformed = cache.transform(handlerSource)
27
+ * ```
28
+ */
29
+ export declare class TranspilerCache {
30
+ private static instance;
31
+ /** 共享的 Bun.Transpiler 實例(避免重複建立) */
32
+ private readonly transpiler;
33
+ /** LRU 快取:原始代碼 → 轉換結果 */
34
+ private readonly cache;
35
+ /** 快取大小上限 */
36
+ private readonly maxSize;
37
+ /** 快取 TTL(毫秒),預設 5 分鐘 */
38
+ private readonly ttlMs;
39
+ private constructor();
40
+ /**
41
+ * 取得單例實例
42
+ * 確保全程只建立一個 Transpiler 實例
43
+ */
44
+ static getInstance(): TranspilerCache;
45
+ /**
46
+ * 重置單例(主要用於測試)
47
+ */
48
+ static resetInstance(): void;
49
+ /**
50
+ * 轉換代碼並快取結果
51
+ *
52
+ * 先嘗試從快取取得,若未命中則呼叫 transformSync 並儲存結果。
53
+ * 快取已滿時淘汰最舊的條目(近似 LRU)。
54
+ *
55
+ * 處理兩個 Bun.Transpiler 邊緣案例:
56
+ * 1. 箭頭函式表達式:`async (ctx) => ...` → transformSync 返回空字串
57
+ * 解法:包裝成 `const __fn = <source>` 後再轉換
58
+ * 2. 匿名函式表達式:`function(ctx) {...}` → transformSync 拋出 Parse error
59
+ * 解法:同樣包裝後轉換
60
+ *
61
+ * @param source - 原始 handler 函式字串
62
+ * @returns 轉換後的標準化代碼,若完全失敗則回傳 null
63
+ */
64
+ transform(source: string): string | null;
65
+ /**
66
+ * 實際執行 transformSync,處理箭頭函式和匿名函式的邊緣案例
67
+ *
68
+ * @param source - 原始代碼字串
69
+ * @returns 轉換後的代碼,或失敗時回傳 null
70
+ */
71
+ private doTransform;
72
+ /**
73
+ * 將代碼包裝成賦值語句後再 transform
74
+ *
75
+ * 用於處理無法直接 transform 的函式表達式。
76
+ * 包裝格式:`const __fn = <source>`
77
+ *
78
+ * @param source - 原始函式字串
79
+ * @returns 包裝後的轉換結果,或失敗時回傳 null
80
+ */
81
+ private transformWrapped;
82
+ /**
83
+ * 取得目前快取大小
84
+ */
85
+ get size(): number;
86
+ /**
87
+ * 清除所有快取條目
88
+ */
89
+ clear(): void;
90
+ }
91
+ /**
92
+ * Transpiler 分析的返回結果
93
+ * 與 HandlerAnalysis 介面對應
94
+ */
95
+ export interface TranspilerAnalysisResult {
96
+ usesHeaders: boolean;
97
+ usesQuery: boolean;
98
+ usesBody: boolean;
99
+ usesParams: boolean;
100
+ isAsync: boolean;
101
+ }
102
+ /**
103
+ * 使用 Bun.Transpiler 進行精確的 handler 靜態分析
104
+ *
105
+ * 相比字串匹配,此函式能正確區分:
106
+ * - API 呼叫(`ctx.req.header(name)`)vs 變數名稱(`const header = '...'`)
107
+ * - 解構賦值(`const { header } = ctx.req`)
108
+ * - Minified 代碼(transformSync 先標準化)
109
+ * - 箭頭函式與匿名函式(包裝策略處理 Bun.Transpiler 邊緣案例)
110
+ *
111
+ * 若 Transpiler 轉換失敗,會自動 fallback 到字串匹配模式。
112
+ *
113
+ * ## isAsync 特殊處理
114
+ *
115
+ * `isAsync` 直接從原始碼偵測 `async` 關鍵字,而不是從 transformSync 結果:
116
+ * - 箭頭函式 `async (ctx) => ...` 的 transformSync 返回空字串
117
+ * - `async` 關鍵字本身不存在假陽性問題
118
+ *
119
+ * @param source - handler 函式的字串表示(通常來自 handler.toString())
120
+ * @returns 分析結果,或在 fallback 模式下的近似結果
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const handler = async (ctx) => {
125
+ * const name = ctx.req.query('name')
126
+ * return ctx.json({ name })
127
+ * }
128
+ * const result = analyzeHandlerWithTranspiler(handler.toString())
129
+ * // result.usesQuery === true
130
+ * // result.usesHeaders === false(即使有 'header' 字串,也不會誤判)
131
+ * // result.isAsync === true(即使是箭頭函式也能正確偵測)
132
+ * ```
133
+ */
134
+ export declare function analyzeHandlerWithTranspiler(source: string): TranspilerAnalysisResult;
135
+ /**
136
+ * 測試 handler 源代碼是否存取特定的 req 成員屬性
137
+ *
138
+ * 工具函式,方便在 Gravito.ts 等地方進行特定屬性的快速檢測。
139
+ *
140
+ * @param source - handler 函式的字串表示
141
+ * @param property - 要測試的屬性名稱(如 'header', 'query', 'body')
142
+ * @returns 若該屬性被存取則回傳 true
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const src = handler.toString()
147
+ * if (hasReqMemberAccess(src, 'header')) {
148
+ * // handler 存取了 header
149
+ * }
150
+ * ```
151
+ */
152
+ export declare function hasReqMemberAccess(source: string, property: string): boolean;
153
+ /**
154
+ * 判斷 handler 是否為非同步函式
155
+ *
156
+ * 直接從原始碼偵測 `async` 關鍵字,不依賴 transformSync 結果,
157
+ * 因為箭頭函式的 transformSync 返回空字串。
158
+ * `async` 關鍵字本身不存在假陽性問題。
159
+ *
160
+ * @param source - handler 函式的字串表示
161
+ * @returns 若為 async 函式則回傳 true
162
+ */
163
+ export declare function isAsyncHandler(source: string): boolean;
164
+ /**
165
+ * 預熱 Transpiler 快取
166
+ *
167
+ * 在應用啟動時呼叫,觸發 Transpiler 實例建立,
168
+ * 避免第一個請求時的冷啟動延遲。
169
+ */
170
+ export declare function warmupTranspilerCache(): void;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Event system type definitions.
3
+ */
4
+ /**
5
+ * Listener interface.
6
+ *
7
+ * All event listeners must implement this interface.
8
+ */
9
+ export interface Listener<TEvent extends Event = Event> {
10
+ /**
11
+ * Handle an event.
12
+ * @param event - Event instance
13
+ */
14
+ handle(event: TEvent): Promise<void> | void;
15
+ }
16
+ /**
17
+ * Marker interface for listeners that should be queued.
18
+ *
19
+ * Listeners implementing this interface can be dispatched asynchronously via a queue.
20
+ */
21
+ export interface ShouldQueue {
22
+ /**
23
+ * Queue name (optional).
24
+ */
25
+ queue?: string;
26
+ /**
27
+ * Connection name (optional).
28
+ */
29
+ connection?: string;
30
+ /**
31
+ * Delay before execution (seconds).
32
+ */
33
+ delay?: number;
34
+ }
35
+ /**
36
+ * Marker interface for events that should be broadcast.
37
+ *
38
+ * Events implementing this interface can be automatically broadcast to clients.
39
+ */
40
+ export interface ShouldBroadcast {
41
+ /**
42
+ * Define the broadcast channel.
43
+ * @returns Channel name or channel object
44
+ */
45
+ broadcastOn(): string | Channel;
46
+ /**
47
+ * Define broadcast payload (optional).
48
+ * If omitted, public event properties will be used.
49
+ * @returns Broadcast payload
50
+ */
51
+ broadcastWith?(): Record<string, unknown>;
52
+ /**
53
+ * Define the broadcast event name (optional).
54
+ * If omitted, the event class name will be used.
55
+ * @returns Event name
56
+ */
57
+ broadcastAs?(): string;
58
+ }
59
+ /**
60
+ * Channel interface.
61
+ */
62
+ export interface Channel {
63
+ /**
64
+ * Channel name.
65
+ */
66
+ name: string;
67
+ /**
68
+ * Channel type.
69
+ */
70
+ type: 'public' | 'private' | 'presence';
71
+ }
72
+ /**
73
+ * Base event class.
74
+ *
75
+ * All events should extend this class.
76
+ */
77
+ export declare abstract class Event {
78
+ /**
79
+ * Whether this event should be broadcast.
80
+ */
81
+ shouldBroadcast(): boolean;
82
+ /**
83
+ * Get broadcast channel.
84
+ */
85
+ getBroadcastChannel(): string | Channel | null;
86
+ /**
87
+ * Get broadcast payload.
88
+ */
89
+ getBroadcastData(): Record<string, unknown>;
90
+ /**
91
+ * Get broadcast event name.
92
+ */
93
+ getBroadcastEventName(): string;
94
+ }
package/dist/index.js CHANGED
@@ -1,276 +1,3 @@
1
- // src/BroadcastManager.ts
2
- class BroadcastManager {
3
- core;
4
- driver = null;
5
- authCallback;
6
- constructor(core) {
7
- this.core = core;
8
- }
9
- setDriver(driver) {
10
- this.driver = driver;
11
- }
12
- setAuthCallback(callback) {
13
- this.authCallback = callback;
14
- }
15
- async broadcast(_event, channel, data, eventName) {
16
- if (!this.driver) {
17
- this.core.logger.warn("[BroadcastManager] No broadcast driver set, skipping broadcast");
18
- return;
19
- }
20
- try {
21
- await this.driver.broadcast(channel, eventName, data);
22
- } catch (error) {
23
- this.core.logger.error(`[BroadcastManager] Failed to broadcast event ${eventName}:`, error);
24
- throw error;
25
- }
26
- }
27
- async authorizeChannel(channel, socketId, userId) {
28
- if (this.authCallback) {
29
- const authorized = await this.authCallback(channel, socketId, userId);
30
- if (!authorized) {
31
- return null;
32
- }
33
- }
34
- if (this.driver?.authorizeChannel) {
35
- return await this.driver.authorizeChannel(channel, socketId, userId);
36
- }
37
- if (channel.startsWith("private-") || channel.startsWith("presence-")) {
38
- return null;
39
- }
40
- return { auth: "" };
41
- }
42
- }
43
- // src/channels/Channel.ts
44
- class PublicChannel {
45
- name;
46
- type = "public";
47
- constructor(name) {
48
- this.name = name;
49
- }
50
- }
51
-
52
- class PrivateChannel {
53
- name;
54
- type = "private";
55
- constructor(name) {
56
- this.name = name;
57
- }
58
- }
59
-
60
- class PresenceChannel {
61
- name;
62
- type = "presence";
63
- constructor(name) {
64
- this.name = name;
65
- }
66
- }
67
- // src/drivers/AblyDriver.ts
68
- class AblyDriver {
69
- config;
70
- baseUrl = "https://rest.ably.io";
71
- constructor(config) {
72
- this.config = config;
73
- }
74
- async broadcast(channel, event, data) {
75
- const path = `/channels/${channel.name}/messages`;
76
- const auth = btoa(this.config.apiKey);
77
- const response = await fetch(`${this.baseUrl}${path}`, {
78
- method: "POST",
79
- headers: {
80
- Authorization: `Basic ${auth}`,
81
- "Content-Type": "application/json"
82
- },
83
- body: JSON.stringify({
84
- name: event,
85
- data
86
- })
87
- });
88
- if (!response.ok) {
89
- const error = await response.text();
90
- throw new Error(`Failed to broadcast via Ably: ${error}`);
91
- }
92
- }
93
- async authorizeChannel(channel, _socketId, userId) {
94
- return {
95
- auth: this.config.apiKey,
96
- ...channel.startsWith("presence-") && userId ? {
97
- channel_data: JSON.stringify({
98
- clientId: userId.toString()
99
- })
100
- } : {}
101
- };
102
- }
103
- }
104
- // src/drivers/PusherDriver.ts
105
- class PusherDriver {
106
- config;
107
- baseUrl;
108
- constructor(config) {
109
- this.config = config;
110
- const cluster = this.config.cluster || "mt1";
111
- this.baseUrl = `https://api-${cluster}.pusher.com`;
112
- }
113
- async broadcast(channel, event, data) {
114
- const path = `/apps/${this.config.appId}/events`;
115
- const body = {
116
- name: event,
117
- channel: channel.name,
118
- data: JSON.stringify(data)
119
- };
120
- const timestamp = Math.floor(Date.now() / 1000);
121
- const queryString = new URLSearchParams({
122
- auth_key: this.config.key,
123
- auth_timestamp: timestamp.toString(),
124
- auth_version: "1.0",
125
- body_md5: this.md5(JSON.stringify(body))
126
- });
127
- const authString = `POST
128
- ${path}
129
- ${queryString.toString()}`;
130
- const authSignature = await this.hmacSHA256(authString, this.config.secret);
131
- queryString.append("auth_signature", authSignature);
132
- const response = await fetch(`${this.baseUrl}${path}?${queryString.toString()}`, {
133
- method: "POST",
134
- headers: {
135
- "Content-Type": "application/json"
136
- },
137
- body: JSON.stringify(body)
138
- });
139
- if (!response.ok) {
140
- const error = await response.text();
141
- throw new Error(`Failed to broadcast via Pusher: ${error}`);
142
- }
143
- }
144
- async authorizeChannel(channel, socketId, userId) {
145
- const stringToSign = `${socketId}:${channel}`;
146
- const signature = await this.hmacSHA256(stringToSign, this.config.secret);
147
- if (channel.startsWith("presence-")) {
148
- const channelData = JSON.stringify({
149
- user_id: userId?.toString(),
150
- user_info: {}
151
- });
152
- return {
153
- auth: `${this.config.key}:${signature}`,
154
- channel_data: channelData
155
- };
156
- }
157
- return {
158
- auth: `${this.config.key}:${signature}`
159
- };
160
- }
161
- async hmacSHA256(message, secret) {
162
- const encoder = new TextEncoder;
163
- const keyData = encoder.encode(secret);
164
- const messageData = encoder.encode(message);
165
- const key = await crypto.subtle.importKey("raw", keyData, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
166
- const signature = await crypto.subtle.sign("HMAC", key, messageData);
167
- const hashArray = Array.from(new Uint8Array(signature));
168
- return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
169
- }
170
- md5(text) {
171
- return btoa(text).replace(/[+/=]/g, "").substring(0, 32);
172
- }
173
- }
174
- // src/drivers/RedisDriver.ts
175
- class RedisDriver {
176
- config;
177
- redis = null;
178
- constructor(config) {
179
- this.config = config;
180
- }
181
- setRedisClient(client) {
182
- this.redis = client;
183
- }
184
- async broadcast(channel, event, data) {
185
- if (!this.redis) {
186
- throw new Error("Redis client not set. Please install a Redis client and call setRedisClient()");
187
- }
188
- const prefix = this.config.keyPrefix || "gravito:broadcast:";
189
- const channelName = `${prefix}${channel.name}`;
190
- const message = JSON.stringify({
191
- event,
192
- data,
193
- channel: channel.name,
194
- type: channel.type
195
- });
196
- await this.redis.publish(channelName, message);
197
- }
198
- }
199
- // src/drivers/WebSocketDriver.ts
200
- class WebSocketDriver {
201
- config;
202
- constructor(config) {
203
- this.config = config;
204
- }
205
- async broadcast(channel, event, data) {
206
- const message = JSON.stringify({
207
- channel: channel.name,
208
- event,
209
- data
210
- });
211
- let connections = this.config.getConnections();
212
- if (this.config.filterConnectionsByChannel) {
213
- connections = this.config.filterConnectionsByChannel(channel.name);
214
- }
215
- for (const connection of connections) {
216
- if (connection.readyState === 1) {
217
- try {
218
- connection.send(message);
219
- } catch (error) {
220
- console.error("Failed to send WebSocket message:", error);
221
- }
222
- }
223
- }
224
- }
225
- }
226
- // src/OrbitRadiance.ts
227
- class OrbitRadiance {
228
- options;
229
- constructor(options) {
230
- this.options = options;
231
- }
232
- static configure(options) {
233
- return new OrbitRadiance(options);
234
- }
235
- async install(core) {
236
- const manager = new BroadcastManager(core);
237
- let driver;
238
- switch (this.options.driver) {
239
- case "pusher":
240
- driver = new PusherDriver(this.options.config);
241
- break;
242
- case "ably":
243
- driver = new AblyDriver(this.options.config);
244
- break;
245
- case "redis": {
246
- driver = new RedisDriver(this.options.config);
247
- const redisClient = core.container.make("redis");
248
- if (redisClient) {
249
- driver.setRedisClient(redisClient);
250
- }
251
- break;
252
- }
253
- case "websocket":
254
- driver = new WebSocketDriver(this.options.config);
255
- break;
256
- default:
257
- throw new Error(`Unsupported broadcast driver: ${this.options.driver}`);
258
- }
259
- manager.setDriver(driver);
260
- if (this.options.authorizeChannel) {
261
- manager.setAuthCallback(this.options.authorizeChannel);
262
- }
263
- core.container.instance("broadcast", manager);
264
- if (core.events) {
265
- core.events.setBroadcastManager({
266
- broadcast: async (event, channel, data, eventName) => {
267
- await manager.broadcast(event, channel, data, eventName);
268
- }
269
- });
270
- }
271
- core.logger.info(`[OrbitRadiance] Installed with ${this.options.driver} driver`);
272
- }
273
- }
274
1
  export {
275
2
  WebSocketDriver,
276
3
  RedisDriver,
@@ -283,4 +10,4 @@ export {
283
10
  AblyDriver
284
11
  };
285
12
 
286
- //# debugId=B3E6ADF62B34DDC264756E2164756E21
13
+ //# debugId=00053E5676168F4764756E2164756E21
package/dist/index.js.map CHANGED
@@ -1,16 +1,9 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/BroadcastManager.ts", "../src/channels/Channel.ts", "../src/drivers/AblyDriver.ts", "../src/drivers/PusherDriver.ts", "../src/drivers/RedisDriver.ts", "../src/drivers/WebSocketDriver.ts", "../src/OrbitRadiance.ts"],
3
+ "sources": [],
4
4
  "sourcesContent": [
5
- "import type { PlanetCore } from '@gravito/core'\nimport type { BroadcastDriver } from './drivers/BroadcastDriver'\n\n/**\n * Channel authorization callback.\n */\nexport type ChannelAuthorizationCallback = (\n channel: string,\n socketId: string,\n userId?: string | number\n) => Promise<boolean>\n\n/**\n * Broadcast manager.\n *\n * Responsible for managing the broadcast driver and handling broadcast requests.\n */\nexport class BroadcastManager {\n private driver: BroadcastDriver | null = null\n private authCallback?: ChannelAuthorizationCallback\n\n constructor(private core: PlanetCore) {}\n\n /**\n * Set the broadcast driver.\n *\n * @param driver - The broadcast driver to use.\n */\n setDriver(driver: BroadcastDriver): void {\n this.driver = driver\n }\n\n /**\n * Set the channel authorization callback.\n *\n * @param callback - The callback function for channel authorization.\n */\n setAuthCallback(callback: ChannelAuthorizationCallback): void {\n this.authCallback = callback\n }\n\n /**\n * Broadcast an event.\n *\n * @param _event - Event instance (unused in current implementation, but kept for signature compatibility).\n * @param channel - Channel object containing name and type.\n * @param data - Event payload.\n * @param eventName - Event name.\n * @returns A promise that resolves when the event is broadcast.\n */\n async broadcast(\n _event: unknown,\n channel: { name: string; type: string },\n data: Record<string, unknown>,\n eventName: string\n ): Promise<void> {\n if (!this.driver) {\n this.core.logger.warn('[BroadcastManager] No broadcast driver set, skipping broadcast')\n return\n }\n\n try {\n await this.driver.broadcast(channel, eventName, data)\n } catch (error) {\n this.core.logger.error(`[BroadcastManager] Failed to broadcast event ${eventName}:`, error)\n throw error\n }\n }\n\n /**\n * Authorize channel access.\n *\n * @param channel - Channel name.\n * @param socketId - Socket ID.\n * @param userId - User ID (optional).\n * @returns A promise resolving to the authorization payload or null if unauthorized.\n */\n async authorizeChannel(\n channel: string,\n socketId: string,\n userId?: string | number\n ): Promise<{ auth: string; channel_data?: string } | null> {\n // Check authorization callback first.\n if (this.authCallback) {\n const authorized = await this.authCallback(channel, socketId, userId)\n if (!authorized) {\n return null\n }\n }\n\n // If the driver supports authorization, use it.\n if (this.driver?.authorizeChannel) {\n return await this.driver.authorizeChannel(channel, socketId, userId)\n }\n\n // Default deny for private/presence channels.\n if (channel.startsWith('private-') || channel.startsWith('presence-')) {\n return null\n }\n\n // Public channels do not require authorization.\n return { auth: '' }\n }\n}\n",
6
- "/**\n * Base channel interface.\n */\nexport interface Channel {\n /**\n * Channel name.\n */\n name: string\n\n /**\n * Channel type.\n */\n type: 'public' | 'private' | 'presence'\n}\n\n/**\n * Public channel.\n */\nexport class PublicChannel implements Channel {\n type = 'public' as const\n\n constructor(public name: string) {}\n}\n\n/**\n * Private channel.\n */\nexport class PrivateChannel implements Channel {\n type = 'private' as const\n\n constructor(public name: string) {}\n}\n\n/**\n * Presence channel (can track online users).\n */\nexport class PresenceChannel implements Channel {\n type = 'presence' as const\n\n constructor(public name: string) {}\n}\n",
7
- "import type { BroadcastDriver } from './BroadcastDriver'\n\n/**\n * Ably driver configuration.\n */\nexport interface AblyDriverConfig {\n apiKey: string\n}\n\n/**\n * Ably driver.\n *\n * Broadcasts through the Ably service.\n */\nexport class AblyDriver implements BroadcastDriver {\n private baseUrl = 'https://rest.ably.io'\n\n constructor(private config: AblyDriverConfig) {}\n\n async broadcast(\n channel: { name: string; type: string },\n event: string,\n data: Record<string, unknown>\n ): Promise<void> {\n const path = `/channels/${channel.name}/messages`\n const auth = btoa(this.config.apiKey)\n\n const response = await fetch(`${this.baseUrl}${path}`, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${auth}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n name: event,\n data,\n }),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to broadcast via Ably: ${error}`)\n }\n }\n\n async authorizeChannel(\n channel: string,\n _socketId: string,\n userId?: string | number\n ): Promise<{ auth: string; channel_data?: string }> {\n // Ably uses a different authorization mechanism.\n // This is only a basic implementation.\n return {\n auth: this.config.apiKey,\n ...(channel.startsWith('presence-') && userId\n ? {\n channel_data: JSON.stringify({\n clientId: userId.toString(),\n }),\n }\n : {}),\n }\n }\n}\n",
8
- "import type { BroadcastDriver } from './BroadcastDriver'\n\n/**\n * Pusher driver configuration.\n */\nexport interface PusherDriverConfig {\n appId: string\n key: string\n secret: string\n cluster?: string\n useTLS?: boolean\n}\n\n/**\n * Pusher driver.\n *\n * Broadcasts through the Pusher service.\n */\nexport class PusherDriver implements BroadcastDriver {\n private baseUrl: string\n\n constructor(private config: PusherDriverConfig) {\n const cluster = this.config.cluster || 'mt1'\n this.baseUrl = `https://api-${cluster}.pusher.com`\n }\n\n async broadcast(\n channel: { name: string; type: string },\n event: string,\n data: Record<string, unknown>\n ): Promise<void> {\n const path = `/apps/${this.config.appId}/events`\n const body = {\n name: event,\n channel: channel.name,\n data: JSON.stringify(data),\n }\n\n const timestamp = Math.floor(Date.now() / 1000)\n const queryString = new URLSearchParams({\n auth_key: this.config.key,\n auth_timestamp: timestamp.toString(),\n auth_version: '1.0',\n body_md5: this.md5(JSON.stringify(body)),\n })\n\n const authString = `POST\\n${path}\\n${queryString.toString()}`\n const authSignature = await this.hmacSHA256(authString, this.config.secret)\n\n queryString.append('auth_signature', authSignature)\n\n const response = await fetch(`${this.baseUrl}${path}?${queryString.toString()}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n const error = await response.text()\n throw new Error(`Failed to broadcast via Pusher: ${error}`)\n }\n }\n\n async authorizeChannel(\n channel: string,\n socketId: string,\n userId?: string | number\n ): Promise<{ auth: string; channel_data?: string }> {\n const stringToSign = `${socketId}:${channel}`\n const signature = await this.hmacSHA256(stringToSign, this.config.secret)\n\n if (channel.startsWith('presence-')) {\n const channelData = JSON.stringify({\n user_id: userId?.toString(),\n user_info: {},\n })\n return {\n auth: `${this.config.key}:${signature}`,\n channel_data: channelData,\n }\n }\n\n return {\n auth: `${this.config.key}:${signature}`,\n }\n }\n\n private async hmacSHA256(message: string, secret: string): Promise<string> {\n // Uses the Web Crypto API.\n const encoder = new TextEncoder()\n const keyData = encoder.encode(secret)\n const messageData = encoder.encode(message)\n\n const key = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n )\n\n const signature = await crypto.subtle.sign('HMAC', key, messageData)\n const hashArray = Array.from(new Uint8Array(signature))\n return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')\n }\n\n private md5(text: string): string {\n // Simplified MD5 implementation (production should use a proper MD5 implementation).\n return btoa(text).replace(/[+/=]/g, '').substring(0, 32)\n }\n}\n",
9
- "import type { BroadcastDriver } from './BroadcastDriver'\n\n/**\n * Redis driver configuration.\n */\nexport interface RedisDriverConfig {\n url?: string\n host?: string\n port?: number\n password?: string\n db?: number\n keyPrefix?: string\n}\n\n/**\n * Redis driver.\n *\n * Broadcasts via Redis Pub/Sub.\n * Requires an external Redis client.\n */\nexport class RedisDriver implements BroadcastDriver {\n private redis: {\n publish(channel: string, message: string): Promise<number>\n } | null = null\n\n constructor(private config: RedisDriverConfig) {\n // The Redis client should be injected from the outside.\n // This class only provides the adapter interface.\n }\n\n /**\n * Set Redis client.\n */\n setRedisClient(client: { publish(channel: string, message: string): Promise<number> }): void {\n this.redis = client\n }\n\n async broadcast(\n channel: { name: string; type: string },\n event: string,\n data: Record<string, unknown>\n ): Promise<void> {\n if (!this.redis) {\n throw new Error(\n 'Redis client not set. Please install a Redis client and call setRedisClient()'\n )\n }\n\n const prefix = this.config.keyPrefix || 'gravito:broadcast:'\n const channelName = `${prefix}${channel.name}`\n const message = JSON.stringify({\n event,\n data,\n channel: channel.name,\n type: channel.type,\n })\n\n await this.redis.publish(channelName, message)\n }\n}\n",
10
- "import type { BroadcastDriver } from './BroadcastDriver'\n\n/**\n * WebSocket connection interface.\n */\nexport interface WebSocketConnection {\n send(data: string): void\n close(): void\n readyState: number\n}\n\n/**\n * WebSocket driver configuration.\n */\nexport interface WebSocketDriverConfig {\n /**\n * Get all active connections.\n */\n getConnections(): WebSocketConnection[]\n\n /**\n * Filter connections by channel (optional).\n */\n filterConnectionsByChannel?(channel: string): WebSocketConnection[]\n}\n\n/**\n * WebSocket driver.\n *\n * Broadcasts via WebSocket.\n * Suitable for single-node deployments or when direct WebSocket connections are required.\n */\nexport class WebSocketDriver implements BroadcastDriver {\n constructor(private config: WebSocketDriverConfig) {}\n\n async broadcast(\n channel: { name: string; type: string },\n event: string,\n data: Record<string, unknown>\n ): Promise<void> {\n const message = JSON.stringify({\n channel: channel.name,\n event,\n data,\n })\n\n let connections = this.config.getConnections()\n\n // If channel filtering is supported, use it.\n if (this.config.filterConnectionsByChannel) {\n connections = this.config.filterConnectionsByChannel(channel.name)\n }\n\n // Send to all connections.\n for (const connection of connections) {\n if (connection.readyState === 1) {\n // WebSocket.OPEN\n try {\n connection.send(message)\n } catch (error) {\n // Ignore failed sends.\n console.error('Failed to send WebSocket message:', error)\n }\n }\n }\n }\n}\n",
11
- "import type { GravitoOrbit, PlanetCore } from '@gravito/core'\nimport { BroadcastManager } from './BroadcastManager'\nimport type { AblyDriverConfig } from './drivers/AblyDriver'\nimport { AblyDriver } from './drivers/AblyDriver'\nimport type { BroadcastDriver } from './drivers/BroadcastDriver'\nimport type { PusherDriverConfig } from './drivers/PusherDriver'\nimport { PusherDriver } from './drivers/PusherDriver'\nimport type { RedisDriverConfig } from './drivers/RedisDriver'\nimport { RedisDriver } from './drivers/RedisDriver'\nimport type { WebSocketDriverConfig } from './drivers/WebSocketDriver'\nimport { WebSocketDriver } from './drivers/WebSocketDriver'\n\n/**\n * Options for configuring OrbitRadiance broadcasting.\n * @public\n */\nexport interface OrbitRadianceOptions {\n /**\n * The broadcast driver to use.\n * - pusher: Official Pusher API\n * - ably: Ably Realtime API\n * - redis: Redis Pub/Sub for custom backends\n * - websocket: Native WebSocket (Experimental)\n */\n driver: 'pusher' | 'ably' | 'redis' | 'websocket'\n\n /**\n * Specific configuration for the selected driver.\n */\n config: PusherDriverConfig | AblyDriverConfig | RedisDriverConfig | WebSocketDriverConfig\n\n /**\n * Optional callback to handle private channel authorization.\n *\n * @param channel - The channel name being accessed.\n * @param socketId - The unique socket ID from the client.\n * @param userId - Optional authenticated user ID.\n * @returns Promise resolving to true if authorized.\n */\n authorizeChannel?: (\n channel: string,\n socketId: string,\n userId?: string | number\n ) => Promise<boolean>\n}\n\n/**\n * OrbitRadiance provides real-time event broadcasting capabilities.\n * It abstracts various delivery providers (Pusher, Ably, etc.) and integrates\n * seamlessly with Gravito's Event system.\n *\n * @example\n * ```typescript\n * const radiance = new OrbitRadiance({\n * driver: 'pusher',\n * config: { appId: '...', key: '...', secret: '...' }\n * });\n * core.addOrbit(radiance);\n *\n * // Broadcasting an event\n * await ctx.get('broadcast').broadcast('my-channel', 'my-event', { data: 'hello' });\n * ```\n * @public\n */\nexport class OrbitRadiance implements GravitoOrbit {\n private options: OrbitRadianceOptions\n\n constructor(options: OrbitRadianceOptions) {\n this.options = options\n }\n\n /**\n * Configure OrbitRadiance.\n */\n static configure(options: OrbitRadianceOptions): OrbitRadiance {\n return new OrbitRadiance(options)\n }\n\n async install(core: PlanetCore): Promise<void> {\n const manager = new BroadcastManager(core)\n\n // Create and set driver.\n let driver: BroadcastDriver\n\n switch (this.options.driver) {\n case 'pusher':\n driver = new PusherDriver(this.options.config as PusherDriverConfig)\n break\n case 'ably':\n driver = new AblyDriver(this.options.config as AblyDriverConfig)\n break\n case 'redis': {\n driver = new RedisDriver(this.options.config as RedisDriverConfig)\n // If a Redis client is provided via core container, set it.\n const redisClient = core.container.make('redis') as\n | { publish(channel: string, message: string): Promise<number> }\n | undefined\n if (redisClient) {\n ;(driver as RedisDriver).setRedisClient(redisClient)\n }\n break\n }\n case 'websocket':\n driver = new WebSocketDriver(this.options.config as WebSocketDriverConfig)\n break\n default:\n throw new Error(`Unsupported broadcast driver: ${this.options.driver}`)\n }\n\n manager.setDriver(driver)\n\n // Set auth callback.\n if (this.options.authorizeChannel) {\n manager.setAuthCallback(this.options.authorizeChannel)\n }\n\n // Register into core container\n core.container.instance('broadcast', manager)\n\n // Integrate with EventManager.\n if (core.events) {\n core.events.setBroadcastManager({\n broadcast: async (event: any, channel: any, data: any, eventName: any) => {\n await manager.broadcast(event, channel, data, eventName)\n },\n })\n }\n\n core.logger.info(`[OrbitRadiance] Installed with ${this.options.driver} driver`)\n }\n}\n\n// Module augmentation for GravitoVariables\ndeclare module '@gravito/core' {\n interface GravitoVariables {\n /** Broadcaster manager for real-time events */\n broadcast?: BroadcastManager\n }\n}\n"
12
5
  ],
13
- "mappings": "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",
14
- "debugId": "B3E6ADF62B34DDC264756E2164756E21",
6
+ "mappings": "",
7
+ "debugId": "00053E5676168F4764756E2164756E21",
15
8
  "names": []
16
9
  }