@aurabase/aurabase-js 0.3.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.
Files changed (344) hide show
  1. package/.changeset/config.json +11 -0
  2. package/CHANGELOG.md +30 -0
  3. package/LICENSE +21 -0
  4. package/README.md +833 -0
  5. package/package.json +90 -0
  6. package/packages/ai/LICENSE +21 -0
  7. package/packages/ai/README.md +106 -0
  8. package/packages/ai/dist/index.cjs +229 -0
  9. package/packages/ai/dist/index.d.cts +139 -0
  10. package/packages/ai/dist/index.d.ts +139 -0
  11. package/packages/ai/dist/index.js +226 -0
  12. package/packages/ai/node_modules/.bin/esbuild +19 -0
  13. package/packages/ai/node_modules/.bin/tsc +22 -0
  14. package/packages/ai/node_modules/.bin/tsserver +22 -0
  15. package/packages/ai/node_modules/.bin/tsup +22 -0
  16. package/packages/ai/node_modules/.bin/tsup-node +22 -0
  17. package/packages/ai/node_modules/.bin/vite +22 -0
  18. package/packages/ai/node_modules/.bin/vitest +22 -0
  19. package/packages/ai/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  20. package/packages/ai/package.json +61 -0
  21. package/packages/ai/src/AiService.ts +226 -0
  22. package/packages/ai/src/index.ts +18 -0
  23. package/packages/ai/src/sse.ts +141 -0
  24. package/packages/ai/src/types.ts +30 -0
  25. package/packages/ai/tests/chat-stream.test.ts +151 -0
  26. package/packages/ai/tests/rag-namespaces.test.ts +54 -0
  27. package/packages/ai/tests/sse.test.ts +69 -0
  28. package/packages/ai/tsconfig.json +5 -0
  29. package/packages/ai/tsup.config.ts +11 -0
  30. package/packages/aurabase/LICENSE +21 -0
  31. package/packages/aurabase/README.md +64 -0
  32. package/packages/aurabase/dist/AuraClient-DAtDbfPB.d.cts +77 -0
  33. package/packages/aurabase/dist/AuraClient-DAtDbfPB.d.ts +77 -0
  34. package/packages/aurabase/dist/index.cjs +237 -0
  35. package/packages/aurabase/dist/index.d.cts +46 -0
  36. package/packages/aurabase/dist/index.d.ts +46 -0
  37. package/packages/aurabase/dist/index.js +177 -0
  38. package/packages/aurabase/dist/ssr.cjs +224 -0
  39. package/packages/aurabase/dist/ssr.d.cts +65 -0
  40. package/packages/aurabase/dist/ssr.d.ts +65 -0
  41. package/packages/aurabase/dist/ssr.js +214 -0
  42. package/packages/aurabase/node_modules/.bin/esbuild +19 -0
  43. package/packages/aurabase/node_modules/.bin/tsc +22 -0
  44. package/packages/aurabase/node_modules/.bin/tsserver +22 -0
  45. package/packages/aurabase/node_modules/.bin/tsup +22 -0
  46. package/packages/aurabase/node_modules/.bin/tsup-node +22 -0
  47. package/packages/aurabase/node_modules/.bin/vite +22 -0
  48. package/packages/aurabase/node_modules/.bin/vitest +22 -0
  49. package/packages/aurabase/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  50. package/packages/aurabase/package.json +80 -0
  51. package/packages/aurabase/src/AuraClient.ts +237 -0
  52. package/packages/aurabase/src/index.ts +152 -0
  53. package/packages/aurabase/src/ssr.ts +156 -0
  54. package/packages/aurabase/tests/ai-streaming-rag-e2e.test.ts +82 -0
  55. package/packages/aurabase/tests/ai.test.ts +111 -0
  56. package/packages/aurabase/tests/auth-admin.test.ts +515 -0
  57. package/packages/aurabase/tests/auth-e2e.test.ts +135 -0
  58. package/packages/aurabase/tests/auth-hardening.test.ts +206 -0
  59. package/packages/aurabase/tests/auth.test.ts +947 -0
  60. package/packages/aurabase/tests/database.test.ts +230 -0
  61. package/packages/aurabase/tests/db-types-e2e.test.ts +217 -0
  62. package/packages/aurabase/tests/dispose.test.ts +23 -0
  63. package/packages/aurabase/tests/foreign-token.e2e.test.ts +129 -0
  64. package/packages/aurabase/tests/functions.test.ts +107 -0
  65. package/packages/aurabase/tests/integration.test.ts +413 -0
  66. package/packages/aurabase/tests/live-production-validation.js +241 -0
  67. package/packages/aurabase/tests/live-sdk-production-validation.js +293 -0
  68. package/packages/aurabase/tests/mocks.ts +139 -0
  69. package/packages/aurabase/tests/notifications.test.ts +314 -0
  70. package/packages/aurabase/tests/observability-backup.test.ts +186 -0
  71. package/packages/aurabase/tests/observability-hook.test.ts +130 -0
  72. package/packages/aurabase/tests/production-robustness.test.ts +268 -0
  73. package/packages/aurabase/tests/public-api-surface.test.ts +53 -0
  74. package/packages/aurabase/tests/query-builder.test.ts +329 -0
  75. package/packages/aurabase/tests/readme-smoke-e2e.test.ts +231 -0
  76. package/packages/aurabase/tests/realtime-filter-e2e.test.ts +344 -0
  77. package/packages/aurabase/tests/refresh-locks.test.ts +210 -0
  78. package/packages/aurabase/tests/retry-option.test.ts +17 -0
  79. package/packages/aurabase/tests/rpc-e2e.test.ts +254 -0
  80. package/packages/aurabase/tests/rs256-local-e2e.test.ts +114 -0
  81. package/packages/aurabase/tests/rt-alias-public-e2e.test.ts +235 -0
  82. package/packages/aurabase/tests/rt-http-broadcast-e2e.test.ts +124 -0
  83. package/packages/aurabase/tests/service-role-guard.test.ts +99 -0
  84. package/packages/aurabase/tests/ssr.test.ts +91 -0
  85. package/packages/aurabase/tests/storage-backend-e2e.test.ts +481 -0
  86. package/packages/aurabase/tests/storage-sdk-parity-e2e.test.ts +104 -0
  87. package/packages/aurabase/tests/storage-transform-e2e.test.ts +684 -0
  88. package/packages/aurabase/tests/storage.test.ts +55 -0
  89. package/packages/aurabase/tests/types/client-generic.test-d.ts +79 -0
  90. package/packages/aurabase/tests/types/docs-snippets.test-d.ts +571 -0
  91. package/packages/aurabase/tests/types/error-code.test-d.ts +53 -0
  92. package/packages/aurabase/tsconfig.json +5 -0
  93. package/packages/aurabase/tsconfig.test-d.json +5 -0
  94. package/packages/aurabase/tsup.config.ts +11 -0
  95. package/packages/aurabase/vitest.config.ts +16 -0
  96. package/packages/aurabase/vitest.e2e.config.ts +9 -0
  97. package/packages/auth/LICENSE +21 -0
  98. package/packages/auth/README.md +215 -0
  99. package/packages/auth/dist/index.cjs +1175 -0
  100. package/packages/auth/dist/index.d.cts +397 -0
  101. package/packages/auth/dist/index.d.ts +397 -0
  102. package/packages/auth/dist/index.js +1170 -0
  103. package/packages/auth/node_modules/.bin/esbuild +19 -0
  104. package/packages/auth/node_modules/.bin/tsc +22 -0
  105. package/packages/auth/node_modules/.bin/tsserver +22 -0
  106. package/packages/auth/node_modules/.bin/tsup +22 -0
  107. package/packages/auth/node_modules/.bin/tsup-node +22 -0
  108. package/packages/auth/node_modules/.bin/vite +22 -0
  109. package/packages/auth/node_modules/.bin/vitest +22 -0
  110. package/packages/auth/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  111. package/packages/auth/package.json +61 -0
  112. package/packages/auth/src/AuthAdminService.ts +149 -0
  113. package/packages/auth/src/AuthService.ts +1166 -0
  114. package/packages/auth/src/SessionManager.ts +92 -0
  115. package/packages/auth/src/index.ts +17 -0
  116. package/packages/auth/src/jwks.ts +337 -0
  117. package/packages/auth/src/pkce.ts +27 -0
  118. package/packages/auth/src/types.ts +89 -0
  119. package/packages/auth/tests/auth-lifecycle.test.ts +149 -0
  120. package/packages/auth/tests/detect-session.test.ts +361 -0
  121. package/packages/auth/tests/getclaims.test.ts +780 -0
  122. package/packages/auth/tests/is-mfa-challenge.test.ts +27 -0
  123. package/packages/auth/tests/password-recovery.test.ts +124 -0
  124. package/packages/auth/tests/pkce.test.ts +192 -0
  125. package/packages/auth/tests/session-manager.test.ts +103 -0
  126. package/packages/auth/tests/set-session.test.ts +139 -0
  127. package/packages/auth/tests/verify-otp.test.ts +153 -0
  128. package/packages/auth/tsconfig.json +5 -0
  129. package/packages/auth/tsup.config.ts +11 -0
  130. package/packages/core/LICENSE +21 -0
  131. package/packages/core/README.md +132 -0
  132. package/packages/core/dist/index.cjs +695 -0
  133. package/packages/core/dist/index.d.cts +1137 -0
  134. package/packages/core/dist/index.d.ts +1137 -0
  135. package/packages/core/dist/index.js +673 -0
  136. package/packages/core/node_modules/.bin/esbuild +22 -0
  137. package/packages/core/node_modules/.bin/tsc +22 -0
  138. package/packages/core/node_modules/.bin/tsserver +22 -0
  139. package/packages/core/node_modules/.bin/tsup +22 -0
  140. package/packages/core/node_modules/.bin/tsup-node +22 -0
  141. package/packages/core/node_modules/.bin/vite +22 -0
  142. package/packages/core/node_modules/.bin/vitest +22 -0
  143. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  144. package/packages/core/package.json +57 -0
  145. package/packages/core/src/AuraError.ts +89 -0
  146. package/packages/core/src/BaseService.ts +44 -0
  147. package/packages/core/src/client.ts +34 -0
  148. package/packages/core/src/cookie-utils.ts +42 -0
  149. package/packages/core/src/fetch.ts +435 -0
  150. package/packages/core/src/index.ts +22 -0
  151. package/packages/core/src/retry.ts +63 -0
  152. package/packages/core/src/serialize.ts +6 -0
  153. package/packages/core/src/stores/BaseAuthStore.ts +164 -0
  154. package/packages/core/src/stores/LocalAuthStore.ts +199 -0
  155. package/packages/core/src/types.ts +1042 -0
  156. package/packages/core/tests/auth-store.test.ts +300 -0
  157. package/packages/core/tests/error-code.test.ts +61 -0
  158. package/packages/core/tests/error.test.ts +24 -0
  159. package/packages/core/tests/fetch.test.ts +286 -0
  160. package/packages/core/tests/mocks.ts +139 -0
  161. package/packages/core/tests/observability.test.ts +86 -0
  162. package/packages/core/tests/refresh-hardening.test.ts +164 -0
  163. package/packages/core/tests/refresh-observability.test.ts +111 -0
  164. package/packages/core/tests/retry.test.ts +106 -0
  165. package/packages/core/tests/serialize.test.ts +12 -0
  166. package/packages/core/tests/timeout.test.ts +79 -0
  167. package/packages/core/tsconfig.json +5 -0
  168. package/packages/core/tsup.config.ts +11 -0
  169. package/packages/db/LICENSE +21 -0
  170. package/packages/db/README.md +152 -0
  171. package/packages/db/VENDORED.md +93 -0
  172. package/packages/db/dist/index.cjs +544 -0
  173. package/packages/db/dist/index.d.cts +1111 -0
  174. package/packages/db/dist/index.d.ts +1111 -0
  175. package/packages/db/dist/index.js +541 -0
  176. package/packages/db/node_modules/.bin/esbuild +19 -0
  177. package/packages/db/node_modules/.bin/tsc +22 -0
  178. package/packages/db/node_modules/.bin/tsserver +22 -0
  179. package/packages/db/node_modules/.bin/tsup +22 -0
  180. package/packages/db/node_modules/.bin/tsup-node +22 -0
  181. package/packages/db/node_modules/.bin/vite +22 -0
  182. package/packages/db/node_modules/.bin/vitest +22 -0
  183. package/packages/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  184. package/packages/db/package.json +62 -0
  185. package/packages/db/src/DatabaseService.ts +170 -0
  186. package/packages/db/src/QueryBuilder.ts +830 -0
  187. package/packages/db/src/index.ts +2 -0
  188. package/packages/db/src/pgrst-types/common/common.ts +86 -0
  189. package/packages/db/src/pgrst-types/common/rpc.ts +151 -0
  190. package/packages/db/src/pgrst-types/feature-flags.ts +20 -0
  191. package/packages/db/src/pgrst-types/types.ts +134 -0
  192. package/packages/db/src/select-query-parser/parser.ts +479 -0
  193. package/packages/db/src/select-query-parser/result.ts +553 -0
  194. package/packages/db/src/select-query-parser/types.ts +132 -0
  195. package/packages/db/src/select-query-parser/utils.ts +707 -0
  196. package/packages/db/tests/filters.test.ts +81 -0
  197. package/packages/db/tests/mutations-filtered.e2e.test.ts +132 -0
  198. package/packages/db/tests/mutations-filtered.test.ts +188 -0
  199. package/packages/db/tests/order.test.ts +45 -0
  200. package/packages/db/tests/rpc.test.ts +41 -0
  201. package/packages/db/tests/scale/build-large-schema.ts +94 -0
  202. package/packages/db/tests/scale/scale-compile.test.ts +167 -0
  203. package/packages/db/tests/schema.test.ts +77 -0
  204. package/packages/db/tests/single-accept.e2e.test.ts +123 -0
  205. package/packages/db/tests/single.test.ts +211 -0
  206. package/packages/db/tests/types/filters.test-d.ts +52 -0
  207. package/packages/db/tests/types/fixtures.ts +40 -0
  208. package/packages/db/tests/types/from-views.test-d.ts +18 -0
  209. package/packages/db/tests/types/mutations.test-d.ts +23 -0
  210. package/packages/db/tests/types/rpc.test-d.ts +60 -0
  211. package/packages/db/tests/types/schema-shape.test-d.ts +8 -0
  212. package/packages/db/tests/types/select-inference.test-d.ts +38 -0
  213. package/packages/db/tests/vendored/fixtures.ts +83 -0
  214. package/packages/db/tests/vendored/get-result.test-d.ts +75 -0
  215. package/packages/db/tsconfig.json +5 -0
  216. package/packages/db/tsconfig.test-d.json +5 -0
  217. package/packages/db/tsup.config.ts +11 -0
  218. package/packages/db/vitest.config.ts +8 -0
  219. package/packages/functions/LICENSE +21 -0
  220. package/packages/functions/README.md +96 -0
  221. package/packages/functions/dist/index.cjs +173 -0
  222. package/packages/functions/dist/index.d.cts +81 -0
  223. package/packages/functions/dist/index.d.ts +81 -0
  224. package/packages/functions/dist/index.js +168 -0
  225. package/packages/functions/node_modules/.bin/esbuild +19 -0
  226. package/packages/functions/node_modules/.bin/tsc +22 -0
  227. package/packages/functions/node_modules/.bin/tsserver +22 -0
  228. package/packages/functions/node_modules/.bin/tsup +22 -0
  229. package/packages/functions/node_modules/.bin/tsup-node +22 -0
  230. package/packages/functions/node_modules/.bin/vite +22 -0
  231. package/packages/functions/node_modules/.bin/vitest +22 -0
  232. package/packages/functions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  233. package/packages/functions/package.json +60 -0
  234. package/packages/functions/src/FunctionsService.ts +188 -0
  235. package/packages/functions/src/errors.ts +70 -0
  236. package/packages/functions/src/index.ts +6 -0
  237. package/packages/functions/tests/invoke.test.ts +97 -0
  238. package/packages/functions/tests/response-type-errors.test.ts +135 -0
  239. package/packages/functions/tsconfig.json +5 -0
  240. package/packages/functions/tsup.config.ts +11 -0
  241. package/packages/gen/LICENSE +21 -0
  242. package/packages/gen/README.md +84 -0
  243. package/packages/gen/dist/cli.cjs +334 -0
  244. package/packages/gen/dist/cli.d.cts +1 -0
  245. package/packages/gen/dist/cli.d.ts +1 -0
  246. package/packages/gen/dist/cli.js +332 -0
  247. package/packages/gen/dist/index.cjs +257 -0
  248. package/packages/gen/dist/index.d.cts +12 -0
  249. package/packages/gen/dist/index.d.ts +12 -0
  250. package/packages/gen/dist/index.js +255 -0
  251. package/packages/gen/node_modules/.bin/esbuild +19 -0
  252. package/packages/gen/node_modules/.bin/tsc +22 -0
  253. package/packages/gen/node_modules/.bin/tsserver +22 -0
  254. package/packages/gen/node_modules/.bin/tsup +22 -0
  255. package/packages/gen/node_modules/.bin/tsup-node +22 -0
  256. package/packages/gen/node_modules/.bin/vite +22 -0
  257. package/packages/gen/node_modules/.bin/vitest +22 -0
  258. package/packages/gen/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  259. package/packages/gen/package.json +66 -0
  260. package/packages/gen/src/cli.ts +67 -0
  261. package/packages/gen/src/generate.ts +0 -0
  262. package/packages/gen/src/index.ts +2 -0
  263. package/packages/gen/tests/compile.test.ts +213 -0
  264. package/packages/gen/tests/e2e.test.ts +130 -0
  265. package/packages/gen/tests/generate.test.ts +396 -0
  266. package/packages/gen/tsconfig.json +5 -0
  267. package/packages/gen/tsup.config.ts +11 -0
  268. package/packages/notifications/LICENSE +21 -0
  269. package/packages/notifications/README.md +134 -0
  270. package/packages/notifications/dist/index.cjs +128 -0
  271. package/packages/notifications/dist/index.d.cts +81 -0
  272. package/packages/notifications/dist/index.d.ts +81 -0
  273. package/packages/notifications/dist/index.js +125 -0
  274. package/packages/notifications/node_modules/.bin/esbuild +19 -0
  275. package/packages/notifications/node_modules/.bin/tsc +22 -0
  276. package/packages/notifications/node_modules/.bin/tsserver +22 -0
  277. package/packages/notifications/node_modules/.bin/tsup +22 -0
  278. package/packages/notifications/node_modules/.bin/tsup-node +22 -0
  279. package/packages/notifications/node_modules/.bin/vite +22 -0
  280. package/packages/notifications/node_modules/.bin/vitest +22 -0
  281. package/packages/notifications/package.json +60 -0
  282. package/packages/notifications/src/NotificationsService.ts +230 -0
  283. package/packages/notifications/src/index.ts +19 -0
  284. package/packages/notifications/tsconfig.json +5 -0
  285. package/packages/notifications/tsup.config.ts +11 -0
  286. package/packages/realtime/LICENSE +21 -0
  287. package/packages/realtime/README.md +183 -0
  288. package/packages/realtime/dist/index.cjs +977 -0
  289. package/packages/realtime/dist/index.d.cts +259 -0
  290. package/packages/realtime/dist/index.d.ts +259 -0
  291. package/packages/realtime/dist/index.js +973 -0
  292. package/packages/realtime/node_modules/.bin/esbuild +19 -0
  293. package/packages/realtime/node_modules/.bin/tsc +22 -0
  294. package/packages/realtime/node_modules/.bin/tsserver +22 -0
  295. package/packages/realtime/node_modules/.bin/tsup +22 -0
  296. package/packages/realtime/node_modules/.bin/tsup-node +22 -0
  297. package/packages/realtime/node_modules/.bin/vite +22 -0
  298. package/packages/realtime/node_modules/.bin/vitest +22 -0
  299. package/packages/realtime/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  300. package/packages/realtime/package.json +60 -0
  301. package/packages/realtime/src/AuraChannel.ts +485 -0
  302. package/packages/realtime/src/HeartbeatManager.ts +73 -0
  303. package/packages/realtime/src/RealtimeService.ts +505 -0
  304. package/packages/realtime/src/columnFilter.ts +301 -0
  305. package/packages/realtime/src/index.ts +4 -0
  306. package/packages/realtime/tests/ack-routing.test.ts +81 -0
  307. package/packages/realtime/tests/column-filter.test.ts +144 -0
  308. package/packages/realtime/tests/dispatch.test.ts +191 -0
  309. package/packages/realtime/tests/heartbeat.test.ts +67 -0
  310. package/packages/realtime/tests/http-broadcast.test.ts +68 -0
  311. package/packages/realtime/tests/realtime-token.test.ts +43 -0
  312. package/packages/realtime/tests/reconnect-race.test.ts +149 -0
  313. package/packages/realtime/tests/ref-id.test.ts +34 -0
  314. package/packages/realtime/tests/set-auth.test.ts +70 -0
  315. package/packages/realtime/tsconfig.json +5 -0
  316. package/packages/realtime/tsup.config.ts +11 -0
  317. package/packages/storage/LICENSE +21 -0
  318. package/packages/storage/README.md +141 -0
  319. package/packages/storage/dist/index.cjs +333 -0
  320. package/packages/storage/dist/index.d.cts +185 -0
  321. package/packages/storage/dist/index.d.ts +185 -0
  322. package/packages/storage/dist/index.js +329 -0
  323. package/packages/storage/node_modules/.bin/esbuild +19 -0
  324. package/packages/storage/node_modules/.bin/tsc +22 -0
  325. package/packages/storage/node_modules/.bin/tsserver +22 -0
  326. package/packages/storage/node_modules/.bin/tsup +22 -0
  327. package/packages/storage/node_modules/.bin/tsup-node +22 -0
  328. package/packages/storage/node_modules/.bin/vite +22 -0
  329. package/packages/storage/node_modules/.bin/vitest +22 -0
  330. package/packages/storage/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  331. package/packages/storage/package.json +60 -0
  332. package/packages/storage/src/DownloadBuilder.ts +60 -0
  333. package/packages/storage/src/StorageService.ts +323 -0
  334. package/packages/storage/src/index.ts +2 -0
  335. package/packages/storage/src/path.ts +35 -0
  336. package/packages/storage/src/transform.ts +15 -0
  337. package/packages/storage/tests/download.test.ts +64 -0
  338. package/packages/storage/tests/parity.test.ts +154 -0
  339. package/packages/storage/tests/path.test.ts +87 -0
  340. package/packages/storage/tests/transform.test.ts +79 -0
  341. package/packages/storage/tsconfig.json +5 -0
  342. package/packages/storage/tsup.config.ts +11 -0
  343. package/pnpm-workspace.yaml +24 -0
  344. package/tsconfig.base.json +15 -0
