@aurabase/aurabase-js 0.3.0 → 0.3.1

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 (258) hide show
  1. package/package.json +4 -4
  2. package/packages/ai/node_modules/.bin/esbuild +0 -19
  3. package/packages/ai/node_modules/.bin/tsc +0 -22
  4. package/packages/ai/node_modules/.bin/tsserver +0 -22
  5. package/packages/ai/node_modules/.bin/tsup +0 -22
  6. package/packages/ai/node_modules/.bin/tsup-node +0 -22
  7. package/packages/ai/node_modules/.bin/vite +0 -22
  8. package/packages/ai/node_modules/.bin/vitest +0 -22
  9. package/packages/ai/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  10. package/packages/ai/src/AiService.ts +0 -226
  11. package/packages/ai/src/index.ts +0 -18
  12. package/packages/ai/src/sse.ts +0 -141
  13. package/packages/ai/src/types.ts +0 -30
  14. package/packages/ai/tests/chat-stream.test.ts +0 -151
  15. package/packages/ai/tests/rag-namespaces.test.ts +0 -54
  16. package/packages/ai/tests/sse.test.ts +0 -69
  17. package/packages/ai/tsconfig.json +0 -5
  18. package/packages/ai/tsup.config.ts +0 -11
  19. package/packages/aurabase/node_modules/.bin/esbuild +0 -19
  20. package/packages/aurabase/node_modules/.bin/tsc +0 -22
  21. package/packages/aurabase/node_modules/.bin/tsserver +0 -22
  22. package/packages/aurabase/node_modules/.bin/tsup +0 -22
  23. package/packages/aurabase/node_modules/.bin/tsup-node +0 -22
  24. package/packages/aurabase/node_modules/.bin/vite +0 -22
  25. package/packages/aurabase/node_modules/.bin/vitest +0 -22
  26. package/packages/aurabase/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  27. package/packages/aurabase/src/AuraClient.ts +0 -237
  28. package/packages/aurabase/src/index.ts +0 -152
  29. package/packages/aurabase/src/ssr.ts +0 -156
  30. package/packages/aurabase/tests/ai-streaming-rag-e2e.test.ts +0 -82
  31. package/packages/aurabase/tests/ai.test.ts +0 -111
  32. package/packages/aurabase/tests/auth-admin.test.ts +0 -515
  33. package/packages/aurabase/tests/auth-e2e.test.ts +0 -135
  34. package/packages/aurabase/tests/auth-hardening.test.ts +0 -206
  35. package/packages/aurabase/tests/auth.test.ts +0 -947
  36. package/packages/aurabase/tests/database.test.ts +0 -230
  37. package/packages/aurabase/tests/db-types-e2e.test.ts +0 -217
  38. package/packages/aurabase/tests/dispose.test.ts +0 -23
  39. package/packages/aurabase/tests/foreign-token.e2e.test.ts +0 -129
  40. package/packages/aurabase/tests/functions.test.ts +0 -107
  41. package/packages/aurabase/tests/integration.test.ts +0 -413
  42. package/packages/aurabase/tests/live-production-validation.js +0 -241
  43. package/packages/aurabase/tests/live-sdk-production-validation.js +0 -293
  44. package/packages/aurabase/tests/mocks.ts +0 -139
  45. package/packages/aurabase/tests/notifications.test.ts +0 -314
  46. package/packages/aurabase/tests/observability-backup.test.ts +0 -186
  47. package/packages/aurabase/tests/observability-hook.test.ts +0 -130
  48. package/packages/aurabase/tests/production-robustness.test.ts +0 -268
  49. package/packages/aurabase/tests/public-api-surface.test.ts +0 -53
  50. package/packages/aurabase/tests/query-builder.test.ts +0 -329
  51. package/packages/aurabase/tests/readme-smoke-e2e.test.ts +0 -231
  52. package/packages/aurabase/tests/realtime-filter-e2e.test.ts +0 -344
  53. package/packages/aurabase/tests/refresh-locks.test.ts +0 -210
  54. package/packages/aurabase/tests/retry-option.test.ts +0 -17
  55. package/packages/aurabase/tests/rpc-e2e.test.ts +0 -254
  56. package/packages/aurabase/tests/rs256-local-e2e.test.ts +0 -114
  57. package/packages/aurabase/tests/rt-alias-public-e2e.test.ts +0 -235
  58. package/packages/aurabase/tests/rt-http-broadcast-e2e.test.ts +0 -124
  59. package/packages/aurabase/tests/service-role-guard.test.ts +0 -99
  60. package/packages/aurabase/tests/ssr.test.ts +0 -91
  61. package/packages/aurabase/tests/storage-backend-e2e.test.ts +0 -481
  62. package/packages/aurabase/tests/storage-sdk-parity-e2e.test.ts +0 -104
  63. package/packages/aurabase/tests/storage-transform-e2e.test.ts +0 -684
  64. package/packages/aurabase/tests/storage.test.ts +0 -55
  65. package/packages/aurabase/tests/types/client-generic.test-d.ts +0 -79
  66. package/packages/aurabase/tests/types/docs-snippets.test-d.ts +0 -571
  67. package/packages/aurabase/tests/types/error-code.test-d.ts +0 -53
  68. package/packages/aurabase/tsconfig.json +0 -5
  69. package/packages/aurabase/tsconfig.test-d.json +0 -5
  70. package/packages/aurabase/tsup.config.ts +0 -11
  71. package/packages/aurabase/vitest.config.ts +0 -16
  72. package/packages/auth/node_modules/.bin/esbuild +0 -19
  73. package/packages/auth/node_modules/.bin/tsc +0 -22
  74. package/packages/auth/node_modules/.bin/tsserver +0 -22
  75. package/packages/auth/node_modules/.bin/tsup +0 -22
  76. package/packages/auth/node_modules/.bin/tsup-node +0 -22
  77. package/packages/auth/node_modules/.bin/vite +0 -22
  78. package/packages/auth/node_modules/.bin/vitest +0 -22
  79. package/packages/auth/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  80. package/packages/auth/src/AuthAdminService.ts +0 -149
  81. package/packages/auth/src/AuthService.ts +0 -1166
  82. package/packages/auth/src/SessionManager.ts +0 -92
  83. package/packages/auth/src/index.ts +0 -17
  84. package/packages/auth/src/jwks.ts +0 -337
  85. package/packages/auth/src/pkce.ts +0 -27
  86. package/packages/auth/src/types.ts +0 -89
  87. package/packages/auth/tests/auth-lifecycle.test.ts +0 -149
  88. package/packages/auth/tests/detect-session.test.ts +0 -361
  89. package/packages/auth/tests/getclaims.test.ts +0 -780
  90. package/packages/auth/tests/is-mfa-challenge.test.ts +0 -27
  91. package/packages/auth/tests/password-recovery.test.ts +0 -124
  92. package/packages/auth/tests/pkce.test.ts +0 -192
  93. package/packages/auth/tests/session-manager.test.ts +0 -103
  94. package/packages/auth/tests/set-session.test.ts +0 -139
  95. package/packages/auth/tests/verify-otp.test.ts +0 -153
  96. package/packages/auth/tsconfig.json +0 -5
  97. package/packages/auth/tsup.config.ts +0 -11
  98. package/packages/core/node_modules/.bin/esbuild +0 -22
  99. package/packages/core/node_modules/.bin/tsc +0 -22
  100. package/packages/core/node_modules/.bin/tsserver +0 -22
  101. package/packages/core/node_modules/.bin/tsup +0 -22
  102. package/packages/core/node_modules/.bin/tsup-node +0 -22
  103. package/packages/core/node_modules/.bin/vite +0 -22
  104. package/packages/core/node_modules/.bin/vitest +0 -22
  105. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  106. package/packages/core/src/AuraError.ts +0 -89
  107. package/packages/core/src/BaseService.ts +0 -44
  108. package/packages/core/src/client.ts +0 -34
  109. package/packages/core/src/cookie-utils.ts +0 -42
  110. package/packages/core/src/fetch.ts +0 -435
  111. package/packages/core/src/index.ts +0 -22
  112. package/packages/core/src/retry.ts +0 -63
  113. package/packages/core/src/serialize.ts +0 -6
  114. package/packages/core/src/stores/BaseAuthStore.ts +0 -164
  115. package/packages/core/src/stores/LocalAuthStore.ts +0 -199
  116. package/packages/core/src/types.ts +0 -1042
  117. package/packages/core/tests/auth-store.test.ts +0 -300
  118. package/packages/core/tests/error-code.test.ts +0 -61
  119. package/packages/core/tests/error.test.ts +0 -24
  120. package/packages/core/tests/fetch.test.ts +0 -286
  121. package/packages/core/tests/mocks.ts +0 -139
  122. package/packages/core/tests/observability.test.ts +0 -86
  123. package/packages/core/tests/refresh-hardening.test.ts +0 -164
  124. package/packages/core/tests/refresh-observability.test.ts +0 -111
  125. package/packages/core/tests/retry.test.ts +0 -106
  126. package/packages/core/tests/serialize.test.ts +0 -12
  127. package/packages/core/tests/timeout.test.ts +0 -79
  128. package/packages/core/tsconfig.json +0 -5
  129. package/packages/core/tsup.config.ts +0 -11
  130. package/packages/db/node_modules/.bin/esbuild +0 -19
  131. package/packages/db/node_modules/.bin/tsc +0 -22
  132. package/packages/db/node_modules/.bin/tsserver +0 -22
  133. package/packages/db/node_modules/.bin/tsup +0 -22
  134. package/packages/db/node_modules/.bin/tsup-node +0 -22
  135. package/packages/db/node_modules/.bin/vite +0 -22
  136. package/packages/db/node_modules/.bin/vitest +0 -22
  137. package/packages/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  138. package/packages/db/src/DatabaseService.ts +0 -170
  139. package/packages/db/src/QueryBuilder.ts +0 -830
  140. package/packages/db/src/index.ts +0 -2
  141. package/packages/db/src/pgrst-types/common/common.ts +0 -86
  142. package/packages/db/src/pgrst-types/common/rpc.ts +0 -151
  143. package/packages/db/src/pgrst-types/feature-flags.ts +0 -20
  144. package/packages/db/src/pgrst-types/types.ts +0 -134
  145. package/packages/db/src/select-query-parser/parser.ts +0 -479
  146. package/packages/db/src/select-query-parser/result.ts +0 -553
  147. package/packages/db/src/select-query-parser/types.ts +0 -132
  148. package/packages/db/src/select-query-parser/utils.ts +0 -707
  149. package/packages/db/tests/filters.test.ts +0 -81
  150. package/packages/db/tests/mutations-filtered.e2e.test.ts +0 -132
  151. package/packages/db/tests/mutations-filtered.test.ts +0 -188
  152. package/packages/db/tests/order.test.ts +0 -45
  153. package/packages/db/tests/rpc.test.ts +0 -41
  154. package/packages/db/tests/scale/build-large-schema.ts +0 -94
  155. package/packages/db/tests/scale/scale-compile.test.ts +0 -167
  156. package/packages/db/tests/schema.test.ts +0 -77
  157. package/packages/db/tests/single-accept.e2e.test.ts +0 -123
  158. package/packages/db/tests/single.test.ts +0 -211
  159. package/packages/db/tests/types/filters.test-d.ts +0 -52
  160. package/packages/db/tests/types/fixtures.ts +0 -40
  161. package/packages/db/tests/types/from-views.test-d.ts +0 -18
  162. package/packages/db/tests/types/mutations.test-d.ts +0 -23
  163. package/packages/db/tests/types/rpc.test-d.ts +0 -60
  164. package/packages/db/tests/types/schema-shape.test-d.ts +0 -8
  165. package/packages/db/tests/types/select-inference.test-d.ts +0 -38
  166. package/packages/db/tests/vendored/fixtures.ts +0 -83
  167. package/packages/db/tests/vendored/get-result.test-d.ts +0 -75
  168. package/packages/db/tsconfig.json +0 -5
  169. package/packages/db/tsconfig.test-d.json +0 -5
  170. package/packages/db/tsup.config.ts +0 -11
  171. package/packages/db/vitest.config.ts +0 -8
  172. package/packages/functions/node_modules/.bin/esbuild +0 -19
  173. package/packages/functions/node_modules/.bin/tsc +0 -22
  174. package/packages/functions/node_modules/.bin/tsserver +0 -22
  175. package/packages/functions/node_modules/.bin/tsup +0 -22
  176. package/packages/functions/node_modules/.bin/tsup-node +0 -22
  177. package/packages/functions/node_modules/.bin/vite +0 -22
  178. package/packages/functions/node_modules/.bin/vitest +0 -22
  179. package/packages/functions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  180. package/packages/functions/src/FunctionsService.ts +0 -188
  181. package/packages/functions/src/errors.ts +0 -70
  182. package/packages/functions/src/index.ts +0 -6
  183. package/packages/functions/tests/invoke.test.ts +0 -97
  184. package/packages/functions/tests/response-type-errors.test.ts +0 -135
  185. package/packages/functions/tsconfig.json +0 -5
  186. package/packages/functions/tsup.config.ts +0 -11
  187. package/packages/gen/node_modules/.bin/esbuild +0 -19
  188. package/packages/gen/node_modules/.bin/tsc +0 -22
  189. package/packages/gen/node_modules/.bin/tsserver +0 -22
  190. package/packages/gen/node_modules/.bin/tsup +0 -22
  191. package/packages/gen/node_modules/.bin/tsup-node +0 -22
  192. package/packages/gen/node_modules/.bin/vite +0 -22
  193. package/packages/gen/node_modules/.bin/vitest +0 -22
  194. package/packages/gen/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  195. package/packages/gen/src/cli.ts +0 -67
  196. package/packages/gen/src/generate.ts +0 -0
  197. package/packages/gen/src/index.ts +0 -2
  198. package/packages/gen/tests/compile.test.ts +0 -213
  199. package/packages/gen/tests/e2e.test.ts +0 -130
  200. package/packages/gen/tests/generate.test.ts +0 -396
  201. package/packages/gen/tsconfig.json +0 -5
  202. package/packages/gen/tsup.config.ts +0 -11
  203. package/packages/notifications/node_modules/.bin/esbuild +0 -19
  204. package/packages/notifications/node_modules/.bin/tsc +0 -22
  205. package/packages/notifications/node_modules/.bin/tsserver +0 -22
  206. package/packages/notifications/node_modules/.bin/tsup +0 -22
  207. package/packages/notifications/node_modules/.bin/tsup-node +0 -22
  208. package/packages/notifications/node_modules/.bin/vite +0 -22
  209. package/packages/notifications/node_modules/.bin/vitest +0 -22
  210. package/packages/notifications/src/NotificationsService.ts +0 -230
  211. package/packages/notifications/src/index.ts +0 -19
  212. package/packages/notifications/tsconfig.json +0 -5
  213. package/packages/notifications/tsup.config.ts +0 -11
  214. package/packages/realtime/node_modules/.bin/esbuild +0 -19
  215. package/packages/realtime/node_modules/.bin/tsc +0 -22
  216. package/packages/realtime/node_modules/.bin/tsserver +0 -22
  217. package/packages/realtime/node_modules/.bin/tsup +0 -22
  218. package/packages/realtime/node_modules/.bin/tsup-node +0 -22
  219. package/packages/realtime/node_modules/.bin/vite +0 -22
  220. package/packages/realtime/node_modules/.bin/vitest +0 -22
  221. package/packages/realtime/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  222. package/packages/realtime/src/AuraChannel.ts +0 -485
  223. package/packages/realtime/src/HeartbeatManager.ts +0 -73
  224. package/packages/realtime/src/RealtimeService.ts +0 -505
  225. package/packages/realtime/src/columnFilter.ts +0 -301
  226. package/packages/realtime/src/index.ts +0 -4
  227. package/packages/realtime/tests/ack-routing.test.ts +0 -81
  228. package/packages/realtime/tests/column-filter.test.ts +0 -144
  229. package/packages/realtime/tests/dispatch.test.ts +0 -191
  230. package/packages/realtime/tests/heartbeat.test.ts +0 -67
  231. package/packages/realtime/tests/http-broadcast.test.ts +0 -68
  232. package/packages/realtime/tests/realtime-token.test.ts +0 -43
  233. package/packages/realtime/tests/reconnect-race.test.ts +0 -149
  234. package/packages/realtime/tests/ref-id.test.ts +0 -34
  235. package/packages/realtime/tests/set-auth.test.ts +0 -70
  236. package/packages/realtime/tsconfig.json +0 -5
  237. package/packages/realtime/tsup.config.ts +0 -11
  238. package/packages/storage/node_modules/.bin/esbuild +0 -19
  239. package/packages/storage/node_modules/.bin/tsc +0 -22
  240. package/packages/storage/node_modules/.bin/tsserver +0 -22
  241. package/packages/storage/node_modules/.bin/tsup +0 -22
  242. package/packages/storage/node_modules/.bin/tsup-node +0 -22
  243. package/packages/storage/node_modules/.bin/vite +0 -22
  244. package/packages/storage/node_modules/.bin/vitest +0 -22
  245. package/packages/storage/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  246. package/packages/storage/src/DownloadBuilder.ts +0 -60
  247. package/packages/storage/src/StorageService.ts +0 -323
  248. package/packages/storage/src/index.ts +0 -2
  249. package/packages/storage/src/path.ts +0 -35
  250. package/packages/storage/src/transform.ts +0 -15
  251. package/packages/storage/tests/download.test.ts +0 -64
  252. package/packages/storage/tests/parity.test.ts +0 -154
  253. package/packages/storage/tests/path.test.ts +0 -87
  254. package/packages/storage/tests/transform.test.ts +0 -79
  255. package/packages/storage/tsconfig.json +0 -5
  256. package/packages/storage/tsup.config.ts +0 -11
  257. package/pnpm-workspace.yaml +0 -24
  258. package/tsconfig.base.json +0 -15
