@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,149 +0,0 @@
1
- import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest'
2
- import { AuthService } from '../src/AuthService'
3
- import { BaseAuthStore } from '@aurabase/core'
4
- import type { AuraClientLike, User } from '@aurabase/core'
5
-
6
- // --- helpers inline (évite un mocks.ts dédié au package auth) ----------------
7
- function b64url(obj: unknown): string {
8
- return btoa(JSON.stringify(obj)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
9
- }
10
- function validJwt(): string {
11
- const exp = Math.floor(Date.now() / 1000) + 3600
12
- return `${b64url({ alg: 'HS256', typ: 'JWT' })}.${b64url({ sub: 'u1', exp })}.sig`
13
- }
14
- function fakeUser(): User {
15
- return {
16
- id: 'u1', email: 't@e.com', role: 'authenticated', email_verified: true,
17
- is_banned: false, is_anonymous: false, mfa_enabled: false,
18
- user_metadata: {}, app_metadata: {}, created_at: '2025-01-01T00:00:00Z',
19
- }
20
- }
21
-
22
- // --- mock BroadcastChannel ---------------------------------------------------
23
- class FakeBC {
24
- static instances: FakeBC[] = []
25
- onmessage: ((e: { data: unknown }) => void) | null = null
26
- posted: unknown[] = []
27
- closed = false
28
- constructor(public name: string) { FakeBC.instances.push(this) }
29
- postMessage(d: unknown) { this.posted.push(d) }
30
- close() { this.closed = true }
31
- }
32
-
33
- beforeEach(() => {
34
- FakeBC.instances = []
35
- ;(globalThis as unknown as { BroadcastChannel: unknown }).BroadcastChannel = FakeBC
36
- })
37
- afterEach(() => {
38
- vi.useRealTimers()
39
- delete (globalThis as unknown as { BroadcastChannel?: unknown }).BroadcastChannel
40
- })
41
-
42
- function newAuth(store: BaseAuthStore) {
43
- const client: AuraClientLike = {
44
- baseUrl: 'http://x', projectId: 'p', apiKey: 'k',
45
- fetchFn: (async () => new Response('{}', { status: 200 })) as unknown as typeof globalThis.fetch,
46
- authStore: store,
47
- auth: null as unknown as AuraClientLike['auth'],
48
- }
49
- const svc = new AuthService(client, { autoRefresh: true, persistSession: true, forceEnabled: true })
50
- ;(client as { auth: unknown }).auth = svc
51
- return { svc, client }
52
- }
53
-
54
- describe('AuthService — cycle de vie session', () => {
55
- it('sign-in (save) démarre le ticker et broadcaste', () => {
56
- vi.useFakeTimers()
57
- const store = new BaseAuthStore()
58
- const { svc } = newAuth(store)
59
- store.save(validJwt(), 'rt', fakeUser())
60
- expect((svc as unknown as { _sessionManager: { isActive: boolean } })._sessionManager.isActive).toBe(true)
61
- expect(FakeBC.instances[0].posted.length).toBe(1)
62
- })
63
-
64
- it('sign-out (clear) arrête le ticker', () => {
65
- const store = new BaseAuthStore()
66
- const { svc } = newAuth(store)
67
- store.save(validJwt(), 'rt', fakeUser())
68
- store.clear()
69
- expect((svc as unknown as { _sessionManager: { isActive: boolean } })._sessionManager.isActive).toBe(false)
70
- })
71
-
72
- it('réception d’un logout distant → SIGNED_OUT local + store vidé, sans rebroadcast', () => {
73
- const store = new BaseAuthStore()
74
- store.save(validJwt(), 'rt', fakeUser())
75
- const { svc } = newAuth(store)
76
- const events: string[] = []
77
- svc.onAuthStateChange(({ event }) => events.push(event))
78
- const bc = FakeBC.instances[0]
79
- const before = bc.posted.length
80
- bc.onmessage!({ data: null }) // null = signed out
81
- expect(store.token).toBeNull()
82
- expect(events).toContain('SIGNED_OUT')
83
- expect(bc.posted.length).toBe(before) // pas de rebroadcast
84
- })
85
-
86
- it('dispose() coupe le ticker, ferme le canal, vide les listeners', async () => {
87
- const store = new BaseAuthStore()
88
- const { svc } = newAuth(store)
89
- store.save(validJwt(), 'rt', fakeUser())
90
- const cb = vi.fn()
91
- svc.onAuthStateChange(cb)
92
- svc.dispose()
93
- expect((svc as unknown as { _sessionManager: { isActive: boolean } })._sessionManager.isActive).toBe(false)
94
- expect(FakeBC.instances[0].closed).toBe(true)
95
- await Promise.resolve() // flush le microtask INITIAL_SESSION
96
- expect(cb).not.toHaveBeenCalled() // listeners vidés → aucun event
97
- })
98
-
99
- // --- Correctifs post-audit ---
100
-
101
- it('F2 : onAuthStateChange APRÈS dispose() n’émet rien', async () => {
102
- const store = new BaseAuthStore()
103
- const { svc } = newAuth(store)
104
- svc.dispose()
105
- const cb = vi.fn()
106
- svc.onAuthStateChange(cb) // abonnement après dispose
107
- await Promise.resolve()
108
- expect(cb).not.toHaveBeenCalled()
109
- })
110
-
111
- it('F3 : un user placeholder (sans id) n’est PAS broadcasté', () => {
112
- const store = new BaseAuthStore()
113
- newAuth(store)
114
- const bc = FakeBC.instances[0]
115
- store.save(validJwt(), 'rt', {} as User) // placeholder incomplet (setSession)
116
- expect(bc.posted.length).toBe(0) // rien diffusé
117
- store.save(validJwt(), 'rt', fakeUser()) // état complet
118
- expect(bc.posted.length).toBe(1)
119
- })
120
-
121
- it('F4 : un message distant malformé est ignoré (store inchangé, aucun event)', () => {
122
- const store = new BaseAuthStore()
123
- store.save(validJwt(), 'rt', fakeUser())
124
- const { svc } = newAuth(store)
125
- const events: string[] = []
126
- svc.onAuthStateChange(({ event }) => events.push(event))
127
- const before = store.token
128
- FakeBC.instances[0].onmessage!({ data: { foo: 1 } }) // malformé
129
- FakeBC.instances[0].onmessage!({ data: { token: 123, refreshToken: 'x', user: {} } }) // token non-string
130
- expect(store.token).toBe(before) // inchangé
131
- expect(events.filter((e) => e !== 'INITIAL_SESSION')).toEqual([]) // aucun event applicatif
132
- })
133
-
134
- it('F6 : inférence d’événement distant (SIGNED_IN / TOKEN_REFRESHED / USER_UPDATED)', () => {
135
- // Tokens explicitement distincts : _applyRemoteState compare des strings (pas de décodage JWT).
136
- const store = new BaseAuthStore()
137
- const { svc } = newAuth(store)
138
- const events: string[] = []
139
- svc.onAuthStateChange(({ event }) => { if (event !== 'INITIAL_SESSION') events.push(event) })
140
- const bc = FakeBC.instances[0]
141
- // 1) pas de session → login distant
142
- bc.onmessage!({ data: { token: 'tokA', refreshToken: 'rt', user: fakeUser() } })
143
- // 2) même token, user modifié → USER_UPDATED
144
- bc.onmessage!({ data: { token: 'tokA', refreshToken: 'rt', user: { ...fakeUser(), email: 'new@e.com' } } })
145
- // 3) token différent → TOKEN_REFRESHED
146
- bc.onmessage!({ data: { token: 'tokB', refreshToken: 'rt2', user: fakeUser() } })
147
- expect(events).toEqual(['SIGNED_IN', 'USER_UPDATED', 'TOKEN_REFRESHED'])
148
- })
149
- })
@@ -1,361 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
2
- import { AuthService } from '../src/AuthService'
3
- import { BaseAuthStore, LocalAuthStore } from '@aurabase/core'
4
- import type { AuraClientLike, User } from '@aurabase/core'
5
-
6
- // --- helpers -----------------------------------------------------------------
7
-
8
- function fakeUser(id = 'u1'): User {
9
- return {
10
- id,
11
- email: 't@e.com',
12
- role: 'authenticated',
13
- email_verified: true,
14
- is_banned: false,
15
- is_anonymous: false,
16
- mfa_enabled: false,
17
- user_metadata: {},
18
- app_metadata: {},
19
- created_at: '2025-01-01T00:00:00Z',
20
- }
21
- }
22
-
23
- class FakeBC {
24
- static instances: FakeBC[] = []
25
- onmessage: ((e: { data: unknown }) => void) | null = null
26
- posted: unknown[] = []
27
- closed = false
28
- constructor(public name: string) {
29
- FakeBC.instances.push(this)
30
- }
31
- postMessage(d: unknown) {
32
- this.posted.push(d)
33
- }
34
- close() {
35
- this.closed = true
36
- }
37
- }
38
-
39
- function b64url(obj: unknown): string {
40
- return btoa(JSON.stringify(obj)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
41
- }
42
- /** JWT non expiré (signature factice — non vérifiée localement en HS256). */
43
- function jwt(sub = 'u1', ttlSec = 3600): string {
44
- const exp = Math.floor(Date.now() / 1000) + ttlSec
45
- return `${b64url({ alg: 'HS256', typ: 'JWT' })}.${b64url({ sub, exp })}.sig`
46
- }
47
-
48
- const VERIFIER_KEY = 'aura-proj-1-pkce-code-verifier'
49
-
50
- beforeEach(() => {
51
- FakeBC.instances = []
52
- ;(globalThis as unknown as { BroadcastChannel: unknown }).BroadcastChannel = FakeBC
53
- })
54
- afterEach(() => {
55
- vi.useRealTimers()
56
- vi.restoreAllMocks()
57
- delete (globalThis as unknown as { BroadcastChannel?: unknown }).BroadcastChannel
58
- delete (globalThis as unknown as { window?: unknown }).window
59
- delete (globalThis as unknown as { localStorage?: unknown }).localStorage
60
- })
61
-
62
- function makeAuth(
63
- fetchFn: typeof globalThis.fetch = (async () =>
64
- new Response('{}', { status: 200 })) as unknown as typeof globalThis.fetch,
65
- store: BaseAuthStore = new BaseAuthStore(),
66
- ) {
67
- // Construit HORS navigateur (pas de window) → le constructeur ne déclenche pas
68
- // _detectSessionInUrl ; on le pilote explicitement dans chaque test.
69
- const client: AuraClientLike = {
70
- baseUrl: 'http://detect.local',
71
- projectId: 'proj-1',
72
- apiKey: 'k',
73
- fetchFn,
74
- authStore: store,
75
- auth: null as unknown as AuraClientLike['auth'],
76
- }
77
- const svc = new AuthService(client, { autoRefresh: false, persistSession: false })
78
- ;(client as { auth: unknown }).auth = svc
79
- return { svc, client, store }
80
- }
81
-
82
- function setWindow(opts: { hash?: string; search?: string; pathname?: string }) {
83
- const replaceState = vi.fn()
84
- ;(globalThis as unknown as { window: unknown }).window = {
85
- location: {
86
- hash: opts.hash ?? '',
87
- search: opts.search ?? '',
88
- pathname: opts.pathname ?? '/app',
89
- },
90
- history: { replaceState },
91
- }
92
- return replaceState
93
- }
94
-
95
- // --- detectSessionInUrl -------------------------------------------------------
96
-
97
- const INITIATED_KEY = 'aura-proj-1-oauth-implicit-initiated'
98
-
99
- describe('AuthService._detectSessionInUrl — callback OAuth au boot', () => {
100
- it('fragment implicit (#access_token) AVEC marqueur d’initiation → setSession + URL nettoyée', async () => {
101
- const store = new BaseAuthStore()
102
- // SEC-F3 : le SDK a initié le flux (marqueur posé par signInWithOAuth).
103
- store.setItem(INITIATED_KEY, '1')
104
- const { svc } = makeAuth(undefined, store)
105
- const setSession = vi
106
- .spyOn(svc, 'setSession')
107
- .mockResolvedValue({ data: fakeUser(), error: null })
108
- const replaceState = setWindow({
109
- hash: '#access_token=AT123&refresh_token=RT456&expires_in=3600&token_type=bearer',
110
- search: '',
111
- pathname: '/callback',
112
- })
113
-
114
- await svc._detectSessionInUrl()
115
-
116
- expect(setSession).toHaveBeenCalledWith('AT123', 'RT456')
117
- // Marqueur à usage unique : purgé après adoption.
118
- expect(store.getItem(INITIATED_KEY)).toBeNull()
119
- // URL nettoyée : replaceState appelé, plus aucun token dans l'URL cible.
120
- expect(replaceState).toHaveBeenCalledTimes(1)
121
- const cleaned = String(replaceState.mock.calls[0]![2])
122
- expect(cleaned).not.toContain('access_token')
123
- expect(cleaned).toBe('/callback')
124
- })
125
-
126
- it('query PKCE (?code) → exchangeCodeForSession(code) + code/state retirés de l’URL', async () => {
127
- const { svc } = makeAuth()
128
- const exchange = vi
129
- .spyOn(svc, 'exchangeCodeForSession')
130
- .mockResolvedValue({ data: null, error: null })
131
- const replaceState = setWindow({
132
- hash: '',
133
- search: '?code=AUTHCODE&state=xyz&foo=bar',
134
- pathname: '/auth/callback',
135
- })
136
-
137
- await svc._detectSessionInUrl()
138
-
139
- expect(exchange).toHaveBeenCalledWith('AUTHCODE')
140
- expect(replaceState).toHaveBeenCalledTimes(1)
141
- const cleaned = String(replaceState.mock.calls[0]![2])
142
- expect(cleaned).not.toContain('code=')
143
- expect(cleaned).not.toContain('state=')
144
- // Les autres query params sont préservés.
145
- expect(cleaned).toContain('foo=bar')
146
- })
147
-
148
- it('URL sans token ni code → no-op (aucun setSession/exchange, aucun nettoyage)', async () => {
149
- const { svc } = makeAuth()
150
- const setSession = vi.spyOn(svc, 'setSession')
151
- const exchange = vi.spyOn(svc, 'exchangeCodeForSession')
152
- const replaceState = setWindow({ hash: '', search: '?foo=bar' })
153
-
154
- await svc._detectSessionInUrl()
155
-
156
- expect(setSession).not.toHaveBeenCalled()
157
- expect(exchange).not.toHaveBeenCalled()
158
- expect(replaceState).not.toHaveBeenCalled()
159
- })
160
-
161
- it('SEC-F3 : fragment implicit SANS marqueur d’initiation (injecté par un attaquant) → NON adopté (aucun setSession)', async () => {
162
- const store = new BaseAuthStore() // pas de marqueur : flux NON initié par ce SDK
163
- const { svc } = makeAuth(undefined, store)
164
- const setSession = vi.spyOn(svc, 'setSession')
165
- const replaceState = setWindow({
166
- hash: '#access_token=ATTACKER&refresh_token=RTATT&token_type=bearer',
167
- pathname: '/callback',
168
- })
169
-
170
- await svc._detectSessionInUrl()
171
-
172
- // Session fixation évitée : le fragment forgé n'est jamais consommé.
173
- expect(setSession).not.toHaveBeenCalled()
174
- expect(replaceState).not.toHaveBeenCalled()
175
- expect(store.token).toBeNull()
176
- })
177
-
178
- it('SEC-F3 : marqueur à usage unique — un 2e fragment (rejeu) après adoption n’est plus adopté', async () => {
179
- const store = new BaseAuthStore()
180
- store.setItem(INITIATED_KEY, '1')
181
- const { svc } = makeAuth(undefined, store)
182
- const setSession = vi
183
- .spyOn(svc, 'setSession')
184
- .mockResolvedValue({ data: fakeUser(), error: null })
185
- setWindow({
186
- hash: '#access_token=AT1&refresh_token=RT1&token_type=bearer',
187
- pathname: '/cb',
188
- })
189
-
190
- await svc._detectSessionInUrl() // 1er passage : marqueur présent → adopté + purgé
191
- expect(setSession).toHaveBeenCalledTimes(1)
192
-
193
- await svc._detectSessionInUrl() // 2e passage : marqueur purgé → plus adopté
194
- expect(setSession).toHaveBeenCalledTimes(1)
195
- })
196
-
197
- it('SEC-F3 : signInWithOAuth (flux implicit) POSE le marqueur d’initiation avant le redirect', async () => {
198
- const store = new LocalAuthStore('aurabase_auth')
199
- // localStorage minimal (persistant → survit au redirect simulé).
200
- const mem = new Map<string, string>()
201
- ;(globalThis as unknown as { localStorage: unknown }).localStorage = {
202
- get length() {
203
- return mem.size
204
- },
205
- key: (i: number) => Array.from(mem.keys())[i] ?? null,
206
- getItem: (k: string) => (mem.has(k) ? mem.get(k)! : null),
207
- setItem: (k: string, v: string) => void mem.set(k, v),
208
- removeItem: (k: string) => void mem.delete(k),
209
- clear: () => mem.clear(),
210
- }
211
- ;(globalThis as unknown as { window: unknown }).window = { location: { href: '' } }
212
- const { svc } = makeAuth(undefined, store)
213
-
214
- await svc.signInWithOAuth('google', { redirectTo: 'http://app/cb' })
215
-
216
- // Marqueur posé (preuve d'initiation) — le fragment retour sera adoptable.
217
- expect(store.getItem(INITIATED_KEY)).toBe('1')
218
- })
219
-
220
- it('SEC-F3 : flux PKCE (?code) reste adopté SANS marqueur implicit (lié au code_verifier)', async () => {
221
- const store = new BaseAuthStore() // aucun marqueur implicit
222
- const { svc } = makeAuth(undefined, store)
223
- const exchange = vi
224
- .spyOn(svc, 'exchangeCodeForSession')
225
- .mockResolvedValue({ data: null, error: null })
226
- setWindow({ hash: '', search: '?code=PKCECODE', pathname: '/cb' })
227
-
228
- await svc._detectSessionInUrl()
229
-
230
- // PKCE est déjà lié cryptographiquement au verifier → inchangé par SEC-F3.
231
- expect(exchange).toHaveBeenCalledWith('PKCECODE')
232
- })
233
-
234
- it('hors navigateur (SSR/Node, pas de window) → no-op, ne throw pas', async () => {
235
- const { svc } = makeAuth()
236
- const setSession = vi.spyOn(svc, 'setSession')
237
- const exchange = vi.spyOn(svc, 'exchangeCodeForSession')
238
- // pas de window
239
- await expect(svc._detectSessionInUrl()).resolves.toBeUndefined()
240
- expect(setSession).not.toHaveBeenCalled()
241
- expect(exchange).not.toHaveBeenCalled()
242
- })
243
-
244
- it('déclenché au boot en navigateur quand détecté (constructeur)', async () => {
245
- // window AVANT construction → le constructeur appelle _detectSessionInUrl.
246
- const at = jwt('u1')
247
- setWindow({
248
- hash: `#access_token=${at}&refresh_token=RT&token_type=bearer`,
249
- pathname: '/cb',
250
- })
251
- const store = new BaseAuthStore()
252
- // SEC-F3 : le flux a été initié par ce SDK (marqueur présent avant le retour OAuth).
253
- store.setItem('aura-proj-1-oauth-implicit-initiated', '1')
254
- let userCalls = 0
255
- const fetchFn = (async (url: string) => {
256
- if (String(url).includes('/user')) {
257
- userCalls++
258
- return new Response(JSON.stringify({ data: fakeUser() }), {
259
- status: 200,
260
- headers: { 'Content-Type': 'application/json' },
261
- })
262
- }
263
- return new Response('{}', { status: 200 })
264
- }) as unknown as typeof globalThis.fetch
265
- const client: AuraClientLike = {
266
- baseUrl: 'http://detect.local',
267
- projectId: 'proj-1',
268
- apiKey: 'k',
269
- fetchFn,
270
- authStore: store,
271
- auth: null as unknown as AuraClientLike['auth'],
272
- }
273
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
274
- const svc = new AuthService(client, { autoRefresh: false, persistSession: true })
275
- ;(client as { auth: unknown }).auth = svc
276
- // Laisse le microtask/await du detect se dérouler.
277
- await new Promise((r) => setTimeout(r, 0))
278
- expect(userCalls).toBeGreaterThanOrEqual(1)
279
- expect(store.token).toBe(at)
280
- })
281
- })
282
-
283
- // --- Purge PKCE ---------------------------------------------------------------
284
-
285
- describe('Purge du code_verifier PKCE', () => {
286
- it('BaseAuthStore.clear() vide aussi le stockage clé/valeur (_kv)', () => {
287
- const store = new BaseAuthStore()
288
- store.setItem(VERIFIER_KEY, 'verifier-value')
289
- store.setItem('other', 'x')
290
- expect(store.getItem(VERIFIER_KEY)).toBe('verifier-value')
291
-
292
- store.clear()
293
-
294
- expect(store.getItem(VERIFIER_KEY)).toBeNull()
295
- expect(store.getItem('other')).toBeNull()
296
- })
297
-
298
- it('signOut purge le code_verifier (via clear)', async () => {
299
- const store = new BaseAuthStore()
300
- const { svc } = makeAuth(undefined, store)
301
- store.setItem(VERIFIER_KEY, 'verifier-value')
302
-
303
- await svc.signOut()
304
-
305
- expect(store.getItem(VERIFIER_KEY)).toBeNull()
306
- })
307
-
308
- it('exchangeCodeForSession en ÉCHEC purge quand même le verifier (usage unique)', async () => {
309
- const store = new BaseAuthStore()
310
- store.setItem(VERIFIER_KEY, 'verifier-value')
311
- const fetchFn = (async (url: string) => {
312
- if (String(url).includes('/oauth/pkce')) {
313
- return new Response(JSON.stringify({ error: { code: 'invalid_grant', message: 'bad code' } }), {
314
- status: 400,
315
- headers: { 'Content-Type': 'application/json' },
316
- })
317
- }
318
- return new Response('{}', { status: 200 })
319
- }) as unknown as typeof globalThis.fetch
320
- const { svc } = makeAuth(fetchFn, store)
321
-
322
- const { error } = await svc.exchangeCodeForSession('auth-code')
323
-
324
- expect(error).toBeTruthy()
325
- // Purge inconditionnelle même à l'échec : plus de réutilisation possible.
326
- expect(store.getItem(VERIFIER_KEY)).toBeNull()
327
- })
328
-
329
- it('LocalAuthStore.clear() supprime les clés PKCE de localStorage (multi-projets)', () => {
330
- // localStorage minimal en mémoire.
331
- const mem = new Map<string, string>()
332
- ;(globalThis as unknown as { localStorage: unknown }).localStorage = {
333
- get length() {
334
- return mem.size
335
- },
336
- key: (i: number) => Array.from(mem.keys())[i] ?? null,
337
- getItem: (k: string) => (mem.has(k) ? mem.get(k)! : null),
338
- setItem: (k: string, v: string) => {
339
- mem.set(k, v)
340
- },
341
- removeItem: (k: string) => {
342
- mem.delete(k)
343
- },
344
- clear: () => mem.clear(),
345
- }
346
-
347
- const store = new LocalAuthStore('aurabase_auth')
348
- store.setItem('aura-proj-1-pkce-code-verifier', 'v1')
349
- store.setItem('aura-proj-2-pkce-code-verifier', 'v2')
350
- store.setItem('unrelated-key', 'keep-me')
351
- expect(mem.get('aura-proj-1-pkce-code-verifier')).toBe('v1')
352
-
353
- store.clear()
354
-
355
- expect(store.getItem('aura-proj-1-pkce-code-verifier')).toBeNull()
356
- expect(mem.get('aura-proj-1-pkce-code-verifier')).toBeUndefined()
357
- expect(mem.get('aura-proj-2-pkce-code-verifier')).toBeUndefined()
358
- // Une clé non-PKCE n'est pas balayée par la purge.
359
- expect(mem.get('unrelated-key')).toBe('keep-me')
360
- })
361
- })