@@ -0,0 +1,191 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { RealtimeService } from '../src/RealtimeService'
3
+ import { AuraChannel } from '../src/AuraChannel'
4
+ import { BaseAuthStore } from '@aurabase/core'
5
+ import type { AuraClientLike } from '@aurabase/core'
6
+
7
+ function client(): AuraClientLike {
8
+ return {
9
+ baseUrl: 'http://x',
10
+ projectId: 'proj',
11
+ apiKey: 'k',
12
+ authStore: new BaseAuthStore(),
13
+ fetchFn: (async () => new Response('{}')) as unknown as typeof globalThis.fetch,
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ auth: { refreshSession: async () => ({ data: null, error: null }) as any },
16
+ }
17
+ }
18
+
19
+ describe('RealtimeService._dispatch — routage CDC borné par ":"', () => {
20
+ it('un event de `room2` ne fuite pas vers le channel `room` (préfixe)', () => {
21
+ const rt = new RealtimeService(client())
22
+ const room = new AuraChannel('room', 'proj')
23
+ const room2 = new AuraChannel('room2', 'proj')
24
+ // Insère `room` en PREMIER (l'ancien startsWith non borné l'aurait fait matcher d'abord).
25
+ const map = (rt as unknown as { _channels: Map<string, AuraChannel> })._channels
26
+ map.set('room', room)
27
+ map.set('room2', room2)
28
+ const spyRoom = vi.spyOn(room, '_onMessage').mockImplementation(() => {})
29
+ const spyRoom2 = vi.spyOn(room2, '_onMessage').mockImplementation(() => {})
30
+
31
+ // Message CDC : topic composite `proj:room2:public.x` (pas de channel exact de ce nom).
32
+ ;(rt as unknown as { _dispatch: (m: unknown) => void })._dispatch({
33
+ type: 'event',
34
+ id: '1',
35
+ event: 'insert',
36
+ topic: 'proj:room2:public.x',
37
+ payload: {},
38
+ timestamp: '',
39
+ })
40
+
41
+ expect(spyRoom2).toHaveBeenCalledTimes(1)
42
+ expect(spyRoom).not.toHaveBeenCalled()
43
+ })
44
+ })
45
+
46
+ describe('AuraChannel._dispatchEvent — fallback client filtre colonne (second rideau)', () => {
47
+ it("un event dont le record ne matche pas `filter` n'atteint pas le callback", () => {
48
+ const channel = new AuraChannel('room', 'proj')
49
+ const cb = vi.fn()
50
+ channel.on(
51
+ 'postgres_changes',
52
+ { event: '*', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
53
+ cb,
54
+ )
55
+
56
+ channel._onMessage({
57
+ type: 'event',
58
+ id: '1',
59
+ event: 'insert',
60
+ topic: 'proj:room:public.messages',
61
+ payload: {
62
+ schema: 'public',
63
+ table: 'messages',
64
+ type: 'INSERT',
65
+ record: { room_id: 7 },
66
+ old_record: null,
67
+ },
68
+ timestamp: '',
69
+ })
70
+
71
+ expect(cb).not.toHaveBeenCalled()
72
+ })
73
+
74
+ it('un event dont le record matche `filter` atteint le callback', () => {
75
+ const channel = new AuraChannel('room', 'proj')
76
+ const cb = vi.fn()
77
+ channel.on(
78
+ 'postgres_changes',
79
+ { event: '*', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
80
+ cb,
81
+ )
82
+
83
+ channel._onMessage({
84
+ type: 'event',
85
+ id: '2',
86
+ event: 'insert',
87
+ topic: 'proj:room:public.messages',
88
+ payload: {
89
+ schema: 'public',
90
+ table: 'messages',
91
+ type: 'INSERT',
92
+ record: { room_id: 42 },
93
+ old_record: null,
94
+ },
95
+ timestamp: '',
96
+ })
97
+
98
+ expect(cb).toHaveBeenCalledTimes(1)
99
+ })
100
+
101
+ it('DELETE : le filtre est évalué sur old_record (record CDC vide)', () => {
102
+ const channel = new AuraChannel('room', 'proj')
103
+ const matched = vi.fn()
104
+ const notMatched = vi.fn()
105
+ channel.on(
106
+ 'postgres_changes',
107
+ { event: '*', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
108
+ matched,
109
+ )
110
+
111
+ channel._onMessage({
112
+ type: 'event',
113
+ id: '3',
114
+ event: 'delete',
115
+ topic: 'proj:room:public.messages',
116
+ payload: {
117
+ schema: 'public',
118
+ table: 'messages',
119
+ type: 'DELETE',
120
+ record: {},
121
+ old_record: { room_id: 42 },
122
+ },
123
+ timestamp: '',
124
+ })
125
+ expect(matched).toHaveBeenCalledTimes(1)
126
+
127
+ channel.on(
128
+ 'postgres_changes',
129
+ { event: '*', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
130
+ notMatched,
131
+ )
132
+ channel._onMessage({
133
+ type: 'event',
134
+ id: '4',
135
+ event: 'delete',
136
+ topic: 'proj:room:public.messages',
137
+ payload: {
138
+ schema: 'public',
139
+ table: 'messages',
140
+ type: 'DELETE',
141
+ record: {},
142
+ old_record: { room_id: 7 },
143
+ },
144
+ timestamp: '',
145
+ })
146
+ expect(notMatched).not.toHaveBeenCalled()
147
+ })
148
+
149
+ it('cible absente/non-objet => ne filtre pas (le serveur a déjà filtré, pas de faux négatif)', () => {
150
+ const channel = new AuraChannel('room', 'proj')
151
+ const cb = vi.fn()
152
+ channel.on(
153
+ 'postgres_changes',
154
+ { event: '*', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
155
+ cb,
156
+ )
157
+
158
+ channel._onMessage({
159
+ type: 'event',
160
+ id: '5',
161
+ event: 'insert',
162
+ topic: 'proj:room:public.messages',
163
+ payload: {
164
+ schema: 'public',
165
+ table: 'messages',
166
+ type: 'INSERT',
167
+ // pas de champ `record` du tout
168
+ },
169
+ timestamp: '',
170
+ })
171
+
172
+ expect(cb).toHaveBeenCalledTimes(1)
173
+ })
174
+
175
+ it('filtre absent (non défini) => pas de fallback appliqué, event livré normalement', () => {
176
+ const channel = new AuraChannel('room', 'proj')
177
+ const cb = vi.fn()
178
+ channel.on('postgres_changes', { event: '*', schema: 'public', table: 'messages' }, cb)
179
+
180
+ channel._onMessage({
181
+ type: 'event',
182
+ id: '6',
183
+ event: 'insert',
184
+ topic: 'proj:room:public.messages',
185
+ payload: { schema: 'public', table: 'messages', type: 'INSERT', record: { room_id: 999 } },
186
+ timestamp: '',
187
+ })
188
+
189
+ expect(cb).toHaveBeenCalledTimes(1)
190
+ })
191
+ })
@@ -0,0 +1,67 @@
1
+ import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest'
2
+ import { HeartbeatManager } from '../src/HeartbeatManager'
3
+
4
+ class FakeWorker {
5
+ static instances: FakeWorker[] = []
6
+ onmessage: ((e: unknown) => void) | null = null
7
+ posted: unknown[] = []
8
+ terminated = false
9
+ constructor(public url: string) {
10
+ FakeWorker.instances.push(this)
11
+ }
12
+ postMessage(d: unknown) {
13
+ this.posted.push(d)
14
+ }
15
+ terminate() {
16
+ this.terminated = true
17
+ }
18
+ }
19
+
20
+ const g = globalThis as unknown as Record<string, unknown>
21
+ let revoke: ReturnType<typeof vi.fn>
22
+
23
+ beforeEach(() => {
24
+ FakeWorker.instances = []
25
+ revoke = vi.fn()
26
+ g.Worker = FakeWorker
27
+ g.URL = { createObjectURL: vi.fn(() => 'blob:x'), revokeObjectURL: revoke }
28
+ })
29
+ afterEach(() => {
30
+ vi.useRealTimers()
31
+ delete g.Worker
32
+ delete g.URL
33
+ })
34
+
35
+ describe('HeartbeatManager — Worker dédié', () => {
36
+ it('start() crée un Worker, ping au message worker, URL non révoquée avant stop', () => {
37
+ const hm = new HeartbeatManager()
38
+ const ping = vi.fn()
39
+ hm.start(ping, 25000)
40
+ expect(FakeWorker.instances.length).toBe(1)
41
+ expect(revoke).not.toHaveBeenCalled()
42
+ FakeWorker.instances[0].onmessage!({})
43
+ expect(ping).toHaveBeenCalledTimes(1)
44
+ })
45
+
46
+ it('stop() termine le worker et révoque l’URL', () => {
47
+ const hm = new HeartbeatManager()
48
+ hm.start(vi.fn())
49
+ hm.stop()
50
+ expect(FakeWorker.instances[0].terminated).toBe(true)
51
+ expect(revoke).toHaveBeenCalledWith('blob:x')
52
+ expect(hm.isActive).toBe(false)
53
+ })
54
+
55
+ it('sans Worker → fallback setInterval', () => {
56
+ delete g.Worker
57
+ vi.useFakeTimers()
58
+ const hm = new HeartbeatManager()
59
+ const ping = vi.fn()
60
+ hm.start(ping, 1000)
61
+ vi.advanceTimersByTime(1000)
62
+ expect(ping).toHaveBeenCalledTimes(1)
63
+ hm.stop()
64
+ vi.advanceTimersByTime(2000)
65
+ expect(ping).toHaveBeenCalledTimes(1)
66
+ })
67
+ })
@@ -0,0 +1,68 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { RealtimeService } from '../src/RealtimeService'
3
+ import { BaseAuthStore } from '@aurabase/core'
4
+ import type { AuraClientLike } from '@aurabase/core'
5
+
6
+ type Captured = { url: string; init: RequestInit }
7
+
8
+ function clientWithSpy(): { client: AuraClientLike; calls: Captured[] } {
9
+ const calls: Captured[] = []
10
+ const fetchFn = (async (url: string, init: RequestInit) => {
11
+ calls.push({ url, init })
12
+ return new Response(JSON.stringify({ data: null, meta: null }), {
13
+ status: 200,
14
+ headers: { 'content-type': 'application/json' },
15
+ })
16
+ }) as unknown as typeof globalThis.fetch
17
+ const store = new BaseAuthStore()
18
+ return {
19
+ calls,
20
+ client: {
21
+ baseUrl: 'http://x',
22
+ projectId: 'proj',
23
+ apiKey: 'k',
24
+ authStore: store,
25
+ fetchFn,
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ auth: { refreshSession: async () => ({ data: null, error: null }) as any },
28
+ },
29
+ }
30
+ }
31
+
32
+ describe('RealtimeService.httpBroadcast — envoi REST hors WebSocket', () => {
33
+ it('POST /v1/realtime/{projectId}/broadcast avec corps { channel, payload:{event,...} } + apikey', async () => {
34
+ const { client, calls } = clientWithSpy()
35
+ const rt = new RealtimeService(client)
36
+
37
+ const res = await rt.httpBroadcast('room-1', 'ping', { a: 1 })
38
+
39
+ expect(res.error).toBeNull()
40
+ expect(calls).toHaveLength(1)
41
+ const { url, init } = calls[0]!
42
+ expect(url).toBe('http://x/v1/realtime/proj/broadcast')
43
+ expect(init.method).toBe('POST')
44
+ expect(JSON.parse(init.body as string)).toEqual({
45
+ channel: 'proj:room-1',
46
+ payload: { event: 'ping', a: 1 },
47
+ })
48
+ expect((init.headers as Record<string, string>)['apikey']).toBe('k')
49
+ })
50
+
51
+ it("ne préfixe pas deux fois un canal déjà préfixé par le projet", async () => {
52
+ const { client, calls } = clientWithSpy()
53
+ const rt = new RealtimeService(client)
54
+
55
+ await rt.httpBroadcast('proj:room-x', 'evt', {})
56
+
57
+ expect(JSON.parse(calls[0]!.init.body as string).channel).toBe('proj:room-x')
58
+ })
59
+
60
+ it("n'ouvre aucune connexion WebSocket", async () => {
61
+ const { client } = clientWithSpy()
62
+ const rt = new RealtimeService(client)
63
+
64
+ await rt.httpBroadcast('room-1', 'ping', {})
65
+
66
+ expect(rt.connectionState).toBe('disconnected')
67
+ })
68
+ })
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { RealtimeService } from '../src/RealtimeService'
3
+ import { BaseAuthStore } from '@aurabase/core'
4
+ import type { AuraClientLike } from '@aurabase/core'
5
+
6
+ function makeClient(): AuraClientLike {
7
+ return {
8
+ baseUrl: 'http://x',
9
+ projectId: 'p',
10
+ apiKey: 'k',
11
+ fetchFn: (async () => new Response('{}')) as unknown as typeof globalThis.fetch,
12
+ authStore: new BaseAuthStore(), // vide → _scheduleTokenRefresh no-op
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ auth: { refreshSession: async () => ({ data: null, error: null }) as any },
15
+ }
16
+ }
17
+
18
+ describe('RealtimeService — propagation token différentielle', () => {
19
+ it('ne renvoie pas un token identique, renvoie un token changé', () => {
20
+ const rt = new RealtimeService(makeClient())
21
+ const send = vi
22
+ .spyOn(rt as unknown as { _send: (d: string) => void }, '_send')
23
+ .mockImplementation(() => {})
24
+ rt.refreshToken('t1')
25
+ expect(send).toHaveBeenCalledTimes(1)
26
+ rt.refreshToken('t1')
27
+ expect(send).toHaveBeenCalledTimes(1) // identique → pas renvoyé
28
+ rt.refreshToken('t2')
29
+ expect(send).toHaveBeenCalledTimes(2)
30
+ })
31
+
32
+ it('disconnect() réarme la propagation (renvoie le token après reconnexion)', () => {
33
+ const rt = new RealtimeService(makeClient())
34
+ const send = vi
35
+ .spyOn(rt as unknown as { _send: (d: string) => void }, '_send')
36
+ .mockImplementation(() => {})
37
+ rt.refreshToken('t1')
38
+ expect(send).toHaveBeenCalledTimes(1)
39
+ rt.disconnect()
40
+ rt.refreshToken('t1')
41
+ expect(send).toHaveBeenCalledTimes(2) // _lastSentToken reset → renvoyé
42
+ })
43
+ })
@@ -0,0 +1,149 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
2
+ import { RealtimeService } from '../src/RealtimeService'
3
+ import { BaseAuthStore } from '@aurabase/core'
4
+ import type { AuraClientLike } from '@aurabase/core'
5
+
6
+ /**
7
+ * Faux WebSocket contrôlable : les transitions (open/close) sont déclenchées
8
+ * manuellement pour reproduire de façon déterministe la race « stale onclose »
9
+ * (un ancien socket dont le onclose se déclenche APRÈS qu'un nouveau socket a
10
+ * été créé).
11
+ */
12
+ class FakeWebSocket {
13
+ static readonly CONNECTING = 0
14
+ static readonly OPEN = 1
15
+ static readonly CLOSING = 2
16
+ static readonly CLOSED = 3
17
+ static instances: FakeWebSocket[] = []
18
+
19
+ url: string
20
+ readyState: number = FakeWebSocket.CONNECTING
21
+ onopen: (() => void) | null = null
22
+ onmessage: ((evt: { data: string }) => void) | null = null
23
+ onclose: (() => void) | null = null
24
+ onerror: ((evt: unknown) => void) | null = null
25
+ sent: string[] = []
26
+
27
+ constructor(url: string) {
28
+ this.url = url
29
+ FakeWebSocket.instances.push(this)
30
+ }
31
+
32
+ send(data: string): void {
33
+ this.sent.push(data)
34
+ }
35
+
36
+ close(): void {
37
+ this.readyState = FakeWebSocket.CLOSING
38
+ }
39
+
40
+ // ─── Helpers de test ───
41
+ fireOpen(): void {
42
+ this.readyState = FakeWebSocket.OPEN
43
+ this.onopen?.()
44
+ }
45
+
46
+ fireClose(): void {
47
+ this.readyState = FakeWebSocket.CLOSED
48
+ this.onclose?.()
49
+ }
50
+ }
51
+
52
+ function client(): AuraClientLike {
53
+ return {
54
+ baseUrl: 'http://x',
55
+ projectId: 'proj',
56
+ apiKey: 'k',
57
+ authStore: new BaseAuthStore(),
58
+ fetchFn: (async () => new Response('{}')) as unknown as typeof globalThis.fetch,
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ auth: { refreshSession: async () => ({ data: null, error: null }) as any },
61
+ }
62
+ }
63
+
64
+ describe('RealtimeService — race « stale onclose »', () => {
65
+ beforeEach(() => {
66
+ vi.useFakeTimers()
67
+ FakeWebSocket.instances = []
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ ;(globalThis as any).WebSocket = FakeWebSocket
70
+ })
71
+
72
+ afterEach(() => {
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
74
+ delete (globalThis as any).WebSocket
75
+ vi.useRealTimers()
76
+ vi.restoreAllMocks()
77
+ })
78
+
79
+ it("le onclose tardif d'un ancien socket n'écrase PAS la connexion courante", () => {
80
+ const rt = new RealtimeService(client())
81
+ rt.setAutoReconnect(false) // isole le test du scheduler de reconnexion
82
+
83
+ rt.connect()
84
+ const ws1 = FakeWebSocket.instances[0]
85
+ ws1.fireOpen()
86
+ expect(rt.connectionState).toBe('connected')
87
+
88
+ // Déconnexion intentionnelle : ferme ws1, mais son onclose est différé.
89
+ rt.disconnect()
90
+ expect(rt.connectionState).toBe('disconnected')
91
+
92
+ // Une nouvelle connexion est établie AVANT que le onclose de ws1 n'arrive.
93
+ rt.connect()
94
+ const ws2 = FakeWebSocket.instances[1]
95
+ expect(ws2).toBeDefined()
96
+ ws2.fireOpen()
97
+ expect(rt.connectionState).toBe('connected')
98
+
99
+ // Le onclose TARDIF de l'ancien socket se déclenche maintenant.
100
+ ws1.fireClose()
101
+
102
+ // Il ne doit ni annuler l'état 'connected', ni détacher le nouveau socket.
103
+ expect(rt.connectionState).toBe('connected')
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ expect((rt as any)._ws).toBe(ws2)
106
+ })
107
+
108
+ it('un socket périmé qui s\'ouvre tardivement est fermé et n\'active rien', () => {
109
+ const rt = new RealtimeService(client())
110
+ rt.setAutoReconnect(false)
111
+
112
+ rt.connect()
113
+ const ws1 = FakeWebSocket.instances[0]
114
+
115
+ // Avant que ws1 ne s'ouvre, on repart sur une nouvelle connexion.
116
+ rt.disconnect()
117
+ rt.connect()
118
+ const ws2 = FakeWebSocket.instances[1]
119
+ ws2.fireOpen()
120
+ expect(rt.connectionState).toBe('connected')
121
+
122
+ // ws1 (périmé) s'ouvre tardivement : doit être fermé, sans toucher l'état.
123
+ const closeSpy = vi.spyOn(ws1, 'close')
124
+ ws1.fireOpen()
125
+ expect(closeSpy).toHaveBeenCalled()
126
+ expect(rt.connectionState).toBe('connected')
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ expect((rt as any)._ws).toBe(ws2)
129
+ })
130
+
131
+ it('après disconnect+reconnect, une coupure inattendue reconnecte bien (flag _intentionalClose non bloqué)', () => {
132
+ const rt = new RealtimeService(client())
133
+
134
+ rt.connect()
135
+ const ws1 = FakeWebSocket.instances[0]
136
+ ws1.fireOpen()
137
+
138
+ rt.disconnect() // pose _intentionalClose = true
139
+ rt.connect() // doit remettre le flag à false
140
+ const ws2 = FakeWebSocket.instances[1]
141
+ ws2.fireOpen()
142
+ expect(rt.connectionState).toBe('connected')
143
+
144
+ // Coupure inattendue de ws2 : doit repasser en 'reconnecting'
145
+ // (et non rester 'disconnected' à cause d'un flag resté à true).
146
+ ws2.fireClose()
147
+ expect(rt.connectionState).toBe('reconnecting')
148
+ })
149
+ })
@@ -0,0 +1,34 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest'
2
+ import { AuraChannel } from '../src/AuraChannel'
3
+
4
+ afterEach(() => vi.useRealTimers())
5
+
6
+ describe('AuraChannel — ref_id global-unique', () => {
7
+ it('deux channels produisent des refs distincts préfixés par fullName', () => {
8
+ vi.useFakeTimers()
9
+ const a = new AuraChannel('a', 'p', { broadcast: { ack: true } })
10
+ const b = new AuraChannel('b', 'p', { broadcast: { ack: true } })
11
+ const sentA: Array<Record<string, unknown>> = []
12
+ const sentB: Array<Record<string, unknown>> = []
13
+ a._bindSend((d) => sentA.push(JSON.parse(d)))
14
+ b._bindSend((d) => sentB.push(JSON.parse(d)))
15
+
16
+ const pa = a.send({ type: 'broadcast', event: 'e', payload: {} })
17
+ const pb = b.send({ type: 'broadcast', event: 'e', payload: {} })
18
+
19
+ const rA = sentA[0].ref_id as string
20
+ const rB = sentB[0].ref_id as string
21
+ expect(rA).not.toBe(rB)
22
+ expect(rA.startsWith('p:a:')).toBe(true)
23
+ expect(rB.startsWith('p:b:')).toBe(true)
24
+
25
+ // broadcast_ack du ref de A → seul A résout ; le pending de B reste
26
+ a._onMessage({ type: 'broadcast_ack', ref_id: rA } as never)
27
+ return Promise.resolve().then(async () => {
28
+ await expect(pa).resolves.toBe('ok')
29
+ expect((b as unknown as { _pendingAcks: Map<string, unknown> })._pendingAcks.has(rB)).toBe(true)
30
+ vi.advanceTimersByTime(5000) // laisse pb timeout (nettoyage)
31
+ await expect(pb).resolves.toBe('timeout')
32
+ })
33
+ })
34
+ })
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect, vi } from 'vitest'
2
+ import { RealtimeService } from '../src/RealtimeService'
3
+ import { BaseAuthStore } from '@aurabase/core'
4
+ import type { AuraClientLike } from '@aurabase/core'
5
+
6
+ function makeClient(store = new BaseAuthStore()): AuraClientLike {
7
+ return {
8
+ baseUrl: 'http://x',
9
+ projectId: 'p',
10
+ apiKey: 'k',
11
+ fetchFn: (async () => new Response('{}')) as unknown as typeof globalThis.fetch,
12
+ authStore: store,
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ auth: { refreshSession: async () => ({ data: null, error: null }) as any },
15
+ }
16
+ }
17
+
18
+ function spySend(rt: RealtimeService) {
19
+ return vi
20
+ .spyOn(rt as unknown as { _send: (d: string) => void }, '_send')
21
+ .mockImplementation(() => {})
22
+ }
23
+
24
+ describe('RealtimeService.setAuth — parité Supabase', () => {
25
+ it("setAuth(token) pousse un seul { type:'access_token', token } (dédupliqué)", () => {
26
+ const rt = new RealtimeService(makeClient())
27
+ const send = spySend(rt)
28
+
29
+ rt.setAuth('tok')
30
+ expect(send).toHaveBeenCalledTimes(1)
31
+ expect(JSON.parse(send.mock.calls[0]![0] as string)).toEqual({
32
+ type: 'access_token',
33
+ token: 'tok',
34
+ })
35
+
36
+ // Second appel identique → pas de renvoi (déduplication _lastSentToken).
37
+ rt.setAuth('tok')
38
+ expect(send).toHaveBeenCalledTimes(1)
39
+ })
40
+
41
+ it('setAuth() sans argument reprend client.authStore.token', () => {
42
+ const store = new BaseAuthStore()
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ store.save('from-store', 'r', {} as any)
45
+ const rt = new RealtimeService(makeClient(store))
46
+ const send = spySend(rt)
47
+
48
+ rt.setAuth()
49
+
50
+ expect(send).toHaveBeenCalledTimes(1)
51
+ expect(JSON.parse(send.mock.calls[0]![0] as string)).toEqual({
52
+ type: 'access_token',
53
+ token: 'from-store',
54
+ })
55
+ })
56
+
57
+ it("setAuth() no-op si aucun token disponible", () => {
58
+ const rt = new RealtimeService(makeClient())
59
+ const send = spySend(rt)
60
+ rt.setAuth()
61
+ expect(send).not.toHaveBeenCalled()
62
+ })
63
+
64
+ it('ne provoque aucune reconnexion WS', () => {
65
+ const rt = new RealtimeService(makeClient())
66
+ spySend(rt)
67
+ rt.setAuth('tok')
68
+ expect(rt.connectionState).toBe('disconnected')
69
+ })
70
+ })
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": { "outDir": "dist", "rootDir": "src" },
4
+ "include": ["src"]
5
+ }
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from 'tsup'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['cjs', 'esm'],
6
+ dts: true,
7
+ splitting: false,
8
+ clean: true,
9
+ treeshake: true,
10
+ minify: false,
11
+ })
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aurabase
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.