@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.
- package/README.md +91 -2
- package/dist/chunk-07j8zre9.js +2 -0
- package/dist/chunk-3886xy48.js +8 -0
- package/dist/chunk-9se82640.js +1 -0
- package/dist/chunk-ahy54f2r.js +2 -0
- package/dist/chunk-ewsp6v3b.js +16 -0
- package/dist/chunk-j1xdrfqj.js +2 -0
- package/dist/chunk-qaa129bd.js +2 -0
- package/dist/chunk-qr0bbnsr.js +1 -0
- package/dist/chunk-rgbpvxbv.js +1 -0
- package/dist/chunk-whc53e0y.js +11 -0
- package/dist/client/adapters/react/hooks/types.d.ts +61 -0
- package/dist/client/adapters/react/hooks/types.d.ts.map +1 -0
- package/dist/client/adapters/react/hooks/useTimebackProfile.d.ts +42 -0
- package/dist/client/adapters/react/hooks/useTimebackProfile.d.ts.map +1 -0
- package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts +18 -0
- package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts.map +1 -0
- package/dist/client/adapters/react/index.d.ts +3 -0
- package/dist/client/adapters/react/index.d.ts.map +1 -1
- package/dist/client/adapters/react/index.js +2 -364
- package/dist/client/adapters/solid/index.d.ts +3 -0
- package/dist/client/adapters/solid/index.d.ts.map +1 -1
- package/dist/client/adapters/solid/index.ts +12 -0
- package/dist/client/adapters/solid/primitives/createTimebackProfile.d.ts +58 -0
- package/dist/client/adapters/solid/primitives/createTimebackProfile.d.ts.map +1 -0
- package/dist/client/adapters/solid/primitives/createTimebackProfile.ts +209 -0
- package/dist/client/adapters/solid/primitives/createTimebackVerification.d.ts +36 -0
- package/dist/client/adapters/solid/primitives/createTimebackVerification.d.ts.map +1 -0
- package/dist/client/adapters/solid/primitives/createTimebackVerification.ts +133 -0
- package/dist/client/adapters/solid/types.d.ts +86 -0
- package/dist/client/adapters/solid/types.d.ts.map +1 -0
- package/dist/client/adapters/solid/types.ts +85 -0
- package/dist/client/adapters/svelte/index.d.ts +2 -1
- package/dist/client/adapters/svelte/index.d.ts.map +1 -1
- package/dist/client/adapters/svelte/index.ts +11 -2
- package/dist/client/adapters/svelte/{stores.d.ts → stores/client.d.ts} +11 -9
- package/dist/client/adapters/svelte/stores/client.d.ts.map +1 -0
- package/dist/client/adapters/svelte/{stores.ts → stores/client.ts} +24 -52
- package/dist/client/adapters/svelte/stores/index.d.ts +10 -0
- package/dist/client/adapters/svelte/stores/index.d.ts.map +1 -0
- package/dist/client/adapters/svelte/stores/index.ts +22 -0
- package/dist/client/adapters/svelte/stores/profile.d.ts +66 -0
- package/dist/client/adapters/svelte/stores/profile.d.ts.map +1 -0
- package/dist/client/adapters/svelte/stores/profile.ts +168 -0
- package/dist/client/adapters/svelte/stores/verification.d.ts +43 -0
- package/dist/client/adapters/svelte/stores/verification.d.ts.map +1 -0
- package/dist/client/adapters/svelte/stores/verification.ts +126 -0
- package/dist/client/adapters/svelte/types.d.ts +35 -0
- package/dist/client/adapters/svelte/types.d.ts.map +1 -0
- package/dist/client/adapters/vue/composables/useTimebackProfile.d.ts +51 -0
- package/dist/client/adapters/vue/composables/useTimebackProfile.d.ts.map +1 -0
- package/dist/client/adapters/vue/composables/useTimebackProfile.ts +186 -0
- package/dist/client/adapters/vue/composables/useTimebackVerification.d.ts +44 -0
- package/dist/client/adapters/vue/composables/useTimebackVerification.d.ts.map +1 -0
- package/dist/client/adapters/vue/composables/useTimebackVerification.ts +128 -0
- package/dist/client/adapters/vue/index.d.ts +3 -0
- package/dist/client/adapters/vue/index.d.ts.map +1 -1
- package/dist/client/adapters/vue/index.ts +12 -1
- package/dist/client/adapters/vue/types.d.ts +86 -0
- package/dist/client/adapters/vue/types.d.ts.map +1 -0
- package/dist/client/adapters/vue/types.ts +85 -0
- package/dist/client/auth/bearer.d.ts +17 -0
- package/dist/client/auth/bearer.d.ts.map +1 -0
- package/dist/client/auth/index.d.ts +3 -0
- package/dist/client/auth/index.d.ts.map +1 -0
- package/dist/client/auth/types.d.ts +39 -0
- package/dist/client/auth/types.d.ts.map +1 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/lib/activity/activity.class.d.ts +5 -5
- package/dist/client/lib/activity/activity.class.d.ts.map +1 -1
- package/dist/client/lib/fetch.d.ts +19 -0
- package/dist/client/lib/fetch.d.ts.map +1 -0
- package/dist/client/lib/user-cache.d.ts +39 -0
- package/dist/client/lib/user-cache.d.ts.map +1 -0
- package/dist/client/lib/user-cache.ts +168 -0
- package/dist/client/namespaces/activity.d.ts +2 -3
- package/dist/client/namespaces/activity.d.ts.map +1 -1
- package/dist/client/namespaces/user.d.ts +25 -2
- package/dist/client/namespaces/user.d.ts.map +1 -1
- package/dist/client/timeback-client.class.d.ts +15 -0
- package/dist/client/timeback-client.class.d.ts.map +1 -1
- package/dist/client/timeback-client.d.ts +3 -0
- package/dist/client/timeback-client.d.ts.map +1 -1
- package/dist/client.d.ts +3 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -194
- package/dist/edge.js +1 -1149
- package/dist/identity.js +1 -1019
- package/dist/index.js +22 -104603
- package/dist/server/adapters/express.d.ts.map +1 -1
- package/dist/server/adapters/express.js +1 -85997
- package/dist/server/adapters/native.d.ts.map +1 -1
- package/dist/server/adapters/native.js +2 -190
- package/dist/server/adapters/nextjs.js +1 -202
- package/dist/server/adapters/nuxt.d.ts.map +1 -1
- package/dist/server/adapters/nuxt.js +1 -86066
- package/dist/server/adapters/solid-start.d.ts.map +1 -1
- package/dist/server/adapters/solid-start.js +1 -85965
- package/dist/server/adapters/svelte-kit.d.ts.map +1 -1
- package/dist/server/adapters/svelte-kit.js +1 -243
- package/dist/server/adapters/tanstack-start.d.ts.map +1 -1
- package/dist/server/adapters/tanstack-start.js +1 -85943
- package/dist/server/adapters/utils.d.ts +1 -1
- package/dist/server/adapters/utils.d.ts.map +1 -1
- package/dist/server/handlers/activity/attempts.d.ts +51 -0
- package/dist/server/handlers/activity/attempts.d.ts.map +1 -0
- package/dist/server/handlers/activity/caliper.d.ts +133 -0
- package/dist/server/handlers/activity/caliper.d.ts.map +1 -0
- package/dist/server/handlers/activity/completion.d.ts +43 -0
- package/dist/server/handlers/activity/completion.d.ts.map +1 -0
- package/dist/server/handlers/activity/handler.d.ts +32 -0
- package/dist/server/handlers/activity/handler.d.ts.map +1 -0
- package/dist/server/handlers/activity/index.d.ts +9 -0
- package/dist/server/handlers/activity/index.d.ts.map +1 -0
- package/dist/server/handlers/activity/progress.d.ts +47 -0
- package/dist/server/handlers/activity/progress.d.ts.map +1 -0
- package/dist/server/handlers/activity/resolve.d.ts +39 -0
- package/dist/server/handlers/activity/resolve.d.ts.map +1 -0
- package/dist/server/handlers/activity/schema.d.ts +51 -0
- package/dist/server/handlers/activity/schema.d.ts.map +1 -0
- package/dist/server/handlers/activity/types.d.ts +51 -0
- package/dist/server/handlers/activity/types.d.ts.map +1 -0
- package/dist/server/handlers/identity/handler.d.ts +14 -0
- package/dist/server/handlers/identity/handler.d.ts.map +1 -0
- package/dist/server/handlers/identity/index.d.ts +8 -0
- package/dist/server/handlers/identity/index.d.ts.map +1 -0
- package/dist/server/handlers/identity/oidc.d.ts +43 -0
- package/dist/server/handlers/identity/oidc.d.ts.map +1 -0
- package/dist/server/handlers/identity/types.d.ts +24 -0
- package/dist/server/handlers/identity/types.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/handler.d.ts +15 -0
- package/dist/server/handlers/identity-only/handler.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/index.d.ts +8 -0
- package/dist/server/handlers/identity-only/index.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/oidc.d.ts +26 -0
- package/dist/server/handlers/identity-only/oidc.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/types.d.ts +19 -0
- package/dist/server/handlers/identity-only/types.d.ts.map +1 -0
- package/dist/server/handlers/index.d.ts +5 -2
- package/dist/server/handlers/index.d.ts.map +1 -1
- package/dist/server/{lib/build-user-profile.d.ts → handlers/user/enrollments.d.ts} +7 -2
- package/dist/server/handlers/user/enrollments.d.ts.map +1 -0
- package/dist/server/handlers/user/handler.d.ts +17 -0
- package/dist/server/handlers/user/handler.d.ts.map +1 -0
- package/dist/server/handlers/user/index.d.ts +10 -0
- package/dist/server/handlers/user/index.d.ts.map +1 -0
- package/dist/server/handlers/user/profile.d.ts +22 -0
- package/dist/server/handlers/user/profile.d.ts.map +1 -0
- package/dist/server/handlers/user/types.d.ts +35 -0
- package/dist/server/handlers/user/types.d.ts.map +1 -0
- package/dist/server/handlers/user/verify.d.ts +25 -0
- package/dist/server/handlers/user/verify.d.ts.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/lib/index.d.ts +4 -5
- package/dist/server/lib/index.d.ts.map +1 -1
- package/dist/server/lib/resolve.d.ts +4 -42
- package/dist/server/lib/resolve.d.ts.map +1 -1
- package/dist/server/lib/sso.d.ts +86 -0
- package/dist/server/lib/sso.d.ts.map +1 -0
- package/dist/server/lib/utils.d.ts +93 -1
- package/dist/server/lib/utils.d.ts.map +1 -1
- package/dist/server/timeback-identity.d.ts.map +1 -1
- package/dist/server/timeback.d.ts.map +1 -1
- package/dist/server/types.d.ts +23 -10
- package/dist/server/types.d.ts.map +1 -1
- package/dist/shared/constants.d.ts +7 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/types.d.ts +77 -8
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/xp-calculator.d.ts +25 -0
- package/dist/shared/xp-calculator.d.ts.map +1 -0
- package/package.json +8 -2
- package/dist/client/adapters/svelte/stores.d.ts.map +0 -1
- package/dist/server/handlers/activity.d.ts +0 -25
- package/dist/server/handlers/activity.d.ts.map +0 -1
- package/dist/server/handlers/identity-full.d.ts +0 -28
- package/dist/server/handlers/identity-full.d.ts.map +0 -1
- package/dist/server/handlers/identity-only.d.ts +0 -22
- package/dist/server/handlers/identity-only.d.ts.map +0 -1
- package/dist/server/handlers/user.d.ts +0 -31
- package/dist/server/handlers/user.d.ts.map +0 -1
- package/dist/server/lib/build-activity-events.d.ts +0 -67
- package/dist/server/lib/build-activity-events.d.ts.map +0 -1
- package/dist/server/lib/build-user-profile.d.ts.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared User Cache
|
|
3
|
+
*
|
|
4
|
+
* Internal module for in-flight deduplication and short-lived caching of
|
|
5
|
+
* verify and profile requests. Used by Solid, Svelte, and Vue adapters.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { TimebackProfile, TimebackVerifyResult } from '../../shared/types'
|
|
9
|
+
import type { TimebackClient } from '../timeback-client.class'
|
|
10
|
+
|
|
11
|
+
const VERIFY_CACHE_TTL_MS = 1500
|
|
12
|
+
const PROFILE_CACHE_TTL_MS = 5000
|
|
13
|
+
|
|
14
|
+
type VerifyCacheEntry = { atMs: number; result: TimebackVerifyResult }
|
|
15
|
+
type ProfileCacheEntry = { atMs: number; profile: TimebackProfile }
|
|
16
|
+
|
|
17
|
+
const verifyInFlight = new WeakMap<TimebackClient, Promise<TimebackVerifyResult>>()
|
|
18
|
+
const verifyCache = new WeakMap<TimebackClient, VerifyCacheEntry>()
|
|
19
|
+
|
|
20
|
+
const profileInFlight = new WeakMap<TimebackClient, Promise<TimebackProfile>>()
|
|
21
|
+
const profileCache = new WeakMap<TimebackClient, ProfileCacheEntry>()
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check whether a cached verification result is still fresh.
|
|
25
|
+
*
|
|
26
|
+
* @param entry - Cached entry (if any)
|
|
27
|
+
* @returns True if the cache entry exists and is within TTL
|
|
28
|
+
*/
|
|
29
|
+
function isVerifyCacheFresh(entry: VerifyCacheEntry | undefined): entry is VerifyCacheEntry {
|
|
30
|
+
return !!entry && Date.now() - entry.atMs < VERIFY_CACHE_TTL_MS
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check whether a cached profile result is still fresh.
|
|
35
|
+
*
|
|
36
|
+
* @param entry - Cached entry (if any)
|
|
37
|
+
* @returns True if the cache entry exists and is within TTL
|
|
38
|
+
*/
|
|
39
|
+
function isProfileCacheFresh(entry: ProfileCacheEntry | undefined): entry is ProfileCacheEntry {
|
|
40
|
+
return !!entry && Date.now() - entry.atMs < PROFILE_CACHE_TTL_MS
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Verify the current user with in-flight dedupe and short-lived caching.
|
|
45
|
+
*
|
|
46
|
+
* @param timeback - Timeback client instance
|
|
47
|
+
* @param force - If true, bypass cache and in-flight reuse
|
|
48
|
+
* @returns Verify result
|
|
49
|
+
*/
|
|
50
|
+
export async function verifyOnce(
|
|
51
|
+
timeback: TimebackClient,
|
|
52
|
+
force: boolean,
|
|
53
|
+
): Promise<TimebackVerifyResult> {
|
|
54
|
+
if (!force) {
|
|
55
|
+
const cached = verifyCache.get(timeback)
|
|
56
|
+
|
|
57
|
+
if (isVerifyCacheFresh(cached)) {
|
|
58
|
+
return cached.result
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const existing = verifyInFlight.get(timeback)
|
|
62
|
+
|
|
63
|
+
if (existing) {
|
|
64
|
+
return await existing
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const p = timeback.user.verify().then(result => {
|
|
69
|
+
/**
|
|
70
|
+
* Guard against stale overwrites:
|
|
71
|
+
*
|
|
72
|
+
* If `force=true` triggers a newer request while an older one is still
|
|
73
|
+
* in-flight, the older promise may resolve later. Only let the most
|
|
74
|
+
* recent in-flight promise update the cache.
|
|
75
|
+
*/
|
|
76
|
+
if (verifyInFlight.get(timeback) === p) {
|
|
77
|
+
verifyCache.set(timeback, { atMs: Date.now(), result })
|
|
78
|
+
}
|
|
79
|
+
return result
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
verifyInFlight.set(timeback, p)
|
|
83
|
+
try {
|
|
84
|
+
return await p
|
|
85
|
+
} finally {
|
|
86
|
+
/**
|
|
87
|
+
* Only remove the in-flight verification promise
|
|
88
|
+
* if it is still the most recent for this client instance.
|
|
89
|
+
*/
|
|
90
|
+
if (verifyInFlight.get(timeback) === p) {
|
|
91
|
+
verifyInFlight.delete(timeback)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get cached verification result if fresh.
|
|
98
|
+
*
|
|
99
|
+
* @param timeback - Timeback client instance
|
|
100
|
+
* @returns Cached result or undefined
|
|
101
|
+
*/
|
|
102
|
+
export function getVerifyCache(timeback: TimebackClient): TimebackVerifyResult | undefined {
|
|
103
|
+
const cached = verifyCache.get(timeback)
|
|
104
|
+
return isVerifyCacheFresh(cached) ? cached.result : undefined
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Fetch the profile with in-flight dedupe and short-lived caching.
|
|
109
|
+
*
|
|
110
|
+
* @param timeback - Timeback client instance
|
|
111
|
+
* @param force - If true, bypass cache and in-flight reuse
|
|
112
|
+
* @returns The user's Timeback profile
|
|
113
|
+
*/
|
|
114
|
+
export async function fetchProfileOnce(
|
|
115
|
+
timeback: TimebackClient,
|
|
116
|
+
force: boolean,
|
|
117
|
+
): Promise<TimebackProfile> {
|
|
118
|
+
if (!force) {
|
|
119
|
+
const cached = profileCache.get(timeback)
|
|
120
|
+
|
|
121
|
+
if (isProfileCacheFresh(cached)) {
|
|
122
|
+
return cached.profile
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const existing = profileInFlight.get(timeback)
|
|
126
|
+
|
|
127
|
+
if (existing) {
|
|
128
|
+
return await existing
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const p = timeback.user.fetch().then(profile => {
|
|
133
|
+
/**
|
|
134
|
+
* Guard against stale overwrites:
|
|
135
|
+
*
|
|
136
|
+
* If `force=true` triggers a newer request while an older one is still
|
|
137
|
+
* in-flight, the older promise may resolve later. Only let the most
|
|
138
|
+
* recent in-flight promise update the cache.
|
|
139
|
+
*/
|
|
140
|
+
if (profileInFlight.get(timeback) === p) {
|
|
141
|
+
profileCache.set(timeback, { atMs: Date.now(), profile })
|
|
142
|
+
}
|
|
143
|
+
return profile
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
profileInFlight.set(timeback, p)
|
|
147
|
+
try {
|
|
148
|
+
return await p
|
|
149
|
+
} finally {
|
|
150
|
+
/**
|
|
151
|
+
* Only remove the in-flight promise if it is still the most recent
|
|
152
|
+
*/
|
|
153
|
+
if (profileInFlight.get(timeback) === p) {
|
|
154
|
+
profileInFlight.delete(timeback)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get cached profile result if fresh.
|
|
161
|
+
*
|
|
162
|
+
* @param timeback - Timeback client instance
|
|
163
|
+
* @returns Cached profile or undefined
|
|
164
|
+
*/
|
|
165
|
+
export function getProfileCache(timeback: TimebackClient): TimebackProfile | undefined {
|
|
166
|
+
const cached = profileCache.get(timeback)
|
|
167
|
+
return isProfileCacheFresh(cached) ? cached.profile : undefined
|
|
168
|
+
}
|
|
@@ -25,7 +25,7 @@ export declare class ActivityManager {
|
|
|
25
25
|
* @param params - Activity parameters
|
|
26
26
|
* @returns Started activity instance
|
|
27
27
|
*
|
|
28
|
-
* @example
|
|
28
|
+
* @example Basic usage
|
|
29
29
|
* ```typescript
|
|
30
30
|
* const activity = timeback.activity.start({
|
|
31
31
|
* id: 'lesson-1',
|
|
@@ -36,8 +36,7 @@ export declare class ActivityManager {
|
|
|
36
36
|
* await activity.end({
|
|
37
37
|
* totalQuestions: 10,
|
|
38
38
|
* correctQuestions: 8,
|
|
39
|
-
*
|
|
40
|
-
* pctCompleteApp: 67,
|
|
39
|
+
* pctComplete: 67,
|
|
41
40
|
* })
|
|
42
41
|
* ```
|
|
43
42
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/client/namespaces/activity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAE1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAE5E;;GAEG;AACH,qBAAa,eAAe;IAMf,OAAO,CAAC,QAAQ,CAAC,YAAY;IALzC;;;;OAIG;IACH,YAA6B,YAAY,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,EAAI;IAE7F
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../../src/client/namespaces/activity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAE1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAE5E;;GAEG;AACH,qBAAa,eAAe;IAMf,OAAO,CAAC,QAAQ,CAAC,YAAY;IALzC;;;;OAIG;IACH,YAA6B,YAAY,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,EAAI;IAE7F;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,QAAQ,CAEtC;CACD"}
|
|
@@ -3,18 +3,21 @@
|
|
|
3
3
|
*
|
|
4
4
|
* User identity and profile data.
|
|
5
5
|
*/
|
|
6
|
-
import type { TimebackProfile } from '../../shared/types';
|
|
6
|
+
import type { TimebackProfile, TimebackVerifyResult } from '../../shared/types';
|
|
7
|
+
import type { TimebackFetch } from '../auth/types';
|
|
7
8
|
/**
|
|
8
9
|
* User namespace for profile data.
|
|
9
10
|
*/
|
|
10
11
|
export declare class User {
|
|
11
12
|
private readonly getBaseURL;
|
|
13
|
+
private readonly fetchImpl;
|
|
12
14
|
/**
|
|
13
15
|
* Create user instance.
|
|
14
16
|
*
|
|
15
17
|
* @param getBaseURL - Function that returns the base URL for API routes
|
|
18
|
+
* @param fetchImpl - Fetch implementation to use for requests
|
|
16
19
|
*/
|
|
17
|
-
constructor(getBaseURL: () => string);
|
|
20
|
+
constructor(getBaseURL: () => string, fetchImpl: TimebackFetch);
|
|
18
21
|
/**
|
|
19
22
|
* Fetch the full user profile from the Timeback API.
|
|
20
23
|
*
|
|
@@ -25,5 +28,25 @@ export declare class User {
|
|
|
25
28
|
* @throws Error if not authenticated or API call fails
|
|
26
29
|
*/
|
|
27
30
|
fetch(): Promise<TimebackProfile>;
|
|
31
|
+
/**
|
|
32
|
+
* Verify if the current user exists in Timeback.
|
|
33
|
+
*
|
|
34
|
+
* Use this to check eligibility before enabling Timeback-gated features
|
|
35
|
+
* (e.g., free tier for Timeback users in a partner app).
|
|
36
|
+
*
|
|
37
|
+
* @returns Verification result with eligibility status and timebackId if eligible
|
|
38
|
+
* @throws Error if not authenticated or API call fails unexpectedly
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const result = await timeback.user.verify()
|
|
43
|
+
* if (result.verified) {
|
|
44
|
+
* console.log('Timeback user:', result.timebackId)
|
|
45
|
+
* } else {
|
|
46
|
+
* console.log('Not a Timeback user')
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
verify(): Promise<TimebackVerifyResult>;
|
|
28
51
|
}
|
|
29
52
|
//# sourceMappingURL=user.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../src/client/namespaces/user.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../../src/client/namespaces/user.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAElD;;GAEG;AACH,qBAAa,IAAI;IAQf,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAR3B;;;;;OAKG;IACH,YACkB,UAAU,EAAE,MAAM,MAAM,EACxB,SAAS,EAAE,aAAa,EACtC;IAEJ;;;;;;;;OAQG;IACG,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC,CAoBtC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACG,MAAM,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA0B5C;CACD"}
|
|
@@ -4,12 +4,26 @@
|
|
|
4
4
|
* Client-side SDK for activity tracking and identity.
|
|
5
5
|
*/
|
|
6
6
|
import { ActivityManager, Auth, User } from './namespaces';
|
|
7
|
+
import type { TimebackClientPlugin, TimebackFetch } from './auth/types';
|
|
7
8
|
/**
|
|
8
9
|
* Timeback client configuration.
|
|
9
10
|
*/
|
|
10
11
|
interface TimebackClientConfig {
|
|
11
12
|
/** Base URL for Timeback API routes. Defaults to window.location.origin + '/api/timeback' */
|
|
12
13
|
baseURL?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Fetch implementation used by the client.
|
|
16
|
+
*
|
|
17
|
+
* Defaults to the global `fetch` when available.
|
|
18
|
+
*/
|
|
19
|
+
fetch?: TimebackFetch;
|
|
20
|
+
/**
|
|
21
|
+
* Optional plugin(s) that can wrap the client fetch.
|
|
22
|
+
*
|
|
23
|
+
* Use this to attach Bearer tokens (Auth0 SPA PKCE) without monkey-patching
|
|
24
|
+
* global `window.fetch`.
|
|
25
|
+
*/
|
|
26
|
+
plugins?: TimebackClientPlugin | TimebackClientPlugin[];
|
|
13
27
|
}
|
|
14
28
|
/**
|
|
15
29
|
* Timeback client for activity tracking and identity.
|
|
@@ -19,6 +33,7 @@ export declare class TimebackClient {
|
|
|
19
33
|
readonly auth: Auth;
|
|
20
34
|
readonly user: User;
|
|
21
35
|
private _baseURL;
|
|
36
|
+
private readonly _fetch;
|
|
22
37
|
/**
|
|
23
38
|
* Create a new Timeback client.
|
|
24
39
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeback-client.class.d.ts","sourceRoot":"","sources":["../../src/client/timeback-client.class.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"timeback-client.class.d.ts","sourceRoot":"","sources":["../../src/client/timeback-client.class.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAG1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEvE;;GAEG;AACH,UAAU,oBAAoB;IAC7B,6FAA6F;IAC7F,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,EAAE,CAAA;CACvD;AAED;;GAEG;AACH,qBAAa,cAAc;IAC1B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;IAClC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IAEtC;;;;OAIG;IACH,YAAY,MAAM,GAAE,oBAAyB,EAmB5C;IAED;;;;OAIG;IACH,OAAO,KAAK,OAAO,GAYlB;YAOa,YAAY;CAiB1B"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Factory function for creating Timeback client instances.
|
|
5
5
|
*/
|
|
6
6
|
import { TimebackClient } from './timeback-client.class';
|
|
7
|
+
import type { TimebackClientPlugin, TimebackFetch } from './auth/types';
|
|
7
8
|
/**
|
|
8
9
|
* Create a Timeback client instance.
|
|
9
10
|
*
|
|
@@ -25,5 +26,7 @@ import { TimebackClient } from './timeback-client.class';
|
|
|
25
26
|
*/
|
|
26
27
|
export declare function createClient(config?: {
|
|
27
28
|
baseURL?: string;
|
|
29
|
+
fetch?: TimebackFetch;
|
|
30
|
+
plugins?: TimebackClientPlugin | TimebackClientPlugin[];
|
|
28
31
|
}): TimebackClient;
|
|
29
32
|
//# sourceMappingURL=timeback-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeback-client.d.ts","sourceRoot":"","sources":["../../src/client/timeback-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"timeback-client.d.ts","sourceRoot":"","sources":["../../src/client/timeback-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAC3B,MAAM,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,OAAO,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,EAAE,CAAA;CAClD,GACJ,cAAc,CAOhB"}
|
package/dist/client.d.ts
CHANGED
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
* activity.resume()
|
|
22
22
|
*
|
|
23
23
|
* // End tracking with metrics
|
|
24
|
-
* await activity.end({ totalQuestions: 10, correctQuestions: 8
|
|
24
|
+
* await activity.end({ totalQuestions: 10, correctQuestions: 8 })
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
export { createClient, TimebackClient } from './client/index';
|
|
28
28
|
export { Activity } from './client/index';
|
|
29
|
-
export
|
|
29
|
+
export { bearer } from './client/auth/bearer';
|
|
30
|
+
export type { TimebackIdentity, TimebackProfile, TimebackSessionUser, TimebackVerifyResult, ActivityParams, ActivityMetrics, } from './shared/types';
|
|
30
31
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAE7C,YAAY,EACX,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,eAAe,GACf,MAAM,gBAAgB,CAAA"}
|
package/dist/client.js
CHANGED
|
@@ -1,194 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var DEFAULT_BASE_PATH = "/api/timeback";
|
|
3
|
-
var ROUTES = {
|
|
4
|
-
ACTIVITY: "/activity",
|
|
5
|
-
IDENTITY: {
|
|
6
|
-
SIGNIN: "/identity/signin",
|
|
7
|
-
SIGNOUT: "/identity/signout",
|
|
8
|
-
CALLBACK: "/identity/callback"
|
|
9
|
-
},
|
|
10
|
-
USER: {
|
|
11
|
-
ME: "/user/me"
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// src/client/lib/utils.ts
|
|
16
|
-
function isBrowser() {
|
|
17
|
-
return typeof window !== "undefined";
|
|
18
|
-
}
|
|
19
|
-
function getDefaultBaseURL() {
|
|
20
|
-
if (!isBrowser()) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
return `${window.location.origin}${DEFAULT_BASE_PATH}`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// src/client/lib/activity/activity.class.ts
|
|
27
|
-
class Activity {
|
|
28
|
-
params;
|
|
29
|
-
sendActivity;
|
|
30
|
-
_startedAt;
|
|
31
|
-
_isPaused = false;
|
|
32
|
-
_pausedAt;
|
|
33
|
-
_totalPausedMs = 0;
|
|
34
|
-
_ended = false;
|
|
35
|
-
constructor(params, sendActivity) {
|
|
36
|
-
this.params = params;
|
|
37
|
-
this.sendActivity = sendActivity;
|
|
38
|
-
this._startedAt = new Date;
|
|
39
|
-
}
|
|
40
|
-
get startedAt() {
|
|
41
|
-
return this._startedAt;
|
|
42
|
-
}
|
|
43
|
-
get isPaused() {
|
|
44
|
-
return this._isPaused;
|
|
45
|
-
}
|
|
46
|
-
get elapsedMs() {
|
|
47
|
-
if (this._ended) {
|
|
48
|
-
return 0;
|
|
49
|
-
}
|
|
50
|
-
const now = new Date;
|
|
51
|
-
let elapsed = now.getTime() - this._startedAt.getTime() - this._totalPausedMs;
|
|
52
|
-
if (this._isPaused && this._pausedAt) {
|
|
53
|
-
elapsed -= now.getTime() - this._pausedAt.getTime();
|
|
54
|
-
}
|
|
55
|
-
return Math.max(0, elapsed);
|
|
56
|
-
}
|
|
57
|
-
_buildPayload(data) {
|
|
58
|
-
const now = new Date;
|
|
59
|
-
const pausedMs = this._totalPausedMs + (this._isPaused && this._pausedAt ? now.getTime() - this._pausedAt.getTime() : 0);
|
|
60
|
-
const elapsedMs = now.getTime() - this._startedAt.getTime() - pausedMs;
|
|
61
|
-
return {
|
|
62
|
-
id: this.params.id,
|
|
63
|
-
name: this.params.name,
|
|
64
|
-
course: this.params.course,
|
|
65
|
-
startedAt: this._startedAt.toISOString(),
|
|
66
|
-
endedAt: now.toISOString(),
|
|
67
|
-
elapsedMs: Math.max(0, elapsedMs),
|
|
68
|
-
pausedMs,
|
|
69
|
-
metrics: {
|
|
70
|
-
totalQuestions: data.totalQuestions,
|
|
71
|
-
correctQuestions: data.correctQuestions,
|
|
72
|
-
...data.xpEarned === undefined ? {} : { xpEarned: data.xpEarned },
|
|
73
|
-
...data.masteredUnits === undefined ? {} : { masteredUnits: data.masteredUnits }
|
|
74
|
-
},
|
|
75
|
-
...data.attemptNumber === undefined ? {} : { attemptNumber: data.attemptNumber },
|
|
76
|
-
...data.pctCompleteApp === undefined ? {} : { pctCompleteApp: data.pctCompleteApp }
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
pause() {
|
|
80
|
-
if (this._isPaused || this._ended)
|
|
81
|
-
return;
|
|
82
|
-
this._isPaused = true;
|
|
83
|
-
this._pausedAt = new Date;
|
|
84
|
-
}
|
|
85
|
-
resume() {
|
|
86
|
-
if (!this._isPaused || this._ended || !this._pausedAt)
|
|
87
|
-
return;
|
|
88
|
-
this._totalPausedMs += new Date().getTime() - this._pausedAt.getTime();
|
|
89
|
-
this._isPaused = false;
|
|
90
|
-
this._pausedAt = undefined;
|
|
91
|
-
}
|
|
92
|
-
async end(data) {
|
|
93
|
-
if (this._ended)
|
|
94
|
-
return;
|
|
95
|
-
this._ended = true;
|
|
96
|
-
if (this._isPaused && this._pausedAt) {
|
|
97
|
-
this._totalPausedMs += new Date().getTime() - this._pausedAt.getTime();
|
|
98
|
-
this._isPaused = false;
|
|
99
|
-
this._pausedAt = undefined;
|
|
100
|
-
}
|
|
101
|
-
const payload = this._buildPayload(data);
|
|
102
|
-
await this.sendActivity(payload);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// src/client/namespaces/activity.ts
|
|
106
|
-
class ActivityManager {
|
|
107
|
-
sendActivity;
|
|
108
|
-
constructor(sendActivity) {
|
|
109
|
-
this.sendActivity = sendActivity;
|
|
110
|
-
}
|
|
111
|
-
start(params) {
|
|
112
|
-
return new Activity(params, this.sendActivity);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// src/client/namespaces/auth.ts
|
|
116
|
-
class Auth {
|
|
117
|
-
getBaseURL;
|
|
118
|
-
constructor(getBaseURL) {
|
|
119
|
-
this.getBaseURL = getBaseURL;
|
|
120
|
-
}
|
|
121
|
-
signIn() {
|
|
122
|
-
if (!isBrowser()) {
|
|
123
|
-
throw new Error("signIn() requires a browser environment");
|
|
124
|
-
}
|
|
125
|
-
window.location.href = `${this.getBaseURL()}${ROUTES.IDENTITY.SIGNIN}`;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
// src/client/namespaces/user.ts
|
|
129
|
-
class User {
|
|
130
|
-
getBaseURL;
|
|
131
|
-
constructor(getBaseURL) {
|
|
132
|
-
this.getBaseURL = getBaseURL;
|
|
133
|
-
}
|
|
134
|
-
async fetch() {
|
|
135
|
-
if (!isBrowser()) {
|
|
136
|
-
throw new Error("user.fetch() requires a browser environment");
|
|
137
|
-
}
|
|
138
|
-
const response = await fetch(`${this.getBaseURL()}${ROUTES.USER.ME}`, {
|
|
139
|
-
method: "GET",
|
|
140
|
-
credentials: "include"
|
|
141
|
-
});
|
|
142
|
-
if (!response.ok) {
|
|
143
|
-
const errorResponse = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
144
|
-
throw new Error(errorResponse.error ?? "Failed to fetch user profile");
|
|
145
|
-
}
|
|
146
|
-
return response.json();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
// src/client/timeback-client.class.ts
|
|
150
|
-
class TimebackClient {
|
|
151
|
-
activity;
|
|
152
|
-
auth;
|
|
153
|
-
user;
|
|
154
|
-
_baseURL;
|
|
155
|
-
constructor(config = {}) {
|
|
156
|
-
this._baseURL = config.baseURL;
|
|
157
|
-
this.activity = new ActivityManager((payload) => this.sendActivity(payload));
|
|
158
|
-
this.auth = new Auth(() => this.baseURL);
|
|
159
|
-
this.user = new User(() => this.baseURL);
|
|
160
|
-
}
|
|
161
|
-
get baseURL() {
|
|
162
|
-
if (!this._baseURL) {
|
|
163
|
-
const resolved = getDefaultBaseURL();
|
|
164
|
-
if (!resolved) {
|
|
165
|
-
throw new Error("Timeback client requires a browser environment for default baseURL. " + "Provide an explicit baseURL for server-side usage.");
|
|
166
|
-
}
|
|
167
|
-
this._baseURL = resolved;
|
|
168
|
-
}
|
|
169
|
-
return this._baseURL;
|
|
170
|
-
}
|
|
171
|
-
async sendActivity(payload) {
|
|
172
|
-
const response = await fetch(`${this.baseURL}${ROUTES.ACTIVITY}`, {
|
|
173
|
-
method: "POST",
|
|
174
|
-
headers: { "Content-Type": "application/json" },
|
|
175
|
-
body: JSON.stringify(payload),
|
|
176
|
-
credentials: "include"
|
|
177
|
-
});
|
|
178
|
-
if (!response.ok) {
|
|
179
|
-
const errorResponse = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
180
|
-
throw new Error(errorResponse.error ?? "Failed to send activity");
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// src/client/timeback-client.ts
|
|
186
|
-
function createClient(config = {}) {
|
|
187
|
-
const baseURL = config.baseURL ?? getDefaultBaseURL();
|
|
188
|
-
return new TimebackClient({ baseURL });
|
|
189
|
-
}
|
|
190
|
-
export {
|
|
191
|
-
createClient,
|
|
192
|
-
TimebackClient,
|
|
193
|
-
Activity
|
|
194
|
-
};
|
|
1
|
+
import{a as o,b as y,c as b}from"./chunk-ahy54f2r.js";function r(e){let i=e.headerName??"Authorization",k=e.prefix??"Bearer ";return{wrapFetch(s){return async(t,m)=>{let a=await e.getToken();if(!a)throw Error("Missing bearer token (are you authenticated yet?)");let c=new Headers(m?.headers??(t instanceof Request?t.headers:void 0));if(!c.has(i))c.set(i,`${k}${a}`);return s(t,{...m,headers:c})}}}}export{b as createClient,r as bearer,y as TimebackClient,o as Activity};
|