@timeback/sdk 0.1.6 → 0.1.8

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 (186) hide show
  1. package/README.md +91 -2
  2. package/dist/chunk-07j8zre9.js +2 -0
  3. package/dist/chunk-3886xy48.js +8 -0
  4. package/dist/chunk-9se82640.js +1 -0
  5. package/dist/chunk-ahy54f2r.js +2 -0
  6. package/dist/chunk-ewsp6v3b.js +16 -0
  7. package/dist/chunk-j1xdrfqj.js +2 -0
  8. package/dist/chunk-qaa129bd.js +2 -0
  9. package/dist/chunk-qr0bbnsr.js +1 -0
  10. package/dist/chunk-rgbpvxbv.js +1 -0
  11. package/dist/chunk-whc53e0y.js +11 -0
  12. package/dist/client/adapters/react/hooks/types.d.ts +61 -0
  13. package/dist/client/adapters/react/hooks/types.d.ts.map +1 -0
  14. package/dist/client/adapters/react/hooks/useTimebackProfile.d.ts +42 -0
  15. package/dist/client/adapters/react/hooks/useTimebackProfile.d.ts.map +1 -0
  16. package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts +18 -0
  17. package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts.map +1 -0
  18. package/dist/client/adapters/react/index.d.ts +3 -0
  19. package/dist/client/adapters/react/index.d.ts.map +1 -1
  20. package/dist/client/adapters/react/index.js +2 -364
  21. package/dist/client/adapters/solid/index.d.ts +3 -0
  22. package/dist/client/adapters/solid/index.d.ts.map +1 -1
  23. package/dist/client/adapters/solid/index.ts +12 -0
  24. package/dist/client/adapters/solid/primitives/createTimebackProfile.d.ts +58 -0
  25. package/dist/client/adapters/solid/primitives/createTimebackProfile.d.ts.map +1 -0
  26. package/dist/client/adapters/solid/primitives/createTimebackProfile.ts +209 -0
  27. package/dist/client/adapters/solid/primitives/createTimebackVerification.d.ts +36 -0
  28. package/dist/client/adapters/solid/primitives/createTimebackVerification.d.ts.map +1 -0
  29. package/dist/client/adapters/solid/primitives/createTimebackVerification.ts +133 -0
  30. package/dist/client/adapters/solid/types.d.ts +86 -0
  31. package/dist/client/adapters/solid/types.d.ts.map +1 -0
  32. package/dist/client/adapters/solid/types.ts +85 -0
  33. package/dist/client/adapters/svelte/index.d.ts +2 -1
  34. package/dist/client/adapters/svelte/index.d.ts.map +1 -1
  35. package/dist/client/adapters/svelte/index.ts +11 -2
  36. package/dist/client/adapters/svelte/{stores.d.ts → stores/client.d.ts} +11 -9
  37. package/dist/client/adapters/svelte/stores/client.d.ts.map +1 -0
  38. package/dist/client/adapters/svelte/{stores.ts → stores/client.ts} +24 -52
  39. package/dist/client/adapters/svelte/stores/index.d.ts +10 -0
  40. package/dist/client/adapters/svelte/stores/index.d.ts.map +1 -0
  41. package/dist/client/adapters/svelte/stores/index.ts +22 -0
  42. package/dist/client/adapters/svelte/stores/profile.d.ts +66 -0
  43. package/dist/client/adapters/svelte/stores/profile.d.ts.map +1 -0
  44. package/dist/client/adapters/svelte/stores/profile.ts +168 -0
  45. package/dist/client/adapters/svelte/stores/verification.d.ts +43 -0
  46. package/dist/client/adapters/svelte/stores/verification.d.ts.map +1 -0
  47. package/dist/client/adapters/svelte/stores/verification.ts +126 -0
  48. package/dist/client/adapters/svelte/types.d.ts +35 -0
  49. package/dist/client/adapters/svelte/types.d.ts.map +1 -0
  50. package/dist/client/adapters/vue/composables/useTimebackProfile.d.ts +51 -0
  51. package/dist/client/adapters/vue/composables/useTimebackProfile.d.ts.map +1 -0
  52. package/dist/client/adapters/vue/composables/useTimebackProfile.ts +186 -0
  53. package/dist/client/adapters/vue/composables/useTimebackVerification.d.ts +44 -0
  54. package/dist/client/adapters/vue/composables/useTimebackVerification.d.ts.map +1 -0
  55. package/dist/client/adapters/vue/composables/useTimebackVerification.ts +128 -0
  56. package/dist/client/adapters/vue/index.d.ts +3 -0
  57. package/dist/client/adapters/vue/index.d.ts.map +1 -1
  58. package/dist/client/adapters/vue/index.ts +12 -1
  59. package/dist/client/adapters/vue/types.d.ts +86 -0
  60. package/dist/client/adapters/vue/types.d.ts.map +1 -0
  61. package/dist/client/adapters/vue/types.ts +85 -0
  62. package/dist/client/auth/bearer.d.ts +17 -0
  63. package/dist/client/auth/bearer.d.ts.map +1 -0
  64. package/dist/client/auth/index.d.ts +3 -0
  65. package/dist/client/auth/index.d.ts.map +1 -0
  66. package/dist/client/auth/types.d.ts +39 -0
  67. package/dist/client/auth/types.d.ts.map +1 -0
  68. package/dist/client/index.d.ts +2 -0
  69. package/dist/client/index.d.ts.map +1 -1
  70. package/dist/client/lib/activity/activity.class.d.ts +5 -5
  71. package/dist/client/lib/activity/activity.class.d.ts.map +1 -1
  72. package/dist/client/lib/fetch.d.ts +19 -0
  73. package/dist/client/lib/fetch.d.ts.map +1 -0
  74. package/dist/client/lib/user-cache.d.ts +39 -0
  75. package/dist/client/lib/user-cache.d.ts.map +1 -0
  76. package/dist/client/lib/user-cache.ts +168 -0
  77. package/dist/client/namespaces/activity.d.ts +2 -3
  78. package/dist/client/namespaces/activity.d.ts.map +1 -1
  79. package/dist/client/namespaces/user.d.ts +25 -2
  80. package/dist/client/namespaces/user.d.ts.map +1 -1
  81. package/dist/client/timeback-client.class.d.ts +15 -0
  82. package/dist/client/timeback-client.class.d.ts.map +1 -1
  83. package/dist/client/timeback-client.d.ts +3 -0
  84. package/dist/client/timeback-client.d.ts.map +1 -1
  85. package/dist/client.d.ts +3 -2
  86. package/dist/client.d.ts.map +1 -1
  87. package/dist/client.js +1 -194
  88. package/dist/edge.js +1 -1149
  89. package/dist/identity.js +1 -1019
  90. package/dist/index.js +22 -104603
  91. package/dist/server/adapters/express.d.ts.map +1 -1
  92. package/dist/server/adapters/express.js +1 -85997
  93. package/dist/server/adapters/native.d.ts.map +1 -1
  94. package/dist/server/adapters/native.js +2 -190
  95. package/dist/server/adapters/nextjs.js +1 -202
  96. package/dist/server/adapters/nuxt.d.ts.map +1 -1
  97. package/dist/server/adapters/nuxt.js +1 -86066
  98. package/dist/server/adapters/solid-start.d.ts.map +1 -1
  99. package/dist/server/adapters/solid-start.js +1 -85965
  100. package/dist/server/adapters/svelte-kit.d.ts.map +1 -1
  101. package/dist/server/adapters/svelte-kit.js +1 -243
  102. package/dist/server/adapters/tanstack-start.d.ts.map +1 -1
  103. package/dist/server/adapters/tanstack-start.js +1 -85943
  104. package/dist/server/adapters/utils.d.ts +1 -1
  105. package/dist/server/adapters/utils.d.ts.map +1 -1
  106. package/dist/server/handlers/activity/attempts.d.ts +51 -0
  107. package/dist/server/handlers/activity/attempts.d.ts.map +1 -0
  108. package/dist/server/handlers/activity/caliper.d.ts +133 -0
  109. package/dist/server/handlers/activity/caliper.d.ts.map +1 -0
  110. package/dist/server/handlers/activity/completion.d.ts +43 -0
  111. package/dist/server/handlers/activity/completion.d.ts.map +1 -0
  112. package/dist/server/handlers/activity/handler.d.ts +32 -0
  113. package/dist/server/handlers/activity/handler.d.ts.map +1 -0
  114. package/dist/server/handlers/activity/index.d.ts +9 -0
  115. package/dist/server/handlers/activity/index.d.ts.map +1 -0
  116. package/dist/server/handlers/activity/progress.d.ts +47 -0
  117. package/dist/server/handlers/activity/progress.d.ts.map +1 -0
  118. package/dist/server/handlers/activity/resolve.d.ts +39 -0
  119. package/dist/server/handlers/activity/resolve.d.ts.map +1 -0
  120. package/dist/server/handlers/activity/schema.d.ts +51 -0
  121. package/dist/server/handlers/activity/schema.d.ts.map +1 -0
  122. package/dist/server/handlers/activity/types.d.ts +51 -0
  123. package/dist/server/handlers/activity/types.d.ts.map +1 -0
  124. package/dist/server/handlers/identity/handler.d.ts +14 -0
  125. package/dist/server/handlers/identity/handler.d.ts.map +1 -0
  126. package/dist/server/handlers/identity/index.d.ts +8 -0
  127. package/dist/server/handlers/identity/index.d.ts.map +1 -0
  128. package/dist/server/handlers/identity/oidc.d.ts +43 -0
  129. package/dist/server/handlers/identity/oidc.d.ts.map +1 -0
  130. package/dist/server/handlers/identity/types.d.ts +24 -0
  131. package/dist/server/handlers/identity/types.d.ts.map +1 -0
  132. package/dist/server/handlers/identity-only/handler.d.ts +15 -0
  133. package/dist/server/handlers/identity-only/handler.d.ts.map +1 -0
  134. package/dist/server/handlers/identity-only/index.d.ts +8 -0
  135. package/dist/server/handlers/identity-only/index.d.ts.map +1 -0
  136. package/dist/server/handlers/identity-only/oidc.d.ts +26 -0
  137. package/dist/server/handlers/identity-only/oidc.d.ts.map +1 -0
  138. package/dist/server/handlers/identity-only/types.d.ts +19 -0
  139. package/dist/server/handlers/identity-only/types.d.ts.map +1 -0
  140. package/dist/server/handlers/index.d.ts +5 -2
  141. package/dist/server/handlers/index.d.ts.map +1 -1
  142. package/dist/server/{lib/build-user-profile.d.ts → handlers/user/enrollments.d.ts} +7 -2
  143. package/dist/server/handlers/user/enrollments.d.ts.map +1 -0
  144. package/dist/server/handlers/user/handler.d.ts +17 -0
  145. package/dist/server/handlers/user/handler.d.ts.map +1 -0
  146. package/dist/server/handlers/user/index.d.ts +10 -0
  147. package/dist/server/handlers/user/index.d.ts.map +1 -0
  148. package/dist/server/handlers/user/profile.d.ts +22 -0
  149. package/dist/server/handlers/user/profile.d.ts.map +1 -0
  150. package/dist/server/handlers/user/types.d.ts +35 -0
  151. package/dist/server/handlers/user/types.d.ts.map +1 -0
  152. package/dist/server/handlers/user/verify.d.ts +25 -0
  153. package/dist/server/handlers/user/verify.d.ts.map +1 -0
  154. package/dist/server/index.d.ts +1 -1
  155. package/dist/server/index.d.ts.map +1 -1
  156. package/dist/server/lib/index.d.ts +4 -5
  157. package/dist/server/lib/index.d.ts.map +1 -1
  158. package/dist/server/lib/resolve.d.ts +4 -42
  159. package/dist/server/lib/resolve.d.ts.map +1 -1
  160. package/dist/server/lib/sso.d.ts +86 -0
  161. package/dist/server/lib/sso.d.ts.map +1 -0
  162. package/dist/server/lib/utils.d.ts +93 -1
  163. package/dist/server/lib/utils.d.ts.map +1 -1
  164. package/dist/server/timeback-identity.d.ts.map +1 -1
  165. package/dist/server/timeback.d.ts.map +1 -1
  166. package/dist/server/types.d.ts +23 -10
  167. package/dist/server/types.d.ts.map +1 -1
  168. package/dist/shared/constants.d.ts +7 -0
  169. package/dist/shared/constants.d.ts.map +1 -1
  170. package/dist/shared/types.d.ts +77 -8
  171. package/dist/shared/types.d.ts.map +1 -1
  172. package/dist/shared/xp-calculator.d.ts +25 -0
  173. package/dist/shared/xp-calculator.d.ts.map +1 -0
  174. package/package.json +8 -2
  175. package/dist/client/adapters/svelte/stores.d.ts.map +0 -1
  176. package/dist/server/handlers/activity.d.ts +0 -25
  177. package/dist/server/handlers/activity.d.ts.map +0 -1
  178. package/dist/server/handlers/identity-full.d.ts +0 -28
  179. package/dist/server/handlers/identity-full.d.ts.map +0 -1
  180. package/dist/server/handlers/identity-only.d.ts +0 -22
  181. package/dist/server/handlers/identity-only.d.ts.map +0 -1
  182. package/dist/server/handlers/user.d.ts +0 -31
  183. package/dist/server/handlers/user.d.ts.map +0 -1
  184. package/dist/server/lib/build-activity-events.d.ts +0 -67
  185. package/dist/server/lib/build-activity-events.d.ts.map +0 -1
  186. package/dist/server/lib/build-user-profile.d.ts.map +0 -1
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Timeback Profile Store
3
+ *
4
+ * Svelte store for user profile state.
5
+ */
6
+
7
+ import { fetchProfileOnce, getProfileCache } from '../../../lib/user-cache'
8
+ import { getClientInstance } from './client'
9
+ import { writable } from 'svelte/store'
10
+ import { verificationStore } from './verification'
11
+
12
+ import type { TimebackProfileState, TimebackVerificationState } from '../types'
13
+ import type { Readable } from 'svelte/store'
14
+
15
+ const profileStore = writable<TimebackProfileState>({ status: 'idle' })
16
+ const canFetchStore = writable<boolean>(false)
17
+ let profileInitialized = false
18
+
19
+ /**
20
+ * Check if we're running in the browser.
21
+ *
22
+ * @returns True if in browser
23
+ */
24
+ function isBrowser(): boolean {
25
+ return typeof window !== 'undefined'
26
+ }
27
+
28
+ /**
29
+ * Run the profile fetch.
30
+ *
31
+ * @param force - If true, bypass cache and force a fresh fetch
32
+ */
33
+ async function runProfileFetch(force: boolean): Promise<void> {
34
+ const client = getClientInstance()
35
+ if (!client) return
36
+
37
+ if (!force) {
38
+ const cached = getProfileCache(client)
39
+ if (cached) {
40
+ profileStore.set({ status: 'loaded', profile: cached })
41
+ return
42
+ }
43
+ }
44
+
45
+ profileStore.set({ status: 'loading' })
46
+
47
+ try {
48
+ const profile = await fetchProfileOnce(client, force)
49
+ profileStore.set({ status: 'loaded', profile })
50
+ } catch (err) {
51
+ profileStore.set({
52
+ status: 'error',
53
+ message: err instanceof Error ? err.message : 'Failed to fetch profile',
54
+ })
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Update canFetch based on verification state.
60
+ *
61
+ * @param verification - Current verification state
62
+ */
63
+ function updateCanFetch(verification: TimebackVerificationState): void {
64
+ const can = verification.status === 'verified' && !!getClientInstance()
65
+ canFetchStore.set(can)
66
+ }
67
+
68
+ /**
69
+ * Initialize profile store subscriptions.
70
+ */
71
+ function initProfile(): void {
72
+ if (profileInitialized) return
73
+ profileInitialized = true
74
+
75
+ verificationStore.subscribe(verification => {
76
+ updateCanFetch(verification)
77
+
78
+ // Reset to idle if not verified
79
+ if (verification.status !== 'verified') {
80
+ profileStore.set({ status: 'idle' })
81
+ }
82
+ })
83
+ }
84
+
85
+ // Auto-init in browser
86
+ if (isBrowser()) {
87
+ initProfile()
88
+ }
89
+
90
+ /**
91
+ * Store containing the Timeback profile state.
92
+ *
93
+ * Use this to access the current user's Timeback profile.
94
+ * Call `fetchTimebackProfile()` to manually fetch, or `refreshTimebackProfile()` to force re-fetch.
95
+ *
96
+ * @example
97
+ * ```svelte
98
+ * <script>
99
+ * import { timebackProfile, timebackProfileCanFetch, fetchTimebackProfile } from '@timeback/sdk/svelte'
100
+ * </script>
101
+ *
102
+ * <button on:click={fetchTimebackProfile} disabled={!$timebackProfileCanFetch}>
103
+ * {$timebackProfile.status === 'loading' ? 'Loading...' : 'Fetch Profile'}
104
+ * </button>
105
+ *
106
+ * {#if $timebackProfile.status === 'loaded'}
107
+ * <pre>{JSON.stringify($timebackProfile.profile, null, 2)}</pre>
108
+ * {/if}
109
+ * ```
110
+ */
111
+ export const timebackProfile: Readable<TimebackProfileState> = profileStore
112
+
113
+ /**
114
+ * Store indicating whether the profile can be fetched.
115
+ *
116
+ * True when the user is verified and the client is ready.
117
+ */
118
+ export const timebackProfileCanFetch: Readable<boolean> = canFetchStore
119
+
120
+ /**
121
+ * Manually fetch the Timeback profile.
122
+ *
123
+ * No-op if the user is not verified or client is not ready.
124
+ *
125
+ * @example
126
+ * ```svelte
127
+ * <script>
128
+ * import { fetchTimebackProfile } from '@timeback/sdk/svelte'
129
+ * </script>
130
+ *
131
+ * <button on:click={fetchTimebackProfile}>Fetch Profile</button>
132
+ * ```
133
+ */
134
+ export function fetchTimebackProfile(): void {
135
+ if (!isBrowser()) return
136
+
137
+ let canFetch = false
138
+ canFetchStore.subscribe(v => (canFetch = v))()
139
+
140
+ if (!canFetch) return
141
+
142
+ void runProfileFetch(false)
143
+ }
144
+
145
+ /**
146
+ * Force a re-fetch of the Timeback profile.
147
+ *
148
+ * No-op if the user is not verified or client is not ready.
149
+ *
150
+ * @example
151
+ * ```svelte
152
+ * <script>
153
+ * import { refreshTimebackProfile } from '@timeback/sdk/svelte'
154
+ * </script>
155
+ *
156
+ * <button on:click={refreshTimebackProfile}>Refresh Profile</button>
157
+ * ```
158
+ */
159
+ export function refreshTimebackProfile(): void {
160
+ if (!isBrowser()) return
161
+
162
+ let canFetch = false
163
+ canFetchStore.subscribe(v => (canFetch = v))()
164
+
165
+ if (!canFetch) return
166
+
167
+ void runProfileFetch(true)
168
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Timeback Verification Store
3
+ *
4
+ * Svelte store for user verification state.
5
+ */
6
+ import type { TimebackVerificationState } from '../types';
7
+ import type { Readable } from 'svelte/store';
8
+ export declare const verificationStore: import("svelte/store").Writable<TimebackVerificationState>;
9
+ /**
10
+ * Store containing the Timeback verification state.
11
+ *
12
+ * Use this to check if the current user is verified in Timeback.
13
+ *
14
+ * @example
15
+ * ```svelte
16
+ * <script>
17
+ * import { timebackVerification, refreshTimebackVerification } from '@timeback/sdk/svelte'
18
+ * </script>
19
+ *
20
+ * {#if $timebackVerification.status === 'verified'}
21
+ * <p>Verified! Timeback ID: {$timebackVerification.timebackId}</p>
22
+ * {:else if $timebackVerification.status === 'loading'}
23
+ * <p>Verifying...</p>
24
+ * {:else}
25
+ * <p>Not verified</p>
26
+ * {/if}
27
+ * ```
28
+ */
29
+ export declare const timebackVerification: Readable<TimebackVerificationState>;
30
+ /**
31
+ * Force a re-verification of the current user.
32
+ *
33
+ * @example
34
+ * ```svelte
35
+ * <script>
36
+ * import { refreshTimebackVerification } from '@timeback/sdk/svelte'
37
+ * </script>
38
+ *
39
+ * <button on:click={refreshTimebackVerification}>Refresh Verification</button>
40
+ * ```
41
+ */
42
+ export declare function refreshTimebackVerification(): void;
43
+ //# sourceMappingURL=verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../../../../../src/client/adapters/svelte/stores/verification.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAc5C,eAAO,MAAM,iBAAiB,4DAA6D,CAAA;AA8D3F;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,yBAAyB,CAAqB,CAAA;AAE1F;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Timeback Verification Store
3
+ *
4
+ * Svelte store for user verification state.
5
+ */
6
+
7
+ import { getVerifyCache, verifyOnce } from '../../../lib/user-cache'
8
+ import { clientStore, getClientInstance } from './client'
9
+ import { writable } from 'svelte/store'
10
+
11
+ import type { TimebackVerifyResult } from '../../../../shared/types'
12
+ import type { TimebackVerificationState } from '../types'
13
+ import type { Readable } from 'svelte/store'
14
+
15
+ /**
16
+ * Convert a verify result into a store-friendly state machine.
17
+ *
18
+ * @param result - Raw verify result from the SDK client
19
+ * @returns Mapped verification state
20
+ */
21
+ function toVerificationState(result: TimebackVerifyResult): TimebackVerificationState {
22
+ return result.verified
23
+ ? { status: 'verified', timebackId: result.timebackId }
24
+ : { status: 'unverified' }
25
+ }
26
+
27
+ export const verificationStore = writable<TimebackVerificationState>({ status: 'loading' })
28
+ let verificationInitialized = false
29
+
30
+ /**
31
+ * Check if we're running in the browser.
32
+ *
33
+ * @returns True if in browser
34
+ */
35
+ function isBrowser(): boolean {
36
+ return typeof window !== 'undefined'
37
+ }
38
+
39
+ /**
40
+ * Run the verification check.
41
+ *
42
+ * @param force - If true, bypass cache and force a fresh verification
43
+ */
44
+ async function runVerification(force: boolean): Promise<void> {
45
+ const client = getClientInstance()
46
+ if (!client) return
47
+
48
+ if (!force) {
49
+ const cached = getVerifyCache(client)
50
+ if (cached) {
51
+ verificationStore.set(toVerificationState(cached))
52
+ return
53
+ }
54
+ }
55
+
56
+ verificationStore.set({ status: 'loading' })
57
+
58
+ try {
59
+ const result = await verifyOnce(client, force)
60
+ verificationStore.set(toVerificationState(result))
61
+ } catch (err) {
62
+ verificationStore.set({
63
+ status: 'error',
64
+ message: err instanceof Error ? err.message : 'Failed to verify Timeback user',
65
+ })
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Initialize verification when client becomes available.
71
+ */
72
+ function initVerification(): void {
73
+ if (verificationInitialized) return
74
+ verificationInitialized = true
75
+
76
+ // Subscribe to client changes to auto-verify
77
+ clientStore.subscribe(client => {
78
+ if (client && isBrowser()) {
79
+ void runVerification(false)
80
+ }
81
+ })
82
+ }
83
+
84
+ // Auto-init in browser
85
+ if (isBrowser()) {
86
+ initVerification()
87
+ }
88
+
89
+ /**
90
+ * Store containing the Timeback verification state.
91
+ *
92
+ * Use this to check if the current user is verified in Timeback.
93
+ *
94
+ * @example
95
+ * ```svelte
96
+ * <script>
97
+ * import { timebackVerification, refreshTimebackVerification } from '@timeback/sdk/svelte'
98
+ * </script>
99
+ *
100
+ * {#if $timebackVerification.status === 'verified'}
101
+ * <p>Verified! Timeback ID: {$timebackVerification.timebackId}</p>
102
+ * {:else if $timebackVerification.status === 'loading'}
103
+ * <p>Verifying...</p>
104
+ * {:else}
105
+ * <p>Not verified</p>
106
+ * {/if}
107
+ * ```
108
+ */
109
+ export const timebackVerification: Readable<TimebackVerificationState> = verificationStore
110
+
111
+ /**
112
+ * Force a re-verification of the current user.
113
+ *
114
+ * @example
115
+ * ```svelte
116
+ * <script>
117
+ * import { refreshTimebackVerification } from '@timeback/sdk/svelte'
118
+ * </script>
119
+ *
120
+ * <button on:click={refreshTimebackVerification}>Refresh Verification</button>
121
+ * ```
122
+ */
123
+ export function refreshTimebackVerification(): void {
124
+ if (!isBrowser()) return
125
+ void runVerification(true)
126
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Svelte Types
3
+ *
4
+ * Types for Svelte-specific stores.
5
+ */
6
+ import type { TimebackProfile } from '../../../shared/types';
7
+ /**
8
+ * Verification state for the current user.
9
+ */
10
+ export type TimebackVerificationState = {
11
+ status: 'loading';
12
+ } | {
13
+ status: 'verified';
14
+ timebackId: string;
15
+ } | {
16
+ status: 'unverified';
17
+ } | {
18
+ status: 'error';
19
+ message: string;
20
+ };
21
+ /**
22
+ * Profile state for the current user.
23
+ */
24
+ export type TimebackProfileState = {
25
+ status: 'idle';
26
+ } | {
27
+ status: 'loading';
28
+ } | {
29
+ status: 'loaded';
30
+ profile: TimebackProfile;
31
+ } | {
32
+ status: 'error';
33
+ message: string;
34
+ };
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/client/adapters/svelte/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAClC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,GACxB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvC;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC7B;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GAC9C;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * useTimebackProfile
3
+ *
4
+ * Vue composable for fetching the current user's Timeback profile.
5
+ *
6
+ * This composable uses `useTimebackVerification` internally and only fetches
7
+ * the profile when the user is verified (i.e., exists in Timeback).
8
+ */
9
+ import type { ComputedRef, Ref } from 'vue';
10
+ import type { TimebackProfileState, UseTimebackProfileOptions } from '../types';
11
+ /**
12
+ * Fetch the current user's Timeback profile.
13
+ *
14
+ * This composable internally uses `useTimebackVerification` to ensure the user
15
+ * is verified before fetching. When `auto: true`, it automatically fetches
16
+ * the profile once verified. Otherwise, call `fetchProfile()` manually.
17
+ *
18
+ * @param options - Composable options
19
+ * @param options.enabled - If false, the composable does nothing and stays in idle state. Defaults to true.
20
+ * @param options.auto - If true, automatically fetch once verified. Defaults to false.
21
+ * @returns Profile state and fetch methods
22
+ *
23
+ * @example
24
+ * ```vue
25
+ * <script setup>
26
+ * import { useTimebackProfile } from '@timeback/sdk/vue'
27
+ *
28
+ * // Manual fetch
29
+ * const { state, canFetch, fetchProfile } = useTimebackProfile()
30
+ *
31
+ * // Or auto-fetch
32
+ * // const { state } = useTimebackProfile({ auto: true })
33
+ * </script>
34
+ *
35
+ * <template>
36
+ * <div v-if="state.status === 'loaded'">
37
+ * XP: {{ state.profile.xp }}
38
+ * </div>
39
+ * <button v-else @click="fetchProfile" :disabled="!canFetch">
40
+ * {{ state.status === 'loading' ? 'Loading...' : 'Load Profile' }}
41
+ * </button>
42
+ * </template>
43
+ * ```
44
+ */
45
+ export declare function useTimebackProfile(options?: UseTimebackProfileOptions): {
46
+ state: Ref<TimebackProfileState>;
47
+ canFetch: ComputedRef<boolean>;
48
+ fetchProfile: () => void;
49
+ refresh: () => void;
50
+ };
51
+ //# sourceMappingURL=useTimebackProfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimebackProfile.d.ts","sourceRoot":"","sources":["../../../../../src/client/adapters/vue/composables/useTimebackProfile.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAA;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,yBAA8B,GAAG;IAC5E,KAAK,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAA;IAChC,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,CAAA;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,OAAO,EAAE,MAAM,IAAI,CAAA;CACnB,CAgIA"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * useTimebackProfile
3
+ *
4
+ * Vue composable for fetching the current user's Timeback profile.
5
+ *
6
+ * This composable uses `useTimebackVerification` internally and only fetches
7
+ * the profile when the user is verified (i.e., exists in Timeback).
8
+ */
9
+
10
+ import { computed, ref, watch } from 'vue'
11
+
12
+ import { fetchProfileOnce, getProfileCache } from '../../../lib/user-cache'
13
+ import { useTimeback } from '../provider'
14
+ import { useTimebackVerification } from './useTimebackVerification'
15
+
16
+ import type { ComputedRef, Ref } from 'vue'
17
+ import type { TimebackProfileState, UseTimebackProfileOptions } from '../types'
18
+
19
+ /**
20
+ * Fetch the current user's Timeback profile.
21
+ *
22
+ * This composable internally uses `useTimebackVerification` to ensure the user
23
+ * is verified before fetching. When `auto: true`, it automatically fetches
24
+ * the profile once verified. Otherwise, call `fetchProfile()` manually.
25
+ *
26
+ * @param options - Composable options
27
+ * @param options.enabled - If false, the composable does nothing and stays in idle state. Defaults to true.
28
+ * @param options.auto - If true, automatically fetch once verified. Defaults to false.
29
+ * @returns Profile state and fetch methods
30
+ *
31
+ * @example
32
+ * ```vue
33
+ * <script setup>
34
+ * import { useTimebackProfile } from '@timeback/sdk/vue'
35
+ *
36
+ * // Manual fetch
37
+ * const { state, canFetch, fetchProfile } = useTimebackProfile()
38
+ *
39
+ * // Or auto-fetch
40
+ * // const { state } = useTimebackProfile({ auto: true })
41
+ * </script>
42
+ *
43
+ * <template>
44
+ * <div v-if="state.status === 'loaded'">
45
+ * XP: {{ state.profile.xp }}
46
+ * </div>
47
+ * <button v-else @click="fetchProfile" :disabled="!canFetch">
48
+ * {{ state.status === 'loading' ? 'Loading...' : 'Load Profile' }}
49
+ * </button>
50
+ * </template>
51
+ * ```
52
+ */
53
+ export function useTimebackProfile(options: UseTimebackProfileOptions = {}): {
54
+ state: Ref<TimebackProfileState>
55
+ canFetch: ComputedRef<boolean>
56
+ fetchProfile: () => void
57
+ refresh: () => void
58
+ } {
59
+ const { enabled = true, auto = false } = options
60
+
61
+ const timebackRef = useTimeback()
62
+ const { state: verificationState } = useTimebackVerification({ enabled })
63
+
64
+ const state = ref<TimebackProfileState>({ status: 'idle' }) as Ref<TimebackProfileState>
65
+ const fetchNonce = ref(0)
66
+ const refreshNonce = ref(0)
67
+
68
+ let lastHandledFetchNonce = 0
69
+ let lastHandledRefreshNonce = 0
70
+ let autoTriggered = false
71
+
72
+ const canFetch = computed(
73
+ () => enabled && verificationState.value.status === 'verified' && !!timebackRef.value,
74
+ )
75
+
76
+ const fetchProfile = () => {
77
+ if (!canFetch.value) {
78
+ return
79
+ }
80
+
81
+ fetchNonce.value++
82
+ }
83
+
84
+ const refresh = () => {
85
+ if (!canFetch.value) {
86
+ return
87
+ }
88
+
89
+ refreshNonce.value++
90
+ }
91
+
92
+ watch(
93
+ [verificationState, fetchNonce, refreshNonce, () => timebackRef.value],
94
+ async ([verification, fetchN, refreshN, timeback], _prev, onCleanup) => {
95
+ if (!enabled) {
96
+ state.value = { status: 'idle' }
97
+
98
+ return
99
+ }
100
+
101
+ let cancelled = false
102
+
103
+ onCleanup(() => {
104
+ cancelled = true
105
+ })
106
+
107
+ if (verification.status !== 'verified') {
108
+ if (state.value.status !== 'idle') {
109
+ state.value = { status: 'idle' }
110
+ }
111
+
112
+ autoTriggered = false
113
+
114
+ return
115
+ }
116
+
117
+ if (auto && !autoTriggered && fetchN === 0 && refreshN === 0) {
118
+ autoTriggered = true
119
+ fetchNonce.value = 1
120
+ return
121
+ }
122
+
123
+ if (fetchN === 0 && refreshN === 0) {
124
+ return
125
+ }
126
+
127
+ const isNewFetch = fetchN > lastHandledFetchNonce
128
+ const isNewRefresh = refreshN > lastHandledRefreshNonce
129
+ const force = isNewRefresh
130
+
131
+ if (!isNewFetch && !isNewRefresh) {
132
+ if (timeback) {
133
+ const cached = getProfileCache(timeback)
134
+
135
+ if (cached) {
136
+ state.value = { status: 'loaded', profile: cached }
137
+
138
+ return
139
+ }
140
+ }
141
+
142
+ return
143
+ }
144
+
145
+ if (timeback && !force) {
146
+ const cached = getProfileCache(timeback)
147
+
148
+ if (cached) {
149
+ state.value = { status: 'loaded', profile: cached }
150
+ lastHandledFetchNonce = fetchN
151
+
152
+ return
153
+ }
154
+ }
155
+
156
+ state.value = { status: 'loading' }
157
+
158
+ try {
159
+ if (!timeback) {
160
+ return
161
+ }
162
+
163
+ lastHandledFetchNonce = fetchN
164
+ lastHandledRefreshNonce = refreshN
165
+
166
+ const profile = await fetchProfileOnce(timeback, force)
167
+
168
+ if (cancelled) {
169
+ return
170
+ }
171
+
172
+ state.value = { status: 'loaded', profile }
173
+ } catch (err) {
174
+ if (!cancelled) {
175
+ state.value = {
176
+ status: 'error',
177
+ message: err instanceof Error ? err.message : 'Failed to fetch profile',
178
+ }
179
+ }
180
+ }
181
+ },
182
+ { immediate: true },
183
+ )
184
+
185
+ return { state, canFetch, fetchProfile, refresh }
186
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * useTimebackVerification
3
+ *
4
+ * Vue composable for checking whether the current user can be verified in Timeback.
5
+ *
6
+ * This is a lightweight check (backed by `/api/timeback/user/verify`) and is
7
+ * intended for partner gating flows (e.g., "free for Timeback users").
8
+ */
9
+ import type { Ref } from 'vue';
10
+ import type { TimebackVerificationState, UseTimebackVerificationOptions } from '../types';
11
+ /**
12
+ * Verify the current user against Timeback.
13
+ *
14
+ * The composable runs automatically once the Timeback client is available, and
15
+ * provides a `refresh()` method to retry.
16
+ *
17
+ * @param options - Composable options
18
+ * @param options.enabled - If false, the composable does nothing and stays in loading state.
19
+ * @returns Verification state and a refresh method
20
+ *
21
+ * @example
22
+ * ```vue
23
+ * <script setup>
24
+ * import { useTimebackVerification } from '@timeback/sdk/vue'
25
+ *
26
+ * const { state, refresh } = useTimebackVerification()
27
+ * </script>
28
+ *
29
+ * <template>
30
+ * <div v-if="state.status === 'verified'">
31
+ * Verified as {{ state.timebackId }}
32
+ * </div>
33
+ * <div v-else-if="state.status === 'loading'">
34
+ * Verifying...
35
+ * </div>
36
+ * <button @click="refresh">Refresh</button>
37
+ * </template>
38
+ * ```
39
+ */
40
+ export declare function useTimebackVerification(options?: UseTimebackVerificationOptions): {
41
+ state: Ref<TimebackVerificationState>;
42
+ refresh: () => void;
43
+ };
44
+ //# sourceMappingURL=useTimebackVerification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTimebackVerification.d.ts","sourceRoot":"","sources":["../../../../../src/client/adapters/vue/composables/useTimebackVerification.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B,OAAO,KAAK,EAAE,yBAAyB,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAA;AAczF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,GAAE,8BAAmC,GAC1C;IACF,KAAK,EAAE,GAAG,CAAC,yBAAyB,CAAC,CAAA;IACrC,OAAO,EAAE,MAAM,IAAI,CAAA;CACnB,CA+DA"}