@authrim/sveltekit 0.1.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 (266) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +531 -0
  3. package/dist/__tests__/client-events.test.d.ts +2 -0
  4. package/dist/__tests__/client-events.test.d.ts.map +1 -0
  5. package/dist/__tests__/client-events.test.js +225 -0
  6. package/dist/__tests__/providers.test.d.ts +2 -0
  7. package/dist/__tests__/providers.test.d.ts.map +1 -0
  8. package/dist/__tests__/providers.test.js +68 -0
  9. package/dist/__tests__/response.test.d.ts +2 -0
  10. package/dist/__tests__/response.test.d.ts.map +1 -0
  11. package/dist/__tests__/response.test.js +99 -0
  12. package/dist/__tests__/stores.test.d.ts +2 -0
  13. package/dist/__tests__/stores.test.d.ts.map +1 -0
  14. package/dist/__tests__/stores.test.js +91 -0
  15. package/dist/client.d.ts +25 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +411 -0
  18. package/dist/components/AuthProvider.svelte +56 -0
  19. package/dist/components/AuthProvider.svelte.d.ts +34 -0
  20. package/dist/components/AuthProvider.svelte.d.ts.map +1 -0
  21. package/dist/components/ProtectedRoute.svelte +71 -0
  22. package/dist/components/ProtectedRoute.svelte.d.ts +38 -0
  23. package/dist/components/ProtectedRoute.svelte.d.ts.map +1 -0
  24. package/dist/components/SignInButton.svelte +93 -0
  25. package/dist/components/SignInButton.svelte.d.ts +43 -0
  26. package/dist/components/SignInButton.svelte.d.ts.map +1 -0
  27. package/dist/components/SignOutButton.svelte +72 -0
  28. package/dist/components/SignOutButton.svelte.d.ts +40 -0
  29. package/dist/components/SignOutButton.svelte.d.ts.map +1 -0
  30. package/dist/components/UserProfile.svelte +71 -0
  31. package/dist/components/UserProfile.svelte.d.ts +51 -0
  32. package/dist/components/UserProfile.svelte.d.ts.map +1 -0
  33. package/dist/components/index.d.ts +6 -0
  34. package/dist/components/index.d.ts.map +1 -0
  35. package/dist/components/index.js +5 -0
  36. package/dist/direct-auth/ciba.d.ts +47 -0
  37. package/dist/direct-auth/ciba.d.ts.map +1 -0
  38. package/dist/direct-auth/ciba.js +77 -0
  39. package/dist/direct-auth/consent.d.ts +85 -0
  40. package/dist/direct-auth/consent.d.ts.map +1 -0
  41. package/dist/direct-auth/consent.js +57 -0
  42. package/dist/direct-auth/device-flow.d.ts +40 -0
  43. package/dist/direct-auth/device-flow.d.ts.map +1 -0
  44. package/dist/direct-auth/device-flow.js +45 -0
  45. package/dist/direct-auth/email-code.d.ts +48 -0
  46. package/dist/direct-auth/email-code.d.ts.map +1 -0
  47. package/dist/direct-auth/email-code.js +265 -0
  48. package/dist/direct-auth/index.d.ts +9 -0
  49. package/dist/direct-auth/index.d.ts.map +1 -0
  50. package/dist/direct-auth/index.js +8 -0
  51. package/dist/direct-auth/login-challenge.d.ts +41 -0
  52. package/dist/direct-auth/login-challenge.d.ts.map +1 -0
  53. package/dist/direct-auth/login-challenge.js +34 -0
  54. package/dist/direct-auth/passkey.d.ts +30 -0
  55. package/dist/direct-auth/passkey.d.ts.map +1 -0
  56. package/dist/direct-auth/passkey.js +392 -0
  57. package/dist/direct-auth/session.d.ts +48 -0
  58. package/dist/direct-auth/session.d.ts.map +1 -0
  59. package/dist/direct-auth/session.js +219 -0
  60. package/dist/direct-auth/social.d.ts +56 -0
  61. package/dist/direct-auth/social.d.ts.map +1 -0
  62. package/dist/direct-auth/social.js +484 -0
  63. package/dist/index.d.ts +17 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +14 -0
  66. package/dist/providers/crypto.d.ts +13 -0
  67. package/dist/providers/crypto.d.ts.map +1 -0
  68. package/dist/providers/crypto.js +27 -0
  69. package/dist/providers/http.d.ts +30 -0
  70. package/dist/providers/http.d.ts.map +1 -0
  71. package/dist/providers/http.js +65 -0
  72. package/dist/providers/index.d.ts +4 -0
  73. package/dist/providers/index.d.ts.map +1 -0
  74. package/dist/providers/index.js +3 -0
  75. package/dist/providers/storage.d.ts +21 -0
  76. package/dist/providers/storage.d.ts.map +1 -0
  77. package/dist/providers/storage.js +83 -0
  78. package/dist/server/handle.d.ts +46 -0
  79. package/dist/server/handle.d.ts.map +1 -0
  80. package/dist/server/handle.js +60 -0
  81. package/dist/server/index.d.ts +4 -0
  82. package/dist/server/index.d.ts.map +1 -0
  83. package/dist/server/index.js +3 -0
  84. package/dist/server/load.d.ts +83 -0
  85. package/dist/server/load.d.ts.map +1 -0
  86. package/dist/server/load.js +86 -0
  87. package/dist/server/session.d.ts +44 -0
  88. package/dist/server/session.d.ts.map +1 -0
  89. package/dist/server/session.js +50 -0
  90. package/dist/stores/auth.d.ts +56 -0
  91. package/dist/stores/auth.d.ts.map +1 -0
  92. package/dist/stores/auth.js +64 -0
  93. package/dist/stores/index.d.ts +2 -0
  94. package/dist/stores/index.d.ts.map +1 -0
  95. package/dist/stores/index.js +1 -0
  96. package/dist/types.d.ts +164 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +4 -0
  99. package/dist/ui/account/LinkAccountButton.svelte +133 -0
  100. package/dist/ui/account/LinkAccountButton.svelte.d.ts +37 -0
  101. package/dist/ui/account/LinkAccountButton.svelte.d.ts.map +1 -0
  102. package/dist/ui/account/LinkedAccountsList.svelte +233 -0
  103. package/dist/ui/account/LinkedAccountsList.svelte.d.ts +32 -0
  104. package/dist/ui/account/LinkedAccountsList.svelte.d.ts.map +1 -0
  105. package/dist/ui/account/UnlinkAccountButton.svelte +179 -0
  106. package/dist/ui/account/UnlinkAccountButton.svelte.d.ts +28 -0
  107. package/dist/ui/account/UnlinkAccountButton.svelte.d.ts.map +1 -0
  108. package/dist/ui/account/index.d.ts +7 -0
  109. package/dist/ui/account/index.d.ts.map +1 -0
  110. package/dist/ui/account/index.js +6 -0
  111. package/dist/ui/context.d.ts +17 -0
  112. package/dist/ui/context.d.ts.map +1 -0
  113. package/dist/ui/context.js +71 -0
  114. package/dist/ui/forms/CIBARequestCard.svelte +315 -0
  115. package/dist/ui/forms/CIBARequestCard.svelte.d.ts +50 -0
  116. package/dist/ui/forms/CIBARequestCard.svelte.d.ts.map +1 -0
  117. package/dist/ui/forms/ClientInfo.svelte +232 -0
  118. package/dist/ui/forms/ClientInfo.svelte.d.ts +35 -0
  119. package/dist/ui/forms/ClientInfo.svelte.d.ts.map +1 -0
  120. package/dist/ui/forms/ConsentScopesList.svelte +109 -0
  121. package/dist/ui/forms/ConsentScopesList.svelte.d.ts +30 -0
  122. package/dist/ui/forms/ConsentScopesList.svelte.d.ts.map +1 -0
  123. package/dist/ui/forms/EmailCodeForm.svelte +224 -0
  124. package/dist/ui/forms/EmailCodeForm.svelte.d.ts +39 -0
  125. package/dist/ui/forms/EmailCodeForm.svelte.d.ts.map +1 -0
  126. package/dist/ui/forms/OrgSelector.svelte +95 -0
  127. package/dist/ui/forms/OrgSelector.svelte.d.ts +37 -0
  128. package/dist/ui/forms/OrgSelector.svelte.d.ts.map +1 -0
  129. package/dist/ui/forms/PasskeyConditionalInput.svelte +173 -0
  130. package/dist/ui/forms/PasskeyConditionalInput.svelte.d.ts +36 -0
  131. package/dist/ui/forms/PasskeyConditionalInput.svelte.d.ts.map +1 -0
  132. package/dist/ui/forms/QRCodeDisplay.svelte +122 -0
  133. package/dist/ui/forms/QRCodeDisplay.svelte.d.ts +27 -0
  134. package/dist/ui/forms/QRCodeDisplay.svelte.d.ts.map +1 -0
  135. package/dist/ui/forms/SocialLoginButtons.svelte +209 -0
  136. package/dist/ui/forms/SocialLoginButtons.svelte.d.ts +33 -0
  137. package/dist/ui/forms/SocialLoginButtons.svelte.d.ts.map +1 -0
  138. package/dist/ui/forms/UserCodeInput.svelte +183 -0
  139. package/dist/ui/forms/UserCodeInput.svelte.d.ts +34 -0
  140. package/dist/ui/forms/UserCodeInput.svelte.d.ts.map +1 -0
  141. package/dist/ui/forms/index.d.ts +13 -0
  142. package/dist/ui/forms/index.d.ts.map +1 -0
  143. package/dist/ui/forms/index.js +12 -0
  144. package/dist/ui/helpers/AuthError.svelte +124 -0
  145. package/dist/ui/helpers/AuthError.svelte.d.ts +26 -0
  146. package/dist/ui/helpers/AuthError.svelte.d.ts.map +1 -0
  147. package/dist/ui/helpers/AuthLoading.svelte +83 -0
  148. package/dist/ui/helpers/AuthLoading.svelte.d.ts +25 -0
  149. package/dist/ui/helpers/AuthLoading.svelte.d.ts.map +1 -0
  150. package/dist/ui/helpers/OTPInput.svelte +214 -0
  151. package/dist/ui/helpers/OTPInput.svelte.d.ts +34 -0
  152. package/dist/ui/helpers/OTPInput.svelte.d.ts.map +1 -0
  153. package/dist/ui/helpers/ResendCodeButton.svelte +140 -0
  154. package/dist/ui/helpers/ResendCodeButton.svelte.d.ts +28 -0
  155. package/dist/ui/helpers/ResendCodeButton.svelte.d.ts.map +1 -0
  156. package/dist/ui/helpers/index.d.ts +8 -0
  157. package/dist/ui/helpers/index.d.ts.map +1 -0
  158. package/dist/ui/helpers/index.js +7 -0
  159. package/dist/ui/index.d.ts +43 -0
  160. package/dist/ui/index.d.ts.map +1 -0
  161. package/dist/ui/index.js +48 -0
  162. package/dist/ui/passkey/PasskeyDeleteButton.svelte +177 -0
  163. package/dist/ui/passkey/PasskeyDeleteButton.svelte.d.ts +26 -0
  164. package/dist/ui/passkey/PasskeyDeleteButton.svelte.d.ts.map +1 -0
  165. package/dist/ui/passkey/PasskeyList.svelte +225 -0
  166. package/dist/ui/passkey/PasskeyList.svelte.d.ts +30 -0
  167. package/dist/ui/passkey/PasskeyList.svelte.d.ts.map +1 -0
  168. package/dist/ui/passkey/PasskeyRegisterButton.svelte +52 -0
  169. package/dist/ui/passkey/PasskeyRegisterButton.svelte.d.ts +38 -0
  170. package/dist/ui/passkey/PasskeyRegisterButton.svelte.d.ts.map +1 -0
  171. package/dist/ui/passkey/index.d.ts +7 -0
  172. package/dist/ui/passkey/index.d.ts.map +1 -0
  173. package/dist/ui/passkey/index.js +6 -0
  174. package/dist/ui/session/SessionExpiryIndicator.svelte +109 -0
  175. package/dist/ui/session/SessionExpiryIndicator.svelte.d.ts +23 -0
  176. package/dist/ui/session/SessionExpiryIndicator.svelte.d.ts.map +1 -0
  177. package/dist/ui/session/SessionList.svelte +231 -0
  178. package/dist/ui/session/SessionList.svelte.d.ts +31 -0
  179. package/dist/ui/session/SessionList.svelte.d.ts.map +1 -0
  180. package/dist/ui/session/SessionRevokeButton.svelte +72 -0
  181. package/dist/ui/session/SessionRevokeButton.svelte.d.ts +26 -0
  182. package/dist/ui/session/SessionRevokeButton.svelte.d.ts.map +1 -0
  183. package/dist/ui/session/index.d.ts +7 -0
  184. package/dist/ui/session/index.d.ts.map +1 -0
  185. package/dist/ui/session/index.js +6 -0
  186. package/dist/ui/shared/Alert.svelte +246 -0
  187. package/dist/ui/shared/Alert.svelte.d.ts +36 -0
  188. package/dist/ui/shared/Alert.svelte.d.ts.map +1 -0
  189. package/dist/ui/shared/Badge.svelte +100 -0
  190. package/dist/ui/shared/Badge.svelte.d.ts +35 -0
  191. package/dist/ui/shared/Badge.svelte.d.ts.map +1 -0
  192. package/dist/ui/shared/Button.svelte +213 -0
  193. package/dist/ui/shared/Button.svelte.d.ts +42 -0
  194. package/dist/ui/shared/Button.svelte.d.ts.map +1 -0
  195. package/dist/ui/shared/Card.svelte +85 -0
  196. package/dist/ui/shared/Card.svelte.d.ts +39 -0
  197. package/dist/ui/shared/Card.svelte.d.ts.map +1 -0
  198. package/dist/ui/shared/CountdownTimer.svelte +150 -0
  199. package/dist/ui/shared/CountdownTimer.svelte.d.ts +30 -0
  200. package/dist/ui/shared/CountdownTimer.svelte.d.ts.map +1 -0
  201. package/dist/ui/shared/Dialog.svelte +240 -0
  202. package/dist/ui/shared/Dialog.svelte.d.ts +39 -0
  203. package/dist/ui/shared/Dialog.svelte.d.ts.map +1 -0
  204. package/dist/ui/shared/Input.svelte +192 -0
  205. package/dist/ui/shared/Input.svelte.d.ts +42 -0
  206. package/dist/ui/shared/Input.svelte.d.ts.map +1 -0
  207. package/dist/ui/shared/LanguageSwitcher.svelte +99 -0
  208. package/dist/ui/shared/LanguageSwitcher.svelte.d.ts +31 -0
  209. package/dist/ui/shared/LanguageSwitcher.svelte.d.ts.map +1 -0
  210. package/dist/ui/shared/Spinner.svelte +75 -0
  211. package/dist/ui/shared/Spinner.svelte.d.ts +24 -0
  212. package/dist/ui/shared/Spinner.svelte.d.ts.map +1 -0
  213. package/dist/ui/shared/index.d.ts +13 -0
  214. package/dist/ui/shared/index.d.ts.map +1 -0
  215. package/dist/ui/shared/index.js +12 -0
  216. package/dist/ui/styles/base.css +168 -0
  217. package/dist/ui/styles/theme.css +279 -0
  218. package/dist/ui/templates/AccountSettingsTemplate.svelte +205 -0
  219. package/dist/ui/templates/AccountSettingsTemplate.svelte.d.ts +49 -0
  220. package/dist/ui/templates/AccountSettingsTemplate.svelte.d.ts.map +1 -0
  221. package/dist/ui/templates/CIBATemplate.svelte +227 -0
  222. package/dist/ui/templates/CIBATemplate.svelte.d.ts +45 -0
  223. package/dist/ui/templates/CIBATemplate.svelte.d.ts.map +1 -0
  224. package/dist/ui/templates/ConsentTemplate.svelte +549 -0
  225. package/dist/ui/templates/ConsentTemplate.svelte.d.ts +76 -0
  226. package/dist/ui/templates/ConsentTemplate.svelte.d.ts.map +1 -0
  227. package/dist/ui/templates/DeviceFlowTemplate.svelte +228 -0
  228. package/dist/ui/templates/DeviceFlowTemplate.svelte.d.ts +47 -0
  229. package/dist/ui/templates/DeviceFlowTemplate.svelte.d.ts.map +1 -0
  230. package/dist/ui/templates/LoginTemplate.svelte +234 -0
  231. package/dist/ui/templates/LoginTemplate.svelte.d.ts +49 -0
  232. package/dist/ui/templates/LoginTemplate.svelte.d.ts.map +1 -0
  233. package/dist/ui/templates/ReauthTemplate.svelte +269 -0
  234. package/dist/ui/templates/ReauthTemplate.svelte.d.ts +54 -0
  235. package/dist/ui/templates/ReauthTemplate.svelte.d.ts.map +1 -0
  236. package/dist/ui/templates/SignUpTemplate.svelte +345 -0
  237. package/dist/ui/templates/SignUpTemplate.svelte.d.ts +53 -0
  238. package/dist/ui/templates/SignUpTemplate.svelte.d.ts.map +1 -0
  239. package/dist/ui/templates/index.d.ts +14 -0
  240. package/dist/ui/templates/index.d.ts.map +1 -0
  241. package/dist/ui/templates/index.js +13 -0
  242. package/dist/ui/types.d.ts +151 -0
  243. package/dist/ui/types.d.ts.map +1 -0
  244. package/dist/ui/types.js +4 -0
  245. package/dist/utils/context.d.ts +12 -0
  246. package/dist/utils/context.d.ts.map +1 -0
  247. package/dist/utils/context.js +26 -0
  248. package/dist/utils/error-mapping.d.ts +29 -0
  249. package/dist/utils/error-mapping.d.ts.map +1 -0
  250. package/dist/utils/error-mapping.js +38 -0
  251. package/dist/utils/index.d.ts +7 -0
  252. package/dist/utils/index.d.ts.map +1 -0
  253. package/dist/utils/index.js +6 -0
  254. package/dist/utils/response.d.ts +21 -0
  255. package/dist/utils/response.d.ts.map +1 -0
  256. package/dist/utils/response.js +84 -0
  257. package/dist/utils/sensitive-data.d.ts +9 -0
  258. package/dist/utils/sensitive-data.d.ts.map +1 -0
  259. package/dist/utils/sensitive-data.js +56 -0
  260. package/dist/utils/ssr.d.ts +38 -0
  261. package/dist/utils/ssr.d.ts.map +1 -0
  262. package/dist/utils/ssr.js +73 -0
  263. package/dist/utils/webauthn-converters.d.ts +9 -0
  264. package/dist/utils/webauthn-converters.d.ts.map +1 -0
  265. package/dist/utils/webauthn-converters.js +75 -0
  266. package/package.json +111 -0