@@ -1,235 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // E2E réel (stack live) — Lot realtime / correctif `rt-alias-public-rls`.
3
- // Réf. : docs/superpowers/specs/2026-07-13-rt-alias-public-rls-design.md
4
- //
5
- // PROUVE la correction du bug backend : un client abonné via l'ALIAS PUBLIC
6
- // `db:public.{table}` (le canal auquel s'abonnent réellement Studio et le SDK)
7
- // reçoit bien les events postgres_changes.
8
- //
9
- // AVANT le fix : le CDC ne collectait `allowed_sub_ids` que sur le canal
10
- // GÉNÉRIQUE (schéma physique `project_<uuid>`) ; un abonné via l'alias public
11
- // n'y figurait jamais → branche fail-closed déclenchée MÊME SANS policy RLS →
12
- // 0 INSERT/UPDATE reçu. C'est d'ailleurs pourquoi le test frère
13
- // `realtime-filter-e2e.test.ts` s'abonne, lui, au canal générique pour
14
- // contourner ce bug (cf. son commentaire l.142-147).
15
- //
16
- // APRÈS le fix (cdc/postgres.rs → get_subscribers_for_channels sur les 3
17
- // formes) : l'abonné via l'alias public est inclus dans le calcul RLS et reçoit
18
- // les events autorisés. Ce test s'abonne DONC volontairement à `db:public.*`.
19
- //
20
- // Mécanisme d'activation realtime + auth WS : identiques au test frère
21
- // (PUT /v1/db/{project}/schema/tables/{table}/realtime, JWT via signUp/signIn).
22
- // Gaté par RUN_E2E + credentials ; skip gracieux sur infra transitoire.
23
- // ---------------------------------------------------------------------------
24
-
25
- import { describe, it, expect } from 'vitest'
26
- import { createClient, createAdminClient } from '../src/index'
27
- import type { AuraResponse, RealtimeEvent, RealtimeSubscribeStatus } from '../src/index'
28
-
29
- const URL = process.env.AURA_E2E_URL
30
- const PROJECT = process.env.AURA_E2E_PROJECT
31
- const ANON = process.env.AURA_E2E_ANON_KEY
32
- const SERVICE = process.env.AURA_E2E_SERVICE_KEY
33
- const RUN = Boolean(process.env.RUN_E2E && URL && PROJECT && ANON && SERVICE)
34
-
35
- const TRANSIENT_STATUS = new Set([408, 429, 502, 503, 504])
36
-
37
- async function retryTransient<T>(fn: () => Promise<AuraResponse<T>>): Promise<AuraResponse<T>> {
38
- let res = await fn()
39
- for (let i = 0; i < 10 && res.error && TRANSIENT_STATUS.has(res.error.status); i++) {
40
- await new Promise((r) => setTimeout(r, 1000))
41
- res = await fn()
42
- }
43
- return res
44
- }
45
-
46
- async function retryFetchTransient(fn: () => Promise<Response>): Promise<Response> {
47
- let res = await fn()
48
- for (let i = 0; i < 10 && TRANSIENT_STATUS.has(res.status); i++) {
49
- await new Promise((r) => setTimeout(r, 1000))
50
- res = await fn()
51
- }
52
- return res
53
- }
54
-
55
- function sleep(ms: number): Promise<void> {
56
- return new Promise((r) => setTimeout(r, ms))
57
- }
58
-
59
- type CdcRecord = Record<string, unknown>
60
- interface CdcPayload {
61
- schema: string
62
- table: string
63
- type: 'INSERT' | 'UPDATE' | 'DELETE'
64
- record: CdcRecord
65
- old_record: CdcRecord | null
66
- }
67
-
68
- function waitForSubscribeStatus(
69
- doSubscribe: (cb: (status: RealtimeSubscribeStatus, err?: Error) => void) => void,
70
- timeoutMs: number,
71
- ): Promise<{ status: RealtimeSubscribeStatus; err?: Error } | 'timeout'> {
72
- return new Promise((resolve) => {
73
- let done = false
74
- const timer = setTimeout(() => {
75
- if (!done) {
76
- done = true
77
- resolve('timeout')
78
- }
79
- }, timeoutMs)
80
- doSubscribe((status, err) => {
81
- if (done) return
82
- done = true
83
- clearTimeout(timer)
84
- resolve({ status, err })
85
- })
86
- })
87
- }
88
-
89
- describe.runIf(RUN)('realtime alias public E2E réel — un abonné à db:public.{table} reçoit les events', () => {
90
- it(
91
- "l'alias public db:public.{table} délivre bien l'INSERT (régression du bug allowed_sub_ids)",
92
- async () => {
93
- const admin = createAdminClient(URL!, PROJECT!, SERVICE!)
94
- const anon = createClient(URL!, PROJECT!, ANON!)
95
- const suffix = process.env.AURA_E2E_SUFFIX ?? Math.random().toString(36).slice(2, 8)
96
- const table = `rt_pub_${suffix}`
97
- // On s'abonne à l'ALIAS PUBLIC (et NON au canal générique physique) :
98
- // c'est précisément le chemin qui donnait 0 event avant le correctif.
99
- const channelName = `db:public.${table}`
100
- const email = `rt-alias-public-e2e-${suffix}@aurabase.dev`
101
- const password = 'EndUserPassword123!'
102
-
103
- let tableCreated = false
104
- let userId: string | null = null
105
-
106
- try {
107
- // -- 1. Setup service_role : table jetable + GRANT + reload PostgREST ----
108
- await admin.db.sql(`DROP TABLE IF EXISTS ${table}`)
109
- const createRes = await admin.db.sql(
110
- `CREATE TABLE ${table} (
111
- id serial PRIMARY KEY,
112
- body text NOT NULL DEFAULT ''
113
- )`,
114
- )
115
- if (createRes.error) {
116
- // eslint-disable-next-line no-console
117
- console.warn(
118
- `[rt-alias-public-e2e] SKIP (infra: CREATE TABLE a échoué — ${createRes.error.status} ` +
119
- `${createRes.error.message ?? ''}).`,
120
- )
121
- return
122
- }
123
- tableCreated = true
124
- await admin.db.sql(`GRANT ALL ON ${table} TO PUBLIC`)
125
- await admin.db.sql(`SELECT pg_notify('pgrst', 'reload schema')`)
126
-
127
- // -- 2. Activer le realtime CDC pour cette table (service_role) ---------
128
- // (aucune policy RLS n'est créée : le bug se déclenchait MÊME sans RLS)
129
- const enableRes = await retryFetchTransient(() =>
130
- fetch(`${admin.baseUrl}/v1/db/${admin.projectId}/schema/tables/${table}/realtime`, {
131
- method: 'PUT',
132
- headers: { apikey: SERVICE!, 'content-type': 'application/json' },
133
- body: JSON.stringify({ enabled: true }),
134
- }),
135
- )
136
- if (!enableRes.ok) {
137
- // eslint-disable-next-line no-console
138
- console.warn(
139
- `[rt-alias-public-e2e] SKIP (infra: PUT .../schema/tables/${table}/realtime → ` +
140
- `${enableRes.status}).`,
141
- )
142
- return
143
- }
144
-
145
- // -- 3. Utilisateur jetable (anon key) — le WS exige un vrai JWT --------
146
- const signUpRes = await retryTransient(() => anon.auth.signUp({ email, password }))
147
- if (signUpRes.error && TRANSIENT_STATUS.has(signUpRes.error.status)) {
148
- // eslint-disable-next-line no-console
149
- console.warn(`[rt-alias-public-e2e] SKIP (infra: signUp — ${signUpRes.error.status}).`)
150
- return
151
- }
152
- expect(signUpRes.error).toBeNull()
153
-
154
- const loginRes = await retryTransient(() => anon.auth.signInWithPassword({ email, password }))
155
- if (loginRes.error && TRANSIENT_STATUS.has(loginRes.error.status)) {
156
- // eslint-disable-next-line no-console
157
- console.warn(`[rt-alias-public-e2e] SKIP (infra: signIn — ${loginRes.error.status}).`)
158
- return
159
- }
160
- expect(loginRes.error).toBeNull()
161
- const loginData = loginRes.data as { user: { id: string } } | null
162
- userId = loginData?.user.id ?? null
163
-
164
- // -- 4. Laisser le filtre CDC se rafraîchir (add-tables, ~3s) -----------
165
- await sleep(4000)
166
-
167
- // -- 5. Connexion WS + abonnement à l'ALIAS PUBLIC ----------------------
168
- anon.realtime.connect()
169
- const received: RealtimeEvent<CdcPayload>[] = []
170
- const channel = anon.channel(channelName)
171
- channel.on(
172
- 'postgres_changes',
173
- // `schema` omis (le payload porte le schéma physique) — on isole la
174
- // livraison via l'alias public, table filtrée par nom.
175
- { event: '*', table },
176
- (payload) => received.push(payload as RealtimeEvent<CdcPayload>),
177
- )
178
-
179
- const result = await waitForSubscribeStatus((cb) => channel.subscribe(cb), 15_000)
180
- if (result === 'timeout' || result.status !== 'SUBSCRIBED') {
181
- // eslint-disable-next-line no-console
182
- console.warn(
183
- `[rt-alias-public-e2e] SKIP (WS/CDC pas prêt — ` +
184
- `${result === 'timeout' ? 'timeout SUBSCRIBED' : `statut ${result.status}`}).`,
185
- )
186
- return
187
- }
188
-
189
- // -- 6. INSERT une ligne via service_role -------------------------------
190
- const marker = `hello-${suffix}`
191
- const ins = await admin.db.sql(`INSERT INTO ${table} (body) VALUES ($1)`, [marker])
192
- expect(ins.error).toBeNull()
193
-
194
- // -- 7. Fenêtre de collecte CDC (poll WAL + pub/sub) --------------------
195
- await sleep(8_000)
196
-
197
- // -- 8. ASSERTION : l'event a bien été livré via l'alias public ---------
198
- const gotInsert = received.some(
199
- (e) => e.payload?.type === 'INSERT' && e.payload?.record?.body === marker,
200
- )
201
- expect(
202
- gotInsert,
203
- `aucun INSERT reçu via l'alias public ${channelName} — le bug allowed_sub_ids n'est PAS corrigé ` +
204
- `(events reçus: ${received.length})`,
205
- ).toBe(true)
206
- } finally {
207
- try {
208
- anon.realtime.removeAllChannels()
209
- } catch {
210
- /* best-effort */
211
- }
212
- try {
213
- anon.realtime.disconnect()
214
- } catch {
215
- /* best-effort */
216
- }
217
- if (userId) {
218
- try {
219
- await admin.authAdmin.deleteUser(userId)
220
- } catch {
221
- /* best-effort */
222
- }
223
- }
224
- if (tableCreated) {
225
- try {
226
- await admin.db.sql(`DROP TABLE IF EXISTS ${table}`)
227
- } catch {
228
- /* best-effort */
229
- }
230
- }
231
- }
232
- },
233
- 120_000,
234
- )
235
- })
@@ -1,124 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // E2E réel (stack live) — Lot sdk-realtime / correctif `rt-http-broadcast`.
3
- // Réf. : docs/superpowers/specs/2026-07-13-rt-http-broadcast-design.md
4
- //
5
- // PROUVE que `realtime.httpBroadcast(channel, event, payload)` (envoi REST hors
6
- // WebSocket, POST /v1/realtime/{project}/broadcast) est bien distribué à un
7
- // abonné connecté en WebSocket sur le même canal broadcast. Valide le contrat
8
- // backend { channel (préfixé projet), payload:{ event, ... } } de bout en bout.
9
- //
10
- // Gaté par RUN_E2E + credentials ; skip gracieux sur infra transitoire.
11
- // ---------------------------------------------------------------------------
12
-
13
- import { describe, it, expect } from 'vitest'
14
- import { createClient } from '../src/index'
15
- import type { RealtimeSubscribeStatus } from '../src/index'
16
-
17
- const URL = process.env.AURA_E2E_URL
18
- const PROJECT = process.env.AURA_E2E_PROJECT
19
- const ANON = process.env.AURA_E2E_ANON_KEY
20
- const SERVICE = process.env.AURA_E2E_SERVICE_KEY
21
- const RUN = Boolean(process.env.RUN_E2E && URL && PROJECT && ANON && SERVICE)
22
-
23
- const TRANSIENT_STATUS = new Set([408, 429, 502, 503, 504])
24
- const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms))
25
-
26
- function waitForSubscribeStatus(
27
- doSubscribe: (cb: (status: RealtimeSubscribeStatus, err?: Error) => void) => void,
28
- timeoutMs: number,
29
- ): Promise<{ status: RealtimeSubscribeStatus } | 'timeout'> {
30
- return new Promise((resolve) => {
31
- let done = false
32
- const timer = setTimeout(() => {
33
- if (!done) {
34
- done = true
35
- resolve('timeout')
36
- }
37
- }, timeoutMs)
38
- doSubscribe((status) => {
39
- if (done) return
40
- done = true
41
- clearTimeout(timer)
42
- resolve({ status })
43
- })
44
- })
45
- }
46
-
47
- describe.runIf(RUN)('realtime httpBroadcast E2E réel — REST → WebSocket', () => {
48
- it(
49
- 'un broadcast émis via httpBroadcast (REST) est livré à un abonné WebSocket du même canal',
50
- async () => {
51
- const anon = createClient(URL!, PROJECT!, ANON!)
52
- const suffix = process.env.AURA_E2E_SUFFIX ?? Math.random().toString(36).slice(2, 8)
53
- const channelName = `httpbcast-${suffix}`
54
- const evt = 'ping'
55
- const marker = `hello-${suffix}`
56
- const email = `rt-httpbcast-e2e-${suffix}@aurabase.dev`
57
- const password = 'EndUserPassword123!'
58
-
59
- let userId: string | null = null
60
- const received: unknown[] = []
61
-
62
- try {
63
- // Le WS exige un vrai JWT → utilisateur jetable via la clé anon.
64
- const signUp = await anon.auth.signUp({ email, password })
65
- if (signUp.error && TRANSIENT_STATUS.has(signUp.error.status)) {
66
- console.warn(`[rt-http-broadcast-e2e] SKIP (signUp ${signUp.error.status}).`)
67
- return
68
- }
69
- const login = await anon.auth.signInWithPassword({ email, password })
70
- if (login.error && TRANSIENT_STATUS.has(login.error.status)) {
71
- console.warn(`[rt-http-broadcast-e2e] SKIP (signIn ${login.error.status}).`)
72
- return
73
- }
74
- expect(login.error).toBeNull()
75
- userId = (login.data as { user?: { id: string } } | null)?.user?.id ?? null
76
-
77
- anon.realtime.connect()
78
- const channel = anon.channel(channelName)
79
- channel.on('broadcast', { event: evt }, (payload) => received.push(payload))
80
-
81
- const res = await waitForSubscribeStatus((cb) => channel.subscribe(cb), 15_000)
82
- if (res === 'timeout' || res.status !== 'SUBSCRIBED') {
83
- console.warn(
84
- `[rt-http-broadcast-e2e] SKIP (WS pas prêt — ${res === 'timeout' ? 'timeout' : res.status}).`,
85
- )
86
- return
87
- }
88
-
89
- // Émission REST (hors WS) — le cœur du correctif.
90
- const bcast = await anon.realtime.httpBroadcast(channelName, evt, { msg: marker })
91
- if (bcast.error && TRANSIENT_STATUS.has(bcast.error.status)) {
92
- console.warn(`[rt-http-broadcast-e2e] SKIP (httpBroadcast ${bcast.error.status}).`)
93
- return
94
- }
95
- expect(bcast.error, `httpBroadcast a échoué: ${JSON.stringify(bcast.error)}`).toBeNull()
96
-
97
- // Fenêtre de livraison WS.
98
- await sleep(6_000)
99
-
100
- const got = received.some((r) => JSON.stringify(r).includes(marker))
101
- expect(
102
- got,
103
- `le broadcast REST n'a pas été livré à l'abonné WS (reçus: ${JSON.stringify(received)})`,
104
- ).toBe(true)
105
- } finally {
106
- try {
107
- anon.realtime.removeAllChannels()
108
- anon.realtime.disconnect()
109
- } catch {
110
- /* best-effort */
111
- }
112
- if (userId) {
113
- try {
114
- const admin = createClient(URL!, PROJECT!, SERVICE!)
115
- await admin.authAdmin?.deleteUser?.(userId)
116
- } catch {
117
- /* best-effort */
118
- }
119
- }
120
- }
121
- },
122
- 90_000,
123
- )
124
- })
@@ -1,99 +0,0 @@
1
- import { describe, it, expect, afterEach, vi } from 'vitest'
2
- import { createClient, createAdminClient, AuraClient } from '../src/index'
3
-
4
- const BASE = 'http://guard.local'
5
- const PROJECT = 'proj-guard'
6
-
7
- afterEach(() => {
8
- delete (globalThis as unknown as { window?: unknown }).window
9
- delete (globalThis as unknown as { DedicatedWorkerGlobalScope?: unknown }).DedicatedWorkerGlobalScope
10
- delete (globalThis as unknown as { SharedWorkerGlobalScope?: unknown }).SharedWorkerGlobalScope
11
- vi.restoreAllMocks()
12
- })
13
-
14
- describe('Garde service_role — authAdmin getter (I3, durci)', () => {
15
- it('THROW en contexte navigateur (window défini) au lieu de warn', () => {
16
- // Client construit hors navigateur (pas de window) : OK.
17
- const client = createClient(BASE, PROJECT, 'aura_anon_x', {
18
- auth: { autoRefresh: false, persistSession: false },
19
- })
20
- // Simule un navigateur.
21
- ;(globalThis as unknown as { window: unknown }).window = {}
22
- expect(() => client.authAdmin).toThrow(/navigateur/)
23
- })
24
-
25
- it('accessible en contexte serveur (pas de window)', () => {
26
- const client = createClient(BASE, PROJECT, 'aura_anon_x', {
27
- auth: { autoRefresh: false, persistSession: false },
28
- })
29
- // Ne throw pas hors navigateur.
30
- expect(() => client.authAdmin).not.toThrow()
31
- })
32
- })
33
-
34
- describe('Garde service_role — createClient côté navigateur (SEC-F5, throw par défaut)', () => {
35
- it('clé aura_sk_ (service_role) en navigateur → THROW par défaut (refuseServiceRoleInBrowser)', () => {
36
- ;(globalThis as unknown as { window: unknown }).window = {}
37
-
38
- expect(() =>
39
- createClient(BASE, PROJECT, 'aura_sk_secret', {
40
- auth: { autoRefresh: false, persistSession: false },
41
- }),
42
- ).toThrow(/service_role/)
43
- })
44
-
45
- it('clé aura_sk_ en navigateur avec refuseServiceRoleInBrowser:false → warn seulement (échappatoire)', () => {
46
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
47
- ;(globalThis as unknown as { window: unknown }).window = {}
48
-
49
- expect(() =>
50
- createClient(BASE, PROJECT, 'aura_sk_secret', {
51
- auth: { autoRefresh: false, persistSession: false },
52
- refuseServiceRoleInBrowser: false,
53
- }),
54
- ).not.toThrow()
55
-
56
- const warned = warn.mock.calls.some((c) => String(c[0]).includes('service_role'))
57
- expect(warned).toBe(true)
58
- })
59
-
60
- it('clé anon (aura_anon_) en navigateur → PAS de throw ni warning service_role (usage légitime)', () => {
61
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
62
- ;(globalThis as unknown as { window: unknown }).window = {}
63
-
64
- createClient(BASE, PROJECT, 'aura_anon_public', {
65
- auth: { autoRefresh: false, persistSession: false },
66
- })
67
-
68
- const warnedSrole = warn.mock.calls.some((c) => String(c[0]).includes('service_role'))
69
- expect(warnedSrole).toBe(false)
70
- })
71
-
72
- it('clé aura_sk_ hors navigateur (serveur) → PAS de warning', () => {
73
- const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
74
- createClient(BASE, PROJECT, 'aura_sk_secret', {
75
- auth: { autoRefresh: false, persistSession: false },
76
- })
77
- const warnedSrole = warn.mock.calls.some((c) => String(c[0]).includes('service_role'))
78
- expect(warnedSrole).toBe(false)
79
- })
80
- })
81
-
82
- describe('Garde service_role — createAdminClient (E21, étendue aux workers navigateur)', () => {
83
- it('THROW en contexte navigateur (window)', () => {
84
- ;(globalThis as unknown as { window: unknown }).window = {}
85
- expect(() => createAdminClient(BASE, PROJECT, 'aura_sk_x')).toThrow(/navigateur/)
86
- })
87
-
88
- it('THROW dans un Web Worker navigateur (DedicatedWorkerGlobalScope, sans window)', () => {
89
- ;(globalThis as unknown as { DedicatedWorkerGlobalScope: unknown }).DedicatedWorkerGlobalScope =
90
- function () {}
91
- expect(() => createAdminClient(BASE, PROJECT, 'aura_sk_x')).toThrow(/navigateur/)
92
- })
93
-
94
- it('OK en contexte serveur (ni window ni worker navigateur)', () => {
95
- const admin = createAdminClient(BASE, PROJECT, 'aura_sk_x')
96
- expect(admin).toBeInstanceOf(AuraClient)
97
- expect(admin.apiKey).toBe('aura_sk_x')
98
- })
99
- })
@@ -1,91 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { createServerClient } from '../src/ssr'
3
- import type { User } from '@aurabase/core'
4
-
5
- function b64url(o: unknown) { return btoa(JSON.stringify(o)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '') }
6
- function validJwt() { return `${b64url({ alg: 'HS256' })}.${b64url({ sub: 'u1', exp: Math.floor(Date.now() / 1000) + 3600 })}.s` }
7
- function user(metaSize = 0): User {
8
- return {
9
- id: 'u1', email: 't@e.com', role: 'authenticated', email_verified: true,
10
- is_banned: false, is_anonymous: false, mfa_enabled: false,
11
- user_metadata: metaSize ? { blob: 'x'.repeat(metaSize) } : {},
12
- app_metadata: {}, created_at: '2025-01-01T00:00:00Z',
13
- }
14
- }
15
-
16
- /** Faux magasin de cookies : setAll écrit / expire (maxAge 0), getAll relit. */
17
- function jar(initial: Array<{ name: string; value: string }> = []) {
18
- const store = new Map(initial.map((c) => [c.name, c.value]))
19
- return {
20
- getAll: () => [...store].map(([name, value]) => ({ name, value })),
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- setAll: (cs: Array<{ name: string; value: string; options: any }>) =>
23
- cs.forEach(({ name, value, options }) => {
24
- if (options?.maxAge === 0) store.delete(name)
25
- else store.set(name, value)
26
- }),
27
- store,
28
- }
29
- }
30
-
31
- describe('createServerClient — cookies SSR', () => {
32
- it('secure calé sur le protocole : false en http (dev), true en https', () => {
33
- const httpCalls: Array<{ options: { secure?: boolean } }> = []
34
- const http = createServerClient('http://localhost:8080', 'p', {
35
- apiKey: 'k',
36
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
- cookies: { getAll: () => [], setAll: (cs: any) => httpCalls.push(...cs) },
38
- })
39
- http.authStore.save(validJwt(), 'rt', user())
40
- expect(httpCalls[0].options.secure).toBe(false)
41
-
42
- const httpsCalls: Array<{ options: { secure?: boolean } }> = []
43
- const https = createServerClient('https://api.example.com', 'p', {
44
- apiKey: 'k',
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- cookies: { getAll: () => [], setAll: (cs: any) => httpsCalls.push(...cs) },
47
- })
48
- https.authStore.save(validJwt(), 'rt', user())
49
- expect(httpsCalls[0].options.secure).toBe(true)
50
- })
51
-
52
- it('session normale → un seul cookie ; round-trip write→read restaure la session', () => {
53
- const j = jar()
54
- const tok = validJwt()
55
- const c1 = createServerClient('https://x', 'p', { apiKey: 'k', cookies: j })
56
- c1.authStore.save(tok, 'rt', user())
57
- // un seul cookie, pas de chunk
58
- expect([...j.store.keys()]).toEqual(['aura-p-auth'])
59
-
60
- const c2 = createServerClient('https://x', 'p', { apiKey: 'k', cookies: j })
61
- expect(c2.authStore.token).toBe(tok)
62
- expect(c2.authStore.user?.id).toBe('u1')
63
- })
64
-
65
- it('session volumineuse → fragmentée en chunks .0/.1… ; round-trip la reconstitue', () => {
66
- const j = jar()
67
- const tok = validJwt()
68
- const c1 = createServerClient('https://x', 'p', { apiKey: 'k', cookies: j })
69
- c1.authStore.save(tok, 'rt', user(5000)) // > MAX_CHUNK_SIZE → chunks
70
- const names = [...j.store.keys()]
71
- expect(names).toContain('aura-p-auth.0')
72
- expect(names).toContain('aura-p-auth.1')
73
- expect(names).not.toContain('aura-p-auth') // pas de cookie unique quand chunké
74
-
75
- const c2 = createServerClient('https://x', 'p', { apiKey: 'k', cookies: j })
76
- expect(c2.authStore.token).toBe(tok)
77
- expect(c2.authStore.user?.user_metadata?.blob).toBe('x'.repeat(5000))
78
- })
79
-
80
- it('signout (clear) expire les cookies auth présents', () => {
81
- const j = jar()
82
- const c1 = createServerClient('https://x', 'p', { apiKey: 'k', cookies: j })
83
- c1.authStore.save(validJwt(), 'rt', user())
84
- expect(j.store.size).toBe(1)
85
-
86
- // Nouveau client qui charge le cookie, puis signout.
87
- const c2 = createServerClient('https://x', 'p', { apiKey: 'k', cookies: j })
88
- c2.authStore.clear()
89
- expect(j.store.size).toBe(0) // cookie expiré/supprimé
90
- })
91
- })