@aurabase/aurabase-js 0.3.0 → 0.4.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 (343) hide show
  1. package/README.md +26 -795
  2. package/{packages/aurabase/dist/AuraClient-DAtDbfPB.d.ts → dist/AuraClient-BcFE8u1v.d.cts} +1 -1
  3. package/{packages/aurabase/dist/AuraClient-DAtDbfPB.d.cts → dist/AuraClient-BcFE8u1v.d.ts} +1 -1
  4. package/{packages/aurabase/dist → dist}/index.d.cts +1 -1
  5. package/{packages/aurabase/dist → dist}/index.d.ts +1 -1
  6. package/{packages/aurabase/dist → dist}/ssr.d.cts +1 -1
  7. package/{packages/aurabase/dist → dist}/ssr.d.ts +1 -1
  8. package/package.json +72 -82
  9. package/.changeset/config.json +0 -11
  10. package/CHANGELOG.md +0 -30
  11. package/packages/ai/LICENSE +0 -21
  12. package/packages/ai/README.md +0 -106
  13. package/packages/ai/dist/index.cjs +0 -229
  14. package/packages/ai/dist/index.d.cts +0 -139
  15. package/packages/ai/dist/index.d.ts +0 -139
  16. package/packages/ai/dist/index.js +0 -226
  17. package/packages/ai/node_modules/.bin/esbuild +0 -19
  18. package/packages/ai/node_modules/.bin/tsc +0 -22
  19. package/packages/ai/node_modules/.bin/tsserver +0 -22
  20. package/packages/ai/node_modules/.bin/tsup +0 -22
  21. package/packages/ai/node_modules/.bin/tsup-node +0 -22
  22. package/packages/ai/node_modules/.bin/vite +0 -22
  23. package/packages/ai/node_modules/.bin/vitest +0 -22
  24. package/packages/ai/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  25. package/packages/ai/package.json +0 -61
  26. package/packages/ai/src/AiService.ts +0 -226
  27. package/packages/ai/src/index.ts +0 -18
  28. package/packages/ai/src/sse.ts +0 -141
  29. package/packages/ai/src/types.ts +0 -30
  30. package/packages/ai/tests/chat-stream.test.ts +0 -151
  31. package/packages/ai/tests/rag-namespaces.test.ts +0 -54
  32. package/packages/ai/tests/sse.test.ts +0 -69
  33. package/packages/ai/tsconfig.json +0 -5
  34. package/packages/ai/tsup.config.ts +0 -11
  35. package/packages/aurabase/LICENSE +0 -21
  36. package/packages/aurabase/README.md +0 -64
  37. package/packages/aurabase/node_modules/.bin/esbuild +0 -19
  38. package/packages/aurabase/node_modules/.bin/tsc +0 -22
  39. package/packages/aurabase/node_modules/.bin/tsserver +0 -22
  40. package/packages/aurabase/node_modules/.bin/tsup +0 -22
  41. package/packages/aurabase/node_modules/.bin/tsup-node +0 -22
  42. package/packages/aurabase/node_modules/.bin/vite +0 -22
  43. package/packages/aurabase/node_modules/.bin/vitest +0 -22
  44. package/packages/aurabase/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  45. package/packages/aurabase/package.json +0 -80
  46. package/packages/aurabase/src/AuraClient.ts +0 -237
  47. package/packages/aurabase/src/index.ts +0 -152
  48. package/packages/aurabase/src/ssr.ts +0 -156
  49. package/packages/aurabase/tests/ai-streaming-rag-e2e.test.ts +0 -82
  50. package/packages/aurabase/tests/ai.test.ts +0 -111
  51. package/packages/aurabase/tests/auth-admin.test.ts +0 -515
  52. package/packages/aurabase/tests/auth-e2e.test.ts +0 -135
  53. package/packages/aurabase/tests/auth-hardening.test.ts +0 -206
  54. package/packages/aurabase/tests/auth.test.ts +0 -947
  55. package/packages/aurabase/tests/database.test.ts +0 -230
  56. package/packages/aurabase/tests/db-types-e2e.test.ts +0 -217
  57. package/packages/aurabase/tests/dispose.test.ts +0 -23
  58. package/packages/aurabase/tests/foreign-token.e2e.test.ts +0 -129
  59. package/packages/aurabase/tests/functions.test.ts +0 -107
  60. package/packages/aurabase/tests/integration.test.ts +0 -413
  61. package/packages/aurabase/tests/live-production-validation.js +0 -241
  62. package/packages/aurabase/tests/live-sdk-production-validation.js +0 -293
  63. package/packages/aurabase/tests/mocks.ts +0 -139
  64. package/packages/aurabase/tests/notifications.test.ts +0 -314
  65. package/packages/aurabase/tests/observability-backup.test.ts +0 -186
  66. package/packages/aurabase/tests/observability-hook.test.ts +0 -130
  67. package/packages/aurabase/tests/production-robustness.test.ts +0 -268
  68. package/packages/aurabase/tests/public-api-surface.test.ts +0 -53
  69. package/packages/aurabase/tests/query-builder.test.ts +0 -329
  70. package/packages/aurabase/tests/readme-smoke-e2e.test.ts +0 -231
  71. package/packages/aurabase/tests/realtime-filter-e2e.test.ts +0 -344
  72. package/packages/aurabase/tests/refresh-locks.test.ts +0 -210
  73. package/packages/aurabase/tests/retry-option.test.ts +0 -17
  74. package/packages/aurabase/tests/rpc-e2e.test.ts +0 -254
  75. package/packages/aurabase/tests/rs256-local-e2e.test.ts +0 -114
  76. package/packages/aurabase/tests/rt-alias-public-e2e.test.ts +0 -235
  77. package/packages/aurabase/tests/rt-http-broadcast-e2e.test.ts +0 -124
  78. package/packages/aurabase/tests/service-role-guard.test.ts +0 -99
  79. package/packages/aurabase/tests/ssr.test.ts +0 -91
  80. package/packages/aurabase/tests/storage-backend-e2e.test.ts +0 -481
  81. package/packages/aurabase/tests/storage-sdk-parity-e2e.test.ts +0 -104
  82. package/packages/aurabase/tests/storage-transform-e2e.test.ts +0 -684
  83. package/packages/aurabase/tests/storage.test.ts +0 -55
  84. package/packages/aurabase/tests/types/client-generic.test-d.ts +0 -79
  85. package/packages/aurabase/tests/types/docs-snippets.test-d.ts +0 -571
  86. package/packages/aurabase/tests/types/error-code.test-d.ts +0 -53
  87. package/packages/aurabase/tsconfig.json +0 -5
  88. package/packages/aurabase/tsconfig.test-d.json +0 -5
  89. package/packages/aurabase/tsup.config.ts +0 -11
  90. package/packages/aurabase/vitest.config.ts +0 -16
  91. package/packages/aurabase/vitest.e2e.config.ts +0 -9
  92. package/packages/auth/LICENSE +0 -21
  93. package/packages/auth/README.md +0 -215
  94. package/packages/auth/dist/index.cjs +0 -1175
  95. package/packages/auth/dist/index.d.cts +0 -397
  96. package/packages/auth/dist/index.d.ts +0 -397
  97. package/packages/auth/dist/index.js +0 -1170
  98. package/packages/auth/node_modules/.bin/esbuild +0 -19
  99. package/packages/auth/node_modules/.bin/tsc +0 -22
  100. package/packages/auth/node_modules/.bin/tsserver +0 -22
  101. package/packages/auth/node_modules/.bin/tsup +0 -22
  102. package/packages/auth/node_modules/.bin/tsup-node +0 -22
  103. package/packages/auth/node_modules/.bin/vite +0 -22
  104. package/packages/auth/node_modules/.bin/vitest +0 -22
  105. package/packages/auth/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  106. package/packages/auth/package.json +0 -61
  107. package/packages/auth/src/AuthAdminService.ts +0 -149
  108. package/packages/auth/src/AuthService.ts +0 -1166
  109. package/packages/auth/src/SessionManager.ts +0 -92
  110. package/packages/auth/src/index.ts +0 -17
  111. package/packages/auth/src/jwks.ts +0 -337
  112. package/packages/auth/src/pkce.ts +0 -27
  113. package/packages/auth/src/types.ts +0 -89
  114. package/packages/auth/tests/auth-lifecycle.test.ts +0 -149
  115. package/packages/auth/tests/detect-session.test.ts +0 -361
  116. package/packages/auth/tests/getclaims.test.ts +0 -780
  117. package/packages/auth/tests/is-mfa-challenge.test.ts +0 -27
  118. package/packages/auth/tests/password-recovery.test.ts +0 -124
  119. package/packages/auth/tests/pkce.test.ts +0 -192
  120. package/packages/auth/tests/session-manager.test.ts +0 -103
  121. package/packages/auth/tests/set-session.test.ts +0 -139
  122. package/packages/auth/tests/verify-otp.test.ts +0 -153
  123. package/packages/auth/tsconfig.json +0 -5
  124. package/packages/auth/tsup.config.ts +0 -11
  125. package/packages/core/LICENSE +0 -21
  126. package/packages/core/README.md +0 -132
  127. package/packages/core/dist/index.cjs +0 -695
  128. package/packages/core/dist/index.d.cts +0 -1137
  129. package/packages/core/dist/index.d.ts +0 -1137
  130. package/packages/core/dist/index.js +0 -673
  131. package/packages/core/node_modules/.bin/esbuild +0 -22
  132. package/packages/core/node_modules/.bin/tsc +0 -22
  133. package/packages/core/node_modules/.bin/tsserver +0 -22
  134. package/packages/core/node_modules/.bin/tsup +0 -22
  135. package/packages/core/node_modules/.bin/tsup-node +0 -22
  136. package/packages/core/node_modules/.bin/vite +0 -22
  137. package/packages/core/node_modules/.bin/vitest +0 -22
  138. package/packages/core/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  139. package/packages/core/package.json +0 -57
  140. package/packages/core/src/AuraError.ts +0 -89
  141. package/packages/core/src/BaseService.ts +0 -44
  142. package/packages/core/src/client.ts +0 -34
  143. package/packages/core/src/cookie-utils.ts +0 -42
  144. package/packages/core/src/fetch.ts +0 -435
  145. package/packages/core/src/index.ts +0 -22
  146. package/packages/core/src/retry.ts +0 -63
  147. package/packages/core/src/serialize.ts +0 -6
  148. package/packages/core/src/stores/BaseAuthStore.ts +0 -164
  149. package/packages/core/src/stores/LocalAuthStore.ts +0 -199
  150. package/packages/core/src/types.ts +0 -1042
  151. package/packages/core/tests/auth-store.test.ts +0 -300
  152. package/packages/core/tests/error-code.test.ts +0 -61
  153. package/packages/core/tests/error.test.ts +0 -24
  154. package/packages/core/tests/fetch.test.ts +0 -286
  155. package/packages/core/tests/mocks.ts +0 -139
  156. package/packages/core/tests/observability.test.ts +0 -86
  157. package/packages/core/tests/refresh-hardening.test.ts +0 -164
  158. package/packages/core/tests/refresh-observability.test.ts +0 -111
  159. package/packages/core/tests/retry.test.ts +0 -106
  160. package/packages/core/tests/serialize.test.ts +0 -12
  161. package/packages/core/tests/timeout.test.ts +0 -79
  162. package/packages/core/tsconfig.json +0 -5
  163. package/packages/core/tsup.config.ts +0 -11
  164. package/packages/db/LICENSE +0 -21
  165. package/packages/db/README.md +0 -152
  166. package/packages/db/VENDORED.md +0 -93
  167. package/packages/db/dist/index.cjs +0 -544
  168. package/packages/db/dist/index.d.cts +0 -1111
  169. package/packages/db/dist/index.d.ts +0 -1111
  170. package/packages/db/dist/index.js +0 -541
  171. package/packages/db/node_modules/.bin/esbuild +0 -19
  172. package/packages/db/node_modules/.bin/tsc +0 -22
  173. package/packages/db/node_modules/.bin/tsserver +0 -22
  174. package/packages/db/node_modules/.bin/tsup +0 -22
  175. package/packages/db/node_modules/.bin/tsup-node +0 -22
  176. package/packages/db/node_modules/.bin/vite +0 -22
  177. package/packages/db/node_modules/.bin/vitest +0 -22
  178. package/packages/db/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  179. package/packages/db/package.json +0 -62
  180. package/packages/db/src/DatabaseService.ts +0 -170
  181. package/packages/db/src/QueryBuilder.ts +0 -830
  182. package/packages/db/src/index.ts +0 -2
  183. package/packages/db/src/pgrst-types/common/common.ts +0 -86
  184. package/packages/db/src/pgrst-types/common/rpc.ts +0 -151
  185. package/packages/db/src/pgrst-types/feature-flags.ts +0 -20
  186. package/packages/db/src/pgrst-types/types.ts +0 -134
  187. package/packages/db/src/select-query-parser/parser.ts +0 -479
  188. package/packages/db/src/select-query-parser/result.ts +0 -553
  189. package/packages/db/src/select-query-parser/types.ts +0 -132
  190. package/packages/db/src/select-query-parser/utils.ts +0 -707
  191. package/packages/db/tests/filters.test.ts +0 -81
  192. package/packages/db/tests/mutations-filtered.e2e.test.ts +0 -132
  193. package/packages/db/tests/mutations-filtered.test.ts +0 -188
  194. package/packages/db/tests/order.test.ts +0 -45
  195. package/packages/db/tests/rpc.test.ts +0 -41
  196. package/packages/db/tests/scale/build-large-schema.ts +0 -94
  197. package/packages/db/tests/scale/scale-compile.test.ts +0 -167
  198. package/packages/db/tests/schema.test.ts +0 -77
  199. package/packages/db/tests/single-accept.e2e.test.ts +0 -123
  200. package/packages/db/tests/single.test.ts +0 -211
  201. package/packages/db/tests/types/filters.test-d.ts +0 -52
  202. package/packages/db/tests/types/fixtures.ts +0 -40
  203. package/packages/db/tests/types/from-views.test-d.ts +0 -18
  204. package/packages/db/tests/types/mutations.test-d.ts +0 -23
  205. package/packages/db/tests/types/rpc.test-d.ts +0 -60
  206. package/packages/db/tests/types/schema-shape.test-d.ts +0 -8
  207. package/packages/db/tests/types/select-inference.test-d.ts +0 -38
  208. package/packages/db/tests/vendored/fixtures.ts +0 -83
  209. package/packages/db/tests/vendored/get-result.test-d.ts +0 -75
  210. package/packages/db/tsconfig.json +0 -5
  211. package/packages/db/tsconfig.test-d.json +0 -5
  212. package/packages/db/tsup.config.ts +0 -11
  213. package/packages/db/vitest.config.ts +0 -8
  214. package/packages/functions/LICENSE +0 -21
  215. package/packages/functions/README.md +0 -96
  216. package/packages/functions/dist/index.cjs +0 -173
  217. package/packages/functions/dist/index.d.cts +0 -81
  218. package/packages/functions/dist/index.d.ts +0 -81
  219. package/packages/functions/dist/index.js +0 -168
  220. package/packages/functions/node_modules/.bin/esbuild +0 -19
  221. package/packages/functions/node_modules/.bin/tsc +0 -22
  222. package/packages/functions/node_modules/.bin/tsserver +0 -22
  223. package/packages/functions/node_modules/.bin/tsup +0 -22
  224. package/packages/functions/node_modules/.bin/tsup-node +0 -22
  225. package/packages/functions/node_modules/.bin/vite +0 -22
  226. package/packages/functions/node_modules/.bin/vitest +0 -22
  227. package/packages/functions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  228. package/packages/functions/package.json +0 -60
  229. package/packages/functions/src/FunctionsService.ts +0 -188
  230. package/packages/functions/src/errors.ts +0 -70
  231. package/packages/functions/src/index.ts +0 -6
  232. package/packages/functions/tests/invoke.test.ts +0 -97
  233. package/packages/functions/tests/response-type-errors.test.ts +0 -135
  234. package/packages/functions/tsconfig.json +0 -5
  235. package/packages/functions/tsup.config.ts +0 -11
  236. package/packages/gen/LICENSE +0 -21
  237. package/packages/gen/README.md +0 -84
  238. package/packages/gen/dist/cli.cjs +0 -334
  239. package/packages/gen/dist/cli.d.cts +0 -1
  240. package/packages/gen/dist/cli.d.ts +0 -1
  241. package/packages/gen/dist/cli.js +0 -332
  242. package/packages/gen/dist/index.cjs +0 -257
  243. package/packages/gen/dist/index.d.cts +0 -12
  244. package/packages/gen/dist/index.d.ts +0 -12
  245. package/packages/gen/dist/index.js +0 -255
  246. package/packages/gen/node_modules/.bin/esbuild +0 -19
  247. package/packages/gen/node_modules/.bin/tsc +0 -22
  248. package/packages/gen/node_modules/.bin/tsserver +0 -22
  249. package/packages/gen/node_modules/.bin/tsup +0 -22
  250. package/packages/gen/node_modules/.bin/tsup-node +0 -22
  251. package/packages/gen/node_modules/.bin/vite +0 -22
  252. package/packages/gen/node_modules/.bin/vitest +0 -22
  253. package/packages/gen/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  254. package/packages/gen/package.json +0 -66
  255. package/packages/gen/src/cli.ts +0 -67
  256. package/packages/gen/src/generate.ts +0 -0
  257. package/packages/gen/src/index.ts +0 -2
  258. package/packages/gen/tests/compile.test.ts +0 -213
  259. package/packages/gen/tests/e2e.test.ts +0 -130
  260. package/packages/gen/tests/generate.test.ts +0 -396
  261. package/packages/gen/tsconfig.json +0 -5
  262. package/packages/gen/tsup.config.ts +0 -11
  263. package/packages/notifications/LICENSE +0 -21
  264. package/packages/notifications/README.md +0 -134
  265. package/packages/notifications/dist/index.cjs +0 -128
  266. package/packages/notifications/dist/index.d.cts +0 -81
  267. package/packages/notifications/dist/index.d.ts +0 -81
  268. package/packages/notifications/dist/index.js +0 -125
  269. package/packages/notifications/node_modules/.bin/esbuild +0 -19
  270. package/packages/notifications/node_modules/.bin/tsc +0 -22
  271. package/packages/notifications/node_modules/.bin/tsserver +0 -22
  272. package/packages/notifications/node_modules/.bin/tsup +0 -22
  273. package/packages/notifications/node_modules/.bin/tsup-node +0 -22
  274. package/packages/notifications/node_modules/.bin/vite +0 -22
  275. package/packages/notifications/node_modules/.bin/vitest +0 -22
  276. package/packages/notifications/package.json +0 -60
  277. package/packages/notifications/src/NotificationsService.ts +0 -230
  278. package/packages/notifications/src/index.ts +0 -19
  279. package/packages/notifications/tsconfig.json +0 -5
  280. package/packages/notifications/tsup.config.ts +0 -11
  281. package/packages/realtime/LICENSE +0 -21
  282. package/packages/realtime/README.md +0 -183
  283. package/packages/realtime/dist/index.cjs +0 -977
  284. package/packages/realtime/dist/index.d.cts +0 -259
  285. package/packages/realtime/dist/index.d.ts +0 -259
  286. package/packages/realtime/dist/index.js +0 -973
  287. package/packages/realtime/node_modules/.bin/esbuild +0 -19
  288. package/packages/realtime/node_modules/.bin/tsc +0 -22
  289. package/packages/realtime/node_modules/.bin/tsserver +0 -22
  290. package/packages/realtime/node_modules/.bin/tsup +0 -22
  291. package/packages/realtime/node_modules/.bin/tsup-node +0 -22
  292. package/packages/realtime/node_modules/.bin/vite +0 -22
  293. package/packages/realtime/node_modules/.bin/vitest +0 -22
  294. package/packages/realtime/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  295. package/packages/realtime/package.json +0 -60
  296. package/packages/realtime/src/AuraChannel.ts +0 -485
  297. package/packages/realtime/src/HeartbeatManager.ts +0 -73
  298. package/packages/realtime/src/RealtimeService.ts +0 -505
  299. package/packages/realtime/src/columnFilter.ts +0 -301
  300. package/packages/realtime/src/index.ts +0 -4
  301. package/packages/realtime/tests/ack-routing.test.ts +0 -81
  302. package/packages/realtime/tests/column-filter.test.ts +0 -144
  303. package/packages/realtime/tests/dispatch.test.ts +0 -191
  304. package/packages/realtime/tests/heartbeat.test.ts +0 -67
  305. package/packages/realtime/tests/http-broadcast.test.ts +0 -68
  306. package/packages/realtime/tests/realtime-token.test.ts +0 -43
  307. package/packages/realtime/tests/reconnect-race.test.ts +0 -149
  308. package/packages/realtime/tests/ref-id.test.ts +0 -34
  309. package/packages/realtime/tests/set-auth.test.ts +0 -70
  310. package/packages/realtime/tsconfig.json +0 -5
  311. package/packages/realtime/tsup.config.ts +0 -11
  312. package/packages/storage/LICENSE +0 -21
  313. package/packages/storage/README.md +0 -141
  314. package/packages/storage/dist/index.cjs +0 -333
  315. package/packages/storage/dist/index.d.cts +0 -185
  316. package/packages/storage/dist/index.d.ts +0 -185
  317. package/packages/storage/dist/index.js +0 -329
  318. package/packages/storage/node_modules/.bin/esbuild +0 -19
  319. package/packages/storage/node_modules/.bin/tsc +0 -22
  320. package/packages/storage/node_modules/.bin/tsserver +0 -22
  321. package/packages/storage/node_modules/.bin/tsup +0 -22
  322. package/packages/storage/node_modules/.bin/tsup-node +0 -22
  323. package/packages/storage/node_modules/.bin/vite +0 -22
  324. package/packages/storage/node_modules/.bin/vitest +0 -22
  325. package/packages/storage/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
  326. package/packages/storage/package.json +0 -60
  327. package/packages/storage/src/DownloadBuilder.ts +0 -60
  328. package/packages/storage/src/StorageService.ts +0 -323
  329. package/packages/storage/src/index.ts +0 -2
  330. package/packages/storage/src/path.ts +0 -35
  331. package/packages/storage/src/transform.ts +0 -15
  332. package/packages/storage/tests/download.test.ts +0 -64
  333. package/packages/storage/tests/parity.test.ts +0 -154
  334. package/packages/storage/tests/path.test.ts +0 -87
  335. package/packages/storage/tests/transform.test.ts +0 -79
  336. package/packages/storage/tsconfig.json +0 -5
  337. package/packages/storage/tsup.config.ts +0 -11
  338. package/pnpm-workspace.yaml +0 -24
  339. package/tsconfig.base.json +0 -15
  340. /package/{packages/aurabase/dist → dist}/index.cjs +0 -0
  341. /package/{packages/aurabase/dist → dist}/index.js +0 -0
  342. /package/{packages/aurabase/dist → dist}/ssr.cjs +0 -0
  343. /package/{packages/aurabase/dist → dist}/ssr.js +0 -0