package/dist/client.js ADDED
@@ -0,0 +1,411 @@
1
+ /**
2
+ * Authrim Svelte SDK Main Entry Point
3
+ */
4
+ import { authResultToResponse, wrapWithAuthResponse, success, } from "./utils/response.js";
5
+ import { PasskeyAuthImpl } from "./direct-auth/passkey.js";
6
+ import { EmailCodeAuthImpl } from "./direct-auth/email-code.js";
7
+ import { SocialAuthImpl } from "./direct-auth/social.js";
8
+ import { SessionAuthImpl } from "./direct-auth/session.js";
9
+ import { ConsentApiImpl } from "./direct-auth/consent.js";
10
+ import { DeviceFlowApiImpl } from "./direct-auth/device-flow.js";
11
+ import { CIBAApiImpl } from "./direct-auth/ciba.js";
12
+ import { LoginChallengeApiImpl } from "./direct-auth/login-challenge.js";
13
+ import { BrowserHttpClient } from "./providers/http.js";
14
+ import { BrowserCryptoProvider } from "./providers/crypto.js";
15
+ import { createBrowserStorage, } from "./providers/storage.js";
16
+ import { createAuthStores, toAuthError, } from "./stores/auth.js";
17
+ /**
18
+ * Event emitter for auth events
19
+ */
20
+ class AuthEventEmitter {
21
+ handlers = new Map();
22
+ on(event, handler) {
23
+ if (!this.handlers.has(event)) {
24
+ this.handlers.set(event, new Set());
25
+ }
26
+ this.handlers.get(event).add(handler);
27
+ return () => {
28
+ this.handlers
29
+ .get(event)
30
+ ?.delete(handler);
31
+ };
32
+ }
33
+ emit(event, payload) {
34
+ const eventHandlers = this.handlers.get(event);
35
+ if (eventHandlers) {
36
+ for (const handler of eventHandlers) {
37
+ try {
38
+ handler(payload);
39
+ }
40
+ catch (error) {
41
+ console.error(`Error in event handler for ${event}:`, error);
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ /**
48
+ * Create Authrim client for Svelte
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * import { createAuthrim } from '@authrim/sveltekit';
53
+ *
54
+ * const auth = await createAuthrim({
55
+ * issuer: 'https://auth.example.com',
56
+ * clientId: 'your-client-id',
57
+ * });
58
+ *
59
+ * // Passkey login
60
+ * const { data, error } = await auth.passkey.login();
61
+ *
62
+ * // Reactive stores
63
+ * const { session, user, isAuthenticated } = auth.stores;
64
+ * ```
65
+ */
66
+ export async function createAuthrim(config) {
67
+ // Initialize providers
68
+ const http = new BrowserHttpClient();
69
+ const crypto = new BrowserCryptoProvider();
70
+ const storageOptions = config.storage ?? {};
71
+ const storage = createBrowserStorage(storageOptions);
72
+ // Initialize event emitter
73
+ const emitter = new AuthEventEmitter();
74
+ // Initialize stores
75
+ const internalStores = createAuthStores();
76
+ // Create session manager
77
+ const sessionManager = new SessionAuthImpl({
78
+ issuer: config.issuer,
79
+ clientId: config.clientId,
80
+ http,
81
+ });
82
+ // Token exchange callback
83
+ const exchangeToken = async (authCode, codeVerifier) => {
84
+ return sessionManager.exchangeToken(authCode, codeVerifier);
85
+ };
86
+ // Create Direct Auth implementations
87
+ const passkeyImpl = new PasskeyAuthImpl({
88
+ issuer: config.issuer,
89
+ clientId: config.clientId,
90
+ http,
91
+ crypto,
92
+ exchangeToken,
93
+ });
94
+ const emailCodeImpl = new EmailCodeAuthImpl({
95
+ issuer: config.issuer,
96
+ clientId: config.clientId,
97
+ http,
98
+ crypto,
99
+ exchangeToken,
100
+ });
101
+ const socialImpl = new SocialAuthImpl({
102
+ issuer: config.issuer,
103
+ clientId: config.clientId,
104
+ crypto,
105
+ storage,
106
+ exchangeToken,
107
+ });
108
+ // ==========================================================================
109
+ // Store updater helpers (イベント→Store の projection)
110
+ // ==========================================================================
111
+ function updateStoresOnLogin(session, user) {
112
+ internalStores._session.set(session);
113
+ internalStores._user.set(user);
114
+ internalStores._loadingState.set("idle");
115
+ internalStores._error.set(null);
116
+ }
117
+ function updateStoresOnLogout() {
118
+ internalStores._session.set(null);
119
+ internalStores._user.set(null);
120
+ internalStores._loadingState.set("idle");
121
+ internalStores._error.set(null);
122
+ }
123
+ function updateStoresOnError(error) {
124
+ if (error) {
125
+ internalStores._error.set(toAuthError(error));
126
+ }
127
+ internalStores._loadingState.set("idle");
128
+ }
129
+ function setLoadingState(state) {
130
+ internalStores._loadingState.set(state);
131
+ }
132
+ // ==========================================================================
133
+ // Event→Store projection
134
+ // ==========================================================================
135
+ emitter.on("auth:login", (payload) => {
136
+ updateStoresOnLogin(payload.session, payload.user);
137
+ });
138
+ emitter.on("auth:logout", () => {
139
+ updateStoresOnLogout();
140
+ });
141
+ emitter.on("auth:error", (payload) => {
142
+ updateStoresOnError(payload.error);
143
+ });
144
+ emitter.on("session:changed", (payload) => {
145
+ internalStores._session.set(payload.session);
146
+ internalStores._user.set(payload.user);
147
+ });
148
+ // ==========================================================================
149
+ // Passkey Namespace
150
+ // ==========================================================================
151
+ const passkey = {
152
+ async login(options) {
153
+ setLoadingState("authenticating");
154
+ const result = await passkeyImpl.login(options);
155
+ const response = authResultToResponse(result);
156
+ if (response.data) {
157
+ emitter.emit("auth:login", {
158
+ session: response.data.session,
159
+ user: response.data.user,
160
+ method: "passkey",
161
+ });
162
+ }
163
+ else if (response.error) {
164
+ emitter.emit("auth:error", { error: response.error });
165
+ }
166
+ return response;
167
+ },
168
+ async signUp(options) {
169
+ setLoadingState("authenticating");
170
+ const result = await passkeyImpl.signUp(options);
171
+ const response = authResultToResponse(result);
172
+ if (response.data) {
173
+ emitter.emit("auth:login", {
174
+ session: response.data.session,
175
+ user: response.data.user,
176
+ method: "passkey",
177
+ });
178
+ }
179
+ else if (response.error) {
180
+ emitter.emit("auth:error", { error: response.error });
181
+ }
182
+ return response;
183
+ },
184
+ async register(options) {
185
+ return wrapWithAuthResponse(() => passkeyImpl.register(options), "AR003000");
186
+ },
187
+ isSupported() {
188
+ return passkeyImpl.isSupported();
189
+ },
190
+ isConditionalUIAvailable() {
191
+ return passkeyImpl.isConditionalUIAvailable();
192
+ },
193
+ cancelConditionalUI() {
194
+ passkeyImpl.cancelConditionalUI();
195
+ },
196
+ };
197
+ // ==========================================================================
198
+ // Email Code Namespace
199
+ // ==========================================================================
200
+ const emailCode = {
201
+ async send(email, options) {
202
+ return wrapWithAuthResponse(async () => emailCodeImpl.send(email, options), "AR002000");
203
+ },
204
+ async verify(email, code, options) {
205
+ setLoadingState("authenticating");
206
+ const result = await emailCodeImpl.verify(email, code, options);
207
+ const response = authResultToResponse(result);
208
+ if (response.data) {
209
+ emitter.emit("auth:login", {
210
+ session: response.data.session,
211
+ user: response.data.user,
212
+ method: "emailCode",
213
+ });
214
+ }
215
+ else if (response.error) {
216
+ emitter.emit("auth:error", { error: response.error });
217
+ }
218
+ return response;
219
+ },
220
+ hasPendingVerification(email) {
221
+ return emailCodeImpl.hasPendingVerification(email);
222
+ },
223
+ getRemainingTime(email) {
224
+ return emailCodeImpl.getRemainingTime(email);
225
+ },
226
+ clearPendingVerification(email) {
227
+ emailCodeImpl.clearPendingVerification(email);
228
+ },
229
+ };
230
+ // ==========================================================================
231
+ // Social Namespace
232
+ // ==========================================================================
233
+ const social = {
234
+ async loginWithPopup(provider, options) {
235
+ setLoadingState("authenticating");
236
+ const result = await socialImpl.loginWithPopup(provider, options);
237
+ const response = authResultToResponse(result);
238
+ if (response.data) {
239
+ emitter.emit("auth:login", {
240
+ session: response.data.session,
241
+ user: response.data.user,
242
+ method: "social",
243
+ });
244
+ }
245
+ else if (response.error) {
246
+ emitter.emit("auth:error", { error: response.error });
247
+ }
248
+ return response;
249
+ },
250
+ async loginWithRedirect(provider, options) {
251
+ setLoadingState("authenticating");
252
+ await socialImpl.loginWithRedirect(provider, options);
253
+ },
254
+ async handleCallback() {
255
+ setLoadingState("authenticating");
256
+ const result = await socialImpl.handleCallback();
257
+ const response = authResultToResponse(result);
258
+ if (response.data) {
259
+ emitter.emit("auth:login", {
260
+ session: response.data.session,
261
+ user: response.data.user,
262
+ method: "social",
263
+ });
264
+ }
265
+ else if (response.error) {
266
+ emitter.emit("auth:error", { error: response.error });
267
+ }
268
+ return response;
269
+ },
270
+ hasCallbackParams() {
271
+ return socialImpl.hasCallbackParams();
272
+ },
273
+ getSupportedProviders() {
274
+ return socialImpl.getSupportedProviders();
275
+ },
276
+ };
277
+ // ==========================================================================
278
+ // Session Namespace
279
+ // ==========================================================================
280
+ const session = {
281
+ async get() {
282
+ const sessionData = await sessionManager.get();
283
+ if (!sessionData) {
284
+ return success(null);
285
+ }
286
+ const user = await sessionManager.getUser();
287
+ if (!user) {
288
+ return success(null);
289
+ }
290
+ // Update stores with fetched session
291
+ internalStores._session.set(sessionData);
292
+ internalStores._user.set(user);
293
+ return success({
294
+ session: sessionData,
295
+ user,
296
+ });
297
+ },
298
+ validate() {
299
+ return sessionManager.validate();
300
+ },
301
+ getUser() {
302
+ return sessionManager.getUser();
303
+ },
304
+ async refresh() {
305
+ setLoadingState("refreshing");
306
+ const result = await sessionManager.refresh();
307
+ internalStores._loadingState.set("idle");
308
+ return result;
309
+ },
310
+ isAuthenticated() {
311
+ return sessionManager.isAuthenticated();
312
+ },
313
+ clearCache() {
314
+ sessionManager.clearCache();
315
+ },
316
+ };
317
+ // ==========================================================================
318
+ // Flow API Implementations (Consent, Device Flow, CIBA, Login Challenge)
319
+ // ==========================================================================
320
+ const consentImpl = new ConsentApiImpl({ issuer: config.issuer, http });
321
+ const deviceFlowImpl = new DeviceFlowApiImpl({ issuer: config.issuer, http });
322
+ const cibaImpl = new CIBAApiImpl({ issuer: config.issuer, http });
323
+ const loginChallengeImpl = new LoginChallengeApiImpl({
324
+ issuer: config.issuer,
325
+ http,
326
+ });
327
+ const consent = {
328
+ getData: (challengeId) => consentImpl.getData(challengeId),
329
+ submit: (challengeId, options) => consentImpl.submit(challengeId, options),
330
+ };
331
+ const deviceFlow = {
332
+ submit: (userCode, approve) => deviceFlowImpl.submit(userCode, approve),
333
+ };
334
+ const ciba = {
335
+ getData: (loginHint) => cibaImpl.getData(loginHint),
336
+ approve: (authReqId, userId, sub) => cibaImpl.approve(authReqId, userId, sub),
337
+ reject: (authReqId, reason) => cibaImpl.reject(authReqId, reason),
338
+ };
339
+ const loginChallenge = {
340
+ getData: (challengeId) => loginChallengeImpl.getData(challengeId),
341
+ };
342
+ // ==========================================================================
343
+ // Sign Out
344
+ // ==========================================================================
345
+ async function signOut(options) {
346
+ setLoadingState("signing_out");
347
+ await sessionManager.logout(options);
348
+ emitter.emit("auth:logout", { redirectUri: options?.redirectUri });
349
+ }
350
+ // ==========================================================================
351
+ // Event System
352
+ // ==========================================================================
353
+ function on(event, handler) {
354
+ return emitter.on(event, handler);
355
+ }
356
+ // ==========================================================================
357
+ // Stores
358
+ // ==========================================================================
359
+ const stores = internalStores.public;
360
+ // ==========================================================================
361
+ // SSR Sync (internal API for AuthProvider)
362
+ // ==========================================================================
363
+ /**
364
+ * Sync session and user from SSR data directly to stores.
365
+ * This is used by AuthProvider to avoid hydration mismatch.
366
+ * @internal
367
+ */
368
+ function _syncFromSSR(session, user) {
369
+ internalStores._session.set(session);
370
+ internalStores._user.set(user);
371
+ }
372
+ // ==========================================================================
373
+ // Destroy (cleanup resources)
374
+ // ==========================================================================
375
+ /**
376
+ * Cleanup resources (event listeners, timers, etc.)
377
+ * IMPORTANT: If not using AuthProvider, you must call this method
378
+ * manually when the auth client is no longer needed.
379
+ */
380
+ function destroy() {
381
+ // Cleanup social auth (message event listener)
382
+ socialImpl.destroy();
383
+ // Cleanup email code auth (cleanup timer)
384
+ emailCodeImpl.destroy();
385
+ }
386
+ // ==========================================================================
387
+ // Return client
388
+ // ==========================================================================
389
+ return {
390
+ passkey,
391
+ emailCode,
392
+ social,
393
+ session,
394
+ consent,
395
+ deviceFlow,
396
+ ciba,
397
+ loginChallenge,
398
+ signIn: {
399
+ passkey: (options) => passkey.login(options),
400
+ social: (provider, options) => social.loginWithPopup(provider, options),
401
+ },
402
+ signUp: {
403
+ passkey: (options) => passkey.signUp(options),
404
+ },
405
+ signOut,
406
+ on,
407
+ stores,
408
+ _syncFromSSR,
409
+ destroy,
410
+ };
411
+ }
@@ -0,0 +1,56 @@
1
+ <!--
2
+ AuthProvider Component
3
+
4
+ Responsibilities (strictly limited):
5
+ - Wire auth instance into Svelte context
6
+ - Sync initial session from SSR (synchronously to avoid hydration mismatch)
7
+
8
+ It must NOT implement business logic.
9
+ -->
10
+ <script lang="ts">
11
+ import { onMount, onDestroy } from 'svelte';
12
+ import { setAuthContext } from '../utils/context.js';
13
+ import type { AuthrimClient } from '../types.js';
14
+ import type { Session, User } from '@authrim/core';
15
+
16
+ /** Authrim client instance */
17
+ export let auth: AuthrimClient;
18
+
19
+ /** Initial session from SSR (optional) */
20
+ export let initialSession: Session | null = null;
21
+
22
+ /** Initial user from SSR (optional) */
23
+ export let initialUser: User | null = null;
24
+
25
+ // Set auth context for child components
26
+ setAuthContext(auth);
27
+
28
+ // Sync initial session from SSR synchronously to avoid hydration mismatch
29
+ // This must happen before the first render
30
+ if (initialSession && initialUser) {
31
+ auth._syncFromSSR(initialSession, initialUser);
32
+ }
33
+
34
+ // Optionally validate session in the background after hydration
35
+ onMount(() => {
36
+ if (initialSession && initialUser) {
37
+ // Session already synced above, optionally revalidate in background
38
+ // This ensures the session is still valid on the server
39
+ auth.session.get().catch((error) => {
40
+ console.warn('[Authrim] Failed to revalidate session:', error);
41
+ });
42
+ } else if (!initialSession && !initialUser) {
43
+ // No SSR session provided, check if there's a session in storage
44
+ auth.session.get().catch((error) => {
45
+ console.warn('[Authrim] Failed to fetch session:', error);
46
+ });
47
+ }
48
+ });
49
+
50
+ // Cleanup on destroy
51
+ onDestroy(() => {
52
+ auth.destroy();
53
+ });
54
+ </script>
55
+
56
+ <slot />
@@ -0,0 +1,34 @@
1
+ import type { AuthrimClient } from '../types.js';
2
+ import type { Session, User } from '@authrim/core';
3
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
4
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
5
+ $$bindings?: Bindings;
6
+ } & Exports;
7
+ (internal: unknown, props: Props & {
8
+ $$events?: Events;
9
+ $$slots?: Slots;
10
+ }): Exports & {
11
+ $set?: any;
12
+ $on?: any;
13
+ };
14
+ z_$$bindings?: Bindings;
15
+ }
16
+ type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
17
+ default: any;
18
+ } ? Props extends Record<string, never> ? any : {
19
+ children?: any;
20
+ } : {});
21
+ declare const AuthProvider: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
22
+ /** Authrim client instance */ auth: AuthrimClient;
23
+ /** Initial session from SSR (optional) */ initialSession?: Session | null;
24
+ /** Initial user from SSR (optional) */ initialUser?: User | null;
25
+ }, {
26
+ default: {};
27
+ }>, {
28
+ [evt: string]: CustomEvent<any>;
29
+ }, {
30
+ default: {};
31
+ }, {}, string>;
32
+ type AuthProvider = InstanceType<typeof AuthProvider>;
33
+ export default AuthProvider;
34
+ //# sourceMappingURL=AuthProvider.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AuthProvider.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAwDnD,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AACD,KAAK,gCAAgC,CAAC,KAAK,EAAE,KAAK,IAAI,KAAK,GACvD,CAAC,KAAK,SAAS;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,GACzB,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACnC,GAAG,GACH;IAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;CAAE,GAClB,EAAE,CAAC,CAAC;AAId,QAAA,MAAM,YAAY;IAjBlB,8BAA8B,OAAM,aAAa;IACjD,0CAA0C,kBAAiB,OAAO,GAAG,IAAI;IACzE,uCAAuC,eAAc,IAAI,GAAG,IAAI;;;;;;;cAeuC,CAAC;AACtF,KAAK,YAAY,GAAG,YAAY,CAAC,OAAO,YAAY,CAAC,CAAC;AACxD,eAAe,YAAY,CAAC"}
@@ -0,0 +1,71 @@
1
+ <!--
2
+ ProtectedRoute Component
3
+
4
+ Shows content only when user is authenticated.
5
+ Redirects or shows fallback when not authenticated.
6
+ -->
7
+ <script lang="ts">
8
+ import { onMount, tick } from 'svelte';
9
+ import { goto } from '$app/navigation';
10
+ import { getAuthContext } from '../utils/context.js';
11
+
12
+ /** Redirect URL for unauthenticated users (if not provided, shows fallback) */
13
+ export let redirectTo: string | undefined = undefined;
14
+
15
+ /** Include current path in redirect URL */
16
+ export let includeReturnPath: boolean = true;
17
+
18
+ /** Return path parameter name */
19
+ export let returnPathParam: string = 'redirectTo';
20
+
21
+ /** Custom class */
22
+ let className: string = '';
23
+ export { className as class };
24
+
25
+ const auth = getAuthContext();
26
+ const { isAuthenticated, loadingState } = auth.stores;
27
+
28
+ // State machine: 'loading' -> 'ready'
29
+ // Prevents race condition where redirect happens before session check completes
30
+ let state: 'loading' | 'ready' = 'loading';
31
+
32
+ onMount(async () => {
33
+ try {
34
+ // Check session on mount
35
+ await auth.session.get();
36
+ } catch (error) {
37
+ console.warn('[Authrim] Failed to check session:', error);
38
+ } finally {
39
+ // Wait for stores to update before changing state
40
+ await tick();
41
+ state = 'ready';
42
+ }
43
+ });
44
+
45
+ // Only perform redirect when:
46
+ // 1. Component has finished initialization (state === 'ready')
47
+ // 2. User is not authenticated
48
+ // 3. No async operation is in progress (loadingState === 'idle')
49
+ // 4. A redirect URL is configured
50
+ $: if (state === 'ready' && !$isAuthenticated && $loadingState === 'idle' && redirectTo) {
51
+ const url = new URL(redirectTo, window.location.origin);
52
+ if (includeReturnPath) {
53
+ url.searchParams.set(returnPathParam, window.location.pathname + window.location.search);
54
+ }
55
+ goto(url.toString());
56
+ }
57
+ </script>
58
+
59
+ {#if state === 'loading' || $loadingState === 'initializing'}
60
+ <slot name="loading">
61
+ <div class={className} {...$$restProps}>Loading...</div>
62
+ </slot>
63
+ {:else if $isAuthenticated}
64
+ <slot />
65
+ {:else if !redirectTo}
66
+ <slot name="unauthenticated">
67
+ <div class={className} {...$$restProps}>
68
+ <p>You must be signed in to view this content.</p>
69
+ </div>
70
+ </slot>
71
+ {/if}
@@ -0,0 +1,38 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: Props & {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
15
+ default: any;
16
+ } ? Props extends Record<string, never> ? any : {
17
+ children?: any;
18
+ } : {});
19
+ declare const ProtectedRoute: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
20
+ [x: string]: any;
21
+ redirectTo?: string | undefined | undefined;
22
+ includeReturnPath?: boolean | undefined;
23
+ returnPathParam?: string | undefined;
24
+ class?: string | undefined;
25
+ }, {
26
+ loading: {};
27
+ default: {};
28
+ unauthenticated: {};
29
+ }>, {
30
+ [evt: string]: CustomEvent<any>;
31
+ }, {
32
+ loading: {};
33
+ default: {};
34
+ unauthenticated: {};
35
+ }, {}, string>;
36
+ type ProtectedRoute = InstanceType<typeof ProtectedRoute>;
37
+ export default ProtectedRoute;
38
+ //# sourceMappingURL=ProtectedRoute.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProtectedRoute.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/ProtectedRoute.svelte.ts"],"names":[],"mappings":"AAgFA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AACD,KAAK,gCAAgC,CAAC,KAAK,EAAE,KAAK,IAAI,KAAK,GACvD,CAAC,KAAK,SAAS;IAAE,OAAO,EAAE,GAAG,CAAA;CAAE,GACzB,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GACnC,GAAG,GACH;IAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;CAAE,GAClB,EAAE,CAAC,CAAC;AAId,QAAA,MAAM,cAAc;;iBAlBwE,MAAM,GAAG,SAAS;wBAC/C,OAAO;sBACnB,MAAM;YAC9B,MAAM;;;;;;;;;;;cAe+F,CAAC;AAC/G,KAAK,cAAc,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC;AAC5D,eAAe,cAAc,CAAC"}