@@ -1,947 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // AuthService tests
3
- // ---------------------------------------------------------------------------
4
-
5
- import { describe, it, expect, beforeEach, afterEach } from 'vitest'
6
- import { AuraClient } from '../src/AuraClient'
7
- import { BaseAuthStore } from '@aurabase/core'
8
- import { FetchMock, expiredJwt, fakeTokenPair, fakeUser, validJwt } from './mocks'
9
-
10
- const BASE = 'http://localhost:8080'
11
- const PROJECT = 'test-project'
12
- const PREFIX = `${BASE}/v1/auth/${PROJECT}`
13
-
14
- let fetchMock: FetchMock
15
- let client: AuraClient
16
-
17
- beforeEach(() => {
18
- fetchMock = new FetchMock()
19
- fetchMock.init()
20
- client = new AuraClient(BASE, PROJECT, {
21
- auth: { persistSession: false },
22
- })
23
- })
24
-
25
- afterEach(() => {
26
- fetchMock.restore()
27
- fetchMock.clearMocks()
28
- })
29
-
30
- // ---------------------------------------------------------------------------
31
- describe('AuthService.signUp', () => {
32
- it('saves tokens on successful registration', async () => {
33
- const tp = fakeTokenPair()
34
- fetchMock.on({
35
- method: 'POST',
36
- url: `${PREFIX}/register`,
37
- replyCode: 200,
38
- replyBody: { data: tp },
39
- })
40
-
41
- const res = await client.auth.signUp({ email: 'a@b.com', password: 'secret' })
42
-
43
- expect(res.error).toBeNull()
44
- expect(res.data).toBeDefined()
45
- expect(client.authStore.token).toBe(tp.access_token)
46
- expect(client.authStore.refreshToken).toBe(tp.refresh_token)
47
- expect(client.authStore.user?.email).toBe('test@example.com')
48
- })
49
-
50
- it('returns error on 400', async () => {
51
- fetchMock.on({
52
- method: 'POST',
53
- url: `${PREFIX}/register`,
54
- replyCode: 400,
55
- replyBody: { error: { code: 'invalid_request', message: 'Email taken' } },
56
- })
57
-
58
- const res = await client.auth.signUp({ email: 'a@b.com', password: 'x' })
59
-
60
- expect(res.error).toBeDefined()
61
- expect(res.error!.code).toBe('invalid_request')
62
- expect(client.authStore.token).toBeNull()
63
- })
64
- })
65
-
66
- // ---------------------------------------------------------------------------
67
- describe('AuthService.signInWithPassword', () => {
68
- it('saves tokens on success', async () => {
69
- const tp = fakeTokenPair()
70
- fetchMock.on({
71
- method: 'POST',
72
- url: `${PREFIX}/login`,
73
- replyCode: 200,
74
- replyBody: { data: tp },
75
- })
76
-
77
- const res = await client.auth.signInWithPassword({ email: 'a@b.com', password: 'pass' })
78
-
79
- expect(res.error).toBeNull()
80
- expect(client.authStore.token).toBe(tp.access_token)
81
- expect(client.authStore.user?.id).toBe('user-1')
82
- })
83
-
84
- it('detects MFA challenge', async () => {
85
- const mfa = { mfa_required: true, mfa_token: 'mfa_tok_123' }
86
- fetchMock.on({
87
- method: 'POST',
88
- url: `${PREFIX}/login`,
89
- replyCode: 200,
90
- replyBody: { data: mfa },
91
- })
92
-
93
- const events: string[] = []
94
- client.auth.onAuthStateChange((payload) => {
95
- events.push(payload.event)
96
- })
97
-
98
- const res = await client.auth.signInWithPassword({ email: 'a@b.com', password: 'pass' })
99
-
100
- expect(res.data).toBeDefined()
101
- expect((res.data as any).mfa_required).toBe(true)
102
- // Token should NOT be saved for MFA challenge
103
- expect(client.authStore.token).toBeNull()
104
- expect(events).toContain('MFA_CHALLENGE')
105
- })
106
-
107
- it('MFA_CHALLENGE porte mfaToken + mfaSetupRequired', async () => {
108
- fetchMock.on({
109
- method: 'POST',
110
- url: `${PREFIX}/login`,
111
- replyCode: 200,
112
- replyBody: { data: { mfa_required: true, mfa_token: 'MT', mfa_setup_required: true } },
113
- })
114
-
115
- const payloads: any[] = []
116
- client.auth.onAuthStateChange((p) => payloads.push(p))
117
-
118
- await client.auth.signInWithPassword({ email: 'e', password: 'p' })
119
-
120
- const c = payloads.find((p) => p.event === 'MFA_CHALLENGE')
121
- expect(c).toBeDefined()
122
- expect(c.mfaToken).toBe('MT')
123
- expect(c.mfaSetupRequired).toBe(true)
124
- })
125
- })
126
-
127
- // ---------------------------------------------------------------------------
128
- describe('AuthService.signOut', () => {
129
- it('clears store on signOut', async () => {
130
- // Pre-populate the store
131
- const tp = fakeTokenPair()
132
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
133
-
134
- fetchMock.on({
135
- method: 'POST',
136
- url: `${PREFIX}/logout`,
137
- replyCode: 200,
138
- replyBody: { data: null },
139
- })
140
-
141
- const res = await client.auth.signOut()
142
-
143
- expect(res.error).toBeNull()
144
- // LOT 3 (I5) : `logout` backend (`services/aura-auth/src/handlers/auth.rs::logout`)
145
- // renvoie réellement `ApiResponse::<()>::empty()` — `fetch.ts` honore maintenant ce
146
- // `null` explicite (`'data' in body`) au lieu de retomber sur l'enveloppe entière.
147
- expect(res.data).toBeNull()
148
- expect(client.authStore.token).toBeNull()
149
- expect(client.authStore.refreshToken).toBeNull()
150
- expect(client.authStore.user).toBeNull()
151
- })
152
-
153
- it('does not refresh before logout', async () => {
154
- const tp = fakeTokenPair({ access_token: expiredJwt(), refresh_token: 'rt_old' })
155
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
156
-
157
- fetchMock.on({
158
- method: 'POST',
159
- url: `${PREFIX}/logout`,
160
- replyCode: 200,
161
- replyBody: { data: null },
162
- })
163
-
164
- const res = await client.auth.signOut()
165
-
166
- expect(res.error).toBeNull()
167
- expect(fetchMock.calls).toHaveLength(1)
168
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/logout`)
169
- expect((fetchMock.calls[0].body as any).refresh_token).toBe('rt_old')
170
- })
171
-
172
- it('clears local store without network when no session exists', async () => {
173
- const res = await client.auth.signOut()
174
-
175
- expect(res.error).toBeNull()
176
- expect(fetchMock.calls).toHaveLength(0)
177
- })
178
- })
179
-
180
- // ---------------------------------------------------------------------------
181
- describe('AuthService.refreshSession', () => {
182
- it('updates store with new tokens', async () => {
183
- const oldTp = fakeTokenPair()
184
- client.authStore.save(oldTp.access_token, oldTp.refresh_token, oldTp.user)
185
-
186
- const newTp = fakeTokenPair({
187
- access_token: validJwt(),
188
- refresh_token: 'rt_new',
189
- user: fakeUser({ email: 'new@example.com' }),
190
- })
191
- fetchMock.on({
192
- method: 'POST',
193
- url: `${PREFIX}/refresh`,
194
- replyCode: 200,
195
- replyBody: { data: newTp },
196
- })
197
-
198
- const events: string[] = []
199
- client.auth.onAuthStateChange((p) => events.push(p.event))
200
-
201
- const res = await client.auth.refreshSession()
202
-
203
- expect(res.error).toBeNull()
204
- expect(client.authStore.refreshToken).toBe('rt_new')
205
- expect(client.authStore.user?.email).toBe('new@example.com')
206
- expect(events).toContain('TOKEN_REFRESHED')
207
- })
208
-
209
- it('returns a local error when no refresh token exists', async () => {
210
- const res = await client.auth.refreshSession()
211
-
212
- expect(res.data).toBeNull()
213
- expect(res.error?.code).toBe('no_session')
214
- expect(fetchMock.calls).toHaveLength(0)
215
- })
216
- })
217
-
218
- // ---------------------------------------------------------------------------
219
- describe('AuthService.sessions', () => {
220
- it('sends X-Refresh-Token when listing sessions', async () => {
221
- const tp = fakeTokenPair({ refresh_token: 'rt_current' })
222
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
223
- fetchMock.on({
224
- method: 'GET',
225
- url: `${PREFIX}/sessions`,
226
- replyCode: 200,
227
- replyBody: { data: [] },
228
- })
229
-
230
- const res = await client.auth.listSessions()
231
-
232
- expect(res.error).toBeNull()
233
- expect(fetchMock.calls[0].headers.get('x-refresh-token')).toBe('rt_current')
234
- })
235
-
236
- it('clears store after global revoke succeeds', async () => {
237
- const tp = fakeTokenPair({ refresh_token: 'rt_global' })
238
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
239
- fetchMock.on({
240
- method: 'POST',
241
- url: `${PREFIX}/logout`,
242
- replyCode: 200,
243
- replyBody: { data: null },
244
- })
245
-
246
- const res = await client.auth.revokeAllSessions()
247
-
248
- expect(res.error).toBeNull()
249
- expect(client.authStore.token).toBeNull()
250
- expect((fetchMock.calls[0].body as any).scope).toBe('global')
251
- expect((fetchMock.calls[0].body as any).refresh_token).toBe('rt_global')
252
- })
253
- })
254
-
255
- // ---------------------------------------------------------------------------
256
- describe('AuthService.getUser', () => {
257
- it('returns user from /me endpoint', async () => {
258
- const tp = fakeTokenPair()
259
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
260
-
261
- const user = fakeUser({ email: 'me@example.com' })
262
- fetchMock.on({
263
- method: 'GET',
264
- url: `${PREFIX}/user`,
265
- replyCode: 200,
266
- replyBody: { data: user },
267
- })
268
-
269
- const res = await client.auth.getUser()
270
-
271
- expect(res.error).toBeNull()
272
- expect(res.data?.email).toBe('me@example.com')
273
- })
274
-
275
- it('returns 401 when not authenticated', async () => {
276
- fetchMock.on({
277
- method: 'GET',
278
- url: `${PREFIX}/user`,
279
- replyCode: 401,
280
- replyBody: { error: { code: 'unauthorized', message: 'Not authenticated' } },
281
- })
282
-
283
- const res = await client.auth.getUser()
284
-
285
- expect(res.error).toBeDefined()
286
- expect(res.error!.code).toBe('unauthorized')
287
- })
288
- })
289
-
290
- // ---------------------------------------------------------------------------
291
- describe('AuthService.onAuthStateChange', () => {
292
- it('fires callback on sign in and sign out', async () => {
293
- const tp = fakeTokenPair()
294
- fetchMock.on({
295
- method: 'POST',
296
- url: `${PREFIX}/login`,
297
- replyCode: 200,
298
- replyBody: { data: tp },
299
- })
300
- fetchMock.on({
301
- method: 'POST',
302
- url: `${PREFIX}/logout`,
303
- replyCode: 200,
304
- replyBody: { data: null },
305
- })
306
-
307
- const events: string[] = []
308
- const { unsubscribe } = client.auth.onAuthStateChange((p) => {
309
- events.push(p.event)
310
- })
311
-
312
- await client.auth.signInWithPassword({ email: 'a@b.com', password: 'pass' })
313
- await client.auth.signOut()
314
-
315
- expect(events).toContain('SIGNED_IN')
316
- expect(events).toContain('SIGNED_OUT')
317
-
318
- unsubscribe()
319
- })
320
-
321
- it('unsubscribe stops further events', async () => {
322
- const tp = fakeTokenPair()
323
- fetchMock.on({
324
- method: 'POST',
325
- url: `${PREFIX}/login`,
326
- replyCode: 200,
327
- replyBody: { data: tp },
328
- })
329
-
330
- const events: string[] = []
331
- const { unsubscribe } = client.auth.onAuthStateChange((p) => {
332
- events.push(p.event)
333
- })
334
-
335
- await client.auth.signInWithPassword({ email: 'a@b.com', password: 'pass' })
336
- expect(events.length).toBeGreaterThan(0)
337
-
338
- const countBefore = events.length
339
- unsubscribe()
340
-
341
- // Manually trigger another change -- should not fire
342
- client.authStore.clear()
343
- expect(events.length).toBe(countBefore)
344
- })
345
- })
346
-
347
- // ---------------------------------------------------------------------------
348
- describe('AuthService.signInAnonymously', () => {
349
- it('saves anonymous session', async () => {
350
- const tp = fakeTokenPair({
351
- user: fakeUser({ is_anonymous: true, email: null }),
352
- })
353
- fetchMock.on({
354
- method: 'POST',
355
- url: `${PREFIX}/anonymous`,
356
- replyCode: 200,
357
- replyBody: { data: tp },
358
- })
359
-
360
- const res = await client.auth.signInAnonymously()
361
-
362
- expect(res.error).toBeNull()
363
- expect(client.authStore.user?.is_anonymous).toBe(true)
364
- expect(client.authStore.token).toBe(tp.access_token)
365
- })
366
- })
367
-
368
- // ---------------------------------------------------------------------------
369
- describe('AuthService.signInWithMagicLink', () => {
370
- it('sends POST /magic-link with email', async () => {
371
- fetchMock.on({
372
- method: 'POST',
373
- url: `${PREFIX}/magic-link`,
374
- replyCode: 200,
375
- replyBody: { data: { message: 'Magic link sent' } },
376
- })
377
-
378
- const res = await client.auth.signInWithMagicLink({ email: 'a@b.com' })
379
-
380
- expect(res.error).toBeNull()
381
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/magic-link`)
382
- expect(fetchMock.calls[0].method).toBe('POST')
383
- expect((fetchMock.calls[0].body as any).email).toBe('a@b.com')
384
- })
385
-
386
- it('returns error on 400', async () => {
387
- fetchMock.on({
388
- method: 'POST',
389
- url: `${PREFIX}/magic-link`,
390
- replyCode: 400,
391
- replyBody: { error: { code: 'invalid_email', message: 'Invalid email' } },
392
- })
393
-
394
- const res = await client.auth.signInWithMagicLink({ email: 'bad' })
395
-
396
- expect(res.error).toBeDefined()
397
- expect(res.error!.code).toBe('invalid_email')
398
- })
399
- })
400
-
401
- // ---------------------------------------------------------------------------
402
- describe('AuthService.signInWithOAuth', () => {
403
- it('renvoie { url } et envoie redirect_uri (pas redirect_to)', async () => {
404
- const { data, error } = await client.auth.signInWithOAuth('github', {
405
- redirectTo: 'http://app/cb',
406
- })
407
- // No fetch call should be made — OAuth start is a redirect
408
- expect(fetchMock.calls.length).toBe(0)
409
- expect(error).toBeNull()
410
- expect(data?.url).toContain('/oauth/github/start')
411
- expect(data?.url).toContain('redirect_uri=')
412
- expect(data?.url).not.toContain('redirect_to=')
413
- })
414
- })
415
-
416
- // ---------------------------------------------------------------------------
417
- describe('AuthService.signInWithEmailOtp', () => {
418
- it('sends POST /email-otp/send with email', async () => {
419
- fetchMock.on({
420
- method: 'POST',
421
- url: `${PREFIX}/email-otp/send`,
422
- replyCode: 200,
423
- replyBody: { data: { message: 'OTP sent' } },
424
- })
425
-
426
- const res = await client.auth.signInWithEmailOtp('otp@example.com')
427
-
428
- expect(res.error).toBeNull()
429
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/email-otp/send`)
430
- expect((fetchMock.calls[0].body as any).email).toBe('otp@example.com')
431
- })
432
- })
433
-
434
- // ---------------------------------------------------------------------------
435
- describe('AuthService.verifyEmailOtp', () => {
436
- it('saves tokens on success', async () => {
437
- const tp = fakeTokenPair()
438
- fetchMock.on({
439
- method: 'POST',
440
- url: `${PREFIX}/email-otp/verify`,
441
- replyCode: 200,
442
- replyBody: { data: tp },
443
- })
444
-
445
- const res = await client.auth.verifyEmailOtp('otp@example.com', '123456')
446
-
447
- expect(res.error).toBeNull()
448
- expect(client.authStore.token).toBe(tp.access_token)
449
- expect((fetchMock.calls[0].body as any).email).toBe('otp@example.com')
450
- expect((fetchMock.calls[0].body as any).code).toBe('123456')
451
- })
452
-
453
- it('returns error on invalid code', async () => {
454
- fetchMock.on({
455
- method: 'POST',
456
- url: `${PREFIX}/email-otp/verify`,
457
- replyCode: 400,
458
- replyBody: { error: { code: 'invalid_otp', message: 'Code invalide' } },
459
- })
460
-
461
- const res = await client.auth.verifyEmailOtp('otp@example.com', '000000')
462
-
463
- expect(res.error).toBeDefined()
464
- expect(res.error!.code).toBe('invalid_otp')
465
- expect(client.authStore.token).toBeNull()
466
- })
467
- })
468
-
469
- // ---------------------------------------------------------------------------
470
- describe('AuthService.signInWithSmsOtp', () => {
471
- it('sends POST /sms/send with phone', async () => {
472
- fetchMock.on({
473
- method: 'POST',
474
- url: `${PREFIX}/sms/send`,
475
- replyCode: 200,
476
- replyBody: { data: { message: 'SMS sent' } },
477
- })
478
-
479
- const res = await client.auth.signInWithSmsOtp('+33612345678')
480
-
481
- expect(res.error).toBeNull()
482
- expect((fetchMock.calls[0].body as any).phone).toBe('+33612345678')
483
- })
484
- })
485
-
486
- // ---------------------------------------------------------------------------
487
- describe('AuthService.verifySmsOtp', () => {
488
- it('saves tokens on success', async () => {
489
- const tp = fakeTokenPair()
490
- fetchMock.on({
491
- method: 'POST',
492
- url: `${PREFIX}/sms/verify`,
493
- replyCode: 200,
494
- replyBody: { data: tp },
495
- })
496
-
497
- const res = await client.auth.verifySmsOtp('+33612345678', '654321')
498
-
499
- expect(res.error).toBeNull()
500
- expect(client.authStore.token).toBe(tp.access_token)
501
- expect((fetchMock.calls[0].body as any).phone).toBe('+33612345678')
502
- expect((fetchMock.calls[0].body as any).code).toBe('654321')
503
- })
504
- })
505
-
506
- // ---------------------------------------------------------------------------
507
- describe('AuthService.verifyEmail', () => {
508
- it('saves tokens after email verification', async () => {
509
- const tp = fakeTokenPair()
510
- fetchMock.on({
511
- method: 'POST',
512
- url: `${PREFIX}/verify-email`,
513
- replyCode: 200,
514
- replyBody: { data: tp },
515
- })
516
-
517
- const res = await client.auth.verifyEmail('verify-token-123')
518
-
519
- expect(res.error).toBeNull()
520
- expect(client.authStore.token).toBe(tp.access_token)
521
- expect((fetchMock.calls[0].body as any).token).toBe('verify-token-123')
522
- })
523
- })
524
-
525
- // ---------------------------------------------------------------------------
526
- describe('AuthService.resendVerificationEmail', () => {
527
- it('sends POST /resend-verification', async () => {
528
- fetchMock.on({
529
- method: 'POST',
530
- url: `${PREFIX}/resend-verification`,
531
- replyCode: 200,
532
- replyBody: { data: { message: 'Email sent' } },
533
- })
534
-
535
- const res = await client.auth.resendVerificationEmail('a@b.com')
536
-
537
- expect(res.error).toBeNull()
538
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/resend-verification`)
539
- expect((fetchMock.calls[0].body as any).email).toBe('a@b.com')
540
- })
541
-
542
- it('returns a local error when email is missing', async () => {
543
- const res = await client.auth.resendVerificationEmail()
544
-
545
- expect(res.data).toBeNull()
546
- expect(res.error?.code).toBe('missing_email')
547
- expect(fetchMock.calls).toHaveLength(0)
548
- })
549
- })
550
-
551
- // ---------------------------------------------------------------------------
552
- describe('AuthService.updateUser', () => {
553
- it('sends PUT /user with body and updates store', async () => {
554
- const tp = fakeTokenPair()
555
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
556
-
557
- const updatedUser = fakeUser({ email: 'updated@example.com' })
558
- fetchMock.on({
559
- method: 'PUT',
560
- url: `${PREFIX}/user`,
561
- replyCode: 200,
562
- replyBody: { data: updatedUser },
563
- })
564
-
565
- const res = await client.auth.updateUser({ email: 'updated@example.com' })
566
-
567
- expect(res.error).toBeNull()
568
- expect(client.authStore.user?.email).toBe('updated@example.com')
569
- expect(fetchMock.calls[0].method).toBe('PUT')
570
- })
571
- })
572
-
573
- // ---------------------------------------------------------------------------
574
- describe('AuthService.resetPasswordForEmail', () => {
575
- it('sends POST /forgot-password with email', async () => {
576
- fetchMock.on({
577
- method: 'POST',
578
- url: `${PREFIX}/forgot-password`,
579
- replyCode: 200,
580
- replyBody: { data: { message: 'Email sent' } },
581
- })
582
-
583
- const res = await client.auth.resetPasswordForEmail({ email: 'reset@example.com' })
584
-
585
- expect(res.error).toBeNull()
586
- expect((fetchMock.calls[0].body as any).email).toBe('reset@example.com')
587
- })
588
- })
589
-
590
- // ---------------------------------------------------------------------------
591
- describe('AuthService.updatePassword', () => {
592
- it('sends PUT /user with password fields', async () => {
593
- const tp = fakeTokenPair()
594
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
595
-
596
- const updatedUser = fakeUser()
597
- fetchMock.on({
598
- method: 'PUT',
599
- url: `${PREFIX}/user`,
600
- replyCode: 200,
601
- replyBody: { data: updatedUser },
602
- })
603
-
604
- const res = await client.auth.updatePassword('newpass123', 'oldpass')
605
-
606
- expect(res.error).toBeNull()
607
- expect((fetchMock.calls[0].body as any).password).toBe('newpass123')
608
- expect((fetchMock.calls[0].body as any).current_password).toBe('oldpass')
609
- })
610
-
611
- it('réussi → clear store + SIGNED_OUT (le backend révoque toutes les sessions)', async () => {
612
- const tp = fakeTokenPair()
613
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
614
-
615
- fetchMock.on({
616
- method: 'PUT',
617
- url: `${PREFIX}/user`,
618
- replyCode: 200,
619
- replyBody: { data: fakeUser() },
620
- })
621
-
622
- const events: string[] = []
623
- client.auth.onAuthStateChange(({ event }) => {
624
- if (event !== 'INITIAL_SESSION') events.push(event)
625
- })
626
-
627
- const res = await client.auth.updatePassword('New123!', 'Old123!')
628
-
629
- expect(res.error).toBeNull()
630
- expect(client.authStore.token).toBeNull()
631
- expect(client.authStore.refreshToken).toBeNull()
632
- expect(events).toContain('SIGNED_OUT')
633
- })
634
-
635
- it('échec → ne déconnecte pas', async () => {
636
- const tp = fakeTokenPair()
637
- client.authStore.save(tp.access_token, tp.refresh_token, tp.user)
638
-
639
- fetchMock.on({
640
- method: 'PUT',
641
- url: `${PREFIX}/user`,
642
- replyCode: 400,
643
- replyBody: { error: { code: 'invalid_password', message: 'Wrong current password' } },
644
- })
645
-
646
- const res = await client.auth.updatePassword('New123!', 'WrongOld')
647
-
648
- expect(res.error).toBeDefined()
649
- expect(client.authStore.token).toBe(tp.access_token)
650
- })
651
- })
652
-
653
- // ---------------------------------------------------------------------------
654
- describe('AuthService.mfaEnroll', () => {
655
- it('returns qr_code and secret', async () => {
656
- fetchMock.on({
657
- method: 'POST',
658
- url: `${PREFIX}/mfa/setup`,
659
- replyCode: 200,
660
- replyBody: { data: { qr_code: 'data:image/png;base64,abc', secret: 'JBSWY3DPEHPK3PXP' } },
661
- })
662
-
663
- const res = await client.auth.mfaEnroll()
664
-
665
- expect(res.error).toBeNull()
666
- expect((res.data as any).qr_code).toContain('data:image')
667
- expect((res.data as any).secret).toBe('JBSWY3DPEHPK3PXP')
668
- })
669
- })
670
-
671
- // ---------------------------------------------------------------------------
672
- describe('AuthService.mfaVerifySetup', () => {
673
- it('returns recovery_codes', async () => {
674
- const codes = ['AAAA-BBBB', 'CCCC-DDDD', 'EEEE-FFFF']
675
- fetchMock.on({
676
- method: 'POST',
677
- url: `${PREFIX}/mfa/setup/verify`,
678
- replyCode: 200,
679
- replyBody: { data: { recovery_codes: codes } },
680
- })
681
-
682
- const res = await client.auth.mfaVerifySetup('123456')
683
-
684
- expect(res.error).toBeNull()
685
- expect((res.data as any).recovery_codes).toEqual(codes)
686
- expect((fetchMock.calls[0].body as any).code).toBe('123456')
687
- })
688
- })
689
-
690
- // ---------------------------------------------------------------------------
691
- describe('AuthService.mfaVerify', () => {
692
- it('saves tokens after MFA verification', async () => {
693
- const tp = fakeTokenPair()
694
- fetchMock.on({
695
- method: 'POST',
696
- url: `${PREFIX}/mfa/verify-login`,
697
- replyCode: 200,
698
- replyBody: { data: tp },
699
- })
700
-
701
- const res = await client.auth.mfaVerify({ mfa_token: 'mfa_tok', code: '654321' })
702
-
703
- expect(res.error).toBeNull()
704
- expect(client.authStore.token).toBe(tp.access_token)
705
- expect(client.authStore.user?.id).toBe('user-1')
706
- })
707
- })
708
-
709
- // ---------------------------------------------------------------------------
710
- describe('AuthService.mfaUnenroll', () => {
711
- it('sends POST /mfa/disable with password', async () => {
712
- fetchMock.on({
713
- method: 'POST',
714
- url: `${PREFIX}/mfa/disable`,
715
- replyCode: 200,
716
- replyBody: { data: { message: 'MFA disabled' } },
717
- })
718
-
719
- const res = await client.auth.mfaUnenroll('mypassword')
720
-
721
- expect(res.error).toBeNull()
722
- expect((fetchMock.calls[0].body as any).password).toBe('mypassword')
723
- })
724
- })
725
-
726
- // ---------------------------------------------------------------------------
727
- describe('AuthService.listIdentities', () => {
728
- it('returns identity list', async () => {
729
- const identities = [{ id: 'id-1', provider: 'google', provider_id: 'g123' }]
730
- fetchMock.on({
731
- method: 'GET',
732
- url: `${PREFIX}/user/identities`,
733
- replyCode: 200,
734
- replyBody: { data: identities },
735
- })
736
-
737
- const res = await client.auth.listIdentities()
738
-
739
- expect(res.error).toBeNull()
740
- expect(res.data).toHaveLength(1)
741
- expect(fetchMock.calls[0].method).toBe('GET')
742
- })
743
- })
744
-
745
- // ---------------------------------------------------------------------------
746
- describe('AuthService.linkIdentity', () => {
747
- it('sends POST to link provider', async () => {
748
- fetchMock.on({
749
- method: 'POST',
750
- url: `${PREFIX}/user/identities/link/github`,
751
- replyCode: 200,
752
- replyBody: { data: { url: 'https://github.com/login/oauth', provider: 'github' } },
753
- })
754
-
755
- const res = await client.auth.linkIdentity('github')
756
-
757
- expect(res.error).toBeNull()
758
- expect((res.data as any).provider).toBe('github')
759
- })
760
- })
761
-
762
- // ---------------------------------------------------------------------------
763
- describe('AuthService.unlinkIdentity', () => {
764
- it('sends DELETE to unlink identity', async () => {
765
- fetchMock.on({
766
- method: 'DELETE',
767
- url: `${PREFIX}/user/identities/id-42`,
768
- replyCode: 200,
769
- replyBody: { data: { message: 'Unlinked' } },
770
- })
771
-
772
- const res = await client.auth.unlinkIdentity('id-42')
773
-
774
- expect(res.error).toBeNull()
775
- expect(fetchMock.calls[0].method).toBe('DELETE')
776
- expect(fetchMock.calls[0].url).toContain('id-42')
777
- })
778
- })
779
-
780
- // ---------------------------------------------------------------------------
781
- describe('AuthService.confirmEmailChange', () => {
782
- it('sends POST with token', async () => {
783
- const user = fakeUser({ email: 'newemail@example.com' })
784
- fetchMock.on({
785
- method: 'POST',
786
- url: `${PREFIX}/user/confirm-email-change`,
787
- replyCode: 200,
788
- replyBody: { data: user },
789
- })
790
-
791
- const res = await client.auth.confirmEmailChange('change-token-abc')
792
-
793
- expect(res.error).toBeNull()
794
- expect((fetchMock.calls[0].body as any).token).toBe('change-token-abc')
795
- })
796
- })
797
-
798
- // ---------------------------------------------------------------------------
799
- describe('AuthService.signInWithIdToken', () => {
800
- it('saves tokens on native mobile sign-in', async () => {
801
- const tp = fakeTokenPair()
802
- fetchMock.on({
803
- method: 'POST',
804
- url: `${PREFIX}/token`,
805
- replyCode: 200,
806
- replyBody: { data: tp },
807
- })
808
-
809
- const res = await client.auth.signInWithIdToken('google', 'google-id-token-abc')
810
-
811
- expect(res.error).toBeNull()
812
- expect(client.authStore.token).toBe(tp.access_token)
813
- expect((fetchMock.calls[0].body as any).provider).toBe('google')
814
- expect((fetchMock.calls[0].body as any).id_token).toBe('google-id-token-abc')
815
- })
816
- })
817
-
818
- // ---------------------------------------------------------------------------
819
- describe('AuthService.getSettings', () => {
820
- it('sends GET /settings and returns the public settings', async () => {
821
- fetchMock.on({
822
- method: 'GET',
823
- url: `${PREFIX}/settings`,
824
- replyCode: 200,
825
- replyBody: {
826
- data: {
827
- disable_signup: false,
828
- external: { google: true, github: false },
829
- mailer_autoconfirm: true,
830
- mfa_enabled: false,
831
- },
832
- },
833
- })
834
-
835
- const res = await client.auth.getSettings()
836
-
837
- expect(res.error).toBeNull()
838
- expect(fetchMock.calls[0].method).toBe('GET')
839
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/settings`)
840
- expect(res.data?.disable_signup).toBe(false)
841
- expect(res.data?.external).toEqual({ google: true, github: false })
842
- expect(res.data?.mailer_autoconfirm).toBe(true)
843
- expect(res.data?.mfa_enabled).toBe(false)
844
- })
845
- })
846
-
847
- // ---------------------------------------------------------------------------
848
- describe('AuthService.getAnonKey', () => {
849
- it('sends GET /anon-key and returns the anon key', async () => {
850
- fetchMock.on({
851
- method: 'GET',
852
- url: `${PREFIX}/anon-key`,
853
- replyCode: 200,
854
- replyBody: { data: { anon_key: 'anon-key-abc123' } },
855
- })
856
-
857
- const res = await client.auth.getAnonKey()
858
-
859
- expect(res.error).toBeNull()
860
- expect(fetchMock.calls[0].method).toBe('GET')
861
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/anon-key`)
862
- expect(res.data?.anon_key).toBe('anon-key-abc123')
863
- })
864
- })
865
-
866
- // ---------------------------------------------------------------------------
867
- describe('AuthService.resetPassword', () => {
868
- it('sends POST /reset-password with token+password and saves tokens (SIGNED_IN)', async () => {
869
- const tp = fakeTokenPair()
870
- fetchMock.on({
871
- method: 'POST',
872
- url: `${PREFIX}/reset-password`,
873
- replyCode: 200,
874
- replyBody: { data: tp },
875
- })
876
-
877
- const events: string[] = []
878
- client.auth.onAuthStateChange((p) => events.push(p.event))
879
-
880
- const res = await client.auth.resetPassword('recovery-token-xyz', 'newSecret123')
881
-
882
- expect(res.error).toBeNull()
883
- expect(fetchMock.calls[0].method).toBe('POST')
884
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/reset-password`)
885
- expect((fetchMock.calls[0].body as any).token).toBe('recovery-token-xyz')
886
- expect((fetchMock.calls[0].body as any).password).toBe('newSecret123')
887
- expect(client.authStore.token).toBe(tp.access_token)
888
- expect(client.authStore.refreshToken).toBe(tp.refresh_token)
889
- await Promise.resolve()
890
- expect(events).toContain('SIGNED_IN')
891
- })
892
- })
893
-
894
- // ---------------------------------------------------------------------------
895
- describe('AuthService.promoteAnonymous', () => {
896
- it('sends POST /anonymous/promote with email+password and saves tokens (USER_UPDATED)', async () => {
897
- const tp = fakeTokenPair()
898
- fetchMock.on({
899
- method: 'POST',
900
- url: `${PREFIX}/anonymous/promote`,
901
- replyCode: 200,
902
- replyBody: { data: tp },
903
- })
904
-
905
- const events: string[] = []
906
- client.auth.onAuthStateChange((p) => events.push(p.event))
907
-
908
- const res = await client.auth.promoteAnonymous({ email: 'promo@example.com', password: 'secret123' })
909
-
910
- expect(res.error).toBeNull()
911
- expect(fetchMock.calls[0].method).toBe('POST')
912
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/anonymous/promote`)
913
- expect((fetchMock.calls[0].body as any).email).toBe('promo@example.com')
914
- expect((fetchMock.calls[0].body as any).password).toBe('secret123')
915
- expect(client.authStore.token).toBe(tp.access_token)
916
- expect(client.authStore.refreshToken).toBe(tp.refresh_token)
917
- await Promise.resolve()
918
- expect(events).toContain('USER_UPDATED')
919
- })
920
- })
921
-
922
- // ---------------------------------------------------------------------------
923
- describe('AuthService.verifyMagicLink', () => {
924
- it('sends POST /magic-link/verify with token and saves tokens (SIGNED_IN)', async () => {
925
- const tp = fakeTokenPair()
926
- fetchMock.on({
927
- method: 'POST',
928
- url: `${PREFIX}/magic-link/verify`,
929
- replyCode: 200,
930
- replyBody: { data: tp },
931
- })
932
-
933
- const events: string[] = []
934
- client.auth.onAuthStateChange((p) => events.push(p.event))
935
-
936
- const res = await client.auth.verifyMagicLink('magic-token-789')
937
-
938
- expect(res.error).toBeNull()
939
- expect(fetchMock.calls[0].method).toBe('POST')
940
- expect(fetchMock.calls[0].url).toBe(`${PREFIX}/magic-link/verify`)
941
- expect((fetchMock.calls[0].body as any).token).toBe('magic-token-789')
942
- expect(client.authStore.token).toBe(tp.access_token)
943
- expect(client.authStore.refreshToken).toBe(tp.refresh_token)
944
- await Promise.resolve()
945
- expect(events).toContain('SIGNED_IN')
946
- })
947
- })